@@ -61,21 +61,29 @@ describeSpec('Persistence Recovery', ['no-ios', 'no-android'], () => {
61
61
'Clients fail to lookup mutations (with recovery)' ,
62
62
[ 'multi-client' ] ,
63
63
( ) => {
64
- return client ( 0 )
65
- . expectPrimaryState ( true )
66
- . failDatabaseTransactions ( 'Lookup mutation documents' )
67
- . client ( 1 )
68
- . expectPrimaryState ( false )
69
- . userSets ( 'collection/a' , { v : 1 } )
70
- . failDatabaseTransactions ( 'Lookup mutation documents' )
71
- . client ( 0 )
72
- . recoverDatabase ( )
73
- . runTimer ( TimerId . AsyncQueueRetry )
74
- . writeAcks ( 'collection/a' , 1 , { expectUserCallback : false } )
75
- . client ( 1 )
76
- . recoverDatabase ( )
77
- . runTimer ( TimerId . AsyncQueueRetry )
78
- . expectUserCallbacks ( { acknowledged : [ 'collection/a' ] } ) ;
64
+ // Multi-Tab uses a Local Storage notification to inform all tabs about
65
+ // changes to a mutation tab. To act upon these changes, the tabs read
66
+ // the mutated document from IndexedDB. This test verifies that mutations
67
+ // are applied even if the lookup fails temporarily.
68
+ return (
69
+ client ( 0 )
70
+ . expectPrimaryState ( true )
71
+ // All tabs fail to act upon the Local Storage notifications
72
+ . failDatabaseTransactions ( 'Lookup mutation documents' )
73
+ . client ( 1 )
74
+ . expectPrimaryState ( false )
75
+ . userSets ( 'collection/a' , { v : 1 } )
76
+ . failDatabaseTransactions ( 'Lookup mutation documents' )
77
+ // All tabs recover and the notifications are processed
78
+ . client ( 0 )
79
+ . recoverDatabase ( )
80
+ . runTimer ( TimerId . AsyncQueueRetry )
81
+ . writeAcks ( 'collection/a' , 1 , { expectUserCallback : false } )
82
+ . client ( 1 )
83
+ . recoverDatabase ( )
84
+ . runTimer ( TimerId . AsyncQueueRetry )
85
+ . expectUserCallbacks ( { acknowledged : [ 'collection/a' ] } )
86
+ ) ;
79
87
}
80
88
) ;
81
89
@@ -140,24 +148,48 @@ describeSpec('Persistence Recovery', ['no-ios', 'no-android'], () => {
140
148
'Ignores intermittent lease refresh failures (with recovery)' ,
141
149
[ 'multi-client' ] ,
142
150
( ) => {
143
- return client ( 0 )
144
- . expectPrimaryState ( true )
145
- . client ( 1 )
146
- . expectPrimaryState ( false )
147
- . client ( 0 )
148
- . failDatabaseTransactions ( 'updateClientMetadataAndTryBecomePrimary' )
149
- . runTimer ( TimerId . ClientMetadataRefresh )
150
- . client ( 1 )
151
- . failDatabaseTransactions ( 'updateClientMetadataAndTryBecomePrimary' )
152
- . runTimer ( TimerId . ClientMetadataRefresh )
153
- . client ( 0 )
154
- . recoverDatabase ( )
155
- . runTimer ( TimerId . ClientMetadataRefresh )
156
- . expectPrimaryState ( true )
157
- . client ( 1 )
158
- . recoverDatabase ( )
159
- . runTimer ( TimerId . ClientMetadataRefresh )
160
- . expectPrimaryState ( false ) ;
151
+ // This test verifies that an IndexedDB failure during a lease refresh
152
+ // does not impact client functionality. Lease refresh failures are
153
+ // ignored, as the lease is also verified each time an operation is
154
+ // run.
155
+ return (
156
+ client ( 0 )
157
+ . expectPrimaryState ( true )
158
+ . client ( 1 )
159
+ . expectPrimaryState ( false )
160
+ // Run the initial sequence: The primary client fails its lease refresh
161
+ // before the secondary client.
162
+ . client ( 0 )
163
+ . failDatabaseTransactions ( 'updateClientMetadataAndTryBecomePrimary' )
164
+ . runTimer ( TimerId . ClientMetadataRefresh )
165
+ . client ( 1 )
166
+ . failDatabaseTransactions ( 'updateClientMetadataAndTryBecomePrimary' )
167
+ . runTimer ( TimerId . ClientMetadataRefresh )
168
+ . client ( 0 )
169
+ . recoverDatabase ( )
170
+ . runTimer ( TimerId . ClientMetadataRefresh )
171
+ . expectPrimaryState ( true )
172
+ . client ( 1 )
173
+ . recoverDatabase ( )
174
+ . runTimer ( TimerId . ClientMetadataRefresh )
175
+ . expectPrimaryState ( false )
176
+ // Run the opposite sequence: The secondary client fails its lease
177
+ // refresh before the primary client.
178
+ . client ( 1 )
179
+ . failDatabaseTransactions ( 'updateClientMetadataAndTryBecomePrimary' )
180
+ . runTimer ( TimerId . ClientMetadataRefresh )
181
+ . client ( 0 )
182
+ . failDatabaseTransactions ( 'updateClientMetadataAndTryBecomePrimary' )
183
+ . runTimer ( TimerId . ClientMetadataRefresh )
184
+ . client ( 1 )
185
+ . recoverDatabase ( )
186
+ . runTimer ( TimerId . ClientMetadataRefresh )
187
+ . expectPrimaryState ( false )
188
+ . client ( 0 )
189
+ . recoverDatabase ( )
190
+ . runTimer ( TimerId . ClientMetadataRefresh )
191
+ . expectPrimaryState ( true )
192
+ ) ;
161
193
}
162
194
) ;
163
195
0 commit comments