Skip to content

Commit 6bd470d

Browse files
1. Encapsulate core data calls within context.performAndWait
1 parent 07173cd commit 6bd470d

File tree

9 files changed

+67
-20
lines changed

9 files changed

+67
-20
lines changed

swift-sdk/Internal/CoreDataUtil.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,13 @@ struct CoreDataUtil {
7272
}
7373
}
7474
}
75+
76+
extension NSManagedObjectContext {
77+
func performAndWait<T>(_ block: () throws -> T) throws -> T {
78+
var result: Result<T, Error>?
79+
performAndWait {
80+
result = Result { try block() }
81+
}
82+
return try result!.get()
83+
}
84+
}

swift-sdk/Internal/HealthMonitor.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ struct HealthMonitorDataProvider: HealthMonitorDataProviderProtocol {
1919
let maxTasks: Int
2020

2121
func countTasks() throws -> Int {
22-
return try persistenceContextProvider.newBackgroundContext().countTasks()
22+
let context = persistenceContextProvider.newBackgroundContext()
23+
return try context.performAndWait {
24+
try context.countTasks()
25+
}
2326
}
2427

2528
private let persistenceContextProvider: IterablePersistenceContextProvider

swift-sdk/Internal/IterableCoreDataPersistence.swift

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,13 @@ struct CoreDataPersistenceContext: IterablePersistenceContext {
130130
}
131131

132132
func nextTask() throws -> IterableTask? {
133-
let taskManagedObjects: [IterableTaskManagedObject] = try CoreDataUtil.findSortedEntities(context: managedObjectContext,
134-
entity: PersistenceConst.Entity.Task.name,
135-
column: PersistenceConst.Entity.Task.Column.scheduledAt,
136-
ascending: true,
137-
limit: 1)
133+
let taskManagedObjects: [IterableTaskManagedObject] = try performAndWait {
134+
try CoreDataUtil.findSortedEntities(context: managedObjectContext,
135+
entity: PersistenceConst.Entity.Task.name,
136+
column: PersistenceConst.Entity.Task.Column.scheduledAt,
137+
ascending: true,
138+
limit: 1)
139+
}
138140
return taskManagedObjects.first.map(PersistenceHelper.task(from:))
139141
}
140142

@@ -179,6 +181,10 @@ struct CoreDataPersistenceContext: IterablePersistenceContext {
179181
managedObjectContext.performAndWait(block)
180182
}
181183

184+
func performAndWait<T>(_ block: () throws -> T) throws -> T {
185+
try managedObjectContext.performAndWait(block)
186+
}
187+
182188
private let managedObjectContext: NSManagedObjectContext
183189
private let dateProvider: DateProviderProtocol
184190

swift-sdk/Internal/IterablePersistence.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ protocol IterablePersistenceContext {
4646
func perform(_ block: @escaping () -> Void)
4747

4848
func performAndWait(_ block: () -> Void)
49+
50+
func performAndWait<T>(_ block: () throws -> T) throws -> T
4951
}
5052

5153
protocol IterablePersistenceContextProvider {

swift-sdk/Internal/IterableTaskRunner.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,10 @@ class IterableTaskRunner: NSObject {
244244

245245
private func deleteTask(task: IterableTask) {
246246
do {
247-
try persistenceContext.delete(task: task)
248-
try persistenceContext.save()
247+
try persistenceContext.performAndWait {
248+
try persistenceContext.delete(task: task)
249+
try persistenceContext.save()
250+
}
249251
} catch let error {
250252
ITBError(error.localizedDescription)
251253
healthMonitor.onDeleteError(task: task)

swift-sdk/Internal/IterableTaskScheduler.swift

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,16 @@ class IterableTaskScheduler {
2323
do {
2424
let data = try JSONEncoder().encode(apiCallRequest)
2525

26-
try persistenceContext.create(task: IterableTask(id: taskId,
27-
name: apiCallRequest.getPath(),
28-
type: .apiCall,
29-
scheduledAt: scheduledAt ?? dateProvider.currentDate,
30-
data: data,
31-
requestedAt: dateProvider.currentDate))
32-
try persistenceContext.save()
33-
26+
try persistenceContext.performAndWait {
27+
try persistenceContext.create(task: IterableTask(id: taskId,
28+
name: apiCallRequest.getPath(),
29+
type: .apiCall,
30+
scheduledAt: scheduledAt ?? dateProvider.currentDate,
31+
data: data,
32+
requestedAt: dateProvider.currentDate))
33+
try persistenceContext.save()
34+
35+
}
3436
notificationCenter.post(name: .iterableTaskScheduled, object: self, userInfo: nil)
3537
} catch let error {
3638
healthMonitor.onScheduleError(apiCallRequest: apiCallRequest)

swift-sdk/Internal/Pending.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,19 @@ 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+
}
174+
175+
return fulfill.flatMap { _ in
176+
block()
177+
}
178+
}
179+
}
180+
168181
// This class takes the responsibility of setting value for Pending
169182
class Fulfill<Value, Failure>: Pending<Value, Failure> where Failure: Error {
170183
public init(value: Value? = nil) {

swift-sdk/Internal/RequestHandler.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -197,11 +197,13 @@ class RequestHandler: RequestHandlerProtocol {
197197
func track(inboxSession: IterableInboxSession,
198198
onSuccess: OnSuccessHandler?,
199199
onFailure: OnFailureHandler?) -> Pending<SendRequestValue, SendRequestError> {
200-
chooseRequestProcessor().track(inboxSession: inboxSession,
201-
onSuccess: onSuccess,
202-
onFailure: onFailure)
200+
Pending<SendRequestValue, SendRequestError>.inBackgroundThread {
201+
self.chooseRequestProcessor().track(inboxSession: inboxSession,
202+
onSuccess: onSuccess,
203+
onFailure: onFailure)
204+
}
203205
}
204-
206+
205207
@discardableResult
206208
func track(inAppDelivery message: IterableInAppMessage,
207209
onSuccess: OnSuccessHandler?,

tests/offline-events-tests/MockPersistence.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class MockPersistenceContext: IterablePersistenceContext {
2020
var saveCallback: (() throws -> Void)? = nil
2121
var performCallback: (() -> Void)? = nil
2222
var performAndWaitCallback: (() -> Void)? = nil
23+
var performAndWaitCallbackWithResult: (() -> Void)? = nil
2324
}
2425

2526
init(input: Input = Input()) {
@@ -105,6 +106,12 @@ class MockPersistenceContext: IterablePersistenceContext {
105106
block()
106107
}
107108

109+
func performAndWait<T>(_ block: () throws -> T) throws -> T {
110+
ITBInfo()
111+
input.performAndWaitCallbackWithResult?()
112+
return try block()
113+
}
114+
108115
private let input: Input
109116
private var tasks = [IterableTask]()
110117
}

0 commit comments

Comments
 (0)