Skip to content

Commit e0cb996

Browse files
authored
Merge pull request #159 from optimizely/datafileIntevalFix
(fix) fix datafile download interval. was incorrect.
2 parents f28b374 + bb4aa1b commit e0cb996

File tree

4 files changed

+59
-71
lines changed

4 files changed

+59
-71
lines changed

OptimizelySDK/Extensions/Date+Extension.swift

Lines changed: 0 additions & 26 deletions
This file was deleted.

OptimizelySDK/Implementation/DefaultDatafileHandler.swift

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import Foundation
1919
class DefaultDatafileHandler : OPTDatafileHandler {
2020
static public var endPointStringFormat = "https://cdn.optimizely.com/datafiles/%@.json"
2121
lazy var logger = HandlerRegistryService.shared.injectLogger()
22-
var timers:AtomicProperty<[String:Timer]> = AtomicProperty(property: [String:Timer]())
22+
var timers:AtomicProperty<[String:(timer:Timer, interval:Int)]> = AtomicProperty(property: [String:(Timer,Int)]())
2323
let dataStore = DataStoreUserDefaults()
2424

2525
required init() {
@@ -95,7 +95,7 @@ class DefaultDatafileHandler : OPTDatafileHandler {
9595

9696
completionHandler(result)
9797

98-
self.logger?.log(level: .debug, message: response.debugDescription)
98+
// self.logger?.log(level: .debug, message: response.debugDescription)
9999

100100
}
101101

@@ -109,7 +109,7 @@ class DefaultDatafileHandler : OPTDatafileHandler {
109109
let now = Date()
110110
if #available(iOS 10.0, tvOS 10.0, *) {
111111
DispatchQueue.main.async {
112-
if let timer = self.timers.property?[sdkKey], timer.isValid {
112+
if let timer = self.timers.property?[sdkKey]?.timer, timer.isValid {
113113
return
114114
}
115115

@@ -123,20 +123,30 @@ class DefaultDatafileHandler : OPTDatafileHandler {
123123
timer.invalidate()
124124
}
125125
self.timers.performAtomic(atomicOperation: { (timers) in
126-
timers[sdkKey] = timer
126+
if let interval = timers[sdkKey]?.interval {
127+
timers[sdkKey] = (timer,interval)
128+
}
129+
else {
130+
timers[sdkKey] = (timer,updateInterval)
131+
}
127132
})
128133
}
129134
} else {
130135
// Fallback on earlier versions
131136
DispatchQueue.main.async {
132-
if let timer = self.timers.property?[sdkKey], timer.isValid {
137+
if let timer = self.timers.property?[sdkKey]?.timer, timer.isValid {
133138
return
134139
}
135140

136-
let timer = Timer.scheduledTimer(timeInterval: TimeInterval(updateInterval), target: self, selector:#selector(self.timerFired(timer:)), userInfo: ["sdkKey": sdkKey, "startTime": Date(), "updateInterval":updateInterval, "datafileChangeNotification":datafileChangeNotification ?? { (data) in }], repeats: false)
141+
let timer = Timer.scheduledTimer(timeInterval: TimeInterval(updateInterval), target: self, selector:#selector(self.timerFired(timer:)), userInfo: ["sdkKey": sdkKey, "startTime": Date(), "updateInterval": updateInterval, "datafileChangeNotification":datafileChangeNotification ?? { (data) in }], repeats: false)
137142

138143
self.timers.performAtomic(atomicOperation: { (timers) in
139-
timers[sdkKey] = timer
144+
if let interval = timers[sdkKey]?.interval {
145+
timers[sdkKey] = (timer,interval)
146+
}
147+
else {
148+
timers[sdkKey] = (timer,updateInterval)
149+
}
140150
})
141151
}
142152

@@ -148,7 +158,7 @@ class DefaultDatafileHandler : OPTDatafileHandler {
148158
if let info = timer.userInfo as? [String:Any],
149159
let sdkKey = info["sdkKey"] as? String,
150160
let updateInterval = info["updateInterval"] as? Int,
151-
let startDate = info["startDate"] as? Date,
161+
let startDate = info["startTime"] as? Date,
152162
let datafileChangeNotification = info["datafileChangeNotification"] as? ((Data)->Void){
153163
self.performPerodicDownload(sdkKey: sdkKey, startTime: startDate, updateInterval: updateInterval, datafileChangeNotification: datafileChangeNotification)
154164
}
@@ -183,12 +193,15 @@ class DefaultDatafileHandler : OPTDatafileHandler {
183193
}
184194

185195
if self.hasPeriodUpdates(sdkKey: sdkKey) {
186-
let minutesSinceFire = startTime.minutesPastSinceNow()
187-
var diff = updateInterval - minutesSinceFire
188-
if diff < 0 {
189-
diff = 0
196+
let interval = self.timers.property?[sdkKey]?.interval ?? updateInterval
197+
let actualDiff = (Int(abs(startTime.timeIntervalSinceNow)) - updateInterval)
198+
var nextInterval = interval
199+
if actualDiff > 0 {
200+
nextInterval -= actualDiff
190201
}
191-
self.startPeriodicUpdates(sdkKey: sdkKey, updateInterval: diff, datafileChangeNotification: datafileChangeNotification)
202+
203+
self.logger?.d("next datafile download is \(nextInterval) seconds \(Date())")
204+
self.startPeriodicUpdates(sdkKey: sdkKey, updateInterval: nextInterval, datafileChangeNotification: datafileChangeNotification)
192205
}
193206
}
194207
}
@@ -198,19 +211,17 @@ class DefaultDatafileHandler : OPTDatafileHandler {
198211
if let timer = timers[sdkKey] {
199212
logger?.log(level: .info, message: "Stopping timer for datafile updates sdkKey: \(sdkKey)")
200213

201-
timer.invalidate()
214+
timer.timer.invalidate()
202215
timers.removeValue(forKey: sdkKey)
203216
}
204217

205218
}
206219
}
207220

208221
func stopPeriodicUpdates() {
209-
timers.performAtomic { (timers) in
210-
for key in timers.keys {
211-
logger?.log(level: .info, message: "Stopping timer for all datafile updates")
212-
stopPeriodicUpdates(sdkKey: key)
213-
}
222+
for key in timers.property?.keys ?? Dictionary<String, (timer: Timer, interval: Int)>().keys {
223+
logger?.log(level: .info, message: "Stopping timer for all datafile updates")
224+
stopPeriodicUpdates(sdkKey: key)
214225
}
215226

216227
}

OptimizelySDK/OptimizelySwiftSDK.xcodeproj/project.pbxproj

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -61,18 +61,6 @@
6161
0B4E11FD21EE90F600D5B370 /* DataStoreUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B4E11FB21EE90F600D5B370 /* DataStoreUserDefaults.swift */; };
6262
0B626D612242B98E00E4F7DA /* NotificationCenterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B626D602242B98D00E4F7DA /* NotificationCenterTests.swift */; };
6363
0B626D622242B98E00E4F7DA /* NotificationCenterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B626D602242B98D00E4F7DA /* NotificationCenterTests.swift */; };
64-
0B74A22E226E23EE007C873C /* Date+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B74A22D226E23EE007C873C /* Date+Extension.swift */; };
65-
0B74A22F226E23EE007C873C /* Date+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B74A22D226E23EE007C873C /* Date+Extension.swift */; };
66-
0B74A230226E23EE007C873C /* Date+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B74A22D226E23EE007C873C /* Date+Extension.swift */; };
67-
0B74A231226E23EE007C873C /* Date+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B74A22D226E23EE007C873C /* Date+Extension.swift */; };
68-
0B74A232226E23EE007C873C /* Date+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B74A22D226E23EE007C873C /* Date+Extension.swift */; };
69-
0B74A233226E23EE007C873C /* Date+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B74A22D226E23EE007C873C /* Date+Extension.swift */; };
70-
0B74A234226E23EE007C873C /* Date+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B74A22D226E23EE007C873C /* Date+Extension.swift */; };
71-
0B74A235226E23EE007C873C /* Date+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B74A22D226E23EE007C873C /* Date+Extension.swift */; };
72-
0B74A236226E23EE007C873C /* Date+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B74A22D226E23EE007C873C /* Date+Extension.swift */; };
73-
0B74A237226E23EE007C873C /* Date+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B74A22D226E23EE007C873C /* Date+Extension.swift */; };
74-
0B74A238226E23EE007C873C /* Date+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B74A22D226E23EE007C873C /* Date+Extension.swift */; };
75-
0B74A239226E23EE007C873C /* Date+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B74A22D226E23EE007C873C /* Date+Extension.swift */; };
7664
0B77D04022331D1E005AA83F /* OptimizelyManager+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B77D03F22331D1E005AA83F /* OptimizelyManager+Extension.swift */; };
7765
0B77D04122331E0D005AA83F /* OptimizelyManager+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B77D03F22331D1E005AA83F /* OptimizelyManager+Extension.swift */; };
7866
0B77D04222331E0E005AA83F /* OptimizelyManager+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B77D03F22331D1E005AA83F /* OptimizelyManager+Extension.swift */; };
@@ -1217,7 +1205,6 @@
12171205
0B61625C21B8B82A000D7A28 /* JSONParse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONParse.swift; sourceTree = "<group>"; };
12181206
0B61625E21B8C3A9000D7A28 /* DefaultLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultLogger.swift; sourceTree = "<group>"; };
12191207
0B626D602242B98D00E4F7DA /* NotificationCenterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationCenterTests.swift; sourceTree = "<group>"; };
1220-
0B74A22D226E23EE007C873C /* Date+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+Extension.swift"; sourceTree = "<group>"; };
12211208
0B77D03F22331D1E005AA83F /* OptimizelyManager+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OptimizelyManager+Extension.swift"; sourceTree = "<group>"; };
12221209
0B77D05722370526005AA83F /* BackgroundingCallbacks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BackgroundingCallbacks.swift; sourceTree = "<group>"; };
12231210
0B7B18842231D8B800A1F85D /* DataStoreMemory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataStoreMemory.swift; sourceTree = "<group>"; };
@@ -1537,7 +1524,6 @@
15371524
0BC48EA422038491003AFD71 /* ArrayEventForDispatch+Extension.swift */,
15381525
6EA4264E22191EEC00B074B5 /* Array+Extension.swift */,
15391526
0B77D03F22331D1E005AA83F /* OptimizelyManager+Extension.swift */,
1540-
0B74A22D226E23EE007C873C /* Date+Extension.swift */,
15411527
);
15421528
path = Extensions;
15431529
sourceTree = "<group>";
@@ -2608,7 +2594,6 @@
26082594
6E4DD87D21E5251800B0C2C7 /* FeatureVariable.swift in Sources */,
26092595
6E4DD87A21E5251800B0C2C7 /* Variation.swift in Sources */,
26102596
6E4DD85B21E5250200B0C2C7 /* OPTErrorHandler.swift in Sources */,
2611-
0B74A22F226E23EE007C873C /* Date+Extension.swift in Sources */,
26122597
6E4DD85921E5250200B0C2C7 /* OPTBucketer.swift in Sources */,
26132598
6E4DD86521E5250B00B0C2C7 /* EventForDispatch.swift in Sources */,
26142599
0B7B18862231D8B800A1F85D /* DataStoreMemory.swift in Sources */,
@@ -2674,7 +2659,6 @@
26742659
0B7B9EC621F51AF700056589 /* DataStoreFile.swift in Sources */,
26752660
6E4DD8B321E5260700B0C2C7 /* OPTNotificationCenter.swift in Sources */,
26762661
6E7C0B7721F1372600ECFF34 /* OptimizelyLogLevel.swift in Sources */,
2677-
0B74A236226E23EE007C873C /* Date+Extension.swift in Sources */,
26782662
6E4DD8D621E5274300B0C2C7 /* UserAttribute.swift in Sources */,
26792663
6E4DD8D821E5274600B0C2C7 /* ConditionHolder.swift in Sources */,
26802664
6E4DD88821E525F600B0C2C7 /* BatchEventBuilder.swift in Sources */,
@@ -2745,7 +2729,6 @@
27452729
6E636BDC2236C9B100AF3CEF /* EventForDispatch.swift in Sources */,
27462730
6EF4B4E5223836C1002DE8B6 /* BackgroundingCallbacks.swift in Sources */,
27472731
6E636C042236C9C500AF3CEF /* ArrayEventForDispatch+Extension.swift in Sources */,
2748-
0B74A232226E23EE007C873C /* Date+Extension.swift in Sources */,
27492732
6E636BBD2236C99300AF3CEF /* DataStoreMemory.swift in Sources */,
27502733
6E636BF42236C9BC00AF3CEF /* FeatureVariable.swift in Sources */,
27512734
6EA0721F223AC72D00F447CF /* Utils.swift in Sources */,
@@ -2819,7 +2802,6 @@
28192802
6E636BDE2236C9B200AF3CEF /* EventForDispatch.swift in Sources */,
28202803
6E636C092236C9C500AF3CEF /* ArrayEventForDispatch+Extension.swift in Sources */,
28212804
6E636BC12236C99400AF3CEF /* DataStoreMemory.swift in Sources */,
2822-
0B74A235226E23EE007C873C /* Date+Extension.swift in Sources */,
28232805
6E636C002236C9BD00AF3CEF /* FeatureVariable.swift in Sources */,
28242806
6E636C102236C9CB00AF3CEF /* MurmurHash3.swift in Sources */,
28252807
6E636BB12236C98400AF3CEF /* DefaultLogger.swift in Sources */,
@@ -2861,7 +2843,6 @@
28612843
6EA425312218E4A300B074B5 /* DefaultNotificationCenter.swift in Sources */,
28622844
6EA425472218E4A300B074B5 /* FeatureVariable.swift in Sources */,
28632845
6EA425222218E46C00B074B5 /* OptimizelyManager.swift in Sources */,
2864-
0B74A237226E23EE007C873C /* Date+Extension.swift in Sources */,
28652846
6E0AFBC42257C49800BC7665 /* BucketTests_Others.swift in Sources */,
28662847
6EA425482218E4A300B074B5 /* TrafficAllocation.swift in Sources */,
28672848
6EA425502218E4A300B074B5 /* DataStoreQueueStackImpl+Extension.swift in Sources */,
@@ -2997,7 +2978,6 @@
29972978
6EA4261B2218E74F00B074B5 /* DefaultUserProfileService.swift in Sources */,
29982979
6EA4261C2218E74F00B074B5 /* OPTLogger.swift in Sources */,
29992980
6EA4263F2218E74F00B074B5 /* Experiment.swift in Sources */,
3000-
0B74A238226E23EE007C873C /* Date+Extension.swift in Sources */,
30012981
6EA426322218E74F00B074B5 /* ConditionHolder.swift in Sources */,
30022982
6EA425A82218E6AE00B074B5 /* EventTests.swift in Sources */,
30032983
6EA426382218E74F00B074B5 /* Attribute.swift in Sources */,
@@ -3039,7 +3019,6 @@
30393019
6EA425DC2218E74D00B074B5 /* ArrayEventForDispatch+Extension.swift in Sources */,
30403020
6EA425CC2218E74D00B074B5 /* UserAttribute.swift in Sources */,
30413021
6E24C4B72257F5E600DF3D71 /* BatchEventBuilderTests_Events.swift in Sources */,
3042-
0B74A231226E23EE007C873C /* Date+Extension.swift in Sources */,
30433022
6EA425D72218E74D00B074B5 /* Experiment.swift in Sources */,
30443023
6EA425C52218E74D00B074B5 /* DataStoreQueueStack.swift in Sources */,
30453024
6EA425D62218E74D00B074B5 /* FeatureFlag.swift in Sources */,
@@ -3175,7 +3154,6 @@
31753154
6EA425E72218E74E00B074B5 /* DefaultUserProfileService.swift in Sources */,
31763155
6EA425E82218E74E00B074B5 /* OPTLogger.swift in Sources */,
31773156
6EA4260B2218E74E00B074B5 /* Experiment.swift in Sources */,
3178-
0B74A233226E23EE007C873C /* Date+Extension.swift in Sources */,
31793157
6EA425FE2218E74E00B074B5 /* ConditionHolder.swift in Sources */,
31803158
6EA425992218E6AD00B074B5 /* EventTests.swift in Sources */,
31813159
6EA426042218E74E00B074B5 /* Attribute.swift in Sources */,
@@ -3230,7 +3208,6 @@
32303208
6EA42687221925B100B074B5 /* Audience.swift in Sources */,
32313209
6EA426CC221925DE00B074B5 /* OptimizelyResult.swift in Sources */,
32323210
6EDE920E22273EE500840112 /* OTUtils.swift in Sources */,
3233-
0B74A234226E23EE007C873C /* Date+Extension.swift in Sources */,
32343211
6EA426D1221925DE00B074B5 /* DefaultUserProfileService.swift in Sources */,
32353212
6EA426B2221925BB00B074B5 /* OPTDataStore.swift in Sources */,
32363213
6EA42692221925B100B074B5 /* Event.swift in Sources */,
@@ -3299,7 +3276,6 @@
32993276
6EA4269A221925B300B074B5 /* Audience.swift in Sources */,
33003277
6EA426D6221925DF00B074B5 /* OptimizelyResult.swift in Sources */,
33013278
6EDE920F22273EE600840112 /* OTUtils.swift in Sources */,
3302-
0B74A239226E23EE007C873C /* Date+Extension.swift in Sources */,
33033279
6EA426DB221925DF00B074B5 /* DefaultUserProfileService.swift in Sources */,
33043280
6EA426BA221925BC00B074B5 /* OPTDataStore.swift in Sources */,
33053281
6EA426A5221925B300B074B5 /* Event.swift in Sources */,
@@ -3386,7 +3362,6 @@
33863362
6E4DD84E21E5250200B0C2C7 /* OPTBucketer.swift in Sources */,
33873363
6E4DD86321E5250B00B0C2C7 /* EventForDispatch.swift in Sources */,
33883364
0BC48EA32203764E003AFD71 /* DataStoreQueueStackImpl+Extension.swift in Sources */,
3389-
0B74A22E226E23EE007C873C /* Date+Extension.swift in Sources */,
33903365
0BE644ED223821D3009A5D1D /* AtomicProperty.swift in Sources */,
33913366
6E4DD84721E524FB00B0C2C7 /* MurmurHash3.swift in Sources */,
33923367
);
@@ -3450,7 +3425,6 @@
34503425
6E4DD8A321E5260600B0C2C7 /* OPTDecisionService.swift in Sources */,
34513426
6E4DD88A21E525FC00B0C2C7 /* DefaultNotificationCenter.swift in Sources */,
34523427
6E4DD8AA21E5260600B0C2C7 /* JSONParse.swift in Sources */,
3453-
0B74A230226E23EE007C873C /* Date+Extension.swift in Sources */,
34543428
6E4DD89C21E5260100B0C2C7 /* Result.swift in Sources */,
34553429
6E4DD89021E525FC00B0C2C7 /* DefaultDatafileHandler.swift in Sources */,
34563430
0B05901A2209DC180007F4A2 /* HandlerRegistryService.swift in Sources */,

