Skip to content

Commit 954dc2d

Browse files
author
Michael Lehenbauer
committed
Offline get() improvements.
[Port of firebase/firebase-js-sdk#1133] 1. Changed MAX_WATCH_STREAM_FAILURES to 1 per conversation with @wilhuff and @jdimond. 2. Fixed a "race" where when a get() triggered a watch stream error, we'd restart the stream, then get() would remove its listener, and so we had no listener left once the watch stream was "opened". Without a listen to send we'd be stuck in Offline state (even though we should be Unknown whenever we have no listens to send), resulting in the next get() returning data from cache without even attempting to reach the backend.
1 parent 4625899 commit 954dc2d

File tree

4 files changed

+38
-67
lines changed

4 files changed

+38
-67
lines changed

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

-63
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,6 @@
3030
}
3131
}
3232
},
33-
{
34-
"watchStreamClose": {
35-
"error": {
36-
"code": 14,
37-
"message": "Simulated Backend Error"
38-
},
39-
"runBackoffTimer": true
40-
}
41-
},
4233
{
4334
"watchStreamClose": {
4435
"error": {
@@ -125,15 +116,6 @@
125116
"runBackoffTimer": true
126117
}
127118
},
128-
{
129-
"watchStreamClose": {
130-
"error": {
131-
"code": 14,
132-
"message": "Simulated Backend Error"
133-
},
134-
"runBackoffTimer": true
135-
}
136-
},
137119
{
138120
"watchStreamClose": {
139121
"error": {
@@ -209,15 +191,6 @@
209191
}
210192
}
211193
},
212-
{
213-
"watchStreamClose": {
214-
"error": {
215-
"code": 14,
216-
"message": "Simulated Backend Error"
217-
},
218-
"runBackoffTimer": true
219-
}
220-
},
221194
{
222195
"watchStreamClose": {
223196
"error": {
@@ -283,15 +256,6 @@
283256
}
284257
}
285258
},
286-
{
287-
"watchStreamClose": {
288-
"error": {
289-
"code": 14,
290-
"message": "Simulated Backend Error"
291-
},
292-
"runBackoffTimer": true
293-
}
294-
},
295259
{
296260
"watchStreamClose": {
297261
"error": {
@@ -422,15 +386,6 @@
422386
}
423387
}
424388
},
425-
{
426-
"watchStreamClose": {
427-
"error": {
428-
"code": 14,
429-
"message": "Simulated Backend Error"
430-
},
431-
"runBackoffTimer": true
432-
}
433-
},
434389
{
435390
"watchStreamClose": {
436391
"error": {
@@ -669,15 +624,6 @@
669624
"runBackoffTimer": true
670625
}
671626
},
672-
{
673-
"watchStreamClose": {
674-
"error": {
675-
"code": 14,
676-
"message": "Simulated Backend Error"
677-
},
678-
"runBackoffTimer": true
679-
}
680-
},
681627
{
682628
"watchAck": [
683629
2
@@ -957,15 +903,6 @@
957903
}
958904
}
959905
},
960-
{
961-
"watchStreamClose": {
962-
"error": {
963-
"code": 14,
964-
"message": "Simulated Backend Error"
965-
},
966-
"runBackoffTimer": true
967-
}
968-
},
969906
{
970907
"watchStreamClose": {
971908
"error": {

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

+25-1
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,19 @@
517517
"message": "Simulated Backend Error"
518518
},
519519
"runBackoffTimer": true
520-
}
520+
},
521+
"expect": [
522+
{
523+
"query": {
524+
"path": "collection",
525+
"filters": [],
526+
"orderBys": []
527+
},
528+
"errorCode": 0,
529+
"fromCache": true,
530+
"hasPendingWrites": false
531+
}
532+
]
521533
},
522534
{
523535
"watchAck": [
@@ -618,6 +630,18 @@
618630
},
619631
"runBackoffTimer": false
620632
},
633+
"expect": [
634+
{
635+
"query": {
636+
"path": "collection",
637+
"filters": [],
638+
"orderBys": []
639+
},
640+
"errorCode": 0,
641+
"fromCache": true,
642+
"hasPendingWrites": false
643+
}
644+
],
621645
"stateExpect": {
622646
"activeTargets": {}
623647
}

Firestore/Source/Remote/FSTOnlineStateTracker.mm

+4-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@
2727

2828
// To deal with transient failures, we allow multiple stream attempts before giving up and
2929
// transitioning from OnlineState Unknown to Offline.
30-
static const int kMaxWatchStreamFailures = 2;
30+
// TODO(mikelehen): This used to be set to 2 as a mitigation for b/66228394. @jdimond thinks that
31+
// bug is sufficiently fixed so that we can set this back to 1. If that works okay, we could
32+
// potentially remove this logic entirely.
33+
static const int kMaxWatchStreamFailures = 1;
3134

3235
// To deal with stream attempts that don't succeed or fail in a timely manner, we have a
3336
// timeout for OnlineState to reach Online or Offline. If the timeout is reached, we transition

Firestore/Source/Remote/FSTRemoteStore.mm

+9-2
Original file line numberDiff line numberDiff line change
@@ -252,13 +252,20 @@ - (void)sendWatchRequestWithQueryData:(FSTQueryData *)queryData {
252252
- (void)stopListeningToTargetID:(TargetId)targetID {
253253
FSTBoxedTargetID *targetKey = @(targetID);
254254
FSTQueryData *queryData = self.listenTargets[targetKey];
255-
HARD_ASSERT(queryData, "unlistenToTarget: target not currently watched: %s", targetKey);
255+
HARD_ASSERT(queryData, "stopListeningToTargetID: target not currently watched: %s", targetKey);
256256

257257
[self.listenTargets removeObjectForKey:targetKey];
258258
if ([self isNetworkEnabled] && [self.watchStream isOpen]) {
259259
[self sendUnwatchRequestForTargetID:targetKey];
260-
if ([self.listenTargets count] == 0) {
260+
}
261+
if ([self.listenTargets count] == 0) {
262+
if ([self isNetworkEnabled] && [self.watchStream isOpen]) {
261263
[self.watchStream markIdle];
264+
} else {
265+
// Revert to OnlineState::Unknown if the watch stream is not open and we have no listeners,
266+
// since without any listens to send we cannot confirm if the stream is healthy and upgrade
267+
// to OnlineState::Online.
268+
[self.onlineStateTracker updateState:OnlineState::Unknown];
262269
}
263270
}
264271
}

0 commit comments

Comments
 (0)