@@ -36,6 +36,9 @@ open class DefaultDatafileHandler: OPTDatafileHandler {
36
36
37
37
// and our download queue to speed things up.
38
38
let downloadQueue = DispatchQueue ( label: " DefaultDatafileHandlerQueue " )
39
+
40
+ // network reachability
41
+ let reachability = NetworkReachability ( maxContiguousFails: 1 )
39
42
40
43
public required init ( ) { }
41
44
@@ -47,45 +50,59 @@ open class DefaultDatafileHandler: OPTDatafileHandler {
47
50
completionHandler: @escaping DatafileDownloadCompletionHandler ) {
48
51
49
52
downloadQueue. async {
53
+
54
+ func returnCached( _ result: OptimizelyResult < Data ? > ? = nil ) -> OptimizelyResult < Data ? > {
55
+ if let data = self . loadSavedDatafile ( sdkKey: sdkKey) {
56
+ return . success( data)
57
+ } else {
58
+ return result ?? . failure( . datafileLoadingFailed( sdkKey) )
59
+ }
60
+ }
61
+
62
+ if self . reachability. shouldBlockNetworkAccess ( ) {
63
+ let optError = OptimizelyError . datafileDownloadFailed ( " NetworkReachability down " )
64
+ self . logger. e ( optError)
65
+
66
+ let result = OptimizelyResult< Data?> . failure( optError)
67
+ completionHandler ( returnCached ( result) )
68
+ return
69
+ }
70
+
50
71
let session = self . getSession ( resourceTimeoutInterval: resourceTimeoutInterval)
51
72
52
73
guard let request = self . getRequest ( sdkKey: sdkKey) else { return }
53
74
54
75
let task = session. downloadTask ( with: request) { ( url, response, error) in
55
- var result = OptimizelyResult< Data?> . failure( . datafileLoadingFailed( sdkKey) )
56
-
57
- let returnCached = {
58
- if let data = self . loadSavedDatafile ( sdkKey: sdkKey) {
59
- result = . success( data)
60
- }
61
- }
76
+ var result = OptimizelyResult< Data?> . failure( . generic)
62
77
63
78
if error != nil {
64
- self . logger . e ( error. debugDescription)
65
- result = . failure ( . datafileDownloadFailed ( error . debugDescription ) )
66
- returnCached ( ) // error recovery
79
+ let optError = OptimizelyError . datafileDownloadFailed ( error. debugDescription)
80
+ self . logger . e ( optError )
81
+ result = returnCached ( . failure ( optError ) ) // error recovery
67
82
} else if let response = response as? HTTPURLResponse {
68
83
switch response. statusCode {
69
84
case 200 :
70
85
if let data = self . getResponseData ( sdkKey: sdkKey, response: response, url: url) {
71
86
result = . success( data)
72
87
} else {
73
- returnCached ( ) // error recovery
88
+ result = returnCached ( ) // error recovery
74
89
}
75
90
case 304 :
76
91
self . logger. d ( " The datafile was not modified and won't be downloaded again " )
77
92
78
93
if returnCacheIfNoChange {
79
- returnCached ( )
94
+ result = returnCached ( )
80
95
} else {
81
96
result = . success( nil )
82
97
}
83
98
default :
84
99
self . logger. i ( " got response code \( response. statusCode) " )
85
- returnCached ( ) // error recovery
100
+ result = returnCached ( ) // error recovery
86
101
}
87
102
}
88
103
104
+ self . reachability. updateNumContiguousFails ( isError: ( error != nil ) )
105
+
89
106
completionHandler ( result)
90
107
}
91
108
@@ -244,6 +261,24 @@ extension DefaultDatafileHandler {
244
261
updateInterval: Int ,
245
262
datafileChangeNotification: ( ( Data ) -> Void ) ? ) {
246
263
let beginDownloading = Date ( )
264
+
265
+ let scheduleNextUpdate : ( ) -> Void = {
266
+ guard self . hasPeriodicInterval ( sdkKey: sdkKey) else { return }
267
+
268
+ // adjust the next fire time so that events will be fired at fixed interval regardless of the download latency
269
+ // if latency is too big (or returning from background mode), fire the next event immediately once
270
+
271
+ var interval = self . timers. property ? [ sdkKey] ? . interval ?? updateInterval
272
+ let delay = Int ( Date ( ) . timeIntervalSince ( beginDownloading) )
273
+ interval -= delay
274
+ if interval < 0 {
275
+ interval = 0
276
+ }
277
+
278
+ self . logger. d ( " next datafile download is \( interval) seconds \( Date ( ) ) " )
279
+ self . startPeriodicUpdates ( sdkKey: sdkKey, updateInterval: interval, datafileChangeNotification: datafileChangeNotification)
280
+ }
281
+
247
282
self . downloadDatafile ( sdkKey: sdkKey) { ( result) in
248
283
switch result {
249
284
case . success( let data) :
@@ -255,20 +290,7 @@ extension DefaultDatafileHandler {
255
290
self . logger. e ( error. reason)
256
291
}
257
292
258
- if self . hasPeriodicInterval ( sdkKey: sdkKey) {
259
- // adjust the next fire time so that events will be fired at fixed interval regardless of the download latency
260
- // if latency is too big (or returning from background mode), fire the next event immediately once
261
-
262
- var interval = self . timers. property ? [ sdkKey] ? . interval ?? updateInterval
263
- let delay = Int ( Date ( ) . timeIntervalSince ( beginDownloading) )
264
- interval -= delay
265
- if interval < 0 {
266
- interval = 0
267
- }
268
-
269
- self . logger. d ( " next datafile download is \( interval) seconds \( Date ( ) ) " )
270
- self . startPeriodicUpdates ( sdkKey: sdkKey, updateInterval: interval, datafileChangeNotification: datafileChangeNotification)
271
- }
293
+ scheduleNextUpdate ( )
272
294
}
273
295
}
274
296
0 commit comments