@@ -887,34 +887,49 @@ export class LocalStore {
887
887
*/
888
888
// PORTING NOTE: `keepPersistedQueryData` is multi-tab only.
889
889
releaseQuery ( query : Query , keepPersistedQueryData : boolean ) : Promise < void > {
890
- const mode = keepPersistedQueryData ? 'readwrite' : 'readwrite-primary' ;
891
- return this . persistence . runTransaction ( 'Release query' , mode , txn => {
892
- const targetId = this . targetIdByQuery . get ( query ) ;
893
- assert (
894
- targetId !== undefined ,
895
- 'Tried to release nonexistent query: ' + query
896
- ) ;
897
- const queryData = this . queryDataByTarget . get ( targetId ! ) ! ;
898
-
899
- // References for documents sent via Watch are automatically removed
900
- // when we delete a query's target data from the reference delegate.
901
- // Since this does not remove references for locally mutated documents,
902
- // we have to remove the target associations for these documents
903
- // manually.
904
- const removed = this . localViewReferences . removeReferencesForId ( targetId ! ) ;
905
- this . queryDataByTarget = this . queryDataByTarget . remove ( targetId ! ) ;
906
- this . targetIdByQuery . delete ( query ) ;
907
-
908
- if ( ! keepPersistedQueryData ) {
909
- return PersistencePromise . forEach ( removed , ( key : DocumentKey ) =>
910
- this . persistence . referenceDelegate . removeReference ( txn , key )
911
- ) . next ( ( ) => {
912
- this . persistence . referenceDelegate . removeTarget ( txn , queryData ) ;
913
- } ) ;
914
- } else {
915
- return PersistencePromise . resolve ( ) ;
916
- }
917
- } ) ;
890
+ let targetId : number ;
891
+
892
+ const mode = keepPersistedQueryData
893
+ ? 'readwrite-idempotent'
894
+ : 'readwrite-primary-idempotent' ;
895
+ return this . persistence
896
+ . runTransaction ( 'Release query' , mode , txn => {
897
+ const cachedTargetId = this . targetIdByQuery . get ( query ) ;
898
+ assert (
899
+ cachedTargetId !== undefined ,
900
+ 'Tried to release nonexistent query: ' + query
901
+ ) ;
902
+ targetId = cachedTargetId ! ;
903
+ const queryData = this . queryDataByTarget . get ( targetId ) ! ;
904
+
905
+ // References for documents sent via Watch are automatically removed
906
+ // when we delete a query's target data from the reference delegate.
907
+ // Since this does not remove references for locally mutated documents,
908
+ // we have to remove the target associations for these documents
909
+ // manually.
910
+ // This operation needs to be run inside the transaction since EagerGC
911
+ // uses the local view references during the transaction's commit.
912
+ // Fortunately, the operation is safe to be re-run in case the
913
+ // transaction fails since there are no side effects if the target has
914
+ // already been removed.
915
+ const removed = this . localViewReferences . removeReferencesForId (
916
+ targetId
917
+ ) ;
918
+
919
+ if ( ! keepPersistedQueryData ) {
920
+ return PersistencePromise . forEach ( removed , ( key : DocumentKey ) =>
921
+ this . persistence . referenceDelegate . removeReference ( txn , key )
922
+ ) . next ( ( ) => {
923
+ this . persistence . referenceDelegate . removeTarget ( txn , queryData ) ;
924
+ } ) ;
925
+ } else {
926
+ return PersistencePromise . resolve ( ) ;
927
+ }
928
+ } )
929
+ . then ( ( ) => {
930
+ this . queryDataByTarget = this . queryDataByTarget . remove ( targetId ) ;
931
+ this . targetIdByQuery . delete ( query ) ;
932
+ } ) ;
918
933
}
919
934
920
935
/**
0 commit comments