mongodb 6.18.0-dev.20250802.sha.be7f808c → 6.18.0-dev.20250806.sha.e628296a
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/beta.d.ts +4 -1
- package/lib/cmap/connection.js.map +1 -1
- package/lib/cursor/aggregation_cursor.js +2 -1
- package/lib/cursor/aggregation_cursor.js.map +1 -1
- package/lib/cursor/explainable_cursor.js +36 -0
- package/lib/cursor/explainable_cursor.js.map +1 -0
- package/lib/cursor/find_cursor.js +2 -1
- package/lib/cursor/find_cursor.js.map +1 -1
- package/lib/explain.js +1 -33
- package/lib/explain.js.map +1 -1
- package/lib/index.js +6 -6
- package/lib/index.js.map +1 -1
- package/lib/operations/aggregate.js +10 -8
- package/lib/operations/aggregate.js.map +1 -1
- package/lib/operations/command.js +68 -6
- package/lib/operations/command.js.map +1 -1
- package/lib/operations/drop.js +2 -1
- package/lib/operations/drop.js.map +1 -1
- package/lib/operations/execute_operation.js +15 -2
- package/lib/operations/execute_operation.js.map +1 -1
- package/lib/operations/find.js +13 -24
- package/lib/operations/find.js.map +1 -1
- package/lib/operations/get_more.js +11 -12
- package/lib/operations/get_more.js.map +1 -1
- package/lib/operations/indexes.js +8 -4
- package/lib/operations/indexes.js.map +1 -1
- package/lib/operations/insert.js +18 -3
- package/lib/operations/insert.js.map +1 -1
- package/lib/operations/kill_cursors.js +14 -16
- package/lib/operations/kill_cursors.js.map +1 -1
- package/lib/operations/list_collections.js +8 -7
- package/lib/operations/list_collections.js.map +1 -1
- package/lib/operations/operation.js +39 -2
- package/lib/operations/operation.js.map +1 -1
- package/lib/operations/search_indexes/drop.js +17 -10
- package/lib/operations/search_indexes/drop.js.map +1 -1
- package/lib/sdam/server.js +86 -7
- package/lib/sdam/server.js.map +1 -1
- package/lib/sdam/topology.js +3 -2
- package/lib/sdam/topology.js.map +1 -1
- package/mongodb.d.ts +4 -1
- package/package.json +1 -1
- package/src/cmap/connection.ts +0 -1
- package/src/cursor/aggregation_cursor.ts +1 -1
- package/src/cursor/explainable_cursor.ts +51 -0
- package/src/cursor/find_cursor.ts +1 -1
- package/src/explain.ts +0 -49
- package/src/index.ts +8 -3
- package/src/operations/aggregate.ts +21 -22
- package/src/operations/command.ts +90 -9
- package/src/operations/drop.ts +2 -1
- package/src/operations/execute_operation.ts +20 -3
- package/src/operations/find.ts +28 -49
- package/src/operations/get_more.ts +18 -20
- package/src/operations/indexes.ts +13 -8
- package/src/operations/insert.ts +22 -9
- package/src/operations/kill_cursors.ts +22 -23
- package/src/operations/list_collections.ts +15 -23
- package/src/operations/operation.ts +60 -4
- package/src/operations/search_indexes/drop.ts +25 -16
- package/src/sdam/server.ts +98 -8
- package/src/sdam/topology.ts +4 -3
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { Long } from '../bson';
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
2
|
+
import { type Connection } from '../cmap/connection';
|
|
3
|
+
import { MongoDBResponse } from '../cmap/wire_protocol/responses';
|
|
4
|
+
import { type MongoError, MongoRuntimeError } from '../error';
|
|
5
|
+
import type { Server, ServerCommandOptions } from '../sdam/server';
|
|
4
6
|
import type { ClientSession } from '../sessions';
|
|
5
7
|
import { type TimeoutContext } from '../timeout';
|
|
6
|
-
import { type MongoDBNamespace
|
|
7
|
-
import {
|
|
8
|
+
import { type MongoDBNamespace } from '../utils';
|
|
9
|
+
import { Aspect, defineAspects, ModernizedOperation, type OperationOptions } from './operation';
|
|
8
10
|
|
|
9
11
|
/**
|
|
10
12
|
* https://www.mongodb.com/docs/manual/reference/command/killCursors/
|
|
@@ -16,7 +18,8 @@ interface KillCursorsCommand {
|
|
|
16
18
|
comment?: unknown;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
|
-
export class KillCursorsOperation extends
|
|
21
|
+
export class KillCursorsOperation extends ModernizedOperation<void> {
|
|
22
|
+
override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
|
|
20
23
|
cursorId: Long;
|
|
21
24
|
|
|
22
25
|
constructor(cursorId: Long, ns: MongoDBNamespace, server: Server, options: OperationOptions) {
|
|
@@ -30,15 +33,7 @@ export class KillCursorsOperation extends AbstractOperation {
|
|
|
30
33
|
return 'killCursors' as const;
|
|
31
34
|
}
|
|
32
35
|
|
|
33
|
-
override
|
|
34
|
-
server: Server,
|
|
35
|
-
session: ClientSession | undefined,
|
|
36
|
-
timeoutContext: TimeoutContext
|
|
37
|
-
): Promise<void> {
|
|
38
|
-
if (server !== this.server) {
|
|
39
|
-
throw new MongoRuntimeError('Killcursor must run on the same server operation began on');
|
|
40
|
-
}
|
|
41
|
-
|
|
36
|
+
override buildCommand(_connection: Connection, _session?: ClientSession): KillCursorsCommand {
|
|
42
37
|
const killCursors = this.ns.collection;
|
|
43
38
|
if (killCursors == null) {
|
|
44
39
|
// Cursors should have adopted the namespace returned by MongoDB
|
|
@@ -50,15 +45,19 @@ export class KillCursorsOperation extends AbstractOperation {
|
|
|
50
45
|
killCursors,
|
|
51
46
|
cursors: [this.cursorId]
|
|
52
47
|
};
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
48
|
+
|
|
49
|
+
return killCursorsCommand;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
override buildOptions(timeoutContext: TimeoutContext): ServerCommandOptions {
|
|
53
|
+
return {
|
|
54
|
+
session: this.session,
|
|
55
|
+
timeoutContext
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
override handleError(_error: MongoError): void {
|
|
60
|
+
// The driver should never emit errors from killCursors, this is spec-ed behavior
|
|
62
61
|
}
|
|
63
62
|
}
|
|
64
63
|
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
+
import { type Connection } from '..';
|
|
1
2
|
import type { Binary, Document } from '../bson';
|
|
2
|
-
import { CursorResponse } from '../cmap/wire_protocol/responses';
|
|
3
|
+
import { CursorResponse, ExplainedCursorResponse } from '../cmap/wire_protocol/responses';
|
|
3
4
|
import { type CursorTimeoutContext, type CursorTimeoutMode } from '../cursor/abstract_cursor';
|
|
4
5
|
import type { Db } from '../db';
|
|
5
6
|
import { type Abortable } from '../mongo_types';
|
|
6
|
-
import type { Server } from '../sdam/server';
|
|
7
|
-
import type { ClientSession } from '../sessions';
|
|
8
|
-
import { type TimeoutContext } from '../timeout';
|
|
9
7
|
import { maxWireVersion } from '../utils';
|
|
10
|
-
import {
|
|
8
|
+
import { type CommandOperationOptions, ModernizedCommandOperation } from './command';
|
|
11
9
|
import { Aspect, defineAspects } from './operation';
|
|
12
10
|
|
|
13
11
|
/** @public */
|
|
@@ -28,7 +26,8 @@ export interface ListCollectionsOptions
|
|
|
28
26
|
}
|
|
29
27
|
|
|
30
28
|
/** @internal */
|
|
31
|
-
export class ListCollectionsOperation extends
|
|
29
|
+
export class ListCollectionsOperation extends ModernizedCommandOperation<CursorResponse> {
|
|
30
|
+
override SERVER_COMMAND_RESPONSE_TYPE = CursorResponse;
|
|
32
31
|
/**
|
|
33
32
|
* @remarks WriteConcern can still be present on the options because
|
|
34
33
|
* we inherit options from the client/db/collection. The
|
|
@@ -56,28 +55,15 @@ export class ListCollectionsOperation extends CommandOperation<CursorResponse> {
|
|
|
56
55
|
if (typeof this.options.batchSize === 'number') {
|
|
57
56
|
this.batchSize = this.options.batchSize;
|
|
58
57
|
}
|
|
58
|
+
|
|
59
|
+
this.SERVER_COMMAND_RESPONSE_TYPE = this.explain ? ExplainedCursorResponse : CursorResponse;
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
override get commandName() {
|
|
62
63
|
return 'listCollections' as const;
|
|
63
64
|
}
|
|
64
65
|
|
|
65
|
-
override
|
|
66
|
-
server: Server,
|
|
67
|
-
session: ClientSession | undefined,
|
|
68
|
-
timeoutContext: TimeoutContext
|
|
69
|
-
): Promise<CursorResponse> {
|
|
70
|
-
return await super.executeCommand(
|
|
71
|
-
server,
|
|
72
|
-
session,
|
|
73
|
-
this.generateCommand(maxWireVersion(server)),
|
|
74
|
-
timeoutContext,
|
|
75
|
-
CursorResponse
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/* This is here for the purpose of unit testing the final command that gets sent. */
|
|
80
|
-
generateCommand(wireVersion: number): Document {
|
|
66
|
+
override buildCommandDocument(connection: Connection): Document {
|
|
81
67
|
const command: Document = {
|
|
82
68
|
listCollections: 1,
|
|
83
69
|
filter: this.filter,
|
|
@@ -88,12 +74,18 @@ export class ListCollectionsOperation extends CommandOperation<CursorResponse> {
|
|
|
88
74
|
|
|
89
75
|
// we check for undefined specifically here to allow falsy values
|
|
90
76
|
// eslint-disable-next-line no-restricted-syntax
|
|
91
|
-
if (
|
|
77
|
+
if (maxWireVersion(connection) >= 9 && this.options.comment !== undefined) {
|
|
92
78
|
command.comment = this.options.comment;
|
|
93
79
|
}
|
|
94
80
|
|
|
95
81
|
return command;
|
|
96
82
|
}
|
|
83
|
+
|
|
84
|
+
override handleOk(
|
|
85
|
+
response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>
|
|
86
|
+
): CursorResponse {
|
|
87
|
+
return response;
|
|
88
|
+
}
|
|
97
89
|
}
|
|
98
90
|
|
|
99
91
|
/** @public */
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { type Connection, type MongoError } from '..';
|
|
1
2
|
import { type BSONSerializeOptions, type Document, resolveBSONOptions } from '../bson';
|
|
3
|
+
import { type MongoDBResponse } from '../cmap/wire_protocol/responses';
|
|
2
4
|
import { type Abortable } from '../mongo_types';
|
|
3
5
|
import { ReadPreference, type ReadPreferenceLike } from '../read_preference';
|
|
4
|
-
import type { Server } from '../sdam/server';
|
|
6
|
+
import type { Server, ServerCommandOptions } from '../sdam/server';
|
|
5
7
|
import type { ClientSession } from '../sessions';
|
|
6
8
|
import { type TimeoutContext } from '../timeout';
|
|
7
9
|
import type { MongoDBNamespace } from '../utils';
|
|
@@ -31,7 +33,6 @@ export interface OperationOptions extends BSONSerializeOptions {
|
|
|
31
33
|
|
|
32
34
|
/** @internal Hints to `executeOperation` that this operation should not unpin on an ended transaction */
|
|
33
35
|
bypassPinningCheck?: boolean;
|
|
34
|
-
omitReadPreference?: boolean;
|
|
35
36
|
|
|
36
37
|
/** @internal Hint to `executeOperation` to omit maxTimeMS */
|
|
37
38
|
omitMaxTimeMS?: boolean;
|
|
@@ -55,7 +56,6 @@ export abstract class AbstractOperation<TResult = any> {
|
|
|
55
56
|
readPreference: ReadPreference;
|
|
56
57
|
server!: Server;
|
|
57
58
|
bypassPinningCheck: boolean;
|
|
58
|
-
trySecondaryWrite: boolean;
|
|
59
59
|
|
|
60
60
|
// BSON serialization options
|
|
61
61
|
bsonOptions?: BSONSerializeOptions;
|
|
@@ -81,7 +81,6 @@ export abstract class AbstractOperation<TResult = any> {
|
|
|
81
81
|
|
|
82
82
|
this.options = options;
|
|
83
83
|
this.bypassPinningCheck = !!options.bypassPinningCheck;
|
|
84
|
-
this.trySecondaryWrite = false;
|
|
85
84
|
}
|
|
86
85
|
|
|
87
86
|
/** Must match the first key of the command object sent to the server.
|
|
@@ -108,6 +107,10 @@ export abstract class AbstractOperation<TResult = any> {
|
|
|
108
107
|
return this._session;
|
|
109
108
|
}
|
|
110
109
|
|
|
110
|
+
set session(session: ClientSession) {
|
|
111
|
+
this._session = session;
|
|
112
|
+
}
|
|
113
|
+
|
|
111
114
|
clearSession() {
|
|
112
115
|
this._session = undefined;
|
|
113
116
|
}
|
|
@@ -125,6 +128,59 @@ export abstract class AbstractOperation<TResult = any> {
|
|
|
125
128
|
}
|
|
126
129
|
}
|
|
127
130
|
|
|
131
|
+
/** @internal */
|
|
132
|
+
export abstract class ModernizedOperation<TResult> extends AbstractOperation<TResult> {
|
|
133
|
+
abstract SERVER_COMMAND_RESPONSE_TYPE: typeof MongoDBResponse;
|
|
134
|
+
|
|
135
|
+
/** this will never be used - but we must implement it to satisfy AbstractOperation's interface */
|
|
136
|
+
override execute(
|
|
137
|
+
_server: Server,
|
|
138
|
+
_session: ClientSession | undefined,
|
|
139
|
+
_timeoutContext: TimeoutContext
|
|
140
|
+
): Promise<TResult> {
|
|
141
|
+
throw new Error('cannot execute!!');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Build a raw command document.
|
|
146
|
+
*/
|
|
147
|
+
abstract buildCommand(connection: Connection, session?: ClientSession): Document;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Builds an instance of `ServerCommandOptions` to be used for operation execution.
|
|
151
|
+
*/
|
|
152
|
+
abstract buildOptions(timeoutContext: TimeoutContext): ServerCommandOptions;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Given an instance of a MongoDBResponse, map the response to the correct result type. For
|
|
156
|
+
* example, a `CountOperation` might map the response as follows:
|
|
157
|
+
*
|
|
158
|
+
* ```typescript
|
|
159
|
+
* override handleOk(response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>): TResult {
|
|
160
|
+
* return response.toObject(this.bsonOptions).n ?? 0;
|
|
161
|
+
* }
|
|
162
|
+
*
|
|
163
|
+
* // or, with type safety:
|
|
164
|
+
* override handleOk(response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>): TResult {
|
|
165
|
+
* return response.getNumber('n') ?? 0;
|
|
166
|
+
* }
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
handleOk(response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>): TResult {
|
|
170
|
+
return response.toObject(this.bsonOptions) as TResult;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Optional.
|
|
175
|
+
*
|
|
176
|
+
* If the operation performs error handling, such as wrapping, renaming the error, or squashing errors
|
|
177
|
+
* this method can be overridden.
|
|
178
|
+
*/
|
|
179
|
+
handleError(error: MongoError): TResult | never {
|
|
180
|
+
throw error;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
128
184
|
export function defineAspects(
|
|
129
185
|
operation: { aspects?: Set<symbol> },
|
|
130
186
|
aspects: symbol | symbol[] | Set<symbol>
|
|
@@ -1,13 +1,17 @@
|
|
|
1
|
+
import { type Connection, type MongoError } from '../..';
|
|
1
2
|
import type { Document } from '../../bson';
|
|
3
|
+
import { MongoDBResponse } from '../../cmap/wire_protocol/responses';
|
|
2
4
|
import type { Collection } from '../../collection';
|
|
3
5
|
import { MONGODB_ERROR_CODES, MongoServerError } from '../../error';
|
|
4
|
-
import type {
|
|
6
|
+
import type { ServerCommandOptions } from '../../sdam/server';
|
|
5
7
|
import type { ClientSession } from '../../sessions';
|
|
6
8
|
import { type TimeoutContext } from '../../timeout';
|
|
7
|
-
import {
|
|
9
|
+
import { ModernizedOperation } from '../operation';
|
|
8
10
|
|
|
9
11
|
/** @internal */
|
|
10
|
-
export class DropSearchIndexOperation extends
|
|
12
|
+
export class DropSearchIndexOperation extends ModernizedOperation<void> {
|
|
13
|
+
override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
|
|
14
|
+
|
|
11
15
|
private readonly collection: Collection;
|
|
12
16
|
private readonly name: string;
|
|
13
17
|
|
|
@@ -15,17 +19,14 @@ export class DropSearchIndexOperation extends AbstractOperation<void> {
|
|
|
15
19
|
super();
|
|
16
20
|
this.collection = collection;
|
|
17
21
|
this.name = name;
|
|
22
|
+
this.ns = collection.fullNamespace;
|
|
18
23
|
}
|
|
19
24
|
|
|
20
25
|
override get commandName() {
|
|
21
26
|
return 'dropSearchIndex' as const;
|
|
22
27
|
}
|
|
23
28
|
|
|
24
|
-
override
|
|
25
|
-
server: Server,
|
|
26
|
-
session: ClientSession | undefined,
|
|
27
|
-
timeoutContext: TimeoutContext
|
|
28
|
-
): Promise<void> {
|
|
29
|
+
override buildCommand(_connection: Connection, _session?: ClientSession): Document {
|
|
29
30
|
const namespace = this.collection.fullNamespace;
|
|
30
31
|
|
|
31
32
|
const command: Document = {
|
|
@@ -36,14 +37,22 @@ export class DropSearchIndexOperation extends AbstractOperation<void> {
|
|
|
36
37
|
command.name = this.name;
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
40
|
+
return command;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
override handleOk(_response: MongoDBResponse): void {
|
|
44
|
+
// do nothing
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
override buildOptions(timeoutContext: TimeoutContext): ServerCommandOptions {
|
|
48
|
+
return { session: this.session, timeoutContext };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
override handleError(error: MongoError): void {
|
|
52
|
+
const isNamespaceNotFoundError =
|
|
53
|
+
error instanceof MongoServerError && error.code === MONGODB_ERROR_CODES.NamespaceNotFound;
|
|
54
|
+
if (!isNamespaceNotFoundError) {
|
|
55
|
+
throw error;
|
|
47
56
|
}
|
|
48
57
|
}
|
|
49
58
|
}
|
package/src/sdam/server.ts
CHANGED
|
@@ -37,7 +37,9 @@ import {
|
|
|
37
37
|
} from '../error';
|
|
38
38
|
import type { ServerApi } from '../mongo_client';
|
|
39
39
|
import { type Abortable, TypedEventEmitter } from '../mongo_types';
|
|
40
|
+
import { AggregateOperation } from '../operations/aggregate';
|
|
40
41
|
import type { GetMoreOptions } from '../operations/get_more';
|
|
42
|
+
import { type ModernizedOperation } from '../operations/operation';
|
|
41
43
|
import type { ClientSession } from '../sessions';
|
|
42
44
|
import { type TimeoutContext } from '../timeout';
|
|
43
45
|
import { isTransactionCommand } from '../transactions';
|
|
@@ -67,6 +69,7 @@ import type {
|
|
|
67
69
|
} from './events';
|
|
68
70
|
import { Monitor, type MonitorOptions } from './monitor';
|
|
69
71
|
import { compareTopologyVersion, ServerDescription } from './server_description';
|
|
72
|
+
import { MIN_SECONDARY_WRITE_WIRE_VERSION } from './server_selection';
|
|
70
73
|
import type { Topology } from './topology';
|
|
71
74
|
|
|
72
75
|
const stateTransition = makeStateMachine({
|
|
@@ -110,6 +113,7 @@ export type ServerEvents = {
|
|
|
110
113
|
/** @internal */
|
|
111
114
|
export type ServerCommandOptions = Omit<CommandOptions, 'timeoutContext' | 'socketTimeoutMS'> & {
|
|
112
115
|
timeoutContext: TimeoutContext;
|
|
116
|
+
returnFieldSelector?: Document | null;
|
|
113
117
|
} & Abortable;
|
|
114
118
|
|
|
115
119
|
/** @internal */
|
|
@@ -277,6 +281,100 @@ export class Server extends TypedEventEmitter<ServerEvents> {
|
|
|
277
281
|
}
|
|
278
282
|
}
|
|
279
283
|
|
|
284
|
+
public async modernCommand<TResult>(
|
|
285
|
+
operation: ModernizedOperation<TResult>,
|
|
286
|
+
timeoutContext: TimeoutContext
|
|
287
|
+
): Promise<InstanceType<typeof operation.SERVER_COMMAND_RESPONSE_TYPE>> {
|
|
288
|
+
if (this.s.state === STATE_CLOSING || this.s.state === STATE_CLOSED) {
|
|
289
|
+
throw new MongoServerClosedError();
|
|
290
|
+
}
|
|
291
|
+
const session = operation.session;
|
|
292
|
+
|
|
293
|
+
let conn = session?.pinnedConnection;
|
|
294
|
+
|
|
295
|
+
this.incrementOperationCount();
|
|
296
|
+
if (conn == null) {
|
|
297
|
+
try {
|
|
298
|
+
conn = await this.pool.checkOut({ timeoutContext });
|
|
299
|
+
} catch (checkoutError) {
|
|
300
|
+
this.decrementOperationCount();
|
|
301
|
+
if (!(checkoutError instanceof PoolClearedError)) this.handleError(checkoutError);
|
|
302
|
+
throw checkoutError;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const cmd = operation.buildCommand(conn, session);
|
|
307
|
+
const options = operation.buildOptions(timeoutContext);
|
|
308
|
+
const ns = operation.ns;
|
|
309
|
+
|
|
310
|
+
if (this.loadBalanced && isPinnableCommand(cmd, session) && !session?.pinnedConnection) {
|
|
311
|
+
session?.pin(conn);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
options.directConnection = this.topology.s.options.directConnection;
|
|
315
|
+
|
|
316
|
+
const omitReadPreference =
|
|
317
|
+
operation instanceof AggregateOperation &&
|
|
318
|
+
operation.hasWriteStage &&
|
|
319
|
+
maxWireVersion(conn) < MIN_SECONDARY_WRITE_WIRE_VERSION;
|
|
320
|
+
if (omitReadPreference) {
|
|
321
|
+
delete options.readPreference;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (this.description.iscryptd) {
|
|
325
|
+
options.omitMaxTimeMS = true;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
let reauthPromise: Promise<void> | null = null;
|
|
329
|
+
|
|
330
|
+
try {
|
|
331
|
+
try {
|
|
332
|
+
const res = await conn.command(ns, cmd, options, operation.SERVER_COMMAND_RESPONSE_TYPE);
|
|
333
|
+
throwIfWriteConcernError(res);
|
|
334
|
+
return res;
|
|
335
|
+
} catch (commandError) {
|
|
336
|
+
throw this.decorateCommandError(conn, cmd, options, commandError);
|
|
337
|
+
}
|
|
338
|
+
} catch (operationError) {
|
|
339
|
+
if (
|
|
340
|
+
operationError instanceof MongoError &&
|
|
341
|
+
operationError.code === MONGODB_ERROR_CODES.Reauthenticate
|
|
342
|
+
) {
|
|
343
|
+
reauthPromise = this.pool.reauthenticate(conn);
|
|
344
|
+
reauthPromise.then(undefined, error => {
|
|
345
|
+
reauthPromise = null;
|
|
346
|
+
squashError(error);
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
await abortable(reauthPromise, options);
|
|
350
|
+
reauthPromise = null; // only reachable if reauth succeeds
|
|
351
|
+
|
|
352
|
+
try {
|
|
353
|
+
const res = await conn.command(ns, cmd, options, operation.SERVER_COMMAND_RESPONSE_TYPE);
|
|
354
|
+
throwIfWriteConcernError(res);
|
|
355
|
+
return res;
|
|
356
|
+
} catch (commandError) {
|
|
357
|
+
throw this.decorateCommandError(conn, cmd, options, commandError);
|
|
358
|
+
}
|
|
359
|
+
} else {
|
|
360
|
+
throw operationError;
|
|
361
|
+
}
|
|
362
|
+
} finally {
|
|
363
|
+
this.decrementOperationCount();
|
|
364
|
+
if (session?.pinnedConnection !== conn) {
|
|
365
|
+
if (reauthPromise != null) {
|
|
366
|
+
// The reauth promise only exists if it hasn't thrown.
|
|
367
|
+
const checkBackIn = () => {
|
|
368
|
+
this.pool.checkIn(conn);
|
|
369
|
+
};
|
|
370
|
+
void reauthPromise.then(checkBackIn, checkBackIn);
|
|
371
|
+
} else {
|
|
372
|
+
this.pool.checkIn(conn);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
280
378
|
public async command<T extends MongoDBResponseConstructor>(
|
|
281
379
|
ns: MongoDBNamespace,
|
|
282
380
|
command: Document,
|
|
@@ -306,14 +404,6 @@ export class Server extends TypedEventEmitter<ServerEvents> {
|
|
|
306
404
|
|
|
307
405
|
options.directConnection = this.topology.s.options.directConnection;
|
|
308
406
|
|
|
309
|
-
// There are cases where we need to flag the read preference not to get sent in
|
|
310
|
-
// the command, such as pre-5.0 servers attempting to perform an aggregate write
|
|
311
|
-
// with a non-primary read preference. In this case the effective read preference
|
|
312
|
-
// (primary) is not the same as the provided and must be removed completely.
|
|
313
|
-
if (options.omitReadPreference) {
|
|
314
|
-
delete options.readPreference;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
407
|
if (this.description.iscryptd) {
|
|
318
408
|
options.omitMaxTimeMS = true;
|
|
319
409
|
}
|
package/src/sdam/topology.ts
CHANGED
|
@@ -46,7 +46,6 @@ import {
|
|
|
46
46
|
makeStateMachine,
|
|
47
47
|
noop,
|
|
48
48
|
now,
|
|
49
|
-
ns,
|
|
50
49
|
promiseWithResolvers,
|
|
51
50
|
shuffle
|
|
52
51
|
} from '../utils';
|
|
@@ -459,7 +458,7 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
|
|
|
459
458
|
waitQueueTimeoutMS: this.client.s.options.waitQueueTimeoutMS
|
|
460
459
|
});
|
|
461
460
|
const selectServerOptions = {
|
|
462
|
-
operationName: '
|
|
461
|
+
operationName: 'handshake',
|
|
463
462
|
...options,
|
|
464
463
|
timeoutContext
|
|
465
464
|
};
|
|
@@ -469,9 +468,11 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
|
|
|
469
468
|
readPreferenceServerSelector(readPreference),
|
|
470
469
|
selectServerOptions
|
|
471
470
|
);
|
|
471
|
+
|
|
472
472
|
const skipPingOnConnect = this.s.options.__skipPingOnConnect === true;
|
|
473
473
|
if (!skipPingOnConnect && this.s.credentials) {
|
|
474
|
-
await server.
|
|
474
|
+
const connection = await server.pool.checkOut({ timeoutContext: timeoutContext });
|
|
475
|
+
server.pool.checkIn(connection);
|
|
475
476
|
stateTransition(this, STATE_CONNECTED);
|
|
476
477
|
this.emit(Topology.OPEN, this);
|
|
477
478
|
this.emit(Topology.CONNECT, this);
|