Skip to content

Commit aab276a

Browse files
authored
Port of fix for b/67042460 (retry more often before considering client offline) (#403)
This ensures FSTRemoteStore always tries to connect at least twice before surfacing an FSTOnlineStateFailed event to external code (which may trigger gets to fail, cached data to be surfaced, etc.).
1 parent 033432f commit aab276a

File tree

5 files changed

+208
-97
lines changed

5 files changed

+208
-97
lines changed

Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.m

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,8 +263,10 @@ - (void)receiveWatchStreamError:(int)errorCode userInfo:(NSDictionary<NSString *
263263
[NSError errorWithDomain:FIRFirestoreErrorDomain code:errorCode userInfo:userInfo];
264264

265265
[self.datastore failWatchStreamWithError:error];
266-
// Unlike web, stream should re-open synchronously
267-
FSTAssert(self.datastore.isWatchStreamOpen, @"Watch stream is open");
266+
// Unlike web, stream should re-open synchronously (if we have any listeners)
267+
if (self.queryListeners.count > 0) {
268+
FSTAssert(self.datastore.isWatchStreamOpen, @"Watch stream is open");
269+
}
268270
}
269271

270272
- (NSDictionary<FSTDocumentKey *, FSTBoxedTargetID *> *)currentLimboDocuments {

Firestore/Example/Tests/SpecTests/json/offline_spec_test.json

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@
2929
}
3030
}
3131
},
32+
{
33+
"watchStreamClose": {
34+
"error": {
35+
"code": 14,
36+
"message": "Simulated Backend Error"
37+
}
38+
}
39+
},
3240
{
3341
"watchStreamClose": {
3442
"error": {
@@ -110,6 +118,14 @@
110118
}
111119
}
112120
},
121+
{
122+
"watchStreamClose": {
123+
"error": {
124+
"code": 14,
125+
"message": "Simulated Backend Error"
126+
}
127+
}
128+
},
113129
{
114130
"watchStreamClose": {
115131
"error": {
@@ -147,5 +163,136 @@
147163
}
148164
}
149165
]
166+
},
167+
"Removing all listeners delays \"Offline\" status on next listen": {
168+
"describeName": "Offline:",
169+
"itName": "Removing all listeners delays \"Offline\" status on next listen",
170+
"tags": [],
171+
"config": {
172+
"useGarbageCollection": true
173+
},
174+
"steps": [
175+
{
176+
"userListen": [
177+
2,
178+
{
179+
"path": "collection",
180+
"filters": [],
181+
"orderBys": []
182+
}
183+
],
184+
"stateExpect": {
185+
"activeTargets": {
186+
"2": {
187+
"query": {
188+
"path": "collection",
189+
"filters": [],
190+
"orderBys": []
191+
},
192+
"resumeToken": ""
193+
}
194+
}
195+
}
196+
},
197+
{
198+
"watchStreamClose": {
199+
"error": {
200+
"code": 14,
201+
"message": "Simulated Backend Error"
202+
}
203+
}
204+
},
205+
{
206+
"watchStreamClose": {
207+
"error": {
208+
"code": 14,
209+
"message": "Simulated Backend Error"
210+
}
211+
},
212+
"expect": [
213+
{
214+
"query": {
215+
"path": "collection",
216+
"filters": [],
217+
"orderBys": []
218+
},
219+
"errorCode": 0,
220+
"fromCache": true,
221+
"hasPendingWrites": false
222+
}
223+
]
224+
},
225+
{
226+
"userUnlisten": [
227+
2,
228+
{
229+
"path": "collection",
230+
"filters": [],
231+
"orderBys": []
232+
}
233+
],
234+
"stateExpect": {
235+
"activeTargets": {}
236+
}
237+
},
238+
{
239+
"watchStreamClose": {
240+
"error": {
241+
"code": 14,
242+
"message": "Simulated Backend Error"
243+
}
244+
}
245+
},
246+
{
247+
"userListen": [
248+
4,
249+
{
250+
"path": "collection",
251+
"filters": [],
252+
"orderBys": []
253+
}
254+
],
255+
"stateExpect": {
256+
"activeTargets": {
257+
"4": {
258+
"query": {
259+
"path": "collection",
260+
"filters": [],
261+
"orderBys": []
262+
},
263+
"resumeToken": ""
264+
}
265+
}
266+
}
267+
},
268+
{
269+
"watchStreamClose": {
270+
"error": {
271+
"code": 14,
272+
"message": "Simulated Backend Error"
273+
}
274+
}
275+
},
276+
{
277+
"watchStreamClose": {
278+
"error": {
279+
"code": 14,
280+
"message": "Simulated Backend Error"
281+
}
282+
},
283+
"expect": [
284+
{
285+
"query": {
286+
"path": "collection",
287+
"filters": [],
288+
"orderBys": []
289+
},
290+
"errorCode": 0,
291+
"fromCache": true,
292+
"hasPendingWrites": false
293+
}
294+
]
295+
}
296+
]
150297
}
151298
}

