@@ -473,182 +473,162 @@ describeSpec('Existence Filters:', [], () => {
473
473
}
474
474
) ;
475
475
476
- specTest (
477
- 'Full re-query is triggered when bloom filter is empty' ,
478
- [ ] ,
479
- ( ) => {
480
- const query1 = query ( 'collection' ) ;
481
- const docA = doc ( 'collection/a' , 1000 , { v : 1 } ) ;
482
- const docB = doc ( 'collection/b' , 1000 , { v : 1 } ) ;
483
-
484
- //Generate an empty bloom filter.
485
- const bloomFilterProto = generateBloomFilterProto ( {
486
- contains : [ ] ,
487
- notContains : [ ] ,
488
- bitCount : 0 ,
489
- hashCount : 0
490
- } ) ;
491
-
492
- return (
493
- spec ( )
494
- . userListens ( query1 )
495
- . watchAcksFull ( query1 , 1000 , docA , docB )
496
- . expectEvents ( query1 , { added : [ docA , docB ] } )
497
- // DocB is deleted in the next sync.
498
- . watchFilters ( [ query1 ] , [ docA . key ] , bloomFilterProto )
499
- . watchSnapshots ( 2000 )
500
- // Re-run query is triggered.
501
- . expectEvents ( query1 , { fromCache : true } )
502
- . expectActiveTargets ( {
503
- query : query1 ,
504
- resumeToken : '' ,
505
- targetPurpose : TargetPurpose . ExistenceFilterMismatch
506
- } )
507
- ) ;
508
- }
509
- ) ;
476
+ specTest ( 'Full re-query is triggered when bloom filter is empty' , [ ] , ( ) => {
477
+ const query1 = query ( 'collection' ) ;
478
+ const docA = doc ( 'collection/a' , 1000 , { v : 1 } ) ;
479
+ const docB = doc ( 'collection/b' , 1000 , { v : 1 } ) ;
510
480
511
- specTest (
512
- 'Same documents can have different bloom filters' ,
513
- [ ] ,
514
- ( ) => {
515
- const query1 = query ( 'collection' , filter ( 'v' , '<=' , 2 ) ) ;
516
- const query2 = query ( 'collection' , filter ( 'v' , '>=' , 2 ) ) ;
481
+ //Generate an empty bloom filter.
482
+ const bloomFilterProto = generateBloomFilterProto ( {
483
+ contains : [ ] ,
484
+ notContains : [ ] ,
485
+ bitCount : 0 ,
486
+ hashCount : 0
487
+ } ) ;
517
488
518
- const docA = doc ( 'collection/a' , 1000 , { v : 1 } ) ;
519
- const docB = doc ( 'collection/b' , 1000 , { v : 2 } ) ;
520
- const docC = doc ( 'collection/c' , 1000 , { v : 3 } ) ;
489
+ return (
490
+ spec ( )
491
+ . userListens ( query1 )
492
+ . watchAcksFull ( query1 , 1000 , docA , docB )
493
+ . expectEvents ( query1 , { added : [ docA , docB ] } )
494
+ // DocB is deleted in the next sync.
495
+ . watchFilters ( [ query1 ] , [ docA . key ] , bloomFilterProto )
496
+ . watchSnapshots ( 2000 )
497
+ // Re-run query is triggered.
498
+ . expectEvents ( query1 , { fromCache : true } )
499
+ . expectActiveTargets ( {
500
+ query : query1 ,
501
+ resumeToken : '' ,
502
+ targetPurpose : TargetPurpose . ExistenceFilterMismatch
503
+ } )
504
+ ) ;
505
+ } ) ;
521
506
522
- const bloomFilterProto1 = generateBloomFilterProto ( {
523
- contains : [ docB ] ,
524
- notContains : [ docA , docC ] ,
525
- bitCount : 5 ,
526
- hashCount : 2
527
- } ) ;
528
- const bloomFilterProto2 = generateBloomFilterProto ( {
529
- contains : [ docB ] ,
530
- notContains : [ docA , docC ] ,
531
- bitCount : 4 ,
532
- hashCount : 1
533
- } ) ;
534
- return (
535
- spec ( )
536
- . userListens ( query1 )
537
- . watchAcksFull ( query1 , 1000 , docA , docB )
538
- . expectEvents ( query1 , { added : [ docA , docB ] } )
539
- . userListens ( query2 )
540
- . expectEvents ( query2 , { added : [ docB ] , fromCache : true } )
541
- . watchAcksFull ( query2 , 1001 , docB , docC )
542
- . expectEvents ( query2 , { added : [ docC ] } )
507
+ specTest ( 'Same documents can have different bloom filters' , [ ] , ( ) => {
508
+ const query1 = query ( 'collection' , filter ( 'v' , '<=' , 2 ) ) ;
509
+ const query2 = query ( 'collection' , filter ( 'v' , '>=' , 2 ) ) ;
543
510
544
- // DocA is deleted in the next sync for query1.
545
- . watchFilters ( [ query1 ] , [ docB . key ] , bloomFilterProto1 )
546
- . watchSnapshots ( 2000 )
547
- // BloomFilter identify docA is deleted, skip full query.
548
- . expectEvents ( query1 , { fromCache : true } )
549
- . expectLimboDocs ( docA . key ) // DocA is now in limbo.
550
-
551
- // DocC is deleted in the next sync for query2.
552
- . watchFilters ( [ query2 ] , [ docB . key ] , bloomFilterProto2 )
553
- . watchSnapshots ( 3000 )
554
- // BloomFilter identify docC is deleted, skip full query.
555
- . expectEvents ( query2 , { fromCache : true } )
556
- . expectLimboDocs ( docA . key , docC . key ) // DocC is now in limbo.
557
- ) ;
558
- }
559
- ) ;
511
+ const docA = doc ( 'collection/a' , 1000 , { v : 1 } ) ;
512
+ const docB = doc ( 'collection/b' , 1000 , { v : 2 } ) ;
513
+ const docC = doc ( 'collection/c' , 1000 , { v : 3 } ) ;
514
+
515
+ const bloomFilterProto1 = generateBloomFilterProto ( {
516
+ contains : [ docB ] ,
517
+ notContains : [ docA , docC ] ,
518
+ bitCount : 5 ,
519
+ hashCount : 2
520
+ } ) ;
521
+ const bloomFilterProto2 = generateBloomFilterProto ( {
522
+ contains : [ docB ] ,
523
+ notContains : [ docA , docC ] ,
524
+ bitCount : 4 ,
525
+ hashCount : 1
526
+ } ) ;
527
+ return (
528
+ spec ( )
529
+ . userListens ( query1 )
530
+ . watchAcksFull ( query1 , 1000 , docA , docB )
531
+ . expectEvents ( query1 , { added : [ docA , docB ] } )
532
+ . userListens ( query2 )
533
+ . expectEvents ( query2 , { added : [ docB ] , fromCache : true } )
534
+ . watchAcksFull ( query2 , 1001 , docB , docC )
535
+ . expectEvents ( query2 , { added : [ docC ] } )
560
536
561
- specTest (
562
- 'Bloom filter is handled at global snapshot' ,
563
- [ ] ,
564
- ( ) => {
565
- const query1 = query ( 'collection' ) ;
566
- const docA = doc ( 'collection/a' , 1000 , { v : 1 } ) ;
567
- const docB = doc ( 'collection/b' , 2000 , { v : 2 } ) ;
568
- const docC = doc ( 'collection/c' , 3000 , { v : 3 } ) ;
537
+ // DocA is deleted in the next sync for query1.
538
+ . watchFilters ( [ query1 ] , [ docB . key ] , bloomFilterProto1 )
539
+ . watchSnapshots ( 2000 )
540
+ // BloomFilter identify docA is deleted, skip full query.
541
+ . expectEvents ( query1 , { fromCache : true } )
542
+ . expectLimboDocs ( docA . key ) // DocA is now in limbo.
543
+
544
+ // DocC is deleted in the next sync for query2.
545
+ . watchFilters ( [ query2 ] , [ docB . key ] , bloomFilterProto2 )
546
+ . watchSnapshots ( 3000 )
547
+ // BloomFilter identify docC is deleted, skip full query.
548
+ . expectEvents ( query2 , { fromCache : true } )
549
+ . expectLimboDocs ( docA . key , docC . key ) // DocC is now in limbo.
550
+ ) ;
551
+ } ) ;
569
552
570
- const bloomFilterProto = generateBloomFilterProto ( {
571
- contains : [ docA ] ,
572
- notContains : [ docB ]
573
- } ) ;
553
+ specTest ( 'Bloom filter is handled at global snapshot' , [ ] , ( ) => {
554
+ const query1 = query ( 'collection' ) ;
555
+ const docA = doc ( 'collection/a' , 1000 , { v : 1 } ) ;
556
+ const docB = doc ( 'collection/b' , 2000 , { v : 2 } ) ;
557
+ const docC = doc ( 'collection/c' , 3000 , { v : 3 } ) ;
574
558
575
- return (
576
- spec ( )
577
- . userListens ( query1 )
578
- . watchAcksFull ( query1 , 1000 , docA , docB )
579
- . expectEvents ( query1 , { added : [ docA , docB ] } )
580
- // Send a mismatching existence filter with one document, but don't
581
- // send a new global snapshot. We should not see an event until we
582
- // receive the snapshot.
583
- . watchFilters ( [ query1 ] , [ docA . key ] , bloomFilterProto )
584
- . watchSends ( { affects : [ query1 ] } , docC )
585
- . watchSnapshots ( 2000 )
586
- . expectEvents ( query1 , { added : [ docC ] , fromCache : true } )
587
- // Re-run of the query1 is skipped, docB is in limbo.
588
- . expectLimboDocs ( docB . key )
589
- ) ;
590
- }
591
- ) ;
559
+ const bloomFilterProto = generateBloomFilterProto ( {
560
+ contains : [ docA ] ,
561
+ notContains : [ docB ]
562
+ } ) ;
592
563
593
- specTest (
594
- 'Bloom filter limbo resolution is denied' ,
595
- [ ] ,
596
- ( ) => {
597
- const query1 = query ( 'collection' ) ;
598
- const docA = doc ( 'collection/a' , 1000 , { v : 1 } ) ;
599
- const docB = doc ( 'collection/b' , 1000 , { v : 1 } ) ;
600
- const bloomFilterProto = generateBloomFilterProto ( {
601
- contains : [ docA ] ,
602
- notContains : [ docB ]
603
- } ) ;
604
- return spec ( )
564
+ return (
565
+ spec ( )
605
566
. userListens ( query1 )
606
567
. watchAcksFull ( query1 , 1000 , docA , docB )
607
568
. expectEvents ( query1 , { added : [ docA , docB ] } )
569
+ // Send a mismatching existence filter with one document, but don't
570
+ // send a new global snapshot. We should not see an event until we
571
+ // receive the snapshot.
608
572
. watchFilters ( [ query1 ] , [ docA . key ] , bloomFilterProto )
573
+ . watchSends ( { affects : [ query1 ] } , docC )
609
574
. watchSnapshots ( 2000 )
610
- . expectEvents ( query1 , { fromCache : true } )
611
- . expectLimboDocs ( docB . key ) // DocB is now in limbo.
612
- . watchRemoves (
613
- newQueryForPath ( docB . key . path ) ,
614
- new RpcError ( Code . PERMISSION_DENIED , 'no' )
615
- )
616
- . expectLimboDocs ( ) // DocB is no longer in limbo.
617
- . expectEvents ( query1 , {
618
- removed : [ docB ]
619
- } ) ;
620
- }
621
- ) ;
622
-
623
- specTest (
624
- 'Bloom filter with large size works as expected' ,
625
- [ ] ,
626
- ( ) => {
627
- const query1 = query ( 'collection' ) ;
628
- const docs = [ ] ;
629
- for ( let i = 0 ; i < 100 ; i ++ ) {
630
- docs . push ( doc ( `collection/doc${ i } ` , 1000 , { v : 1 } ) ) ;
631
- }
632
- const docKeys = docs . map ( item => item . key ) ;
575
+ . expectEvents ( query1 , { added : [ docC ] , fromCache : true } )
576
+ // Re-run of the query1 is skipped, docB is in limbo.
577
+ . expectLimboDocs ( docB . key )
578
+ ) ;
579
+ } ) ;
633
580
634
- const bloomFilterProto = generateBloomFilterProto ( {
635
- contains : docs . slice ( 0 , 50 ) ,
636
- notContains : docs . slice ( 50 ) ,
637
- bitCount : 1000 ,
638
- hashCount : 16
581
+ specTest ( 'Bloom filter limbo resolution is denied' , [ ] , ( ) => {
582
+ const query1 = query ( 'collection' ) ;
583
+ const docA = doc ( 'collection/a' , 1000 , { v : 1 } ) ;
584
+ const docB = doc ( 'collection/b' , 1000 , { v : 1 } ) ;
585
+ const bloomFilterProto = generateBloomFilterProto ( {
586
+ contains : [ docA ] ,
587
+ notContains : [ docB ]
588
+ } ) ;
589
+ return spec ( )
590
+ . userListens ( query1 )
591
+ . watchAcksFull ( query1 , 1000 , docA , docB )
592
+ . expectEvents ( query1 , { added : [ docA , docB ] } )
593
+ . watchFilters ( [ query1 ] , [ docA . key ] , bloomFilterProto )
594
+ . watchSnapshots ( 2000 )
595
+ . expectEvents ( query1 , { fromCache : true } )
596
+ . expectLimboDocs ( docB . key ) // DocB is now in limbo.
597
+ . watchRemoves (
598
+ newQueryForPath ( docB . key . path ) ,
599
+ new RpcError ( Code . PERMISSION_DENIED , 'no' )
600
+ )
601
+ . expectLimboDocs ( ) // DocB is no longer in limbo.
602
+ . expectEvents ( query1 , {
603
+ removed : [ docB ]
639
604
} ) ;
640
- return (
641
- spec ( )
642
- . userListens ( query1 )
643
- . watchAcksFull ( query1 , 1000 , ...docs )
644
- . expectEvents ( query1 , { added : docs } )
645
- // Doc0 to doc49 are deleted in the next sync.
646
- . watchFilters ( [ query1 ] , docKeys . slice ( 0 , 50 ) , bloomFilterProto )
647
- . watchSnapshots ( 2000 )
648
- // BloomFilter correctly identifies docs that deleted, skip full query.
649
- . expectEvents ( query1 , { fromCache : true } )
650
- . expectLimboDocs ( ...docKeys . slice ( 50 ) )
651
- ) ;
605
+ } ) ;
606
+
607
+ specTest ( 'Bloom filter with large size works as expected' , [ ] , ( ) => {
608
+ const query1 = query ( 'collection' ) ;
609
+ const docs = [ ] ;
610
+ for ( let i = 0 ; i < 100 ; i ++ ) {
611
+ docs . push ( doc ( `collection/doc${ i } ` , 1000 , { v : 1 } ) ) ;
652
612
}
653
- ) ;
613
+ const docKeys = docs . map ( item => item . key ) ;
614
+
615
+ const bloomFilterProto = generateBloomFilterProto ( {
616
+ contains : docs . slice ( 0 , 50 ) ,
617
+ notContains : docs . slice ( 50 ) ,
618
+ bitCount : 1000 ,
619
+ hashCount : 16
620
+ } ) ;
621
+ return (
622
+ spec ( )
623
+ . userListens ( query1 )
624
+ . watchAcksFull ( query1 , 1000 , ...docs )
625
+ . expectEvents ( query1 , { added : docs } )
626
+ // Doc0 to doc49 are deleted in the next sync.
627
+ . watchFilters ( [ query1 ] , docKeys . slice ( 0 , 50 ) , bloomFilterProto )
628
+ . watchSnapshots ( 2000 )
629
+ // BloomFilter correctly identifies docs that deleted, skip full query.
630
+ . expectEvents ( query1 , { fromCache : true } )
631
+ . expectLimboDocs ( ...docKeys . slice ( 50 ) )
632
+ ) ;
633
+ } ) ;
654
634
} ) ;
0 commit comments