Skip to content

Commit 651446b

Browse files
authored
Merge pull request #1279 from OneSignal/5.0.0/server_error_responses
[5.0.0] Better handling server error responses
2 parents 208bc8d + 57e4b80 commit 651446b

File tree

7 files changed

+176
-69
lines changed

7 files changed

+176
-69
lines changed

iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSNetworkingUtils.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,18 @@
2929

3030
// NS_ASSUME_NONNULL_BEGIN
3131

32+
typedef NS_ENUM(NSInteger, OSResponseStatusType) {
33+
OSResponseStatusInvalid = 0,
34+
OSResponseStatusRetryable,
35+
OSResponseStatusUnauthorized,
36+
OSResponseStatusMissing,
37+
OSResponseStatusConflict
38+
};
39+
3240
@interface OSNetworkingUtils : NSObject
3341

3442
+ (NSNumber*)getNetType;
43+
+ (OSResponseStatusType)getResponseStatusType:(NSInteger)statusCode;
3544

3645
@end
3746

iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSNetworkingUtils.m

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,18 @@ + (NSNumber *)getNetType {
3838
return @1;
3939
}
4040

41+
+ (OSResponseStatusType)getResponseStatusType:(NSInteger)statusCode {
42+
if (statusCode == 400 || statusCode == 402) {
43+
return OSResponseStatusInvalid;
44+
} else if (statusCode == 401 || statusCode == 403) {
45+
return OSResponseStatusUnauthorized;
46+
} else if (statusCode == 404 || statusCode == 410) {
47+
return OSResponseStatusMissing;
48+
} else if (statusCode == 409) {
49+
return OSResponseStatusConflict;
50+
} else {
51+
return OSResponseStatusRetryable;
52+
}
53+
}
54+
4155
@end

iOS_SDK/OneSignalSDK/OneSignalUser/Source/OSIdentityOperationExecutor.swift

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -180,14 +180,35 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
180180
self.addRequestQueue.removeAll(where: { $0 == request})
181181
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self.addRequestQueue)
182182
} onFailure: { error in
183-
// TODO: What happened, maybe alias exists on another user
184183
OneSignalLog.onesignalLog(.LL_ERROR, message: "OSIdentityOperationExecutor add aliases request failed with error: \(error.debugDescription)")
185-
// TODO: Differentiate error cases
186-
// If the error is not retryable, remove from cache and queue
187-
if let nsError = error as? NSError,
188-
nsError.code < 500 && nsError.code != 0 {
189-
self.addRequestQueue.removeAll(where: { $0 == request})
190-
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self.addRequestQueue)
184+
if let nsError = error as? NSError {
185+
let responseType = OSNetworkingUtils.getResponseStatusType(nsError.code)
186+
if responseType == .missing {
187+
// Remove from cache and queue
188+
self.addRequestQueue.removeAll(where: { $0 == request})
189+
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self.addRequestQueue)
190+
// Logout if the user in the SDK is the same
191+
guard OneSignalUserManagerImpl.sharedInstance.isCurrentUser(request.identityModel)
192+
else {
193+
return
194+
}
195+
// The subscription has been deleted along with the user, so remove the subscription_id but keep the same push subscription model
196+
OneSignalUserManagerImpl.sharedInstance.pushSubscriptionModelStore.getModels()[OS_PUSH_SUBSCRIPTION_MODEL_KEY]?.subscriptionId = nil
197+
OneSignalUserManagerImpl.sharedInstance._logout()
198+
} else if responseType == .conflict {
199+
self.addRequestQueue.removeAll(where: { $0 == request})
200+
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self.addRequestQueue)
201+
guard OneSignalUserManagerImpl.sharedInstance.isCurrentUser(request.identityModel)
202+
else {
203+
return
204+
}
205+
// Alias(es) already exists on another user, remove from identity model
206+
OneSignalUserManagerImpl.sharedInstance.user.identityModel.removeAliases(Array(request.aliases.keys))
207+
} else if responseType != .retryable {
208+
// Fail, no retry, remove from cache and queue
209+
self.addRequestQueue.removeAll(where: { $0 == request})
210+
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self.addRequestQueue)
211+
}
191212
}
192213
}
193214
}
@@ -210,12 +231,15 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
210231
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self.removeRequestQueue)
211232
} onFailure: { error in
212233
OneSignalLog.onesignalLog(.LL_ERROR, message: "OSIdentityOperationExecutor remove alias request failed with error: \(error.debugDescription)")
213-
// TODO: Differentiate error cases
214-
// If the error is not retryable, remove from cache and queue
215-
if let nsError = error as? NSError,
216-
nsError.code < 500 && nsError.code != 0 {
217-
self.removeRequestQueue.removeAll(where: { $0 == request})
218-
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self.removeRequestQueue)
234+
235+
if let nsError = error as? NSError {
236+
let responseType = OSNetworkingUtils.getResponseStatusType(nsError.code)
237+
if responseType != .retryable {
238+
// Fail, no retry, remove from cache and queue
239+
// A response of .missing could mean the alias doesn't exist on this user OR this user has been deleted
240+
self.removeRequestQueue.removeAll(where: { $0 == request})
241+
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self.removeRequestQueue)
242+
}
219243
}
220244
}
221245
}

