Skip to content

Commit d9e6d6c

Browse files
Health monitor is also asynchronous now
1 parent 356a847 commit d9e6d6c

File tree

5 files changed

+130
-99
lines changed

5 files changed

+130
-99
lines changed

swift-sdk/Internal/HealthMonitor.swift

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import Foundation
66

77
protocol HealthMonitorDataProviderProtocol {
88
var maxTasks: Int { get }
9-
func countTasks() throws -> Int
9+
func countTasks() throws -> Pending<Int, IterableTaskError>
1010
}
1111

1212
struct HealthMonitorDataProvider: HealthMonitorDataProviderProtocol {
@@ -18,11 +18,18 @@ struct HealthMonitorDataProvider: HealthMonitorDataProviderProtocol {
1818

1919
let maxTasks: Int
2020

21-
func countTasks() throws -> Int {
21+
func countTasks() throws -> Pending<Int, IterableTaskError> {
22+
let result = Fulfill<Int, IterableTaskError>()
2223
let context = persistenceContextProvider.newBackgroundContext()
23-
return try context.performAndWait {
24-
try context.countTasks()
24+
context.perform {
25+
do {
26+
let count = try context.countTasks()
27+
result.resolve(with: count)
28+
} catch let error {
29+
result.reject(with: IterableTaskError.general(error.localizedDescription))
30+
}
2531
}
32+
return result
2633
}
2734

2835
private let persistenceContextProvider: IterablePersistenceContextProvider
@@ -48,23 +55,35 @@ class HealthMonitor {
4855

4956
weak var delegate: HealthMonitorDelegate?
5057

51-
func canSchedule() -> Bool {
58+
func canSchedule() -> Pending<Bool, Never> {
5259
ITBInfo()
5360
// do not schedule further on error
5461
guard errored == false else {
55-
return false
62+
return Fulfill<Bool, Never>(value: false)
5663
}
5764

65+
let fulfill = Fulfill<Bool, Never>()
5866
do {
59-
let count = try dataProvider.countTasks()
60-
return count < dataProvider.maxTasks
67+
try dataProvider.countTasks().onCompletion { count in
68+
if count < self.dataProvider.maxTasks {
69+
fulfill.resolve(with: true)
70+
} else {
71+
fulfill.resolve(with: false)
72+
}
73+
} receiveError: { error in
74+
ITBError("DBError: " + error.localizedDescription)
75+
self.onError()
76+
fulfill.resolve(with: false)
77+
}
6178
} catch let error {
6279
ITBError("DBError: " + error.localizedDescription)
6380
onError()
64-
return false
81+
fulfill.resolve(with: false)
6582
}
83+
84+
return fulfill
6685
}
67-
86+
6887
func canProcess() -> Bool {
6988
ITBInfo()
7089
return !errored

swift-sdk/Internal/IterableTaskRunner.swift

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ class IterableTaskRunner: NSObject {
1515
dateProvider: DateProviderProtocol = SystemDateProvider()) {
1616
ITBInfo()
1717
self.networkSession = networkSession
18-
self.persistenceContextProvider = persistenceContextProvider
1918
self.healthMonitor = healthMonitor
2019
self.notificationCenter = notificationCenter
2120
self.timeInterval = timeInterval
2221
self.dateProvider = dateProvider
2322
self.connectivityManager = connectivityManager
23+
self.persistenceContext = persistenceContextProvider.newBackgroundContext()
2424

2525
super.init()
2626

@@ -299,15 +299,12 @@ class IterableTaskRunner: NSObject {
299299
private var workItem: DispatchWorkItem?
300300
private var paused = false
301301
private let networkSession: NetworkSessionProtocol
302-
private let persistenceContextProvider: IterablePersistenceContextProvider
303302
private let healthMonitor: HealthMonitor
304303
private let notificationCenter: NotificationCenterProtocol
305304
private let timeInterval: TimeInterval
306305
private let dateProvider: DateProviderProtocol
307306
private let connectivityManager: NetworkConnectivityManager
308307
private var running = false
309-
310-
private lazy var persistenceContext: IterablePersistenceContext = {
311-
return persistenceContextProvider.newBackgroundContext()
312-
}()
308+
309+
private let persistenceContext: IterablePersistenceContext
313310
}

swift-sdk/Internal/Pending.swift

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -165,16 +165,23 @@ extension Pending {
165165
}
166166
}
167167

168-
extension Pending {
169-
static func inBackgroundThread<Value, Failure>(_ block: @escaping () -> Pending<Value, Failure>) -> Pending<Value, Failure> {
170-
let fulfill = Fulfill<Void, Failure>()
171-
DispatchQueue.global(qos: .background).async {
172-
fulfill.resolve(with: ())
173-
}
168+
extension Pending where Failure == Never {
169+
func flatMap<NewValue, NewFailure>(_ closure: @escaping (Value) -> Pending<NewValue, NewFailure>) -> Pending<NewValue, NewFailure> {
170+
let fulfill = Fulfill<NewValue, NewFailure>()
171+
172+
onSuccess { value in
173+
let pending = closure(value)
174+
175+
pending.onSuccess { futureValue in
176+
fulfill.resolve(with: futureValue)
177+
}
174178

175-
return fulfill.flatMap { _ in
176-
block()
179+
pending.onError { futureError in
180+
fulfill.reject(with: futureError)
181+
}
177182
}
183+
184+
return fulfill
178185
}
179186
}
180187

swift-sdk/Internal/RequestHandler.swift

Lines changed: 79 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,10 @@ class RequestHandler: RequestHandlerProtocol {
8989
func updateCart(items: [CommerceItem],
9090
onSuccess: OnSuccessHandler?,
9191
onFailure: OnFailureHandler?) -> Pending<SendRequestValue, SendRequestError> {
92-
Pending<SendRequestValue, SendRequestError>.inBackgroundThread {
93-
self.chooseRequestProcessor().updateCart(items: items,
94-
onSuccess: onSuccess,
95-
onFailure: onFailure)
92+
sendUsingRequestProcessor { processor in
93+
processor.updateCart(items: items,
94+
onSuccess: onSuccess,
95+
onFailure: onFailure)
9696
}
9797
}
9898

@@ -104,14 +104,14 @@ class RequestHandler: RequestHandlerProtocol {
104104
templateId: NSNumber?,
105105
onSuccess: OnSuccessHandler?,
106106
onFailure: OnFailureHandler?) -> Pending<SendRequestValue, SendRequestError> {
107-
Pending<SendRequestValue, SendRequestError>.inBackgroundThread {
108-
self.chooseRequestProcessor().trackPurchase(total,
109-
items: items,
110-
dataFields: dataFields,
111-
campaignId: campaignId,
112-
templateId: templateId,
113-
onSuccess: onSuccess,
114-
onFailure: onFailure)
107+
sendUsingRequestProcessor { processor in
108+
processor.trackPurchase(total,
109+
items: items,
110+
dataFields: dataFields,
111+
campaignId: campaignId,
112+
templateId: templateId,
113+
onSuccess: onSuccess,
114+
onFailure: onFailure)
115115
}
116116
}
117117

@@ -123,14 +123,14 @@ class RequestHandler: RequestHandlerProtocol {
123123
dataFields: [AnyHashable: Any]?,
124124
onSuccess: OnSuccessHandler?,
125125
onFailure: OnFailureHandler?) -> Pending<SendRequestValue, SendRequestError> {
126-
Pending<SendRequestValue, SendRequestError>.inBackgroundThread {
127-
self.chooseRequestProcessor().trackPushOpen(campaignId,
128-
templateId: templateId,
129-
messageId: messageId,
130-
appAlreadyRunning: appAlreadyRunning,
131-
dataFields: dataFields,
132-
onSuccess: onSuccess,
133-
onFailure: onFailure)
126+
sendUsingRequestProcessor { processor in
127+
processor.trackPushOpen(campaignId,
128+
templateId: templateId,
129+
messageId: messageId,
130+
appAlreadyRunning: appAlreadyRunning,
131+
dataFields: dataFields,
132+
onSuccess: onSuccess,
133+
onFailure: onFailure)
134134
}
135135
}
136136

@@ -139,11 +139,11 @@ class RequestHandler: RequestHandlerProtocol {
139139
dataFields: [AnyHashable: Any]?,
140140
onSuccess: OnSuccessHandler?,
141141
onFailure: OnFailureHandler?) -> Pending<SendRequestValue, SendRequestError> {
142-
Pending<SendRequestValue, SendRequestError>.inBackgroundThread {
143-
self.chooseRequestProcessor().track(event: event,
144-
dataFields: dataFields,
145-
onSuccess: onSuccess,
146-
onFailure: onFailure)
142+
sendUsingRequestProcessor { processor in
143+
processor.track(event: event,
144+
dataFields: dataFields,
145+
onSuccess: onSuccess,
146+
onFailure: onFailure)
147147
}
148148
}
149149

@@ -162,12 +162,12 @@ class RequestHandler: RequestHandlerProtocol {
162162
inboxSessionId: String?,
163163
onSuccess: OnSuccessHandler?,
164164
onFailure: OnFailureHandler?) -> Pending<SendRequestValue, SendRequestError> {
165-
Pending<SendRequestValue, SendRequestError>.inBackgroundThread {
166-
self.chooseRequestProcessor().trackInAppOpen(message,
167-
location: location,
168-
inboxSessionId: inboxSessionId,
169-
onSuccess: onSuccess,
170-
onFailure: onFailure)
165+
sendUsingRequestProcessor { processor in
166+
processor.trackInAppOpen(message,
167+
location: location,
168+
inboxSessionId: inboxSessionId,
169+
onSuccess: onSuccess,
170+
onFailure: onFailure)
171171
}
172172
}
173173

@@ -178,13 +178,13 @@ class RequestHandler: RequestHandlerProtocol {
178178
clickedUrl: String,
179179
onSuccess: OnSuccessHandler?,
180180
onFailure: OnFailureHandler?) -> Pending<SendRequestValue, SendRequestError> {
181-
Pending<SendRequestValue, SendRequestError>.inBackgroundThread {
182-
self.chooseRequestProcessor().trackInAppClick(message,
183-
location: location,
184-
inboxSessionId: inboxSessionId,
185-
clickedUrl: clickedUrl,
186-
onSuccess: onSuccess,
187-
onFailure: onFailure)
181+
sendUsingRequestProcessor { processor in
182+
processor.trackInAppClick(message,
183+
location: location,
184+
inboxSessionId: inboxSessionId,
185+
clickedUrl: clickedUrl,
186+
onSuccess: onSuccess,
187+
onFailure: onFailure)
188188
}
189189
}
190190

@@ -196,47 +196,47 @@ class RequestHandler: RequestHandlerProtocol {
196196
clickedUrl: String?,
197197
onSuccess: OnSuccessHandler?,
198198
onFailure: OnFailureHandler?) -> Pending<SendRequestValue, SendRequestError> {
199-
Pending<SendRequestValue, SendRequestError>.inBackgroundThread {
200-
self.chooseRequestProcessor().trackInAppClose(message,
201-
location: location,
202-
inboxSessionId: inboxSessionId,
203-
source: source,
204-
clickedUrl: clickedUrl,
205-
onSuccess: onSuccess,
206-
onFailure: onFailure)
199+
sendUsingRequestProcessor { processor in
200+
processor.trackInAppClose(message,
201+
location: location,
202+
inboxSessionId: inboxSessionId,
203+
source: source,
204+
clickedUrl: clickedUrl,
205+
onSuccess: onSuccess,
206+
onFailure: onFailure)
207207
}
208208
}
209209

210210
@discardableResult
211211
func track(inboxSession: IterableInboxSession,
212212
onSuccess: OnSuccessHandler?,
213213
onFailure: OnFailureHandler?) -> Pending<SendRequestValue, SendRequestError> {
214-
Pending<SendRequestValue, SendRequestError>.inBackgroundThread {
215-
self.chooseRequestProcessor().track(inboxSession: inboxSession,
216-
onSuccess: onSuccess,
217-
onFailure: onFailure)
214+
sendUsingRequestProcessor { processor in
215+
processor.track(inboxSession: inboxSession,
216+
onSuccess: onSuccess,
217+
onFailure: onFailure)
218218
}
219219
}
220220

221221
@discardableResult
222222
func track(inAppDelivery message: IterableInAppMessage,
223223
onSuccess: OnSuccessHandler?,
224224
onFailure: OnFailureHandler?) -> Pending<SendRequestValue, SendRequestError> {
225-
Pending<SendRequestValue, SendRequestError>.inBackgroundThread {
226-
self.chooseRequestProcessor().track(inAppDelivery: message,
227-
onSuccess: onSuccess,
228-
onFailure: onFailure)
225+
sendUsingRequestProcessor { processor in
226+
processor.track(inAppDelivery: message,
227+
onSuccess: onSuccess,
228+
onFailure: onFailure)
229229
}
230230
}
231231

232232
@discardableResult
233233
func inAppConsume(_ messageId: String,
234234
onSuccess: OnSuccessHandler?,
235235
onFailure: OnFailureHandler?) -> Pending<SendRequestValue, SendRequestError> {
236-
Pending<SendRequestValue, SendRequestError>.inBackgroundThread {
237-
self.chooseRequestProcessor().inAppConsume(messageId,
238-
onSuccess: onSuccess,
239-
onFailure: onFailure)
236+
sendUsingRequestProcessor { processor in
237+
processor.inAppConsume(messageId,
238+
onSuccess: onSuccess,
239+
onFailure: onFailure)
240240
}
241241
}
242242

@@ -247,13 +247,13 @@ class RequestHandler: RequestHandlerProtocol {
247247
inboxSessionId: String?,
248248
onSuccess: OnSuccessHandler?,
249249
onFailure: OnFailureHandler?) -> Pending<SendRequestValue, SendRequestError> {
250-
Pending<SendRequestValue, SendRequestError>.inBackgroundThread {
251-
self.chooseRequestProcessor().inAppConsume(message: message,
252-
location: location,
253-
source: source,
254-
inboxSessionId: inboxSessionId,
255-
onSuccess: onSuccess,
256-
onFailure: onFailure)
250+
sendUsingRequestProcessor { processor in
251+
processor.inAppConsume(message: message,
252+
location: location,
253+
source: source,
254+
inboxSessionId: inboxSessionId,
255+
onSuccess: onSuccess,
256+
onFailure: onFailure)
257257
}
258258
}
259259

@@ -272,19 +272,27 @@ class RequestHandler: RequestHandlerProtocol {
272272
private let offlineProcessor: OfflineRequestProcessor?
273273
private let healthMonitor: HealthMonitor?
274274
private let onlineProcessor: OnlineRequestProcessor
275-
276-
private func chooseRequestProcessor() -> RequestProcessorProtocol {
275+
276+
private func sendUsingRequestProcessor(closure: @escaping (RequestProcessorProtocol) -> Pending<SendRequestValue, SendRequestError>) -> Pending<SendRequestValue, SendRequestError> {
277+
chooseRequestProcessor().flatMap { processor in
278+
closure(processor)
279+
}
280+
}
281+
282+
private func chooseRequestProcessor() -> Pending<RequestProcessorProtocol, Never> {
277283
guard offlineMode else {
278-
return onlineProcessor
284+
return Fulfill<RequestProcessorProtocol, Never>(value: onlineProcessor)
279285
}
280286
guard
281287
let offlineProcessor = offlineProcessor,
282288
let healthMonitor = healthMonitor
283289
else {
284-
return onlineProcessor
290+
return Fulfill<RequestProcessorProtocol, Never>(value: onlineProcessor)
291+
}
292+
293+
return healthMonitor.canSchedule().map { value -> RequestProcessorProtocol in
294+
value ? offlineProcessor : self.onlineProcessor
285295
}
286-
287-
return healthMonitor.canSchedule() ? offlineProcessor : onlineProcessor
288296
}
289297
}
290298

tests/offline-events-tests/RequestHandlerTests.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,10 +1012,10 @@ class RequestHandlerTests: XCTestCase {
10121012
let request = { requestGenerator(requestHandler) }
10131013
let expectation1 = expectation(description: #function)
10141014
handleRequestWithSuccess(request: request,
1015-
networkSession: networkSession,
1016-
path: path,
1017-
bodyDict: bodyDict,
1018-
expectation: expectation1)
1015+
networkSession: networkSession,
1016+
path: path,
1017+
bodyDict: bodyDict,
1018+
expectation: expectation1)
10191019
waitForTaskRunner(requestHandler: requestHandler,
10201020
expectation: expectation1)
10211021
}

0 commit comments

Comments
 (0)