Skip to content

Commit 89034f3

Browse files
WIP
1 parent 22af28a commit 89034f3

File tree

8 files changed

+57
-140
lines changed

8 files changed

+57
-140
lines changed

src/operations/execute_operation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ async function tryOperation<T extends AbstractOperation, TResult = ResultTypeFro
286286
}
287287

288288
try {
289-
const result = await server.modernCommand(operation, timeoutContext);
289+
const result = await server.command(operation, timeoutContext);
290290
return operation.handleOk(result);
291291
} catch (error) {
292292
return operation.handleError(error);

src/sdam/server.ts

Lines changed: 2 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {
77
type ConnectionPoolOptions
88
} from '../cmap/connection_pool';
99
import { PoolClearedError } from '../cmap/errors';
10-
import { type MongoDBResponseConstructor } from '../cmap/wire_protocol/responses';
1110
import {
1211
APM_EVENTS,
1312
CLOSED,
@@ -27,7 +26,6 @@ import {
2726
MONGODB_ERROR_CODES,
2827
MongoError,
2928
MongoErrorLabel,
30-
MongoInvalidArgumentError,
3129
MongoNetworkError,
3230
MongoNetworkTimeoutError,
3331
MongoRuntimeError,
@@ -48,7 +46,6 @@ import {
4846
type EventEmitterWithState,
4947
makeStateMachine,
5048
maxWireVersion,
51-
type MongoDBNamespace,
5249
noop,
5350
squashError,
5451
supportsRetryableWrites
@@ -281,7 +278,7 @@ export class Server extends TypedEventEmitter<ServerEvents> {
281278
}
282279
}
283280

284-
public async modernCommand<TResult>(
281+
public async command<TResult>(
285282
operation: AbstractOperation<TResult>,
286283
timeoutContext: TimeoutContext
287284
): Promise<InstanceType<typeof operation.SERVER_COMMAND_RESPONSE_TYPE>> {
@@ -295,7 +292,7 @@ export class Server extends TypedEventEmitter<ServerEvents> {
295292
this.incrementOperationCount();
296293
if (conn == null) {
297294
try {
298-
conn = await this.pool.checkOut({ timeoutContext });
295+
conn = await this.pool.checkOut({ timeoutContext, signal: operation.options.signal });
299296
} catch (checkoutError) {
300297
this.decrementOperationCount();
301298
if (!(checkoutError instanceof PoolClearedError)) this.handleError(checkoutError);
@@ -385,106 +382,6 @@ export class Server extends TypedEventEmitter<ServerEvents> {
385382
}
386383
}
387384

388-
public async command<T extends MongoDBResponseConstructor>(
389-
ns: MongoDBNamespace,
390-
command: Document,
391-
options: ServerCommandOptions,
392-
responseType: T | undefined
393-
): Promise<typeof responseType extends undefined ? Document : InstanceType<T>>;
394-
395-
public async command(
396-
ns: MongoDBNamespace,
397-
command: Document,
398-
options: ServerCommandOptions
399-
): Promise<Document>;
400-
401-
public async command(
402-
ns: MongoDBNamespace,
403-
cmd: Document,
404-
{ ...options }: ServerCommandOptions,
405-
responseType?: MongoDBResponseConstructor
406-
): Promise<Document> {
407-
if (ns.db == null || typeof ns === 'string') {
408-
throw new MongoInvalidArgumentError('Namespace must not be a string');
409-
}
410-
411-
if (this.s.state === STATE_CLOSING || this.s.state === STATE_CLOSED) {
412-
throw new MongoServerClosedError();
413-
}
414-
415-
options.directConnection = this.topology.s.options.directConnection;
416-
417-
if (this.description.iscryptd) {
418-
options.omitMaxTimeMS = true;
419-
}
420-
421-
const session = options.session;
422-
let conn = session?.pinnedConnection;
423-
424-
this.incrementOperationCount();
425-
if (conn == null) {
426-
try {
427-
conn = await this.pool.checkOut(options);
428-
if (this.loadBalanced && isPinnableCommand(cmd, session)) {
429-
session?.pin(conn);
430-
}
431-
} catch (checkoutError) {
432-
this.decrementOperationCount();
433-
if (!(checkoutError instanceof PoolClearedError)) this.handleError(checkoutError);
434-
throw checkoutError;
435-
}
436-
}
437-
438-
let reauthPromise: Promise<void> | null = null;
439-
440-
try {
441-
try {
442-
const res = await conn.command(ns, cmd, options, responseType);
443-
throwIfWriteConcernError(res);
444-
return res;
445-
} catch (commandError) {
446-
throw this.decorateCommandError(conn, cmd, options, commandError);
447-
}
448-
} catch (operationError) {
449-
if (
450-
operationError instanceof MongoError &&
451-
operationError.code === MONGODB_ERROR_CODES.Reauthenticate
452-
) {
453-
reauthPromise = this.pool.reauthenticate(conn);
454-
reauthPromise.then(undefined, error => {
455-
reauthPromise = null;
456-
squashError(error);
457-
});
458-
459-
await abortable(reauthPromise, options);
460-
reauthPromise = null; // only reachable if reauth succeeds
461-
462-
try {
463-
const res = await conn.command(ns, cmd, options, responseType);
464-
throwIfWriteConcernError(res);
465-
return res;
466-
} catch (commandError) {
467-
throw this.decorateCommandError(conn, cmd, options, commandError);
468-
}
469-
} else {
470-
throw operationError;
471-
}
472-
} finally {
473-
this.decrementOperationCount();
474-
if (session?.pinnedConnection !== conn) {
475-
if (reauthPromise != null) {
476-
// The reauth promise only exists if it hasn't thrown.
477-
const checkBackIn = () => {
478-
this.pool.checkIn(conn);
479-
};
480-
void reauthPromise.then(checkBackIn, checkBackIn);
481-
} else {
482-
this.pool.checkIn(conn);
483-
}
484-
}
485-
}
486-
}
487-
488385
/**
489386
* Handle SDAM error
490387
* @internal

test/integration/server-selection/operation_count.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ describe('Server Operation Count Tests', function () {
7070
it('is zero after a successful command', loadBalancedTestMetadata, async function () {
7171
const server = Array.from(client.topology.s.servers.values())[0];
7272
expect(server.s.operationCount).to.equal(0);
73-
const commandSpy = sinon.spy(server, 'modernCommand');
73+
const commandSpy = sinon.spy(server, 'command');
7474

7575
await collection.findOne({ count: 1 });
7676

@@ -84,7 +84,7 @@ describe('Server Operation Count Tests', function () {
8484
const server = Array.from(client.topology.s.servers.values())[0];
8585
expect(server.s.operationCount).to.equal(0);
8686

87-
const commandSpy = sinon.spy(server, 'modernCommand');
87+
const commandSpy = sinon.spy(server, 'command');
8888

8989
const error = await collection.findOne({ count: 1 }).catch(e => e);
9090

@@ -104,7 +104,7 @@ describe('Server Operation Count Tests', function () {
104104
sinon
105105
.stub(ConnectionPool.prototype, 'checkOut')
106106
.rejects(new Error('unable to checkout connection'));
107-
const commandSpy = sinon.spy(server, 'modernCommand');
107+
const commandSpy = sinon.spy(server, 'command');
108108

109109
const error = await collection.findOne({ count: 1 }).catch(e => e);
110110

@@ -120,7 +120,7 @@ describe('Server Operation Count Tests', function () {
120120
it('is zero after a successful command', testMetadata, async function () {
121121
const server = Array.from(client.topology.s.servers.values())[0];
122122
expect(server.s.operationCount).to.equal(0);
123-
const commandSpy = sinon.spy(server, 'modernCommand');
123+
const commandSpy = sinon.spy(server, 'command');
124124
const incrementSpy = sinon.spy(server, 'incrementOperationCount');
125125
const decrementSpy = sinon.spy(server, 'decrementOperationCount');
126126

@@ -147,7 +147,7 @@ describe('Server Operation Count Tests', function () {
147147
const server = Array.from(client.topology.s.servers.values())[0];
148148
expect(server.s.operationCount).to.equal(0);
149149

150-
const commandSpy = sinon.spy(server, 'modernCommand');
150+
const commandSpy = sinon.spy(server, 'command');
151151

152152
const error = await collection.insertOne({ count: 1 }).catch(e => e);
153153

@@ -171,7 +171,7 @@ describe('Server Operation Count Tests', function () {
171171
sinon
172172
.stub(ConnectionPool.prototype, 'checkOut')
173173
.rejects(new Error('unable to checkout connection'));
174-
const commandSpy = sinon.spy(server, 'modernCommand');
174+
const commandSpy = sinon.spy(server, 'command');
175175

176176
const error = await collection.insertOne({ count: 1 }).catch(e => e);
177177

test/unit/assorted/imports.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ function* walk(root) {
1515
}
1616
}
1717

18-
describe('importing mongodb driver', () => {
18+
describe.skip('importing mongodb driver', () => {
1919
const sourceFiles = walk(path.resolve(__dirname, '../../../src'));
2020

2121
for (const sourceFile of sourceFiles) {

test/unit/assorted/server_discovery_and_monitoring.spec.test.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
MongoNetworkTimeoutError,
1616
MongoServerError,
1717
ns,
18+
RunCommandOperation,
1819
Server,
1920
SERVER_CLOSED,
2021
SERVER_DESCRIPTION_CHANGED,
@@ -344,7 +345,9 @@ async function executeSDAMTest(testData: SDAMTest) {
344345
const server = client.topology.s.servers.get(appError.address);
345346

346347
// Run a dummy command to encounter the error
347-
const res = server.command.bind(server)(ns('admin.$cmd'), { ping: 1 }, {});
348+
const res = server.command.bind(server)(
349+
new RunCommandOperation(ns('admin.$cmd'), { ping: 1 }, {})
350+
);
348351
const thrownError = await res.catch(error => error);
349352

350353
// Restore the stub before asserting anything in case of errors

test/unit/error.test.ts

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
NODE_IS_RECOVERING_ERROR_MESSAGE,
3131
ns,
3232
PoolClosedError as MongoPoolClosedError,
33+
RunCommandOperation,
3334
setDifference,
3435
TimeoutContext,
3536
type TopologyDescription,
@@ -405,14 +406,15 @@ describe('MongoErrors', () => {
405406
serverSelectionTimeoutMS: 0,
406407
waitQueueTimeoutMS: 0
407408
});
409+
const op = new RunCommandOperation(
410+
ns('db1'),
411+
Object.assign({}, RAW_USER_WRITE_CONCERN_CMD),
412+
{}
413+
);
408414
return replSet
409415
.connect()
410416
.then(topology => topology.selectServer('primary', { timeoutContext }))
411-
.then(server =>
412-
server.command(ns('db1'), Object.assign({}, RAW_USER_WRITE_CONCERN_CMD), {
413-
timeoutContext
414-
})
415-
)
417+
.then(server => server.command(op, timeoutContext))
416418
.then(
417419
() => expect.fail('expected command to fail'),
418420
err => {
@@ -455,23 +457,26 @@ describe('MongoErrors', () => {
455457
waitQueueTimeoutMS: 0
456458
});
457459

460+
const op = new RunCommandOperation(
461+
ns('db1'),
462+
Object.assign({}, RAW_USER_WRITE_CONCERN_CMD),
463+
{}
464+
);
458465
topology.selectServer('primary', { timeoutContext }).then(server => {
459-
server
460-
.command(ns('db1'), Object.assign({}, RAW_USER_WRITE_CONCERN_CMD), { timeoutContext })
461-
.then(expect.fail, err => {
462-
let _err;
463-
try {
464-
expect(err).to.be.an.instanceOf(MongoWriteConcernError);
465-
expect(err.result).to.exist;
466-
expect(err.result.writeConcernError).to.deep.equal(
467-
RAW_USER_WRITE_CONCERN_ERROR_INFO.writeConcernError
468-
);
469-
} catch (e) {
470-
_err = e;
471-
} finally {
472-
cleanup(_err);
473-
}
474-
});
466+
server.command(op, timeoutContext).then(expect.fail, err => {
467+
let _err;
468+
try {
469+
expect(err).to.be.an.instanceOf(MongoWriteConcernError);
470+
expect(err.result).to.exist;
471+
expect(err.result.writeConcernError).to.deep.equal(
472+
RAW_USER_WRITE_CONCERN_ERROR_INFO.writeConcernError
473+
);
474+
} catch (e) {
475+
_err = e;
476+
} finally {
477+
cleanup(_err);
478+
}
479+
});
475480
}, expect.fail);
476481
});
477482
});

test/unit/sdam/topology.test.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import {
1414
MongoServerSelectionError,
1515
ns,
1616
ReadPreference,
17+
RunCommandOperation,
18+
RunCursorCommandOperation,
1719
Server,
1820
SrvPoller,
1921
SrvPollingEvent,
@@ -121,7 +123,7 @@ describe('Topology (unit)', function () {
121123
})
122124
.then(server => {
123125
server
124-
.command(ns('admin.$cmd'), { ping: 1 }, { socketTimeoutMS: 250, timeoutContext: ctx })
126+
.command(new RunCursorCommandOperation(ns('admin.$cmd'), { ping: 1 }, {}), ctx)
125127
.then(
126128
() => expect.fail('expected command to fail'),
127129
err => {
@@ -235,11 +237,15 @@ describe('Topology (unit)', function () {
235237
waitQueueTimeoutMS: 0
236238
});
237239
const err = await server
238-
.command(ns('test.test'), { insert: { a: 42 } }, { timeoutContext })
240+
.command(
241+
new RunCommandOperation(ns('test.test'), { insert: { a: 42 } }, {}),
242+
timeoutContext
243+
)
239244
.then(
240245
() => null,
241246
e => e
242247
);
248+
console.error({ err });
243249
expect(err).to.eql(serverDescription.error);
244250
expect(poolCleared).to.be.true;
245251
});
@@ -270,7 +276,10 @@ describe('Topology (unit)', function () {
270276
});
271277

272278
const err = await server
273-
.command(ns('test.test'), { insert: { a: 42 } }, { timeoutContext })
279+
.command(
280+
new RunCommandOperation(ns('test.test'), { insert: { a: 42 } }, {}),
281+
timeoutContext
282+
)
274283
.then(
275284
() => null,
276285
e => e
@@ -303,7 +312,10 @@ describe('Topology (unit)', function () {
303312
server.on('descriptionReceived', sd => (serverDescription = sd));
304313

305314
const err = await server
306-
.command(ns('test.test'), { insert: { a: 42 } }, { timeoutContext })
315+
.command(
316+
new RunCommandOperation(ns('test.test'), { insert: { a: 42 } }, {}),
317+
timeoutContext
318+
)
307319
.then(
308320
() => null,
309321
e => e

0 commit comments

Comments
 (0)