iOS_SDK/OneSignalSDK/OneSignalUser/Source/OSPropertyOperationExecutor.swift

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -135,17 +135,30 @@ class OSPropertyOperationExecutor: OSOperationExecutor {
135135

136136
OneSignalClient.shared().execute(request) { _ in
137137
// On success, remove request from cache, and we do need to hydrate
138-
// TODO: We need to hydrate after all
138+
// TODO: We need to hydrate after all ? What why ?
139139
self.updateRequestQueue.removeAll(where: { $0 == request})
140140
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_PROPERTIES_EXECUTOR_UPDATE_REQUEST_QUEUE_KEY, withValue: self.updateRequestQueue)
141141
} onFailure: { error in
142142
OneSignalLog.onesignalLog(.LL_ERROR, message: "OSPropertyOperationExecutor update properties request failed with error: \(error.debugDescription)")
143-
// TODO: Differentiate error cases
144-
// If the error is not retryable, remove from cache and queue
145-
if let nsError = error as? NSError,
146-
nsError.code < 500 && nsError.code != 0 {
147-
self.updateRequestQueue.removeAll(where: { $0 == request})
148-
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_PROPERTIES_EXECUTOR_UPDATE_REQUEST_QUEUE_KEY, withValue: self.updateRequestQueue)
143+
if let nsError = error as? NSError {
144+
let responseType = OSNetworkingUtils.getResponseStatusType(nsError.code)
145+
if responseType == .missing {
146+
// remove from cache and queue
147+
self.updateRequestQueue.removeAll(where: { $0 == request})
148+
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_PROPERTIES_EXECUTOR_UPDATE_REQUEST_QUEUE_KEY, withValue: self.updateRequestQueue)
149+
// Logout if the user in the SDK is the same
150+
guard OneSignalUserManagerImpl.sharedInstance.isCurrentUser(request.identityModel)
151+
else {
152+
return
153+
}
154+
// The subscription has been deleted along with the user, so remove the subscription_id but keep the same push subscription model
155+
OneSignalUserManagerImpl.sharedInstance.pushSubscriptionModelStore.getModels()[OS_PUSH_SUBSCRIPTION_MODEL_KEY]?.subscriptionId = nil
156+
OneSignalUserManagerImpl.sharedInstance._logout()
157+
} else if responseType != .retryable {
158+
// Fail, no retry, remove from cache and queue
159+
self.updateRequestQueue.removeAll(where: { $0 == request})
160+
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_PROPERTIES_EXECUTOR_UPDATE_REQUEST_QUEUE_KEY, withValue: self.updateRequestQueue)
161+
}
149162
}
150163
}
151164
}

