Skip to content

Commit be242a5

Browse files
basic implementation completed
1 parent d6a9e48 commit be242a5

File tree

9 files changed

+193
-64
lines changed

9 files changed

+193
-64
lines changed

src/index.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,13 @@ export {
147147
TopologyDescriptionChangedEvent,
148148
TopologyOpeningEvent
149149
} from './sdam/events';
150+
export {
151+
ServerSelectionEvent,
152+
ServerSelectionFailedEvent,
153+
ServerSelectionStartedEvent,
154+
ServerSelectionSucceededEvent,
155+
WaitingForSuitableServerEvent
156+
} from './sdam/server_selection_events';
150157
export { SrvPollingEvent } from './sdam/srv_polling';
151158

152159
// type only exports below, these are removed from emitted JS
@@ -305,7 +312,11 @@ export type {
305312
CONNECTION_POOL_CREATED,
306313
CONNECTION_POOL_READY,
307314
CONNECTION_READY,
308-
MONGO_CLIENT_EVENTS
315+
MONGO_CLIENT_EVENTS,
316+
SERVER_SELECTION_FAILED,
317+
SERVER_SELECTION_STARTED,
318+
SERVER_SELECTION_SUCCEEDED,
319+
WAITING_FOR_SUITABLE_SERVER
309320
} from './constants';
310321
export type {
311322
AbstractCursorEvents,

src/mongo_logger.ts

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import type {
1717
ConnectionPoolClearedEvent,
1818
ConnectionPoolClosedEvent,
1919
ConnectionPoolCreatedEvent,
20-
ConnectionPoolMonitoringEvent,
2120
ConnectionPoolReadyEvent,
2221
ConnectionReadyEvent
2322
} from './cmap/connection_pool_events';
@@ -35,8 +34,19 @@ import {
3534
CONNECTION_POOL_CLOSED,
3635
CONNECTION_POOL_CREATED,
3736
CONNECTION_POOL_READY,
38-
CONNECTION_READY
37+
CONNECTION_READY,
38+
SERVER_SELECTION_FAILED,
39+
SERVER_SELECTION_STARTED,
40+
SERVER_SELECTION_SUCCEEDED,
41+
WAITING_FOR_SUITABLE_SERVER
3942
} from './constants';
43+
import type {
44+
ServerSelectionEvent,
45+
ServerSelectionFailedEvent,
46+
ServerSelectionStartedEvent,
47+
ServerSelectionSucceededEvent,
48+
WaitingForSuitableServerEvent
49+
} from './sdam/server_selection_events';
4050
import { HostAddress, parseUnsignedInteger } from './utils';
4151

4252
/** @internal */
@@ -272,6 +282,10 @@ function compareSeverity(s0: SeverityLevel, s1: SeverityLevel): 1 | 0 | -1 {
272282

273283
/** @internal */
274284
export type LoggableEvent =
285+
| ServerSelectionStartedEvent
286+
| ServerSelectionFailedEvent
287+
| ServerSelectionSucceededEvent
288+
| WaitingForSuitableServerEvent
275289
| CommandStartedEvent
276290
| CommandSucceededEvent
277291
| CommandFailedEvent
@@ -310,6 +324,20 @@ function isLogConvertible(obj: Loggable): obj is LogConvertible {
310324
return objAsLogConvertible.toLog !== undefined && typeof objAsLogConvertible.toLog === 'function';
311325
}
312326

327+
function attachServerSelectionFields(
328+
log: Record<string, any>,
329+
serverSelectionEvent: ServerSelectionEvent,
330+
maxDocumentLength: number = DEFAULT_MAX_DOCUMENT_LENGTH
331+
) {
332+
const { selector, operation, topologyDescription, message } = serverSelectionEvent;
333+
log.selector = stringifyWithMaxLen(selector, maxDocumentLength);
334+
log.operation = operation;
335+
log.topologyDescription = stringifyWithMaxLen(topologyDescription, maxDocumentLength);
336+
log.message = message;
337+
338+
return log;
339+
}
340+
313341
function attachCommandFields(
314342
log: Record<string, any>,
315343
commandEvent: CommandStartedEvent | CommandSucceededEvent | CommandFailedEvent
@@ -327,11 +355,8 @@ function attachCommandFields(
327355
return log;
328356
}
329357

330-
function attachConnectionFields(
331-
log: Record<string, any>,
332-
connectionPoolEvent: ConnectionPoolMonitoringEvent
333-
) {
334-
const { host, port } = HostAddress.fromString(connectionPoolEvent.address).toHostPort();
358+
function attachConnectionFields(log: Record<string, any>, event: any) {
359+
const { host, port } = HostAddress.fromString(event.address).toHostPort();
335360
log.serverHost = host;
336361
log.serverPort = port;
337362

@@ -345,6 +370,21 @@ function defaultLogTransform(
345370
let log: Omit<Log, 's' | 't' | 'c'> = Object.create(null);
346371

347372
switch (logObject.name) {
373+
case SERVER_SELECTION_STARTED:
374+
log = attachServerSelectionFields(log, logObject, maxDocumentLength);
375+
return log;
376+
case SERVER_SELECTION_FAILED:
377+
log = attachServerSelectionFields(log, logObject, maxDocumentLength);
378+
log.failure = logObject.failure.message;
379+
return log;
380+
case SERVER_SELECTION_SUCCEEDED:
381+
log = attachServerSelectionFields(log, logObject, maxDocumentLength);
382+
log = attachConnectionFields(log, logObject);
383+
return log;
384+
case WAITING_FOR_SUITABLE_SERVER:
385+
log = attachServerSelectionFields(log, logObject, maxDocumentLength);
386+
log.remainingTimeMS = logObject.remainingTimeMS;
387+
return log;
348388
case COMMAND_STARTED:
349389
log = attachCommandFields(log, logObject);
350390
log.message = 'Command started';

src/operations/execute_operation.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,10 @@ async function executeOperationAsync<
151151
selector = readPreference;
152152
}
153153

154-
const server = await topology.selectServerAsync(selector, { session });
154+
const server = await topology.selectServerAsync(selector, {
155+
session: session,
156+
operationName: operation.commandName
157+
});
155158

156159
if (session == null) {
157160
// No session also means it is not retryable, early exit
@@ -251,7 +254,10 @@ async function retryOperation<
251254
}
252255

253256
// select a new server, and attempt to retry the operation
254-
const server = await topology.selectServerAsync(selector, { session });
257+
const server = await topology.selectServerAsync(selector, {
258+
session: session,
259+
operationName: operation.commandName
260+
});
255261

256262
if (isWriteOperation && !supportsRetryableWrites(server)) {
257263
throw new MongoUnexpectedServerResponseError(

src/sdam/server_selection_events.ts

Lines changed: 38 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,24 @@ import {
55
WAITING_FOR_SUITABLE_SERVER
66
} from '../constants';
77
import { type ReadPreference } from '../read_preference';
8+
import { HostAddress } from '../utils';
89
import { type ServerSelector } from './server_selection';
910
import type { TopologyDescription } from './topology_description';
1011

1112
/**
12-
* The base export class for all monitoring events published from server selection
13-
* @public
14-
* @category Event
13+
* The base export class for all logs published from server selection
14+
* @internal
15+
* @category Log Type
1516
*/
1617
export abstract class ServerSelectionEvent {
1718
/** String representation of the selector being used to select the server.
1819
* Defaults to 'custom selector' for application-provided custom selector case.
1920
*/
20-
selector: string;
21+
selector: string | ReadPreference | ServerSelector;
2122
/** The name of the operation for which a server is being selected. */
2223
operation: string;
23-
/** String representation of the current topology description. */
24-
topologyDescription: string;
24+
/** The current topology description. */
25+
topologyDescription: TopologyDescription;
2526

2627
/** @internal */
2728
abstract name:
@@ -30,26 +31,23 @@ export abstract class ServerSelectionEvent {
3031
| typeof SERVER_SELECTION_FAILED
3132
| typeof WAITING_FOR_SUITABLE_SERVER;
3233

34+
abstract message: string;
35+
3336
/** @internal */
3437
constructor(
3538
selector: string | ReadPreference | ServerSelector,
36-
operation: string | undefined,
37-
topologyDescription: TopologyDescription
39+
topologyDescription: TopologyDescription,
40+
operation?: string
3841
) {
39-
this.selector =
40-
typeof selector === 'string'
41-
? selector
42-
: typeof selector === 'function'
43-
? 'custom selector'
44-
: JSON.stringify(selector.toJSON(), null, 2);
45-
this.operation = operation ?? 'custom operation';
46-
this.topologyDescription = topologyDescription.toString();
42+
this.selector = selector;
43+
this.operation = operation ?? 'n/a';
44+
this.topologyDescription = topologyDescription;
4745
}
4846
}
4947

5048
/**
5149
* An event published when server selection starts
52-
* @public
50+
* @internal
5351
* @category Event
5452
*/
5553
export class ServerSelectionStartedEvent extends ServerSelectionEvent {
@@ -60,43 +58,43 @@ export class ServerSelectionStartedEvent extends ServerSelectionEvent {
6058
/** @internal */
6159
constructor(
6260
selector: string | ReadPreference | ServerSelector,
63-
operation: string | undefined,
64-
topologyDescription: TopologyDescription
61+
topologyDescription: TopologyDescription,
62+
operation?: string
6563
) {
66-
super(selector, operation, topologyDescription);
64+
super(selector, topologyDescription, operation);
6765
}
6866
}
6967

7068
/**
7169
* An event published when a server selection fails
72-
* @public
70+
* @internal
7371
* @category Event
7472
*/
7573
export class ServerSelectionFailedEvent extends ServerSelectionEvent {
7674
/** @internal */
7775
name = SERVER_SELECTION_FAILED;
7876
message = 'Server selection failed';
7977
/** Representation of the error the driver will throw regarding server selection failing. */
80-
failure: string;
78+
failure: Error;
8179

8280
/** @internal */
8381
constructor(
8482
selector: string | ReadPreference | ServerSelector,
85-
operation: string | undefined,
8683
topologyDescription: TopologyDescription,
87-
errMsg: string
84+
error: Error,
85+
operation?: string
8886
) {
89-
super(selector, operation, topologyDescription);
90-
this.failure = errMsg;
87+
super(selector, topologyDescription, operation);
88+
this.failure = error;
9189
}
9290
}
9391

9492
/**
9593
* An event published when server selection succeeds
96-
* @public
94+
* @internal
9795
* @category Event
9896
*/
99-
export class ServerSelectionSuccessEvent extends ServerSelectionEvent {
97+
export class ServerSelectionSucceededEvent extends ServerSelectionEvent {
10098
/** @internal */
10199
name = SERVER_SELECTION_SUCCEEDED;
102100
message = 'Server selection succeeded';
@@ -110,39 +108,37 @@ export class ServerSelectionSuccessEvent extends ServerSelectionEvent {
110108
/** @internal */
111109
constructor(
112110
selector: string | ReadPreference | ServerSelector,
113-
operation: string | undefined,
114111
topologyDescription: TopologyDescription,
115-
serverHost: string,
116-
serverPort: number
112+
address: string,
113+
operation?: string
117114
) {
118-
super(selector, operation, topologyDescription);
119-
this.serverHost = serverHost;
120-
this.serverPort = serverPort;
115+
super(selector, topologyDescription, operation);
116+
const { host, port } = HostAddress.fromString(address).toHostPort();
117+
this.serverHost = host;
118+
this.serverPort = port;
121119
}
122120
}
123121

124122
/**
125123
* An event published when server selection is waiting for a suitable server to become available
126-
* @public
124+
* @internal
127125
* @category Event
128126
*/
129127
export class WaitingForSuitableServerEvent extends ServerSelectionEvent {
130128
/** @internal */
131129
name = WAITING_FOR_SUITABLE_SERVER;
132130
message = 'Waiting for suitable server to become available';
133131
/** The remaining time left until server selection will time out. */
134-
remainingTimeMS?: number;
132+
remainingTimeMS: number;
135133

136134
/** @internal */
137135
constructor(
138136
selector: string | ReadPreference | ServerSelector,
139-
operation: string | undefined,
140137
topologyDescription: TopologyDescription,
141-
remainingTimeMS: number | undefined
138+
remainingTimeMS: number,
139+
operation?: string
142140
) {
143-
super(selector, operation, topologyDescription);
144-
if (remainingTimeMS) {
145-
this.remainingTimeMS = remainingTimeMS;
146-
}
141+
super(selector, topologyDescription, operation);
142+
this.remainingTimeMS = remainingTimeMS;
147143
}
148144
}

0 commit comments

Comments
 (0)