Firestore/Example/Tests/SpecTests/json/remote_store_spec_test.json

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -489,19 +489,7 @@
489489
"code": 14,
490490
"message": "Simulated Backend Error"
491491
}
492-
},
493-
"expect": [
494-
{
495-
"query": {
496-
"path": "collection",
497-
"filters": [],
498-
"orderBys": []
499-
},
500-
"errorCode": 0,
501-
"fromCache": true,
502-
"hasPendingWrites": false
503-
}
504-
]
492+
}
505493
},
506494
{
507495
"watchAck": [

Firestore/Example/Tests/SpecTests/json/write_spec_test.json

Lines changed: 12 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -4372,9 +4372,9 @@
43724372
}
43734373
]
43744374
},
4375-
"Writes that fail with code cancelled are retried": {
4375+
"Writes that fail with code resource_exhausted are not rejected": {
43764376
"describeName": "Writes:",
4377-
"itName": "Writes that fail with code cancelled are retried",
4377+
"itName": "Writes that fail with code resource_exhausted are not rejected",
43784378
"tags": [],
43794379
"config": {
43804380
"useGarbageCollection": true
@@ -4435,73 +4435,16 @@
44354435
{
44364436
"failWrite": {
44374437
"error": {
4438-
"code": 1
4438+
"code": 8
44394439
},
44404440
"expectUserCallback": false
44414441
}
4442-
},
4443-
{
4444-
"writeAck": {
4445-
"version": 1000,
4446-
"expectUserCallback": true
4447-
}
4448-
},
4449-
{
4450-
"watchAck": [
4451-
2
4452-
]
4453-
},
4454-
{
4455-
"watchEntity": {
4456-
"docs": [
4457-
[
4458-
"collection/key",
4459-
0,
4460-
{
4461-
"foo": "bar"
4462-
}
4463-
]
4464-
],
4465-
"targets": [
4466-
2
4467-
]
4468-
}
4469-
},
4470-
{
4471-
"watchCurrent": [
4472-
[
4473-
2
4474-
],
4475-
"resume-token-1000"
4476-
],
4477-
"watchSnapshot": 1000,
4478-
"expect": [
4479-
{
4480-
"query": {
4481-
"path": "collection/key",
4482-
"filters": [],
4483-
"orderBys": []
4484-
},
4485-
"metadata": [
4486-
[
4487-
"collection/key",
4488-
0,
4489-
{
4490-
"foo": "bar"
4491-
}
4492-
]
4493-
],
4494-
"errorCode": 0,
4495-
"fromCache": false,
4496-
"hasPendingWrites": false
4497-
}
4498-
]
44994442
}
45004443
]
45014444
},
4502-
"Writes that fail with code unknown are retried": {
4445+
"Writes that fail with code cancelled are retried": {
45034446
"describeName": "Writes:",
4504-
"itName": "Writes that fail with code unknown are retried",
4447+
"itName": "Writes that fail with code cancelled are retried",
45054448
"tags": [],
45064449
"config": {
45074450
"useGarbageCollection": true
@@ -4562,7 +4505,7 @@
45624505
{
45634506
"failWrite": {
45644507
"error": {
4565-
"code": 2
4508+
"code": 1
45664509
},
45674510
"expectUserCallback": false
45684511
}
@@ -4626,9 +4569,9 @@
46264569
}
46274570
]
46284571
},
4629-
"Writes that fail with code deadline-exceeded are retried": {
4572+
"Writes that fail with code unknown are retried": {
46304573
"describeName": "Writes:",
4631-
"itName": "Writes that fail with code deadline-exceeded are retried",
4574+
"itName": "Writes that fail with code unknown are retried",
46324575
"tags": [],
46334576
"config": {
46344577
"useGarbageCollection": true
@@ -4689,7 +4632,7 @@
46894632
{
46904633
"failWrite": {
46914634
"error": {
4692-
"code": 4
4635+
"code": 2
46934636
},
46944637
"expectUserCallback": false
46954638
}
@@ -4753,9 +4696,9 @@
47534696
}
47544697
]
47554698
},
4756-
"Writes that fail with code resource-exhausted are retried": {
4699+
"Writes that fail with code deadline-exceeded are retried": {
47574700
"describeName": "Writes:",
4758-
"itName": "Writes that fail with code resource-exhausted are retried",
4701+
"itName": "Writes that fail with code deadline-exceeded are retried",
47594702
"tags": [],
47604703
"config": {
47614704
"useGarbageCollection": true
@@ -4816,7 +4759,7 @@
48164759
{
48174760
"failWrite": {
48184761
"error": {
4819-
"code": 8
4762+
"code": 4
48204763
},
48214764
"expectUserCallback": false
48224765
}

0 commit comments

Comments
 (0)