iOS_SDK/OneSignalSDK/OneSignalUser/Source/OSSubscriptionOperationExecutor.swift

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -246,12 +246,24 @@ class OSSubscriptionOperationExecutor: OSOperationExecutor {
246246
request.subscriptionModel.hydrate(response)
247247
} onFailure: { error in
248248
OneSignalLog.onesignalLog(.LL_ERROR, message: "OSSubscriptionOperationExecutor create subscription request failed with error: \(error.debugDescription)")
249-
// TODO: Differentiate error cases
250-
// If the error is not retryable, remove from cache and queue
251-
if let nsError = error as? NSError,
252-
nsError.code < 500 && nsError.code != 0 {
253-
self.addRequestQueue.removeAll(where: { $0 == request})
254-
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_SUBSCRIPTION_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self.addRequestQueue)
249+
if let nsError = error as? NSError {
250+
let responseType = OSNetworkingUtils.getResponseStatusType(nsError.code)
251+
if responseType == .missing {
252+
self.addRequestQueue.removeAll(where: { $0 == request})
253+
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_SUBSCRIPTION_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self.addRequestQueue)
254+
// Logout if the user in the SDK is the same
255+
guard OneSignalUserManagerImpl.sharedInstance.isCurrentUser(request.identityModel)
256+
else {
257+
return
258+
}
259+
// The subscription has been deleted along with the user, so remove the subscription_id but keep the same push subscription model
260+
OneSignalUserManagerImpl.sharedInstance.pushSubscriptionModelStore.getModels()[OS_PUSH_SUBSCRIPTION_MODEL_KEY]?.subscriptionId = nil
261+
OneSignalUserManagerImpl.sharedInstance._logout()
262+
} else if responseType != .retryable {
263+
// Fail, no retry, remove from cache and queue
264+
self.addRequestQueue.removeAll(where: { $0 == request})
265+
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_SUBSCRIPTION_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self.addRequestQueue)
266+
}
255267
}
256268
}
257269
}
@@ -276,12 +288,14 @@ class OSSubscriptionOperationExecutor: OSOperationExecutor {
276288

277289
} onFailure: { error in
278290
OneSignalLog.onesignalLog(.LL_ERROR, message: "OSSubscriptionOperationExecutor delete subscription request failed with error: \(error.debugDescription)")
279-
// TODO: Differentiate error cases
280-
// If the error is not retryable, remove from cache and queue
281-
if let nsError = error as? NSError,
282-
nsError.code < 500 && nsError.code != 0 {
283-
self.removeRequestQueue.removeAll(where: { $0 == request})
284-
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_SUBSCRIPTION_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self.removeRequestQueue)
291+
if let nsError = error as? NSError {
292+
let responseType = OSNetworkingUtils.getResponseStatusType(nsError.code)
293+
if responseType != .retryable {
294+
// Fail, no retry, remove from cache and queue
295+
// If this request returns a missing status, that is ok as this is a delete request
296+
self.removeRequestQueue.removeAll(where: { $0 == request})
297+
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_SUBSCRIPTION_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self.removeRequestQueue)
298+
}
285299
}
286300
}
287301
}
@@ -306,12 +320,13 @@ class OSSubscriptionOperationExecutor: OSOperationExecutor {
306320

307321
} onFailure: { error in
308322
OneSignalLog.onesignalLog(.LL_ERROR, message: "OSSubscriptionOperationExecutor update subscription request failed with error: \(error.debugDescription)")
309-
// TODO: Differentiate error cases
310-
// If the error is not retryable, remove from cache and queue
311-
if let nsError = error as? NSError,
312-
nsError.code < 500 && nsError.code != 0 {
313-
self.updateRequestQueue.removeAll(where: { $0 == request})
314-
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_SUBSCRIPTION_EXECUTOR_UPDATE_REQUEST_QUEUE_KEY, withValue: self.updateRequestQueue)
323+
if let nsError = error as? NSError {
324+
let responseType = OSNetworkingUtils.getResponseStatusType(nsError.code)
325+
if responseType != .retryable {
326+
// Fail, no retry, remove from cache and queue
327+
self.updateRequestQueue.removeAll(where: { $0 == request})
328+
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_SUBSCRIPTION_EXECUTOR_UPDATE_REQUEST_QUEUE_KEY, withValue: self.updateRequestQueue)
329+
}
315330
}
316331
}
317332
}

0 commit comments

Comments
 (0)