Skip to content

Commit

Permalink
Add lock around accessing OpRepo delta queue
Browse files Browse the repository at this point in the history
* Add lock around appending to the queue
* Add lock around entire logic of flushing the delta queue, including enqueuing and flushing in the executors
  • Loading branch information
nan-li committed Feb 22, 2024
1 parent 10bd2cf commit 09272b4
Showing 1 changed file with 32 additions and 27 deletions.
59 changes: 32 additions & 27 deletions iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/OSOperationRepo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,12 @@ import OneSignalCore
public class OSOperationRepo: NSObject {
public static let sharedInstance = OSOperationRepo()
private var hasCalledStart = false
private let deltaQueueLock = UnfairLock()

// Maps delta names to the interfaces for the operation executors
var deltasToExecutorMap: [String: OSOperationExecutor] = [:]
var executors: [OSOperationExecutor] = []
var deltaQueue: [OSDelta] = []
private var deltaQueue: [OSDelta] = []

// TODO: This could come from a config, plist, method, remote params
var pollIntervalMilliseconds = Int(POLL_INTERVAL_MS)
Expand Down Expand Up @@ -102,10 +103,12 @@ public class OSOperationRepo: NSObject {
}
start()
OneSignalLog.onesignalLog(.LL_VERBOSE, message: "OSOperationRepo enqueueDelta: \(delta)")
deltaQueue.append(delta)

// Persist the deltas (including new delta) to storage
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_OPERATION_REPO_DELTA_QUEUE_KEY, withValue: self.deltaQueue)
deltaQueueLock.locked {
deltaQueue.append(delta)
// Persist the deltas (including new delta) to storage
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_OPERATION_REPO_DELTA_QUEUE_KEY, withValue: self.deltaQueue)
}
}

@objc public func flushDeltaQueue(inBackground: Bool = false) {
Expand All @@ -123,35 +126,37 @@ public class OSOperationRepo: NSObject {
}

start()
if !deltaQueue.isEmpty {
OneSignalLog.onesignalLog(.LL_VERBOSE, message: "OSOperationRepo flushDeltaQueue in background: \(inBackground) with queue: \(deltaQueue)")
}

var index = 0
for delta in deltaQueue {
if let executor = deltasToExecutorMap[delta.name] {
executor.enqueueDelta(delta)
deltaQueue.remove(at: index)
} else {
// keep in queue if no executor matches, we may not have the executor available yet
index += 1
deltaQueueLock.locked {
if !deltaQueue.isEmpty {
OneSignalLog.onesignalLog(.LL_VERBOSE, message: "OSOperationRepo flushDeltaQueue in background: \(inBackground) with queue: \(deltaQueue)")
}
}

// Persist the deltas (including removed deltas) to storage after they are divvy'd up to executors.
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_OPERATION_REPO_DELTA_QUEUE_KEY, withValue: self.deltaQueue)
var index = 0
for delta in deltaQueue {
if let executor = deltasToExecutorMap[delta.name] {
executor.enqueueDelta(delta)
deltaQueue.remove(at: index)
} else {
// keep in queue if no executor matches, we may not have the executor available yet
index += 1
}
}

for executor in executors {
executor.cacheDeltaQueue()
}
// Persist the deltas (including removed deltas) to storage after they are divvy'd up to executors.
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_OPERATION_REPO_DELTA_QUEUE_KEY, withValue: self.deltaQueue)

for executor in executors {
executor.processDeltaQueue(inBackground: inBackground)
}
for executor in executors {
executor.cacheDeltaQueue()
}

if inBackground {
OSBackgroundTaskManager.endBackgroundTask(OPERATION_REPO_BACKGROUND_TASK)
}
for executor in executors {
executor.processDeltaQueue(inBackground: inBackground)
}

if inBackground {
OSBackgroundTaskManager.endBackgroundTask(OPERATION_REPO_BACKGROUND_TASK)
}
}
}
}

0 comments on commit 09272b4

Please sign in to comment.