@@ -4,6 +4,7 @@ import * as net from 'net';
4
4
import * as sinon from 'sinon' ;
5
5
6
6
import {
7
+ type Collection ,
7
8
type CommandFailedEvent ,
8
9
type CommandStartedEvent ,
9
10
type CommandSucceededEvent ,
@@ -31,7 +32,6 @@ describe('class MongoClient', function () {
31
32
afterEach ( async ( ) => {
32
33
sinon . restore ( ) ;
33
34
await client ?. close ( ) ;
34
- // @ts -expect-error: Put this variable back to undefined to force tests to make their own client
35
35
client = undefined ;
36
36
} ) ;
37
37
@@ -567,7 +567,44 @@ describe('class MongoClient', function () {
567
567
} ) ;
568
568
} ) ;
569
569
570
- context ( '#close()' , ( ) => {
570
+ describe ( 'active cursors' , function ( ) {
571
+ let client : MongoClient ;
572
+ let collection : Collection < { _id : number } > ;
573
+ const kills = [ ] ;
574
+
575
+ beforeEach ( async function ( ) {
576
+ client = this . configuration . newClient ( ) ;
577
+ collection = client . db ( 'activeCursors' ) . collection ( 'activeCursors' ) ;
578
+ await collection . drop ( ) . catch ( ( ) => null ) ;
579
+ await collection . insertMany ( Array . from ( { length : 50 } , ( _ , _id ) => ( { _id } ) ) ) ;
580
+
581
+ kills . length = 0 ;
582
+ client . on ( 'commandStarted' , ev => ev . commandName === 'killCursors' && kills . push ( ev ) ) ;
583
+ } ) ;
584
+
585
+ afterEach ( async function ( ) {
586
+ await client . close ( ) ;
587
+ } ) ;
588
+
589
+ it ( 'are tracked upon creation and removed upon exhaustion' , async ( ) => {
590
+ const cursors = Array . from ( { length : 30 } , ( _ , skip ) =>
591
+ collection . find ( { } , { skip, batchSize : 1 } )
592
+ ) ;
593
+ expect ( client . s . activeCursors ) . to . have . lengthOf ( 30 ) ;
594
+ await Promise . all ( cursors . map ( c => c . toArray ( ) ) ) ;
595
+ expect ( client . s . activeCursors ) . to . have . lengthOf ( 0 ) ;
596
+ expect ( kills ) . to . have . lengthOf ( 0 ) ;
597
+ } ) ;
598
+
599
+ it ( 'are removed from tracking if exhausted in first batch' , async ( ) => {
600
+ const cursors = Array . from ( { length : 30 } , ( ) => collection . find ( ) ) ;
601
+ expect ( client . s . activeCursors ) . to . have . lengthOf ( 30 ) ;
602
+ await Promise . all ( cursors . map ( c => c . next ( ) ) ) ; // only one document pulled from each.
603
+ expect ( client . s . activeCursors ) . to . have . lengthOf ( 0 ) ;
604
+ } ) ;
605
+ } ) ;
606
+
607
+ describe ( '#close()' , ( ) => {
571
608
let client : MongoClient ;
572
609
let db : Db ;
573
610
@@ -702,7 +739,7 @@ describe('class MongoClient', function () {
702
739
expect ( endEvents [ 0 ] ) . to . have . property ( 'reply' , undefined ) ; // noReponse: true
703
740
} ) ;
704
741
705
- context ( 'when server selection would return no servers' , ( ) => {
742
+ describe ( 'when server selection would return no servers' , ( ) => {
706
743
const serverDescription = new ServerDescription ( 'a:1' ) ;
707
744
708
745
it ( 'short circuits and does not end sessions' , async ( ) => {
@@ -722,6 +759,49 @@ describe('class MongoClient', function () {
722
759
expect ( client . s . sessionPool . sessions ) . to . have . lengthOf ( 1 ) ;
723
760
} ) ;
724
761
} ) ;
762
+
763
+ describe ( 'active cursors' , function ( ) {
764
+ let collection : Collection < { _id : number } > ;
765
+ const kills = [ ] ;
766
+
767
+ beforeEach ( async ( ) => {
768
+ collection = client . db ( 'test' ) . collection ( 'activeCursors' ) ;
769
+ await collection . drop ( ) . catch ( ( ) => null ) ;
770
+ await collection . insertMany ( Array . from ( { length : 50 } , ( _ , _id ) => ( { _id } ) ) ) ;
771
+
772
+ kills . length = 0 ;
773
+ client . on ( 'commandStarted' , ev => ev . commandName === 'killCursors' && kills . push ( ev ) ) ;
774
+ } ) ;
775
+
776
+ it ( 'are all closed' , async ( ) => {
777
+ const cursors = Array . from ( { length : 30 } , ( _ , skip ) =>
778
+ collection . find ( { } , { skip, batchSize : 1 } )
779
+ ) ;
780
+ await Promise . all ( cursors . map ( c => c . next ( ) ) ) ;
781
+ expect ( client . s . activeCursors ) . to . have . lengthOf ( 30 ) ;
782
+ await client . close ( ) ;
783
+ expect ( client . s . activeCursors ) . to . have . lengthOf ( 0 ) ;
784
+ expect ( kills ) . to . have . lengthOf ( 30 ) ;
785
+ } ) ;
786
+
787
+ it ( 'creating cursors after close adds to activeCursors' , async ( ) => {
788
+ expect ( client . s . activeCursors ) . to . have . lengthOf ( 0 ) ;
789
+ await client . close ( ) ;
790
+ collection . find ( { } ) ;
791
+ expect ( client . s . activeCursors ) . to . have . lengthOf ( 1 ) ;
792
+ } ) ;
793
+
794
+ it ( 'rewinding cursors after close adds to activeCursors' , async ( ) => {
795
+ expect ( client . s . activeCursors ) . to . have . lengthOf ( 0 ) ;
796
+ const cursor = collection . find ( { } , { batchSize : 1 } ) ;
797
+ await cursor . next ( ) ;
798
+ expect ( client . s . activeCursors ) . to . have . lengthOf ( 1 ) ;
799
+ await client . close ( ) ;
800
+ expect ( client . s . activeCursors ) . to . have . lengthOf ( 0 ) ;
801
+ cursor . rewind ( ) ;
802
+ expect ( client . s . activeCursors ) . to . have . lengthOf ( 1 ) ;
803
+ } ) ;
804
+ } ) ;
725
805
} ) ;
726
806
727
807
context ( 'when connecting' , function ( ) {
0 commit comments