Skip to content

Commit fbb40bd

Browse files
committed
Operation Repo - refactor and update for JWT
* Refactor from a static shared instance to a instance managed by User Manager * Operation Repo does not flush while Identity Verification is unknown * Currently it is not going to process Deltas based on JWT. Executors will.
1 parent f3e6256 commit fbb40bd

8 files changed

+81
-37
lines changed

iOS_SDK/OneSignalSDK/OneSignalCore/Source/OneSignalCommonDefines.h

+1
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ typedef enum {GET, POST, HEAD, PUT, DELETE, OPTIONS, CONNECT, TRACE, PATCH} HTTP
340340
#define OS_UPDATE_SUBSCRIPTION_DELTA @"OS_UPDATE_SUBSCRIPTION_DELTA"
341341

342342
// Operation Repo
343+
#define OS_OPERATION_REPO @"OS_OPERATION_REPO"
343344
#define OS_OPERATION_REPO_DELTA_QUEUE_KEY @"OS_OPERATION_REPO_DELTA_QUEUE_KEY"
344345

345346
// User Executor

iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/OSModelStoreListener.swift

+6-4
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,11 @@ import OneSignalCore
3131
public protocol OSModelStoreListener: OSModelStoreChangedHandler {
3232
associatedtype TModel: OSModel
3333

34+
var operationRepo: OSOperationRepo { get }
35+
3436
var store: OSModelStore<TModel> { get }
3537

36-
init(store: OSModelStore<TModel>)
38+
init(store: OSModelStore<TModel>, operationRepo: OSOperationRepo)
3739

3840
func getAddModelDelta(_ model: TModel) -> OSDelta?
3941

@@ -59,13 +61,13 @@ extension OSModelStoreListener {
5961
return
6062
}
6163
if let delta = getAddModelDelta(addedModel) {
62-
OSOperationRepo.sharedInstance.enqueueDelta(delta)
64+
operationRepo.enqueueDelta(delta)
6365
}
6466
}
6567

6668
public func onUpdated(_ args: OSModelChangedArgs) {
6769
if let delta = getUpdateModelDelta(args) {
68-
OSOperationRepo.sharedInstance.enqueueDelta(delta)
70+
operationRepo.enqueueDelta(delta)
6971
}
7072
}
7173

@@ -76,7 +78,7 @@ extension OSModelStoreListener {
7678
return
7779
}
7880
if let delta = getRemoveModelDelta(removedModel) {
79-
OSOperationRepo.sharedInstance.enqueueDelta(delta)
81+
operationRepo.enqueueDelta(delta)
8082
}
8183
}
8284
}

iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/OSOperationRepo.swift

