@@ -62,6 +62,15 @@ const LOG_TAG = 'RemoteStore';
62
62
// TODO(b/35853402): Negotiate this with the stream.
63
63
const MAX_PENDING_WRITES = 10 ;
64
64
65
+ const enum OfflineCause {
66
+ UserDisabled ,
67
+ IndexedDbFailed ,
68
+ IsSecondary ,
69
+ CredentialChange ,
70
+ Shutdown ,
71
+ ConnectivityChange
72
+ }
73
+
65
74
/**
66
75
* RemoteStore - An interface to remotely stored data, basically providing a
67
76
* wrapper around the Datastore that is more reliable for the rest of the
@@ -117,20 +126,7 @@ export class RemoteStore implements TargetMetadataProvider {
117
126
private writeStream : PersistentWriteStream ;
118
127
private watchChangeAggregator : WatchChangeAggregator | null = null ;
119
128
120
- /**
121
- * Set to true by enableNetwork() and false by disableNetwork() and indicates
122
- * the user-preferred network state.
123
- */
124
- private networkEnabled = false ;
125
-
126
- private isPrimary = false ;
127
-
128
- /**
129
- * When set to `true`, the network was taken offline due to an IndexedDB
130
- * failure. The state is flipped to `false` when access becomes available
131
- * again.
132
- */
133
- private indexedDbFailed = false ;
129
+ private offlineCauses = new Set < OfflineCause > ( ) ;
134
130
135
131
private onlineStateTracker : OnlineStateTracker ;
136
132
@@ -194,7 +190,7 @@ export class RemoteStore implements TargetMetadataProvider {
194
190
195
191
/** Re-enables the network. Idempotent. */
196
192
enableNetwork ( ) : Promise < void > {
197
- this . networkEnabled = true ;
193
+ this . offlineCauses . delete ( OfflineCause . UserDisabled ) ;
198
194
return this . enableNetworkInternal ( ) ;
199
195
}
200
196
@@ -216,7 +212,7 @@ export class RemoteStore implements TargetMetadataProvider {
216
212
* enableNetwork().
217
213
*/
218
214
async disableNetwork ( ) : Promise < void > {
219
- this . networkEnabled = false ;
215
+ this . offlineCauses . add ( OfflineCause . UserDisabled ) ;
220
216
await this . disableNetworkInternal ( ) ;
221
217
222
218
// Set the OnlineState to Offline so get()s return from cache, etc.
@@ -240,7 +236,7 @@ export class RemoteStore implements TargetMetadataProvider {
240
236
241
237
async shutdown ( ) : Promise < void > {
242
238
logDebug ( LOG_TAG , 'RemoteStore shutting down.' ) ;
243
- this . networkEnabled = false ;
239
+ this . offlineCauses . add ( OfflineCause . Shutdown ) ;
244
240
await this . disableNetworkInternal ( ) ;
245
241
this . connectivityMonitor . shutdown ( ) ;
246
242
@@ -349,7 +345,7 @@ export class RemoteStore implements TargetMetadataProvider {
349
345
}
350
346
351
347
canUseNetwork ( ) : boolean {
352
- return ! this . indexedDbFailed && this . isPrimary && this . networkEnabled ;
348
+ return this . offlineCauses . size === 0 ;
353
349
}
354
350
355
351
private cleanUpWatchStreamState ( ) : void {
@@ -457,10 +453,10 @@ export class RemoteStore implements TargetMetadataProvider {
457
453
) : Promise < void > {
458
454
if ( isIndexedDbTransactionError ( e ) ) {
459
455
debugAssert (
460
- ! this . indexedDbFailed ,
456
+ ! this . offlineCauses . has ( OfflineCause . IndexedDbFailed ) ,
461
457
'Unexpected network event when IndexedDB was marked failed.'
462
458
) ;
463
- this . indexedDbFailed = true ;
459
+ this . offlineCauses . add ( OfflineCause . IndexedDbFailed ) ;
464
460
465
461
// Disable network and raise offline snapshots
466
462
await this . disableNetworkInternal ( ) ;
@@ -477,7 +473,7 @@ export class RemoteStore implements TargetMetadataProvider {
477
473
this . asyncQueue . enqueueRetryable ( async ( ) => {
478
474
logDebug ( LOG_TAG , 'Retrying IndexedDB access' ) ;
479
475
await op ! ( ) ;
480
- this . indexedDbFailed = false ;
476
+ this . offlineCauses . delete ( OfflineCause . IndexedDbFailed ) ;
481
477
await this . enableNetworkInternal ( ) ;
482
478
} ) ;
483
479
} else {
@@ -751,45 +747,39 @@ export class RemoteStore implements TargetMetadataProvider {
751
747
}
752
748
753
749
private async restartNetwork ( ) : Promise < void > {
754
- this . networkEnabled = false ;
750
+ this . offlineCauses . add ( OfflineCause . ConnectivityChange ) ;
755
751
await this . disableNetworkInternal ( ) ;
756
752
this . onlineStateTracker . set ( OnlineState . Unknown ) ;
757
- await this . enableNetwork ( ) ;
753
+ this . offlineCauses . delete ( OfflineCause . ConnectivityChange ) ;
754
+ await this . enableNetworkInternal ( ) ;
758
755
}
759
756
760
757
async handleCredentialChange ( user : User ) : Promise < void > {
761
758
this . asyncQueue . verifyOperationInProgress ( ) ;
762
759
763
- if ( this . canUseNetwork ( ) ) {
764
- // Tear down and re-create our network streams. This will ensure we get a
765
- // fresh auth token for the new user and re-fill the write pipeline with
766
- // new mutations from the LocalStore (since mutations are per-user).
767
- logDebug ( LOG_TAG , 'RemoteStore restarting streams for new credential' ) ;
760
+ // Tear down and re-create our network streams. This will ensure we get a
761
+ // fresh auth token for the new user and re-fill the write pipeline with
762
+ // new mutations from the LocalStore (since mutations are per-user).
763
+ logDebug ( LOG_TAG , 'RemoteStore received new credential' ) ;
764
+ this . offlineCauses . add ( OfflineCause . CredentialChange ) ;
768
765
769
- this . networkEnabled = false ;
770
- await this . disableNetworkInternal ( ) ;
771
- this . onlineStateTracker . set ( OnlineState . Unknown ) ;
766
+ await this . disableNetworkInternal ( ) ;
767
+ this . onlineStateTracker . set ( OnlineState . Unknown ) ;
768
+ await this . syncEngine . handleUserChange ( user ) ;
772
769
773
- await this . executeWithRecovery ( async ( ) => {
774
- await this . syncEngine . handleUserChange ( user ) ;
775
- await this . enableNetwork ( ) ;
776
- } ) ;
777
- } else {
778
- await this . executeWithRecovery ( ( ) =>
779
- this . syncEngine . handleUserChange ( user )
780
- ) ;
781
- }
770
+ this . offlineCauses . delete ( OfflineCause . CredentialChange ) ;
771
+ await this . enableNetworkInternal ( ) ;
782
772
}
783
773
784
774
/**
785
775
* Toggles the network state when the client gains or loses its primary lease.
786
776
*/
787
777
async applyPrimaryState ( isPrimary : boolean ) : Promise < void > {
788
- this . isPrimary = isPrimary ;
789
-
790
- if ( isPrimary && this . networkEnabled ) {
791
- await this . enableNetwork ( ) ;
778
+ if ( isPrimary ) {
779
+ this . offlineCauses . delete ( OfflineCause . IsSecondary ) ;
780
+ await this . enableNetworkInternal ( ) ;
792
781
} else if ( ! isPrimary ) {
782
+ this . offlineCauses . add ( OfflineCause . IsSecondary ) ;
793
783
await this . disableNetworkInternal ( ) ;
794
784
this . onlineStateTracker . set ( OnlineState . Unknown ) ;
795
785
}
0 commit comments