OptimizelySDK/OptimizelyTests/OptimizelyTests-Common/DatafileHandlerTests.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,35 @@ class DatafileHandlerTests: XCTestCase {
6565
// This is an example of a functional test case.
6666
// Use XCTAssert and related functions to verify your tests produce the correct results.
6767
}
68+
69+
func testPeriodicDownload() {
70+
class FakeDatafileHandler : DefaultDatafileHandler {
71+
let data = Data()
72+
override func downloadDatafile(sdkKey: String, resourceTimeoutInterval: Double?, completionHandler: @escaping DatafileDownloadCompletionHandler) {
73+
completionHandler(.success(data))
74+
}
75+
}
76+
let expection = XCTestExpectation(description: "Expect 10 periodic downloads")
77+
let handler = FakeDatafileHandler()
78+
let now = Date()
79+
var count = 0;
80+
var seconds = 0
81+
handler.startPeriodicUpdates(sdkKey: "notrealkey", updateInterval: 1) { (data) in
82+
count += 1
83+
if count == 10 {
84+
handler.stopPeriodicUpdates()
85+
expection.fulfill()
86+
seconds = Int(abs(now.timeIntervalSinceNow))
87+
}
88+
}
89+
90+
wait(for: [expection], timeout: 20)
91+
92+
XCTAssert(count == 10)
93+
XCTAssert(seconds == 10)
94+
95+
96+
}
6897

6998
func testPerformanceExample() {
7099
// This is an example of a performance test case.

0 commit comments

Comments
 (0)