+50-17
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ import OneSignalCore
3232
The OSOperationRepo is a static singleton.
3333
OSDeltas are enqueued when model store observers observe changes to their models, and sorted to their appropriate executors.
3434
*/
35-
public class OSOperationRepo: NSObject {
36-
public static let sharedInstance = OSOperationRepo()
35+
public class OSOperationRepo {
3736
private var hasCalledStart = false
3837

3938
// The Operation Repo dispatch queue, serial. This synchronizes access to `deltaQueue` and flushing behavior.
@@ -47,16 +46,37 @@ public class OSOperationRepo: NSObject {
4746
// TODO: This could come from a config, plist, method, remote params
4847
var pollIntervalMilliseconds = Int(POLL_INTERVAL_MS)
4948
public var paused = false
49+
let jwtConfig: OSUserJwtConfig
5050

5151
/**
52-
Initilize this Operation Repo. Read from the cache. Executors may not be available by this time.
53-
If everything starts up on initialize(), order can matter, ideally not but it can.
54-
Likely call init on this from oneSignal but exeuctors can come from diff modules.
52+
Sets the jwt config and uncaches
53+
*/
54+
public init(jwtConfig: OSUserJwtConfig) {
55+
self.jwtConfig = jwtConfig
56+
self.jwtConfig.subscribe(self, key: OS_OPERATION_REPO)
57+
print("❌ OSOperationRepo init(\(String(describing: jwtConfig.isRequired))) called")
58+
59+
// Read the Deltas from cache, if any...
60+
guard let deltaQueue = OneSignalUserDefaults.initShared().getSavedCodeableData(forKey: OS_OPERATION_REPO_DELTA_QUEUE_KEY, defaultValue: []) as? [OSDelta] else {
61+
OneSignalLog.onesignalLog(.LL_ERROR, message: "OSOperationRepo is unable to uncache the OSDelta queue.")
62+
return
63+
}
64+
self.deltaQueue = deltaQueue
65+
}
66+
67+
/**
68+
Start this Operation Repo.
5569
*/
5670
public func start() {
5771
guard !OneSignalConfigManager.shouldAwaitAppIdAndLogMissingPrivacyConsent(forMethod: nil) else {
5872
return
5973
}
74+
75+
guard jwtConfig.isRequired != nil else {
76+
print("❌ OSOperationRepo.start() returning early due to unknown Identity Verification status.")
77+
return
78+
}
79+
6080
guard !hasCalledStart else {
6181
return
6282
}
@@ -68,13 +88,6 @@ public class OSOperationRepo: NSObject {
6888
selector: #selector(self.addFlushDeltaQueueToDispatchQueue),
6989
name: Notification.Name(OS_ON_USER_WILL_CHANGE),
7090
object: nil)
71-
// Read the Deltas from cache, if any...
72-
if let deltaQueue = OneSignalUserDefaults.initShared().getSavedCodeableData(forKey: OS_OPERATION_REPO_DELTA_QUEUE_KEY, defaultValue: []) as? [OSDelta] {
73-
self.deltaQueue = deltaQueue
74-
OneSignalLog.onesignalLog(.LL_VERBOSE, message: "OSOperationRepo.start() with deltaQueue: \(deltaQueue)")
75-
} else {
76-
OneSignalLog.onesignalLog(.LL_ERROR, message: "OSOperationRepo.start() is unable to uncache the OSDelta queue.")
77-
}
7891

7992
pollFlushQueue()
8093
}
@@ -87,13 +100,12 @@ public class OSOperationRepo: NSObject {
87100
}
88101

89102
/**
90-
Add and start an executor.
103+
Add an executor.
91104
*/
92105
public func addExecutor(_ executor: OSOperationExecutor) {
93106
guard !OneSignalConfigManager.shouldAwaitAppIdAndLogMissingPrivacyConsent(forMethod: nil) else {
94107
return
95108
}
96-
start()
97109
executors.append(executor)
98110
for delta in executor.supportedDeltas {
99111
deltasToExecutorMap[delta] = executor
@@ -111,7 +123,6 @@ public class OSOperationRepo: NSObject {
111123
guard !OneSignalConfigManager.shouldAwaitAppIdAndLogMissingPrivacyConsent(forMethod: nil) else {
112124
return
113125
}
114-
start()
115126
self.dispatchQueue.async {
116127
OneSignalLog.onesignalLog(.LL_VERBOSE, message: "OSOperationRepo enqueueDelta: \(delta)")
117128
self.deltaQueue.append(delta)
@@ -140,8 +151,6 @@ public class OSOperationRepo: NSObject {
140151
OSBackgroundTaskManager.beginBackgroundTask(OPERATION_REPO_BACKGROUND_TASK)
141152
}
142153

143-
self.start()
144-
145154
if !self.deltaQueue.isEmpty {
146155
OneSignalLog.onesignalLog(.LL_VERBOSE, message: "OSOperationRepo flushDeltaQueue in background: \(inBackground) with queue: \(self.deltaQueue)")
147156
}
@@ -174,6 +183,30 @@ public class OSOperationRepo: NSObject {
174183
}
175184
}
176185

186+
extension OSOperationRepo: OSUserJwtConfigListener {
187+
public func onRequiresUserAuthChanged(from: Bool?, to: Bool?) {
188+
print("❌ OSOperationRepo onRequiresUserAuthChanged from \(String(describing: from)) to \(String(describing: to))")
189+
// If auth changed from false or unknown to true, process deltas
190+
if to == true {
191+
removeInvalidDeltas()
192+
}
193+
start()
194+
}
195+
196+
public func onJwtUpdated(externalId: String, to: String?) {
197+
print("❌ OSOperationRepo onJwtUpdated for \(externalId) to \(String(describing: to))")
198+
}
199+
200+
/**
201+
TODO: The operation repo cannot easily remove invalid Deltas that do not have an External ID.
202+
Deltas have an Identity Model ID only and would need to access the User module to find the corresponding Identity Model.
203+
Executors will handle this.
204+
*/
205+
func removeInvalidDeltas() {
206+
print("❌ OSOperationRepo removeInvalidDeltas TODO!")
207+
}
208+
}
209+
177210
extension OSOperationRepo: OSLoggable {
178211
public func logSelf() {
179212
print("💛 Operation Repo: deltaQueue: \(self.deltaQueue )")

iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSUserExecutor.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ extension OSUserExecutor {
335335
self.executePendingRequests()
336336
}
337337
}
338-
OSOperationRepo.sharedInstance.paused = false
338+
OneSignalUserManagerImpl.sharedInstance.operationRepo.paused = false
339339
} onFailure: { error in
340340
OneSignalLog.onesignalLog(.LL_ERROR, message: "OSUserExecutor create user request failed with error: \(error.debugDescription)")
341341
if let nsError = error as? NSError {
@@ -344,7 +344,7 @@ extension OSUserExecutor {
344344
// A failed create user request would leave the SDK in a bad state
345345
// Don't remove the request from cache and pause the operation repo
346346
// We will retry this request on a new session
347-
OSOperationRepo.sharedInstance.paused = true
347+
OneSignalUserManagerImpl.sharedInstance.operationRepo.paused = true
348348
request.sentToClient = false
349349
}
350350
} else {

iOS_SDK/OneSignalSDK/OneSignalUser/Source/OSIdentityModelStoreListener.swift

+3-1
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,11 @@ import OneSignalCore
3030
import OneSignalOSCore
3131

3232
class OSIdentityModelStoreListener: OSModelStoreListener {
33+
let operationRepo: OSOperationRepo
3334
var store: OSModelStore<OSIdentityModel>
3435

35-
required init(store: OSModelStore<OSIdentityModel>) {
36+
required init(store: OSModelStore<OSIdentityModel>, operationRepo: OSOperationRepo) {
37+
self.operationRepo = operationRepo
3638
self.store = store
3739
}
3840

iOS_SDK/OneSignalSDK/OneSignalUser/Source/OSPropertiesModelStoreListener.swift

+3-1
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,11 @@ import OneSignalCore
3030
import OneSignalOSCore
3131

3232
class OSPropertiesModelStoreListener: OSModelStoreListener {
33+
let operationRepo: OSOperationRepo
3334
var store: OSModelStore<OSPropertiesModel>
3435

35-
required init(store: OSModelStore<OSPropertiesModel>) {
36+
required init(store: OSModelStore<OSPropertiesModel>, operationRepo: OSOperationRepo) {
37+
self.operationRepo = operationRepo
3638
self.store = store
3739
}
3840

iOS_SDK/OneSignalSDK/OneSignalUser/Source/OSSubscriptionModelStoreListener.swift

+3-1
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,11 @@ import OneSignalCore
3030
import OneSignalOSCore
3131

3232
class OSSubscriptionModelStoreListener: OSModelStoreListener {
33+
let operationRepo: OSOperationRepo
3334
var store: OSModelStore<OSSubscriptionModel>
3435

35-
required init(store: OSModelStore<OSSubscriptionModel>) {
36+
required init(store: OSModelStore<OSSubscriptionModel>, operationRepo: OSOperationRepo) {
37+
self.operationRepo = operationRepo
3638
self.store = store
3739
}
3840

iOS_SDK/OneSignalSDK/OneSignalUser/Source/OneSignalUserManagerImpl.swift

+13-11
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ public class OneSignalUserManagerImpl: NSObject, OneSignalUserManager {
173173
let pushSubscriptionModelStore = OSModelStore<OSSubscriptionModel>(changeSubscription: OSEventProducer(), storeKey: OS_PUSH_SUBSCRIPTION_MODEL_STORE_KEY)
174174

175175
// These must be initialized in init()
176+
let operationRepo: OSOperationRepo
176177
let identityModelStoreListener: OSIdentityModelStoreListener
177178
let propertiesModelStoreListener: OSPropertiesModelStoreListener
178179
let subscriptionModelStoreListener: OSSubscriptionModelStoreListener
@@ -186,10 +187,11 @@ public class OneSignalUserManagerImpl: NSObject, OneSignalUserManager {
186187

187188
private init(jwtConfig: OSUserJwtConfig) {
188189
self.jwtConfig = jwtConfig
189-
self.identityModelStoreListener = OSIdentityModelStoreListener(store: identityModelStore)
190-
self.propertiesModelStoreListener = OSPropertiesModelStoreListener(store: propertiesModelStore)
191-
self.subscriptionModelStoreListener = OSSubscriptionModelStoreListener(store: subscriptionModelStore)
192-
self.pushSubscriptionModelStoreListener = OSSubscriptionModelStoreListener(store: pushSubscriptionModelStore)
190+
self.operationRepo = OSOperationRepo(jwtConfig: jwtConfig)
191+
self.identityModelStoreListener = OSIdentityModelStoreListener(store: identityModelStore, operationRepo: operationRepo)
192+
self.propertiesModelStoreListener = OSPropertiesModelStoreListener(store: propertiesModelStore, operationRepo: operationRepo)
193+
self.subscriptionModelStoreListener = OSSubscriptionModelStoreListener(store: subscriptionModelStore, operationRepo: operationRepo)
194+
self.pushSubscriptionModelStoreListener = OSSubscriptionModelStoreListener(store: pushSubscriptionModelStore, operationRepo: operationRepo)
193195
self.pushSubscriptionImpl = OSPushSubscriptionImpl(pushSubscriptionModelStore: pushSubscriptionModelStore)
194196
}
195197

@@ -226,7 +228,7 @@ public class OneSignalUserManagerImpl: NSObject, OneSignalUserManager {
226228
// Setup the executors
227229
// The OSUserExecutor has to run first, before other executors
228230
self.userExecutor = OSUserExecutor(newRecordsState: newRecordsState, jwtConfig: jwtConfig)
229-
OSOperationRepo.sharedInstance.start()
231+
operationRepo.start()
230232

231233
// Cannot initialize these executors in `init` as they reference the sharedInstance
232234
let propertyExecutor = OSPropertyOperationExecutor(newRecordsState: newRecordsState, jwtConfig: jwtConfig)
@@ -235,9 +237,9 @@ public class OneSignalUserManagerImpl: NSObject, OneSignalUserManager {
235237
self.propertyExecutor = propertyExecutor
236238
self.identityExecutor = identityExecutor
237239
self.subscriptionExecutor = subscriptionExecutor
238-
OSOperationRepo.sharedInstance.addExecutor(identityExecutor)
239-
OSOperationRepo.sharedInstance.addExecutor(propertyExecutor)
240-
OSOperationRepo.sharedInstance.addExecutor(subscriptionExecutor)
240+
operationRepo.addExecutor(identityExecutor)
241+
operationRepo.addExecutor(propertyExecutor)
242+
operationRepo.addExecutor(subscriptionExecutor)
241243

242244
// Path 2. There is a legacy player to migrate
243245
if let legacyPlayerId = OneSignalUserDefaults.initShared().getSavedString(forKey: OSUD_LEGACY_PLAYER_ID, defaultValue: nil) {
@@ -561,7 +563,7 @@ extension OneSignalUserManagerImpl {
561563
start()
562564

563565
userExecutor!.executePendingRequests()
564-
OSOperationRepo.sharedInstance.paused = false
566+
operationRepo.paused = false
565567
updatePropertiesDeltas(property: .session_count, value: 1)
566568

567569
// Fetch the user's data if there is a onesignal_id
@@ -594,7 +596,7 @@ extension OneSignalUserManagerImpl {
594596
property: property.rawValue,
595597
value: value
596598
)
597-
OSOperationRepo.sharedInstance.enqueueDelta(delta)
599+
operationRepo.enqueueDelta(delta)
598600
}
599601

600602
/// Time processors forward the session time to this method.
@@ -612,7 +614,7 @@ extension OneSignalUserManagerImpl {
612614
*/
613615
@objc
614616
public func runBackgroundTasks() {
615-
OSOperationRepo.sharedInstance.addFlushDeltaQueueToDispatchQueue(inBackground: true)
617+
operationRepo.addFlushDeltaQueueToDispatchQueue(inBackground: true)
616618
}
617619
}
618620

0 commit comments

Comments
 (0)