@@ -3,6 +3,7 @@ import { clearTimeout, setTimeout } from 'timers';
3
3
import { type Document , Long } from '../bson' ;
4
4
import { connect } from '../cmap/connect' ;
5
5
import { Connection , type ConnectionOptions } from '../cmap/connection' ;
6
+ import { getFAASEnv } from '../cmap/handshake/client_metadata' ;
6
7
import { LEGACY_HELLO_COMMAND } from '../constants' ;
7
8
import { MongoError , MongoErrorLabel , MongoNetworkTimeoutError } from '../error' ;
8
9
import { CancellationToken , TypedEventEmitter } from '../mongo_types' ;
@@ -44,6 +45,11 @@ function isInCloseState(monitor: Monitor) {
44
45
return monitor . s . state === STATE_CLOSED || monitor . s . state === STATE_CLOSING ;
45
46
}
46
47
48
+ /** @public */
49
+ export const ServerMonitoringModes = [ 'auto' , 'poll' , 'stream' ] ;
50
+ /** @public */
51
+ export type ServerMonitoringMode = ( typeof ServerMonitoringModes ) [ number ] ;
52
+
47
53
/** @internal */
48
54
export interface MonitorPrivate {
49
55
state : string ;
@@ -55,6 +61,7 @@ export interface MonitorOptions
55
61
connectTimeoutMS : number ;
56
62
heartbeatFrequencyMS : number ;
57
63
minHeartbeatFrequencyMS : number ;
64
+ serverMonitoringMode : ServerMonitoringMode ;
58
65
}
59
66
60
67
/** @public */
@@ -73,9 +80,16 @@ export class Monitor extends TypedEventEmitter<MonitorEvents> {
73
80
s : MonitorPrivate ;
74
81
address : string ;
75
82
options : Readonly <
76
- Pick < MonitorOptions , 'connectTimeoutMS' | 'heartbeatFrequencyMS' | 'minHeartbeatFrequencyMS' >
83
+ Pick <
84
+ MonitorOptions ,
85
+ | 'connectTimeoutMS'
86
+ | 'heartbeatFrequencyMS'
87
+ | 'minHeartbeatFrequencyMS'
88
+ | 'serverMonitoringMode'
89
+ >
77
90
> ;
78
91
connectOptions : ConnectionOptions ;
92
+ isRunningInFaasEnv : boolean ;
79
93
[ kServer ] : Server ;
80
94
[ kConnection ] ?: Connection ;
81
95
[ kCancellationToken ] : CancellationToken ;
@@ -103,8 +117,11 @@ export class Monitor extends TypedEventEmitter<MonitorEvents> {
103
117
this . options = Object . freeze ( {
104
118
connectTimeoutMS : options . connectTimeoutMS ?? 10000 ,
105
119
heartbeatFrequencyMS : options . heartbeatFrequencyMS ?? 10000 ,
106
- minHeartbeatFrequencyMS : options . minHeartbeatFrequencyMS ?? 500
120
+ minHeartbeatFrequencyMS : options . minHeartbeatFrequencyMS ?? 500 ,
121
+ serverMonitoringMode : options . serverMonitoringMode
107
122
} ) ;
123
+ console . log ( getFAASEnv ( ) ) ;
124
+ this . isRunningInFaasEnv = getFAASEnv ( ) != null ;
108
125
109
126
const cancellationToken = this [ kCancellationToken ] ;
110
127
// TODO: refactor this to pull it directly from the pool, requires new ConnectionPool integration
@@ -207,10 +224,26 @@ function resetMonitorState(monitor: Monitor) {
207
224
monitor [ kConnection ] = undefined ;
208
225
}
209
226
227
+ function useStreamingProtocol ( monitor : Monitor , topologyVersion : TopologyVersion | null ) : boolean {
228
+ // If we have no topology version we always poll no matter
229
+ // what the user provided.
230
+ if ( topologyVersion == null ) return false ;
231
+
232
+ const serverMonitoringMode = monitor . options . serverMonitoringMode ;
233
+ if ( serverMonitoringMode === 'poll' ) return false ;
234
+ if ( serverMonitoringMode === 'stream' ) return true ;
235
+
236
+ // If we are in auto mode, we need to figure out if we're in a FaaS
237
+ // environment or not and choose the appropriate mode.
238
+ if ( monitor . isRunningInFaasEnv ) return false ;
239
+ return true ;
240
+ }
241
+
210
242
function checkServer ( monitor : Monitor , callback : Callback < Document | null > ) {
211
243
let start = now ( ) ;
212
244
const topologyVersion = monitor [ kServer ] . description . topologyVersion ;
213
- const isAwaitable = topologyVersion != null ;
245
+ console . log ( 'checkServer' , topologyVersion ) ;
246
+ const isAwaitable = useStreamingProtocol ( monitor , topologyVersion ) ;
214
247
monitor . emit (
215
248
Server . SERVER_HEARTBEAT_STARTED ,
216
249
new ServerHeartbeatStartedEvent ( monitor . address , isAwaitable )
@@ -286,7 +319,8 @@ function checkServer(monitor: Monitor, callback: Callback<Document | null>) {
286
319
const duration =
287
320
isAwaitable && rttPinger ? rttPinger . roundTripTime : calculateDurationInMs ( start ) ;
288
321
289
- const awaited = isAwaitable && hello . topologyVersion != null ;
322
+ console . log ( 'command' , topologyVersion , hello . topologyVersion , hello ) ;
323
+ const awaited = useStreamingProtocol ( monitor , hello . topologyVersion ) ;
290
324
monitor . emit (
291
325
Server . SERVER_HEARTBEAT_SUCCEEDED ,
292
326
new ServerHeartbeatSucceededEvent ( monitor . address , duration , hello , awaited )
@@ -370,7 +404,8 @@ function monitorServer(monitor: Monitor) {
370
404
}
371
405
372
406
// if the check indicates streaming is supported, immediately reschedule monitoring
373
- if ( hello && hello . topologyVersion ) {
407
+ console . log ( 'checkServerCallback' , hello ?. topologyVersion ) ;
408
+ if ( useStreamingProtocol ( monitor , hello ?. topologyVersion ) ) {
374
409
setTimeout ( ( ) => {
375
410
if ( ! isInCloseState ( monitor ) ) {
376
411
monitor [ kMonitorId ] ?. wake ( ) ;
0 commit comments