@@ -22,7 +22,7 @@ import {
22
22
} from '../../mongodb' ;
23
23
import * as mock from '../../tools/mongodb-mock/index' ;
24
24
import { skipBrokenAuthTestBeforeEachHook } from '../../tools/runner/hooks/configuration' ;
25
- import { sleep } from '../../tools/utils' ;
25
+ import { processTick , sleep } from '../../tools/utils' ;
26
26
import { assert as test , setupDatabase } from '../shared' ;
27
27
28
28
const commonConnectOptions = {
@@ -249,6 +249,55 @@ describe('Connection', function () {
249
249
client . connect ( ) ;
250
250
} ) ;
251
251
252
+ describe (
253
+ 'when a monitoring Connection receives many hellos in one chunk' ,
254
+ { requires : { topology : 'replicaset' } } ,
255
+ function ( ) {
256
+ let client : MongoClient ;
257
+ let hbSuccess = 0 ;
258
+
259
+ beforeEach ( async function ( ) {
260
+ client = this . configuration . newClient ( { } , { heartbeatFrequencyMS : 100 } ) ; // just so we don't have to wait so long for a hello
261
+ hbSuccess = 0 ;
262
+ client . on ( 'serverHeartbeatSucceeded' , ( ) => ( hbSuccess += 1 ) ) ;
263
+ } ) ;
264
+
265
+ afterEach ( async function ( ) {
266
+ hbSuccess = 0 ;
267
+ await client . close ( ) ;
268
+ } ) ;
269
+
270
+ // In the future we may want to skip processing concatenated heartbeats.
271
+ // This test exists to prevent regression of processing many messages inside one chunk.
272
+ it (
273
+ 'processes all of them and emits heartbeats' ,
274
+ { requires : { topology : 'replicaset' } } ,
275
+ async function ( ) {
276
+ expect ( hbSuccess ) . to . equal ( 0 ) ;
277
+
278
+ await client . db ( ) . command ( { ping : 1 } ) ; // start monitoring.
279
+ const monitor = [ ...client . topology . s . servers . values ( ) ] [ 0 ] . monitor ;
280
+
281
+ // @ts -expect-error: accessing private property
282
+ const messageStream = monitor . connection . messageStream ;
283
+ // @ts -expect-error: accessing private property
284
+ const socket = monitor . connection . socket ;
285
+
286
+ const [ hello ] = ( await once ( messageStream , 'data' ) ) as [ Buffer ] ;
287
+
288
+ const thousandHellos = Array . from ( { length : 1000 } , ( ) => [ ...hello ] ) . flat ( 1 ) ;
289
+
290
+ // pretend this came from the server
291
+ socket . emit ( 'data' , Buffer . from ( thousandHellos ) ) ;
292
+
293
+ // All of the hb will be emitted synchronously in the next tick as the entire chunk is processed.
294
+ await processTick ( ) ;
295
+ expect ( hbSuccess ) . to . be . greaterThan ( 100 ) ;
296
+ }
297
+ ) ;
298
+ }
299
+ ) ;
300
+
252
301
context (
253
302
'when a large message is written to the socket' ,
254
303
{ requires : { topology : 'single' , auth : 'disabled' } } ,
0 commit comments