diff options
author | Michael Lehenbauer <mikelehen@gmail.com> | 2018-02-15 16:17:44 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-02-15 16:17:44 -0800 |
commit | 81ee594e325a922a91557d82563132f22977c947 (patch) | |
tree | 89ea78b6ccc77fa2f11e1c6b1fa40f3c8d54a3b2 /Firestore/Source/Remote/FSTStream.mm | |
parent | fd9fd271d0dba3935a6f5611a1554f2c59b696af (diff) |
DispatchQueue delayed callback improvements + testing (#784)
Basically a port of https://github.com/firebase/firebase-js-sdk/commit/a1e346ff93c6cbcc0a1b3b33f0fbc3a7b66e7e12 and https://github.com/firebase/firebase-js-sdk/commit/fce4168309f42aa038125f39818fbf654b65b05f
* Introduces a DelayedCallback helper class in FSTDispatchQueue to encapsulate delayed callback logic.
* Adds cancellation support.
* Updates the idle timer in FSTStream to use new cancellation support.
* Adds a FSTTimerId enum for identifying delayed operations on the queue and uses it to identify our existing backoff and idle timers.
* Added containsDelayedCallback: and runDelayedCallbacksUntil: methods to FSTDispatchQueue which can be used from tests to check for the presence of a callback or to schedule them to run early.
* Removes FSTTestDispatchQueue and changes idle tests to use new test methods.
Diffstat (limited to 'Firestore/Source/Remote/FSTStream.mm')
-rw-r--r-- | Firestore/Source/Remote/FSTStream.mm | 40 |
1 files changed, 27 insertions, 13 deletions
diff --git a/Firestore/Source/Remote/FSTStream.mm b/Firestore/Source/Remote/FSTStream.mm index c1479c5..f859fbb 100644 --- a/Firestore/Source/Remote/FSTStream.mm +++ b/Firestore/Source/Remote/FSTStream.mm @@ -113,7 +113,8 @@ typedef NS_ENUM(NSInteger, FSTStreamState) { @interface FSTStream () -@property(nonatomic, getter=isIdle) BOOL idle; +@property(nonatomic, assign, readonly) FSTTimerID idleTimerID; +@property(nonatomic, strong, nullable) FSTDelayedCallback *idleTimerCallback; @property(nonatomic, weak, readwrite, nullable) id delegate; @end @@ -203,18 +204,22 @@ static const NSTimeInterval kIdleTimeout = 60.0; - (instancetype)initWithDatabase:(const DatabaseInfo *)database workerDispatchQueue:(FSTDispatchQueue *)workerDispatchQueue + connectionTimerID:(FSTTimerID)connectionTimerID + idleTimerID:(FSTTimerID)idleTimerID credentials:(id<FSTCredentialsProvider>)credentials responseMessageClass:(Class)responseMessageClass { if (self = [super init]) { _databaseInfo = database; _workerDispatchQueue = workerDispatchQueue; + _idleTimerID = idleTimerID; _credentials = credentials; _responseMessageClass = responseMessageClass; - _backoff = [FSTExponentialBackoff exponentialBackoffWithDispatchQueue:workerDispatchQueue - initialDelay:kBackoffInitialDelay - backoffFactor:kBackoffFactor - maxDelay:kBackoffMaxDelay]; + _backoff = [[FSTExponentialBackoff alloc] initWithDispatchQueue:workerDispatchQueue + timerID:connectionTimerID + initialDelay:kBackoffInitialDelay + backoffFactor:kBackoffFactor + maxDelay:kBackoffMaxDelay]; _state = FSTStreamStateInitial; } return self; @@ -418,7 +423,7 @@ static const NSTimeInterval kIdleTimeout = 60.0; /** Called by the idle timer when the stream should close due to inactivity. */ - (void)handleIdleCloseTimer { [self.workerDispatchQueue verifyIsCurrentQueue]; - if (self.state == FSTStreamStateOpen && [self isIdle]) { + if ([self isOpen]) { // When timing out an idle stream there's no reason to force the stream into backoff when // it restarts so set the stream state to Initial instead of Error. [self closeWithFinalState:FSTStreamStateInitial error:nil]; @@ -427,18 +432,23 @@ static const NSTimeInterval kIdleTimeout = 60.0; - (void)markIdle { [self.workerDispatchQueue verifyIsCurrentQueue]; - if (self.state == FSTStreamStateOpen) { - self.idle = YES; - [self.workerDispatchQueue dispatchAfterDelay:kIdleTimeout - block:^() { - [self handleIdleCloseTimer]; - }]; + // Starts the idle timer if we are in state 'Open' and are not yet already running a timer (in + // which case the previous idle timeout still applies). + if ([self isOpen] && !self.idleTimerCallback) { + self.idleTimerCallback = [self.workerDispatchQueue dispatchAfterDelay:kIdleTimeout + timerID:self.idleTimerID + block:^() { + [self handleIdleCloseTimer]; + }]; } } - (void)cancelIdleCheck { [self.workerDispatchQueue verifyIsCurrentQueue]; - self.idle = NO; + if (self.idleTimerCallback) { + [self.idleTimerCallback cancel]; + self.idleTimerCallback = nil; + } } /** @@ -606,6 +616,8 @@ static const NSTimeInterval kIdleTimeout = 60.0; serializer:(FSTSerializerBeta *)serializer { self = [super initWithDatabase:database workerDispatchQueue:workerDispatchQueue + connectionTimerID:FSTTimerIDListenStreamConnection + idleTimerID:FSTTimerIDListenStreamIdle credentials:credentials responseMessageClass:[GCFSListenResponse class]]; if (self) { @@ -689,6 +701,8 @@ static const NSTimeInterval kIdleTimeout = 60.0; serializer:(FSTSerializerBeta *)serializer { self = [super initWithDatabase:database workerDispatchQueue:workerDispatchQueue + connectionTimerID:FSTTimerIDWriteStreamConnection + idleTimerID:FSTTimerIDWriteStreamIdle credentials:credentials responseMessageClass:[GCFSWriteResponse class]]; if (self) { |