@@ -48,8 +48,7 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
4848 print ( " ❌ OSIdentityOperationExecutor init( \( jwtConfig. isRequired) ) " )
4949 // Read unfinished deltas and requests from cache, if any...
5050 uncacheDeltas ( )
51- uncacheAddAliasRequests ( )
52- uncacheRemoveAliasRequests ( )
51+ uncacheRequests ( )
5352 }
5453
5554 private func uncacheDeltas( ) {
@@ -82,19 +81,42 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
8281 OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_DELTA_QUEUE_KEY, withValue: self . deltaQueue)
8382 }
8483
85- private func uncacheAddAliasRequests( ) {
86- guard var addRequestQueue = OneSignalUserDefaults . initShared ( ) . getSavedCodeableData ( forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, defaultValue: [ ] ) as? [ OSRequestAddAliases ] else {
87- OneSignalLog . onesignalLog ( . LL_ERROR, message: " OSIdentityOperationExecutor error encountered reading from cache for \( OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY) " )
88- return
84+ private func uncacheRequests( ) {
85+ var addRequestQueue : [ OSRequestAddAliases ] = [ ]
86+ var removeRequestQueue : [ OSRequestRemoveAlias ] = [ ]
87+
88+ if let cachedAddRequestQueue = OneSignalUserDefaults . initShared ( ) . getSavedCodeableData ( forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, defaultValue: [ ] ) as? [ OSRequestAddAliases ] {
89+ addRequestQueue = cachedAddRequestQueue
90+ }
91+
92+ if let cachedRemoveRequestQueue = OneSignalUserDefaults . initShared ( ) . getSavedCodeableData ( forKey: OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, defaultValue: [ ] ) as? [ OSRequestRemoveAlias ] {
93+ removeRequestQueue = cachedRemoveRequestQueue
94+ }
95+
96+ if let pendingRequests = OneSignalUserDefaults . initShared ( ) . getSavedCodeableData ( forKey: OS_IDENTITY_EXECUTOR_PENDING_QUEUE_KEY, defaultValue: [ : ] ) as? [ String : [ OSUserRequest ] ] {
97+ for requests in pendingRequests. values {
98+ for request in requests {
99+ if request. isKind ( of: OSRequestAddAliases . self) , let req = request as? OSRequestAddAliases {
100+ addRequestQueue. append ( req)
101+ } else if request. isKind ( of: OSRequestRemoveAlias . self) , let req = request as? OSRequestRemoveAlias {
102+ removeRequestQueue. append ( req)
103+ }
104+ }
105+ }
89106 }
90107
108+ linkAddAliasRequests ( requests: & addRequestQueue)
109+ linkRemoveAliasRequests ( requests: & removeRequestQueue)
110+ }
111+
112+ private func linkAddAliasRequests( requests: inout [ OSRequestAddAliases ] ) {
91113 // Hook each uncached Request to the model in the store
92- for (index, request) in addRequestQueue . enumerated ( ) . reversed ( ) {
114+ for (index, request) in requests . enumerated ( ) . reversed ( ) {
93115 if jwtConfig. isRequired == true ,
94116 request. identityModel. externalId == nil
95117 {
96118 // remove if jwt is on but the model does not have external ID
97- addRequestQueue . remove ( at: index)
119+ requests . remove ( at: index)
98120 continue
99121 }
100122
@@ -107,27 +129,22 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
107129 } else {
108130 // 3. The model do not exist AND this request cannot be sent, drop this Request
109131 OneSignalLog . onesignalLog ( . LL_ERROR, message: " OSIdentityOperationExecutor.init dropped \( request) " )
110- addRequestQueue . remove ( at: index)
132+ requests . remove ( at: index)
111133 }
112134 }
113135
114- self . addRequestQueue = addRequestQueue
136+ self . addRequestQueue = requests
115137 OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self . addRequestQueue)
116138 }
117139
118- private func uncacheRemoveAliasRequests( ) {
119- guard var removeRequestQueue = OneSignalUserDefaults . initShared ( ) . getSavedCodeableData ( forKey: OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, defaultValue: [ ] ) as? [ OSRequestRemoveAlias ] else {
120- OneSignalLog . onesignalLog ( . LL_ERROR, message: " OSIdentityOperationExecutor error encountered reading from cache for \( OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY) " )
121- return
122- }
123-
140+ private func linkRemoveAliasRequests( requests: inout [ OSRequestRemoveAlias ] ) {
124141 // Hook each uncached Request to the model in the store
125- for (index, request) in removeRequestQueue . enumerated ( ) . reversed ( ) {
142+ for (index, request) in requests . enumerated ( ) . reversed ( ) {
126143 if jwtConfig. isRequired == true ,
127144 request. identityModel. externalId == nil
128145 {
129146 // remove if jwt is on but the model does not have external ID
130- removeRequestQueue . remove ( at: index)
147+ requests . remove ( at: index)
131148 continue
132149 }
133150
@@ -140,11 +157,11 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
140157 } else {
141158 // 3. The model do not exist AND this request cannot be sent, drop this Request
142159 OneSignalLog . onesignalLog ( . LL_ERROR, message: " OSIdentityOperationExecutor.init dropped \( request) " )
143- removeRequestQueue . remove ( at: index)
160+ requests . remove ( at: index)
144161 }
145162 }
146163
147- self . removeRequestQueue = removeRequestQueue
164+ self . removeRequestQueue = requests
148165 OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self . removeRequestQueue)
149166 }
150167
@@ -161,6 +178,19 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
161178 }
162179 }
163180
181+ /**
182+ This method does not handle concurrency; it should be called with thread-safe usage.
183+ */
184+ private func removeFromRequestQueueAndPersist( _ request: OSUserRequest ) {
185+ if request. isKind ( of: OSRequestAddAliases . self) {
186+ self . addRequestQueue. removeAll ( where: { $0 == request} )
187+ OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self . addRequestQueue)
188+ } else if request. isKind ( of: OSRequestRemoveAlias . self) {
189+ self . removeRequestQueue. removeAll ( where: { $0 == request} )
190+ OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self . removeRequestQueue)
191+ }
192+ }
193+
164194 func processDeltaQueue( inBackground: Bool ) {
165195 self . dispatchQueue. async {
166196 if !self . deltaQueue. isEmpty {
@@ -238,8 +268,7 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
238268
239269 func pendRequestUntilAuthUpdated( _ request: OSUserRequest , externalId: String ? ) {
240270 self . dispatchQueue. async {
241- self . addRequestQueue. removeAll ( where: { $0 == request} )
242- self . removeRequestQueue. removeAll ( where: { $0 == request} )
271+ self . removeFromRequestQueueAndPersist ( request)
243272 guard let externalId = externalId else {
244273 return
245274 }
@@ -250,6 +279,7 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
250279 }
251280 requests. append ( request)
252281 self . pendingAuthRequests [ externalId] = requests
282+ OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_PENDING_QUEUE_KEY, withValue: self . pendingAuthRequests)
253283 }
254284 }
255285
@@ -277,8 +307,7 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
277307 // No hydration from response
278308 // On success, remove request from cache
279309 self . dispatchQueue. async {
280- self . addRequestQueue. removeAll ( where: { $0 == request} )
281- OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self . addRequestQueue)
310+ self . removeFromRequestQueueAndPersist ( request)
282311 if inBackground {
283312 OSBackgroundTaskManager . endBackgroundTask ( backgroundTaskIdentifier)
284313 }
@@ -288,9 +317,7 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
288317 if let nsError = error as? NSError {
289318 let responseType = OSNetworkingUtils . getResponseStatusType ( nsError. code)
290319 if responseType == . missing {
291- // Remove from cache and queue
292- self . addRequestQueue. removeAll ( where: { $0 == request} )
293- OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self . addRequestQueue)
320+ self . removeFromRequestQueueAndPersist ( request)
294321 // Logout if the user in the SDK is the same
295322 guard OneSignalUserManagerImpl . sharedInstance. isCurrentUser ( request. identityModel)
296323 else {
@@ -309,8 +336,7 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
309336 request. sentToClient = false
310337 } else if responseType != . retryable {
311338 // Fail, no retry, remove from cache and queue
312- self . addRequestQueue. removeAll ( where: { $0 == request} )
313- OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self . addRequestQueue)
339+ self . removeFromRequestQueueAndPersist ( request)
314340 }
315341 }
316342 if inBackground {
@@ -344,8 +370,7 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
344370 // There is nothing to hydrate
345371 // On success, remove request from cache
346372 self . dispatchQueue. async {
347- self . removeRequestQueue. removeAll ( where: { $0 == request} )
348- OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self . removeRequestQueue)
373+ self . removeFromRequestQueueAndPersist ( request)
349374 if inBackground {
350375 OSBackgroundTaskManager . endBackgroundTask ( backgroundTaskIdentifier)
351376 }
@@ -363,8 +388,7 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
363388 } else if responseType != . retryable {
364389 // Fail, no retry, remove from cache and queue
365390 // A response of .missing could mean the alias doesn't exist on this user OR this user has been deleted
366- self . removeRequestQueue. removeAll ( where: { $0 == request} )
367- OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self . removeRequestQueue)
391+ self . removeFromRequestQueueAndPersist ( request)
368392 }
369393 }
370394 if inBackground {
@@ -404,6 +428,7 @@ extension OSIdentityOperationExecutor: OSUserJwtConfigListener {
404428 OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self . addRequestQueue)
405429 OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self . removeRequestQueue)
406430 self . pendingAuthRequests [ externalId] = nil
431+ OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_PENDING_QUEUE_KEY, withValue: self . pendingAuthRequests)
407432 self . processRequestQueue ( inBackground: false )
408433 }
409434 }
@@ -446,6 +471,7 @@ extension OSIdentityOperationExecutor: OSLoggable {
446471 addRequestQueue: \( self . addRequestQueue)
447472 removeRequestQueue: \( self . removeRequestQueue)
448473 deltaQueue: \( self . deltaQueue)
474+ pendingAuthRequests: \( self . pendingAuthRequests)
449475 """
450476 )
451477 }
0 commit comments