diff --git a/CHANGELOG.md b/CHANGELOG.md index 12af0abd..92f3978d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to the LaunchDarkly Python SDK will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org). +## [2.2.0] - 2017-04-05 +### Added +- Ability to disable streaming and enable interval-based polling + ## [2.1.3] - 2017-04-05 ### Fixed - Uncaught exception `NSInvalidArgumentException` in `performEventRequest` diff --git a/Darkly/DarklyConstants.h b/Darkly/DarklyConstants.h index 36748ca4..6c0b8600 100644 --- a/Darkly/DarklyConstants.h +++ b/Darkly/DarklyConstants.h @@ -38,5 +38,7 @@ extern NSString *const kLDBackgroundFetchInitiated; extern int const kCapacity; extern int const kConnectionTimeout; extern int const kDefaultFlushInterval; -extern int const kMinimumPollingIntervalMillis; +extern int const kMinimumFlushIntervalMillis; +extern int const kDefaultPollingInterval; +extern int const kMinimumPollingInterval; extern int const kMillisInSecs; diff --git a/Darkly/DarklyConstants.m b/Darkly/DarklyConstants.m index 96d3416b..6ff131f1 100644 --- a/Darkly/DarklyConstants.m +++ b/Darkly/DarklyConstants.m @@ -4,7 +4,7 @@ #import "DarklyConstants.h" -NSString * const kClientVersion = @"2.1.3"; +NSString * const kClientVersion = @"2.2.0"; NSString * const kBaseUrl = @"https://app.launchdarkly.com"; NSString * const kEventsUrl = @"https://mobile.launchdarkly.com"; NSString * const kStreamUrl = @"https://stream.launchdarkly.com/mping"; @@ -25,5 +25,7 @@ int const kCapacity = 100; int const kConnectionTimeout = 10; int const kDefaultFlushInterval = 30; -int const kMinimumPollingIntervalMillis = 0; +int const kMinimumFlushIntervalMillis = 0; +int const kDefaultPollingInterval = 3600; +int const kMinimumPollingInterval = 300; int const kMillisInSecs = 1000; diff --git a/Darkly/LDClientManager.h b/Darkly/LDClientManager.h index af5d827c..913ebb1c 100644 --- a/Darkly/LDClientManager.h +++ b/Darkly/LDClientManager.h @@ -17,7 +17,7 @@ - (void)syncWithServerForEvents; - (void)syncWithServerForConfig; -- (void)processedEvents:(BOOL)success jsonEventArray:(NSArray *)jsonEventArray eventIntervalMillis:(int)eventIntervalMillis; +- (void)processedEvents:(BOOL)success jsonEventArray:(NSArray *)jsonEventArray; - (void)processedConfig:(BOOL)success jsonConfigDictionary:(NSDictionary *)jsonConfigDictionary; - (void)startPolling; - (void)stopPolling; diff --git a/Darkly/LDClientManager.m b/Darkly/LDClientManager.m index 31514ef0..053e8be8 100644 --- a/Darkly/LDClientManager.m +++ b/Darkly/LDClientManager.m @@ -33,17 +33,22 @@ +(LDClientManager *)sharedInstance { - (void)startPolling { LDPollingManager *pollingMgr = [LDPollingManager sharedInstance]; - LDClient *client = [LDClient sharedInstance]; - LDConfig *config = client.ldConfig; - pollingMgr.eventTimerPollingIntervalMillis = [config.flushInterval intValue] * kMillisInSecs; - DEBUG_LOG(@"ClientManager startPolling method called with eventTimerPollingInterval=%f", pollingMgr.eventTimerPollingIntervalMillis); + LDConfig *config = [[LDClient sharedInstance] ldConfig]; + pollingMgr.eventPollingIntervalMillis = [config.flushInterval intValue] * kMillisInSecs; + DEBUG_LOG(@"ClientManager startPolling method called with pollingInterval=%f", pollingMgr.eventPollingIntervalMillis); [pollingMgr startEventPolling]; - eventSource = [EventSource eventSourceWithURL:[NSURL URLWithString:kStreamUrl] mobileKey:config.mobileKey]; - - [eventSource onMessage:^(Event *e) { - [self syncWithServerForConfig]; - }]; + if ([config streaming]) { + eventSource = [EventSource eventSourceWithURL:[NSURL URLWithString:kStreamUrl] mobileKey:config.mobileKey]; + + [eventSource onMessage:^(Event *e) { + [self syncWithServerForConfig]; + }]; + } + else{ + pollingMgr.configPollingIntervalMillis = [config.pollingInterval intValue] * kMillisInSecs; + [pollingMgr startConfigPolling]; + } } @@ -53,7 +58,12 @@ - (void)stopPolling { [pollingMgr stopEventPolling]; - [eventSource close]; + if ([[[LDClient sharedInstance] ldConfig] streaming]) { + [eventSource close]; + } + else{ + [pollingMgr stopConfigPolling]; + } [self flushEvents]; } @@ -64,7 +74,12 @@ - (void)willEnterBackground { [pollingMgr suspendEventPolling]; - [eventSource close]; + if ([[[LDClient sharedInstance] ldConfig] streaming]) { + [eventSource close]; + } + else{ + [pollingMgr suspendConfigPolling]; + } [self flushEvents]; } @@ -75,11 +90,17 @@ - (void)willEnterForeground { [pollingMgr resumeEventPolling]; LDClient *client = [LDClient sharedInstance]; - eventSource = [EventSource eventSourceWithURL:[NSURL URLWithString:kStreamUrl] mobileKey:client.ldConfig.mobileKey]; - [eventSource onMessage:^(Event *e) { - [self syncWithServerForConfig]; - }]; + if ([[client ldConfig] streaming]) { + eventSource = [EventSource eventSourceWithURL:[NSURL URLWithString:kStreamUrl] mobileKey:client.ldConfig.mobileKey]; + + [eventSource onMessage:^(Event *e) { + [self syncWithServerForConfig]; + }]; + } + else{ + [pollingMgr resumeConfigPolling]; + } } -(void)syncWithServerForEvents { @@ -124,7 +145,7 @@ - (void)flushEvents { [self syncWithServerForEvents]; } -- (void)processedEvents:(BOOL)success jsonEventArray:(NSArray *)jsonEventArray eventIntervalMillis:(int)eventIntervalMillis { +- (void)processedEvents:(BOOL)success jsonEventArray:(NSArray *)jsonEventArray { // If Success if (success) { DEBUG_LOGX(@"ClientManager processedEvents method called after receiving successful response from server"); @@ -132,11 +153,6 @@ - (void)processedEvents:(BOOL)success jsonEventArray:(NSArray *)jsonEventArray e if (jsonEventArray) { [[LDDataManager sharedManager] deleteProcessedEvents: jsonEventArray]; } - } else { - DEBUG_LOGX(@"ClientManager processedEvents method called after receiving failure response from server"); - LDPollingManager *pollingMgr = [LDPollingManager sharedInstance]; - DEBUG_LOG(@"ClientManager setting event interval to: %d", eventIntervalMillis); - pollingMgr.eventTimerPollingIntervalMillis = eventIntervalMillis; } } diff --git a/Darkly/LDConfig.h b/Darkly/LDConfig.h index 0f2862f1..9dc47a01 100644 --- a/Darkly/LDConfig.h +++ b/Darkly/LDConfig.h @@ -12,6 +12,8 @@ @property (nonatomic) NSNumber* capacity; @property (nonatomic) NSNumber* connectionTimeout; @property (nonatomic) NSNumber* flushInterval; +@property (nonatomic) NSNumber* pollingInterval; +@property (nonatomic) BOOL streaming; @property (nonatomic) BOOL debugEnabled; @end @@ -65,15 +67,31 @@ - (LDConfigBuilder *)withConnectionTimeout:(int)connectionTimeout; /** * The interval at which events are synced to the server. The default - * is 30 seconds. (Optional) + * is 30 seconds for streaming mode; in polling mode, the flush interval defaults to the polling interval. (Optional) * - * @param flushInverval the flush interval in seconds + * @param flushInterval the flush interval in seconds * @return the configuration builder */ - (LDConfigBuilder *)withFlushInterval:(int)flushInterval; +/** + * Set the polling interval (in seconds) for polling mode only. An interval + * less than 300 is set to the default (5 minutes). + * + * @param pollingInterval the polling interval in seconds + * @return the configuration builder + */ +- (LDConfigBuilder *)withPollingInterval:(int)pollingInterval; +/** + * Enable streaming mode for flags. When streaming is false, disable streaming and switch to polling mode. (Optional) + * + * @param streamingEnabled Whether streaming is enabled or not + * @return the configuration builder + */ +- (LDConfigBuilder *)withStreaming:(BOOL)streamingEnabled; /** * Enable debug mode to allow things such as logging. (Optional) * + * @param debugEnabled Whether debugging is enabled or not * @return the configuration builder */ - (LDConfigBuilder *)withDebugEnabled:(BOOL)debugEnabled; diff --git a/Darkly/LDConfig.m b/Darkly/LDConfig.m index ecc840fe..64b79cc1 100644 --- a/Darkly/LDConfig.m +++ b/Darkly/LDConfig.m @@ -7,7 +7,7 @@ @implementation LDConfig -@synthesize mobileKey, baseUrl, eventsUrl, capacity, connectionTimeout, flushInterval, debugEnabled; +@synthesize mobileKey, baseUrl, eventsUrl, capacity, connectionTimeout, flushInterval, pollingInterval, streaming, debugEnabled; @end @@ -18,6 +18,8 @@ @interface LDConfigBuilder() { NSNumber *capacity; NSNumber *connectionTimeout; NSNumber *flushInterval; + NSNumber *pollingInterval; + BOOL streaming; BOOL debugEnabled; } @@ -25,6 +27,12 @@ @interface LDConfigBuilder() { @implementation LDConfigBuilder +- (id)init { + self = [super init]; + streaming = YES; + return self; +} + - (LDConfigBuilder *)withMobileKey:(NSString *)inputMobileKey { mobileKey = inputMobileKey; @@ -60,6 +68,18 @@ - (LDConfigBuilder *)withFlushInterval:(int)inputFlushInterval return self; } +- (LDConfigBuilder *)withPollingInterval:(int)inputPollingInterval +{ + pollingInterval = [NSNumber numberWithInt:MAX(inputPollingInterval, kMinimumPollingInterval)]; + return self; +} + +- (LDConfigBuilder *)withStreaming:(BOOL)inputStreamingEnabled +{ + streaming = inputStreamingEnabled; + return self; +} + - (LDConfigBuilder *)withDebugEnabled:(BOOL)inputDebugEnabled { debugEnabled = inputDebugEnabled; @@ -112,6 +132,17 @@ -(LDConfig *)build DEBUG_LOG(@"LDConfigBuilder building LDConfig with default flush interval: %d", kDefaultFlushInterval); [config setFlushInterval:[NSNumber numberWithInt:kDefaultFlushInterval]]; } + if (pollingInterval) { + DEBUG_LOG(@"LDConfigBuilder building LDConfig with polling interval: %@", pollingInterval); + [config setPollingInterval:pollingInterval]; + } else { + DEBUG_LOG(@"LDConfigBuilder building LDConfig with default polling interval: %d", kDefaultPollingInterval); + [config setPollingInterval:[NSNumber numberWithInt:kDefaultPollingInterval]]; + } + + DEBUG_LOG(@"LDConfigBuilder building LDConfig with streaming enabled: %d", streaming); + [config setStreaming:streaming]; + if (debugEnabled) { DEBUG_LOG(@"LDConfigBuilder building LDConfig with debug enabled: %d", debugEnabled); [config setDebugEnabled:debugEnabled]; @@ -119,4 +150,4 @@ -(LDConfig *)build return config; } -@end \ No newline at end of file +@end diff --git a/Darkly/LDPollingManager.h b/Darkly/LDPollingManager.h index 5dd97080..53e4f5a1 100644 --- a/Darkly/LDPollingManager.h +++ b/Darkly/LDPollingManager.h @@ -14,18 +14,30 @@ typedef enum { @interface LDPollingManager : NSObject { @protected - PollingState pollEventState; + PollingState configPollingState; + PollingState eventPollingState; } + (id)sharedInstance; -@property (nonatomic, assign) PollingState pollEventState; +@property (nonatomic, assign) PollingState configPollingState; +@property (nonatomic, assign) PollingState eventPollingState; +@property (strong, nonatomic) dispatch_source_t configTimer; +@property (nonatomic) NSTimeInterval configPollingIntervalMillis; @property (strong, nonatomic) dispatch_source_t eventTimer; -@property (nonatomic) NSTimeInterval eventTimerPollingIntervalMillis; +@property (nonatomic) NSTimeInterval eventPollingIntervalMillis; ++ (NSUInteger)configPollingCount; + (NSUInteger)eventPollingCount; +- (void) startConfigPolling; +- (void) pauseConfigPolling; +- (void) suspendConfigPolling; +- (void) resumeConfigPolling; +- (void) stopConfigPolling; +- (PollingState)configPollingState; + // event polling is passed in from the LDClient object. can be modified... - (void) startEventPolling; - (void) pauseEventPolling; @@ -34,4 +46,4 @@ typedef enum { - (void) stopEventPolling; - (PollingState)eventPollingState; -@end \ No newline at end of file +@end diff --git a/Darkly/LDPollingManager.m b/Darkly/LDPollingManager.m index 6f549527..fd6f9f30 100644 --- a/Darkly/LDPollingManager.m +++ b/Darkly/LDPollingManager.m @@ -11,9 +11,13 @@ @implementation LDPollingManager @synthesize eventTimer; -@synthesize eventTimerPollingIntervalMillis; -@synthesize pollEventState; +@synthesize eventPollingIntervalMillis; +@synthesize eventPollingState; +@synthesize configTimer; +@synthesize configPollingIntervalMillis; +@synthesize configPollingState; +static NSUInteger configPollingCount=0; static NSUInteger eventPollingCount=0; static id sharedInstance = nil; @@ -30,17 +34,34 @@ + (instancetype)sharedInstance - (id)init { if ((self = [super init])) { + configPollingCount = 0; eventPollingCount = 0; - self.pollEventState = POLL_STOPPED; - self.eventTimerPollingIntervalMillis = kDefaultFlushInterval*kMillisInSecs; + + self.configPollingState = POLL_STOPPED; + self.eventPollingState = POLL_STOPPED; + + self.configPollingIntervalMillis = kDefaultPollingInterval*kMillisInSecs; + self.eventPollingIntervalMillis = kDefaultFlushInterval*kMillisInSecs; } return self; } - (void)dealloc { + [self stopConfigPolling]; [self stopEventPolling]; + configPollingCount = 0; eventPollingCount = 0; - pollEventState = POLL_STOPPED; + + configPollingState = POLL_STOPPED; + eventPollingState = POLL_STOPPED; +} + ++ (NSUInteger)configPollingCount { + return configPollingCount; +} + +- (PollingState)configPollingState { + return configPollingState; } + (NSUInteger)eventPollingCount { @@ -48,18 +69,113 @@ + (NSUInteger)eventPollingCount { } - (PollingState)eventPollingState { - return pollEventState; + return eventPollingState; +} + +#pragma mark - Config Polling methods + +- (void)startConfigPollTimer +{ + DEBUG_LOGX(@"PollingManager starting initial config polling"); + if ((!self.configTimer) && (self.configPollingIntervalMillis > 0.0)) { + self.configTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); + } + if (self.configTimer) { + configPollingState = POLL_RUNNING; + + dispatch_source_set_event_handler(self.configTimer, ^(void) { + [self configPoll]; + }); + + [self updateConfigPollingTimer]; + dispatch_resume(self.configTimer); + } +} + +- (void)configPoll { + if (configPollingState != POLL_STOPPED || configPollingState != POLL_SUSPENDED) + { + DEBUG_LOGX(@"PollingManager config interval reached"); + configPollingCount +=1; + + LDClientManager *clientManager = [LDClientManager sharedInstance]; + if (![[[LDClient sharedInstance] ldConfig] streaming]) { + [clientManager syncWithServerForConfig]; + } + } +} + +- (void)updateConfigPollingTimer { + if ((self.configTimer != NULL) && (self.configPollingIntervalMillis > 0.0)) { + uint64_t interval = (uint64_t)(self.configPollingIntervalMillis * NSEC_PER_MSEC); + dispatch_time_t startTime = dispatch_time(DISPATCH_TIME_NOW, interval); + dispatch_source_set_timer(self.configTimer, startTime, interval, 1.0); + } +} + +- (void) startConfigPolling { + if (configPollingState == POLL_STOPPED) { + DEBUG_LOGX(@"PollingManager starting config polling"); + [self startConfigPollTimer]; + } +} + +- (void) pauseConfigPolling { + if (configPollingState == POLL_RUNNING) { + DEBUG_LOGX(@"PollingManager pausing config polling"); + dispatch_suspend(self.configTimer); + configPollingState = POLL_PAUSED; + } +} + +- (void) suspendConfigPolling { + if (configPollingState == POLL_RUNNING) { + DEBUG_LOGX(@"PollingManager suspending config polling"); + dispatch_suspend(self.configTimer); + configPollingState = POLL_SUSPENDED; + } +} + +- (void) resumeConfigPolling{ + if (configPollingState == POLL_PAUSED || configPollingState == POLL_SUSPENDED) { + DEBUG_LOGX(@"PollingManager resuming config polling"); + BOOL checkconfig = configPollingState == POLL_SUSPENDED ? YES : NO; + dispatch_resume(self.configTimer); + configPollingState = POLL_RUNNING; + if (checkconfig) { + [self configPoll]; + } + } } +- (void)stopConfigPolling { + DEBUG_LOGX(@"PollingManager stopping config polling"); + if (self.configTimer) { + dispatch_source_cancel(self.configTimer); + + if (configPollingState == POLL_PAUSED || configPollingState == POLL_SUSPENDED) + { + dispatch_resume(self.configTimer); + } + +#if !OS_OBJECT_USE_OBJC + dispatch_release(self.pollingTimer); +#endif + self.configTimer = NULL; + configPollingState = POLL_STOPPED; + } +} + +#pragma mark - Event Polling methods //Setter method -- (void) setEventTimerPollingIntervalMillis:(NSTimeInterval)eTimerPollingInterval { - eventTimerPollingIntervalMillis = [self calculateEventPollingIntervalMillis:eTimerPollingInterval]; - if (pollEventState != POLL_STOPPED && pollEventState != POLL_SUSPENDED) { +- (void) setEventPollingIntervalMillis:(NSTimeInterval)eTimerPollingInterval { + eventPollingIntervalMillis = [self calculateEventPollingIntervalMillis:eTimerPollingInterval]; + if (eventPollingState != POLL_STOPPED && eventPollingState != POLL_SUSPENDED) { // pause the event polling interval DEBUG_LOGX(@"Pausing event Polling"); [self pauseEventPolling]; - if (eTimerPollingInterval == kMinimumPollingIntervalMillis && [[[LDClient sharedInstance] ldConfig] debugEnabled] == YES) { + if (eTimerPollingInterval == kMinimumFlushIntervalMillis && [[[LDClient sharedInstance] ldConfig] debugEnabled] == YES) { [self eventPoll]; } @@ -68,11 +184,14 @@ - (void) setEventTimerPollingIntervalMillis:(NSTimeInterval)eTimerPollingInterva [self resumeEventPolling]; DEBUG_LOGX(@"resuming event Polling"); } - } -(NSTimeInterval)calculateEventPollingIntervalMillis:(NSTimeInterval)eTimerPollingInterval { - if (eTimerPollingInterval <= kMinimumPollingIntervalMillis) { + LDConfig *config = [[LDClient sharedInstance] ldConfig]; + if (![config streaming] && [[config flushInterval] intValue] == kDefaultFlushInterval) { + return [config.pollingInterval intValue] * kMillisInSecs; + } + if (eTimerPollingInterval <= kMinimumFlushIntervalMillis) { return kDefaultFlushInterval*kMillisInSecs; } else { return eTimerPollingInterval; @@ -83,16 +202,14 @@ -(NSTimeInterval)calculateEventPollingIntervalMillis:(NSTimeInterval)eTimerPolli - (void)startEventPollTimer { DEBUG_LOGX(@"PollingManager starting initial event polling"); - if ((!self.eventTimer) && (self.eventTimerPollingIntervalMillis > 0.0)) { + if ((!self.eventTimer) && (self.eventPollingIntervalMillis > 0.0)) { self.eventTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); } if (self.eventTimer) { - pollEventState = POLL_RUNNING; + eventPollingState = POLL_RUNNING; dispatch_source_set_event_handler(self.eventTimer, ^(void) { - [self eventPoll]; - }); [self updateEventPollingTimer]; @@ -101,7 +218,7 @@ - (void)startEventPollTimer } - (void)eventPoll { - if (pollEventState != POLL_STOPPED || pollEventState != POLL_SUSPENDED) + if (eventPollingState != POLL_STOPPED || eventPollingState != POLL_SUSPENDED) { DEBUG_LOGX(@"PollingManager event interval reached"); eventPollingCount +=1; @@ -112,43 +229,42 @@ - (void)eventPoll { } - (void)updateEventPollingTimer { - if ((self.eventTimer != NULL) && (self.eventTimerPollingIntervalMillis > 0.0)) { - uint64_t interval = (uint64_t)(self.eventTimerPollingIntervalMillis * NSEC_PER_MSEC); + if ((self.eventTimer != NULL) && (self.eventPollingIntervalMillis > 0.0)) { + uint64_t interval = (uint64_t)(self.eventPollingIntervalMillis * NSEC_PER_MSEC); dispatch_time_t startTime = dispatch_time(DISPATCH_TIME_NOW, interval); dispatch_source_set_timer(self.eventTimer, startTime, interval, 1.0); } } - - (void) startEventPolling { - if (pollEventState == POLL_STOPPED) { + if (eventPollingState == POLL_STOPPED) { DEBUG_LOGX(@"PollingManager starting event polling"); [self startEventPollTimer]; } } - (void) pauseEventPolling { - if (pollEventState == POLL_RUNNING) { + if (eventPollingState == POLL_RUNNING) { DEBUG_LOGX(@"PollingManager pausing event polling"); dispatch_suspend(self.eventTimer); - pollEventState = POLL_PAUSED; + eventPollingState = POLL_PAUSED; } } - (void) suspendEventPolling { - if (pollEventState == POLL_RUNNING) { + if (eventPollingState == POLL_RUNNING) { DEBUG_LOGX(@"PollingManager suspending event polling"); dispatch_suspend(self.eventTimer); - pollEventState = POLL_SUSPENDED; + eventPollingState = POLL_SUSPENDED; } } - (void) resumeEventPolling{ - if (pollEventState == POLL_PAUSED || pollEventState == POLL_SUSPENDED) { + if (eventPollingState == POLL_PAUSED || eventPollingState == POLL_SUSPENDED) { DEBUG_LOGX(@"PollingManager resuming event polling"); - BOOL checkEvent = pollEventState == POLL_SUSPENDED ? YES : NO; + BOOL checkEvent = eventPollingState == POLL_SUSPENDED ? YES : NO; dispatch_resume(self.eventTimer); - pollEventState = POLL_RUNNING; + eventPollingState = POLL_RUNNING; if (checkEvent) { [self eventPoll]; } @@ -160,16 +276,16 @@ - (void)stopEventPolling { if (self.eventTimer) { dispatch_source_cancel(self.eventTimer); - if (pollEventState == POLL_PAUSED || pollEventState == POLL_SUSPENDED) + if (eventPollingState == POLL_PAUSED || eventPollingState == POLL_SUSPENDED) { dispatch_resume(self.eventTimer); } #if !OS_OBJECT_USE_OBJC - dispatch_release(self.eventTimer); + dispatch_release(self.pollingTimer); #endif self.eventTimer = NULL; - pollEventState = POLL_STOPPED; + eventPollingState = POLL_STOPPED; } } diff --git a/Darkly/LDRequestManager.h b/Darkly/LDRequestManager.h index 934115cf..5564f199 100644 --- a/Darkly/LDRequestManager.h +++ b/Darkly/LDRequestManager.h @@ -7,7 +7,7 @@ @protocol RequestManagerDelegate -- (void)processedEvents:(BOOL)success jsonEventArray:(NSArray *)jsonEventArray eventIntervalMillis:(int)eventIntervalMillis; +- (void)processedEvents:(BOOL)success jsonEventArray:(NSArray *)jsonEventArray; - (void)processedConfig:(BOOL)success jsonConfigDictionary:(NSDictionary *)jsonConfigDictionary; @end diff --git a/Darkly/LDRequestManager.m b/Darkly/LDRequestManager.m index 5fabe875..091fd8de 100644 --- a/Darkly/LDRequestManager.m +++ b/Darkly/LDRequestManager.m @@ -113,14 +113,8 @@ -(void)performEventRequest:(NSArray *)jsonEventArray NSURLSessionDataTask *dataTask = [defaultSession dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { dispatch_async(dispatch_get_main_queue(), ^{ eventRequestInProgress = NO; - if (!error) { - LDClient *client = [LDClient sharedInstance]; - LDConfig *config = client.ldConfig; - [delegate processedEvents:YES jsonEventArray:jsonEventArray eventIntervalMillis:[config.flushInterval intValue] * kMillisInSecs]; - } - else{ - [delegate processedEvents:NO jsonEventArray:jsonEventArray eventIntervalMillis:kMinimumPollingIntervalMillis]; - } + BOOL processedEvents = !error ? YES : NO; + [delegate processedEvents:processedEvents jsonEventArray:jsonEventArray]; }); }]; diff --git a/Darkly/Models/LDDataManager.m b/Darkly/Models/LDDataManager.m index 07e987a4..ac54152c 100644 --- a/Darkly/Models/LDDataManager.m +++ b/Darkly/Models/LDDataManager.m @@ -161,7 +161,7 @@ -(void) createCustomEvent: (NSString *)eventKey withCustomValuesDictionary: (NSD -(BOOL)isAtEventCapacity:(NSArray *)currentArray { LDConfig *ldConfig = [[LDClient sharedInstance] ldConfig]; - return ldConfig.capacity && currentArray && [NSNumber numberWithInteger:[currentArray count]] >= ldConfig.capacity; + return ldConfig.capacity && currentArray && [currentArray count] >= [ldConfig.capacity integerValue]; } -(void) deleteProcessedEvents: (NSArray *) processedJsonArray { diff --git a/DarklyTests/LDClientManagerTest.m b/DarklyTests/LDClientManagerTest.m index dfeeb951..9c0bb52d 100644 --- a/DarklyTests/LDClientManagerTest.m +++ b/DarklyTests/LDClientManagerTest.m @@ -149,20 +149,18 @@ - (void)testWillEnterForeground { } - (void)testProcessedEventsSuccessWithProcessedEvents { - int eventIntervalMillis = 10; LDEventModel *event = [[LDEventModel alloc] initFeatureEventWithKey:@"blah" keyValue:[NSNumber numberWithBool:NO] defaultKeyValue:[NSNumber numberWithBool:NO] userValue:[[LDClient sharedInstance] ldUser]]; LDClientManager *clientManager = [LDClientManager sharedInstance]; - [clientManager processedEvents:YES jsonEventArray:@[[event dictionaryValue]] eventIntervalMillis:eventIntervalMillis]; + [clientManager processedEvents:YES jsonEventArray:@[[event dictionaryValue]]]; OCMVerify([dataManagerMock deleteProcessedEvents:[OCMArg any]]); } - (void)testProcessedEventsSuccessWithoutProcessedEvents { - int eventIntervalMillis = 10; LDClientManager *clientManager = [LDClientManager sharedInstance]; - [clientManager processedEvents:YES jsonEventArray:@[] eventIntervalMillis:eventIntervalMillis]; + [clientManager processedEvents:YES jsonEventArray:@[]]; [[dataManagerMock reject] deleteProcessedEvents:[OCMArg any]]; @@ -170,10 +168,9 @@ - (void)testProcessedEventsSuccessWithoutProcessedEvents { } - (void)testProcessedEventsFailure { - int eventIntervalMillis = 10; LDClientManager *clientManager = [LDClientManager sharedInstance]; - [clientManager processedEvents:NO jsonEventArray:nil eventIntervalMillis:eventIntervalMillis]; + [clientManager processedEvents:NO jsonEventArray:nil]; [[dataManagerMock reject] deleteProcessedEvents:[OCMArg any]]; diff --git a/DarklyTests/LDClientTest.m b/DarklyTests/LDClientTest.m index 6b54b71c..d8612ad1 100644 --- a/DarklyTests/LDClientTest.m +++ b/DarklyTests/LDClientTest.m @@ -12,7 +12,7 @@ #import -@interface LDClientTest : DarklyXCTestCase +@interface LDClientTest : DarklyXCTestCase @end diff --git a/DarklyTests/LDConfigTest.m b/DarklyTests/LDConfigTest.m index 183f21ca..2c484c41 100644 --- a/DarklyTests/LDConfigTest.m +++ b/DarklyTests/LDConfigTest.m @@ -94,6 +94,39 @@ - (void)testConfigOverrideFlushInterval { XCTAssertFalse([config debugEnabled]); } +- (void)testConfigOverridePollingInterval { + NSString *testMobileKey = @"testMobileKey"; + LDConfigBuilder *builder = [[LDConfigBuilder alloc] init]; + [builder withMobileKey:testMobileKey]; + + LDConfig *config = [builder build]; + XCTAssertEqualObjects([config mobileKey], testMobileKey); + XCTAssertEqualObjects([config pollingInterval], [NSNumber numberWithInt:kDefaultPollingInterval]); + XCTAssertFalse([config debugEnabled]); + + [builder withPollingInterval:5000]; + config = [builder build]; + XCTAssertEqualObjects([config pollingInterval], [NSNumber numberWithInt:5000]); + + [builder withPollingInterval:50]; + config = [builder build]; + XCTAssertEqualObjects([config pollingInterval], [NSNumber numberWithInt:kMinimumPollingInterval]); +} + +- (void)testConfigOverrideStreaming { + NSString *testMobileKey = @"testMobileKey"; + LDConfigBuilder *builder = [[LDConfigBuilder alloc] init]; + [builder withMobileKey:testMobileKey]; + + LDConfig *config = [builder build]; + XCTAssertEqualObjects([config mobileKey], testMobileKey); + XCTAssertTrue([config streaming]); + + [builder withStreaming:NO]; + config = [builder build]; + XCTAssertFalse([config streaming]); +} + - (void)testConfigOverrideDebug { NSString *testMobileKey = @"testMobileKey"; LDConfigBuilder *builder = [[LDConfigBuilder alloc] init]; diff --git a/DarklyTests/LDPollingManagerTest.m b/DarklyTests/LDPollingManagerTest.m index 8a2609de..3e846497 100644 --- a/DarklyTests/LDPollingManagerTest.m +++ b/DarklyTests/LDPollingManagerTest.m @@ -6,6 +6,8 @@ #import "LDPollingManager.h" #import "LDDataManager.h" #import "LDRequestManager.h" +#import "LDConfig.h" +#import "LDClient.h" #import @interface LDPollingManagerTest : DarklyXCTestCase @@ -37,7 +39,7 @@ - (void)tearDown { - (void)testEventPollingStates { // create the expectation with a nice descriptive message LDPollingManager *dnu = [LDPollingManager sharedInstance]; - dnu.eventTimerPollingIntervalMillis = 5000; // for the purposes of the unit tests set it to 5 secs. + dnu.eventPollingIntervalMillis = 5000; // for the purposes of the unit tests set it to 5 secs. [dnu startEventPolling]; NSInteger expectedValue = POLL_RUNNING; @@ -60,4 +62,36 @@ - (void)testEventPollingStates { XCTAssertTrue(actualValue == expectedValue); } +- (void)testPollingInterval { + NSString *testMobileKey = @"testMobileKey"; + LDConfigBuilder *builder = [[LDConfigBuilder alloc] init]; + [builder withMobileKey:testMobileKey]; + LDClient *client = [LDClient sharedInstance]; + LDPollingManager *pollingManager = [LDPollingManager sharedInstance]; + + [client start:builder userBuilder:nil]; + XCTAssertEqual(pollingManager.eventPollingIntervalMillis, kDefaultFlushInterval*kMillisInSecs); + XCTAssertEqual([pollingManager configPollingState], POLL_STOPPED); + [client stopClient]; + + [builder withStreaming:NO]; + [client start:builder userBuilder:nil]; + XCTAssertEqual(pollingManager.eventPollingIntervalMillis, kDefaultPollingInterval*kMillisInSecs); + XCTAssertEqual(pollingManager.configPollingIntervalMillis, kDefaultPollingInterval*kMillisInSecs); + XCTAssertEqual([pollingManager configPollingState], POLL_RUNNING); + [client stopClient]; + + [builder withPollingInterval:50]; + [client start:builder userBuilder:nil]; + XCTAssertEqual(pollingManager.eventPollingIntervalMillis, kMinimumPollingInterval*kMillisInSecs); + XCTAssertEqual(pollingManager.configPollingIntervalMillis, kMinimumPollingInterval*kMillisInSecs); + [client stopClient]; + + [builder withFlushInterval:50]; + [client start:builder userBuilder:nil]; + XCTAssertEqual(pollingManager.eventPollingIntervalMillis, 50*kMillisInSecs); + XCTAssertEqual(pollingManager.configPollingIntervalMillis, kMinimumPollingInterval*kMillisInSecs); + [client stopClient]; +} + @end diff --git a/LaunchDarkly.podspec b/LaunchDarkly.podspec index ab3e9246..3db571ac 100644 --- a/LaunchDarkly.podspec +++ b/LaunchDarkly.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| # s.name = "LaunchDarkly" - s.version = "2.1.3" + s.version = "2.2.0" s.summary = "iOS SDK for LaunchDarkly" s.description = <<-DESC @@ -74,7 +74,7 @@ Pod::Spec.new do |s| # Supports git, hg, bzr, svn and HTTP. # - s.source = { :git => "https://github.com/launchdarkly/ios-client.git", :tag => "2.1.3" } + s.source = { :git => "https://github.com/launchdarkly/ios-client.git", :tag => "2.2.0" } # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #