Skip to content

Commit 5c99575

Browse files
author
Michael Lehenbauer
committed
Fix for b/74749605: Cancel pending backoff operations when closing streams.
Port of firebase/firebase-js-sdk#564.
1 parent 308acc0 commit 5c99575

9 files changed

+150
-35
lines changed

Firestore/Example/Tests/SpecTests/FSTSpecTests.mm

+5
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,11 @@ - (void)doWatchReset:(NSArray<NSNumber *> *)watchReset snapshot:(NSNumber *_Null
296296
- (void)doWatchStreamClose:(NSDictionary *)closeSpec {
297297
NSDictionary *errorSpec = closeSpec[@"error"];
298298
int code = ((NSNumber *)(errorSpec[@"code"])).intValue;
299+
300+
NSNumber *runBackoffTimer = closeSpec[@"runBackoffTimer"];
301+
// TODO(b/72313632): Incorporate backoff in iOS Spec Tests.
302+
FSTAssert(runBackoffTimer.boolValue, @"iOS Spec Tests don't support backoff.");
303+
299304
[self.driver receiveWatchStreamError:code userInfo:errorSpec];
300305
}
301306

Firestore/Example/Tests/SpecTests/json/existence_filter_spec_test.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,8 @@
337337
"error": {
338338
"code": 14,
339339
"message": "Simulated Backend Error"
340-
}
340+
},
341+
"runBackoffTimer": true
341342
},
342343
"stateExpect": {
343344
"activeTargets": {

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

+46-23
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,17 @@
3434
"error": {
3535
"code": 14,
3636
"message": "Simulated Backend Error"
37-
}
37+
},
38+
"runBackoffTimer": true
3839
}
3940
},
4041
{
4142
"watchStreamClose": {
4243
"error": {
4344
"code": 14,
4445
"message": "Simulated Backend Error"
45-
}
46+
},
47+
"runBackoffTimer": true
4648
},
4749
"expect": [
4850
{
@@ -62,15 +64,17 @@
6264
"error": {
6365
"code": 14,
6466
"message": "Simulated Backend Error"
65-
}
67+
},
68+
"runBackoffTimer": true
6669
}
6770
},
6871
{
6972
"watchStreamClose": {
7073
"error": {
7174
"code": 14,
7275
"message": "Simulated Backend Error"
73-
}
76+
},
77+
"runBackoffTimer": true
7478
}
7579
}
7680
]
@@ -115,23 +119,26 @@
115119
"error": {
116120
"code": 14,
117121
"message": "Simulated Backend Error"
118-
}
122+
},
123+
"runBackoffTimer": true
119124
}
120125
},
121126
{
122127
"watchStreamClose": {
123128
"error": {
124129
"code": 14,
125130
"message": "Simulated Backend Error"
126-
}
131+
},
132+
"runBackoffTimer": true
127133
}
128134
},
129135
{
130136
"watchStreamClose": {
131137
"error": {
132138
"code": 14,
133139
"message": "Simulated Backend Error"
134-
}
140+
},
141+
"runBackoffTimer": true
135142
},
136143
"expect": [
137144
{
@@ -151,15 +158,17 @@
151158
"error": {
152159
"code": 14,
153160
"message": "Simulated Backend Error"
154-
}
161+
},
162+
"runBackoffTimer": true
155163
}
156164
},
157165
{
158166
"watchStreamClose": {
159167
"error": {
160168
"code": 14,
161169
"message": "Simulated Backend Error"
162-
}
170+
},
171+
"runBackoffTimer": true
163172
}
164173
}
165174
]
@@ -199,15 +208,17 @@
199208
"error": {
200209
"code": 14,
201210
"message": "Simulated Backend Error"
202-
}
211+
},
212+
"runBackoffTimer": true
203213
}
204214
},
205215
{
206216
"watchStreamClose": {
207217
"error": {
208218
"code": 14,
209219
"message": "Simulated Backend Error"
210-
}
220+
},
221+
"runBackoffTimer": true
211222
},
212223
"expect": [
213224
{
@@ -240,7 +251,8 @@
240251
"error": {
241252
"code": 14,
242253
"message": "Simulated Backend Error"
243-
}
254+
},
255+
"runBackoffTimer": true
244256
}
245257
},
246258
{
@@ -270,15 +282,17 @@
270282
"error": {
271283
"code": 14,
272284
"message": "Simulated Backend Error"
273-
}
285+
},
286+
"runBackoffTimer": true
274287
}
275288
},
276289
{
277290
"watchStreamClose": {
278291
"error": {
279292
"code": 14,
280293
"message": "Simulated Backend Error"
281-
}
294+
},
295+
"runBackoffTimer": true
282296
},
283297
"expect": [
284298
{
@@ -381,7 +395,8 @@
381395
"error": {
382396
"code": 14,
383397
"message": "Simulated Backend Error"
384-
}
398+
},
399+
"runBackoffTimer": true
385400
},
386401
"stateExpect": {
387402
"activeTargets": {
@@ -401,15 +416,17 @@
401416
"error": {
402417
"code": 14,
403418
"message": "Simulated Backend Error"
404-
}
419+
},
420+
"runBackoffTimer": true
405421
}
406422
},
407423
{
408424
"watchStreamClose": {
409425
"error": {
410426
"code": 14,
411427
"message": "Simulated Backend Error"
412-
}
428+
},
429+
"runBackoffTimer": true
413430
},
414431
"expect": [
415432
{
@@ -595,7 +612,8 @@
595612
"error": {
596613
"code": 14,
597614
"message": "Simulated Backend Error"
598-
}
615+
},
616+
"runBackoffTimer": true
599617
},
600618
"stateExpect": {
601619
"activeTargets": {
@@ -623,15 +641,17 @@
623641
"error": {
624642
"code": 14,
625643
"message": "Simulated Backend Error"
626-
}
644+
},
645+
"runBackoffTimer": true
627646
}
628647
},
629648
{
630649
"watchStreamClose": {
631650
"error": {
632651
"code": 14,
633652
"message": "Simulated Backend Error"
634-
}
653+
},
654+
"runBackoffTimer": true
635655
}
636656
},
637657
{
@@ -764,15 +784,17 @@
764784
"error": {
765785
"code": 14,
766786
"message": "Simulated Backend Error"
767-
}
787+
},
788+
"runBackoffTimer": true
768789
}
769790
},
770791
{
771792
"watchStreamClose": {
772793
"error": {
773794
"code": 14,
774795
"message": "Simulated Backend Error"
775-
}
796+
},
797+
"runBackoffTimer": true
776798
}
777799
},
778800
{
@@ -834,7 +856,8 @@
834856
"error": {
835857
"code": 14,
836858
"message": "Simulated Backend Error"
837-
}
859+
},
860+
"runBackoffTimer": true
838861
},
839862
"stateExpect": {
840863
"activeTargets": {

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

+73-1
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,8 @@
488488
"error": {
489489
"code": 14,
490490
"message": "Simulated Backend Error"
491-
}
491+
},
492+
"runBackoffTimer": true
492493
}
493494
},
494495
{
@@ -543,5 +544,76 @@
543544
]
544545
}
545546
]
547+
},
548+
"Handles user changes while offline (b/74749605).": {
549+
"describeName": "Remote store:",
550+
"itName": "Handles user changes while offline (b/74749605).",
551+
"tags": [
552+
"no-android",
553+
"no-ios"
554+
],
555+
"config": {
556+
"useGarbageCollection": true
557+
},
558+
"steps": [
559+
{
560+
"userListen": [
561+
2,
562+
{
563+
"path": "collection",
564+
"filters": [],
565+
"orderBys": []
566+
}
567+
],
568+
"stateExpect": {
569+
"activeTargets": {
570+
"2": {
571+
"query": {
572+
"path": "collection",
573+
"filters": [],
574+
"orderBys": []
575+
},
576+
"resumeToken": ""
577+
}
578+
}
579+
}
580+
},
581+
{
582+
"watchStreamClose": {
583+
"error": {
584+
"code": 14,
585+
"message": "Simulated Backend Error"
586+
},
587+
"runBackoffTimer": false
588+
},
589+
"stateExpect": {
590+
"activeTargets": {}
591+
}
592+
},
593+
{
594+
"changeUser": "abc",
595+
"stateExpect": {
596+
"activeTargets": {
597+
"2": {
598+
"query": {
599+
"path": "collection",
600+
"filters": [],
601+
"orderBys": []
602+
},
603+
"resumeToken": ""
604+
}
605+
}
606+
}
607+
},
608+
{
609+
"watchStreamClose": {
610+
"error": {
611+
"code": 14,
612+
"message": "Simulated Backend Error"
613+
},
614+
"runBackoffTimer": true
615+
}
616+
}
617+
]
546618
}
547619
}

