@@ -922,4 +922,149 @@ describeSpec('Limbo Documents:', [], () => {
922
922
) ;
923
923
}
924
924
) ;
925
+
926
+ specTest (
927
+ 'A limbo resolution for a document should not be started if one is already active' ,
928
+ [ ] ,
929
+ ( ) => {
930
+ const doc1 = doc ( 'collection/doc' , 1000 , { key : 1 } ) ;
931
+ const fullQuery = query ( 'collection' ) ;
932
+ const filteredQuery1 = query ( 'collection' , filter ( 'key' , '==' , 1 ) ) ;
933
+ const filteredQuery2 = query ( 'collection' , filter ( 'key' , '>=' , 1 ) ) ;
934
+
935
+ return (
936
+ spec ( )
937
+ . withGCEnabled ( false )
938
+
939
+ // Start a limbo resolution listen for a document (doc1).
940
+ . userListens ( fullQuery )
941
+ . watchAcksFull ( fullQuery , 1000 , doc1 )
942
+ . expectEvents ( fullQuery , { added : [ doc1 ] } )
943
+ . userUnlistens ( fullQuery )
944
+ . userListens ( filteredQuery1 )
945
+ . expectEvents ( filteredQuery1 , { added : [ doc1 ] , fromCache : true } )
946
+ . watchAcksFull ( filteredQuery1 , 1001 )
947
+ . expectLimboDocs ( doc1 . key )
948
+ . expectEnqueuedLimboDocs ( )
949
+
950
+ // Put doc1 into limbo in a different query; verify that another limbo
951
+ // resolution is neither started nor enqueued.
952
+ . userListens ( filteredQuery2 )
953
+ . expectEvents ( filteredQuery2 , { added : [ doc1 ] , fromCache : true } )
954
+ . watchAcksFull ( filteredQuery2 , 1002 )
955
+ . expectLimboDocs ( doc1 . key )
956
+ . expectEnqueuedLimboDocs ( )
957
+ ) ;
958
+ }
959
+ ) ;
960
+
961
+ specTest (
962
+ 'A limbo resolution for a document should not be enqueued if one is already enqueued' ,
963
+ [ ] ,
964
+ ( ) => {
965
+ const doc1 = doc ( 'collection1/doc1' , 1000 , { key : 1 } ) ;
966
+ const fullQuery1 = query ( 'collection1' ) ;
967
+ const filteredQuery1 = query ( 'collection1' , filter ( 'key' , '==' , 1 ) ) ;
968
+ const doc2 = doc ( 'collection2/doc2' , 1000 , { key : 2 } ) ;
969
+ const fullQuery2 = query ( 'collection2' ) ;
970
+ const filteredQuery2a = query ( 'collection2' , filter ( 'key' , '==' , 2 ) ) ;
971
+ const filteredQuery2b = query ( 'collection2' , filter ( 'key' , '>=' , 2 ) ) ;
972
+
973
+ return (
974
+ spec ( )
975
+ . withGCEnabled ( false )
976
+ . withMaxConcurrentLimboResolutions ( 1 )
977
+
978
+ // Max out the number of active limbo resolutions.
979
+ . userListens ( fullQuery1 )
980
+ . watchAcksFull ( fullQuery1 , 1000 , doc1 )
981
+ . expectEvents ( fullQuery1 , { added : [ doc1 ] } )
982
+ . userUnlistens ( fullQuery1 )
983
+ . userListens ( filteredQuery1 )
984
+ . expectEvents ( filteredQuery1 , { added : [ doc1 ] , fromCache : true } )
985
+ . watchAcksFull ( filteredQuery1 , 1001 )
986
+ . expectLimboDocs ( doc1 . key )
987
+
988
+ // Start a limbo resolution listen for a different document (doc2).
989
+ . userListens ( fullQuery2 )
990
+ . watchAcksFull ( fullQuery2 , 1002 , doc2 )
991
+ . expectEvents ( fullQuery2 , { added : [ doc2 ] } )
992
+ . userUnlistens ( fullQuery2 )
993
+ . userListens ( filteredQuery2a )
994
+ . expectEvents ( filteredQuery2a , { added : [ doc2 ] , fromCache : true } )
995
+ . watchAcksFull ( filteredQuery2a , 1003 )
996
+ . expectLimboDocs ( doc1 . key )
997
+ . expectEnqueuedLimboDocs ( doc2 . key )
998
+
999
+ // Put doc2 into limbo in a different query and verify that it's not
1000
+ // added to the limbo resolution queue again.
1001
+ . userListens ( filteredQuery2b )
1002
+ . expectEvents ( filteredQuery2b , { added : [ doc2 ] , fromCache : true } )
1003
+ . watchAcksFull ( filteredQuery2b , 1004 )
1004
+ . expectLimboDocs ( doc1 . key )
1005
+ . expectEnqueuedLimboDocs ( doc2 . key )
1006
+ ) ;
1007
+ }
1008
+ ) ;
1009
+
1010
+ specTest (
1011
+ 'A limbo resolution for a document should be removed from the queue when the last query listen stops' ,
1012
+ [ ] ,
1013
+ ( ) => {
1014
+ const doc1 = doc ( 'collection1/doc' , 1000 , { key : 1 } ) ;
1015
+ const fullQuery1 = query ( 'collection1' ) ;
1016
+ const filteredQuery1 = query ( 'collection1' , filter ( 'key' , '==' , 1 ) ) ;
1017
+
1018
+ const doc2 = doc ( 'collection2/doc' , 1000 , { key : 2 } ) ;
1019
+ const fullQuery2 = query ( 'collection2' ) ;
1020
+ const filteredQuery2a = query ( 'collection2' , filter ( 'key' , '==' , 2 ) ) ;
1021
+ const filteredQuery2b = query ( 'collection2' , filter ( 'key' , '>=' , 2 ) ) ;
1022
+
1023
+ return (
1024
+ spec ( )
1025
+ . withGCEnabled ( false )
1026
+ . withMaxConcurrentLimboResolutions ( 1 )
1027
+
1028
+ // Max out the number of active limbo resolutions.
1029
+ . userListens ( fullQuery1 )
1030
+ . watchAcksFull ( fullQuery1 , 1000 , doc1 )
1031
+ . expectEvents ( fullQuery1 , { added : [ doc1 ] } )
1032
+ . userUnlistens ( fullQuery1 )
1033
+ . userListens ( filteredQuery1 )
1034
+ . expectEvents ( filteredQuery1 , { added : [ doc1 ] , fromCache : true } )
1035
+ . watchAcksFull ( filteredQuery1 , 1001 )
1036
+ . expectLimboDocs ( doc1 . key )
1037
+
1038
+ // Enqueue a limbo resolution for doc2.
1039
+ . userListens ( fullQuery2 )
1040
+ . watchAcksFull ( fullQuery2 , 1002 , doc2 )
1041
+ . expectEvents ( fullQuery2 , { added : [ doc2 ] } )
1042
+ . userUnlistens ( fullQuery2 )
1043
+ . userListens ( filteredQuery2a )
1044
+ . expectEvents ( filteredQuery2a , { added : [ doc2 ] , fromCache : true } )
1045
+ . watchAcksFull ( filteredQuery2a , 1003 )
1046
+ . expectLimboDocs ( doc1 . key )
1047
+ . expectEnqueuedLimboDocs ( doc2 . key )
1048
+
1049
+ // Start another query that puts doc2 into limbo again.
1050
+ . userListens ( filteredQuery2b )
1051
+ . expectEvents ( filteredQuery2b , { added : [ doc2 ] , fromCache : true } )
1052
+ . watchAcksFull ( filteredQuery2b , 1004 )
1053
+ . expectLimboDocs ( doc1 . key )
1054
+ . expectEnqueuedLimboDocs ( doc2 . key )
1055
+
1056
+ // Stop one of the queries that enqueued a limbo resolution for doc2;
1057
+ // verify that doc2 is not removed from the limbo resolution queue.
1058
+ . userUnlistens ( filteredQuery2b )
1059
+ . expectLimboDocs ( doc1 . key )
1060
+ . expectEnqueuedLimboDocs ( doc2 . key )
1061
+
1062
+ // Stop the other query that enqueued a limbo resolution for doc2;
1063
+ // verify that doc2 *is* removed from the limbo resolution queue.
1064
+ . userUnlistens ( filteredQuery2a )
1065
+ . expectLimboDocs ( doc1 . key )
1066
+ . expectEnqueuedLimboDocs ( )
1067
+ ) ;
1068
+ }
1069
+ ) ;
925
1070
} ) ;
0 commit comments