Firestore/Example/Tests/SpecTests/json/resume_token_spec_test.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@
8585
"error": {
8686
"code": 14,
8787
"message": "Simulated Backend Error"
88-
}
88+
},
89+
"runBackoffTimer": true
8990
},
9091
"stateExpect": {
9192
"activeTargets": {

Firestore/Source/Remote/FSTExponentialBackoff.h

+3
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ NS_ASSUME_NONNULL_BEGIN
7676
*/
7777
- (void)backoffAndRunBlock:(void (^)(void))block;
7878

79+
/** Cancels any pending backoff block scheduled via backoffAndRunBlock:. */
80+
- (void)cancel;
81+
7982
@end
8083

8184
NS_ASSUME_NONNULL_END

Firestore/Source/Remote/FSTExponentialBackoff.mm

+9-3
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,8 @@ - (void)resetToMax {
6666
}
6767

6868
- (void)backoffAndRunBlock:(void (^)(void))block {
69-
if (self.timerCallback) {
70-
[self.timerCallback cancel];
71-
}
69+
[self cancel];
70+
7271
// First schedule the block using the current base (which may be 0 and should be honored as such).
7372
NSTimeInterval delayWithJitter = _currentBase + [self jitterDelay];
7473
if (_currentBase > 0) {
@@ -89,6 +88,13 @@ - (void)backoffAndRunBlock:(void (^)(void))block {
8988
}
9089
}
9190

91+
- (void)cancel {
92+
if (self.timerCallback) {
93+
[self.timerCallback cancel];
94+
self.timerCallback = nil;
95+
}
96+
}
97+
9298
/** Returns a random value in the range [-currentBase/2, currentBase/2] */
9399
- (NSTimeInterval)jitterDelay {
94100
std::uniform_real_distribution<double> dist;

0 commit comments

Comments
 (0)