Skip to content

Commit

Permalink
Merge pull request #1279 from OneSignal/5.0.0/server_error_responses
Browse files Browse the repository at this point in the history
[5.0.0] Better handling server error responses
  • Loading branch information
nan-li committed Oct 30, 2023
2 parents 841a5d4 + 0fda0b1 commit b63e854
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,18 @@

// NS_ASSUME_NONNULL_BEGIN

typedef NS_ENUM(NSInteger, OSResponseStatusType) {
OSResponseStatusInvalid = 0,
OSResponseStatusRetryable,
OSResponseStatusUnauthorized,
OSResponseStatusMissing,
OSResponseStatusConflict
};

@interface OSNetworkingUtils : NSObject

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

@end

Expand Down
14 changes: 14 additions & 0 deletions iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSNetworkingUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,18 @@ + (NSNumber *)getNetType {
return @1;
}

+ (OSResponseStatusType)getResponseStatusType:(NSInteger)statusCode {
if (statusCode == 400 || statusCode == 402) {
return OSResponseStatusInvalid;
} else if (statusCode == 401 || statusCode == 403) {
return OSResponseStatusUnauthorized;
} else if (statusCode == 404 || statusCode == 410) {
return OSResponseStatusMissing;
} else if (statusCode == 409) {
return OSResponseStatusConflict;
} else {
return OSResponseStatusRetryable;
}
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -180,14 +180,35 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
self.addRequestQueue.removeAll(where: { $0 == request})
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self.addRequestQueue)
} onFailure: { error in
// TODO: What happened, maybe alias exists on another user
OneSignalLog.onesignalLog(.LL_ERROR, message: "OSIdentityOperationExecutor add aliases request failed with error: \(error.debugDescription)")
// TODO: Differentiate error cases
// If the error is not retryable, remove from cache and queue
if let nsError = error as? NSError,
nsError.code < 500 && nsError.code != 0 {
self.addRequestQueue.removeAll(where: { $0 == request})
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self.addRequestQueue)
if let nsError = error as? NSError {
let responseType = OSNetworkingUtils.getResponseStatusType(nsError.code)
if responseType == .missing {
// Remove from cache and queue
self.addRequestQueue.removeAll(where: { $0 == request})
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self.addRequestQueue)
// Logout if the user in the SDK is the same
guard OneSignalUserManagerImpl.sharedInstance.isCurrentUser(request.identityModel)
else {
return
}
// The subscription has been deleted along with the user, so remove the subscription_id but keep the same push subscription model
OneSignalUserManagerImpl.sharedInstance.pushSubscriptionModelStore.getModels()[OS_PUSH_SUBSCRIPTION_MODEL_KEY]?.subscriptionId = nil
OneSignalUserManagerImpl.sharedInstance._logout()
} else if responseType == .conflict {
self.addRequestQueue.removeAll(where: { $0 == request})
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self.addRequestQueue)
guard OneSignalUserManagerImpl.sharedInstance.isCurrentUser(request.identityModel)
else {
return
}
// Alias(es) already exists on another user, remove from identity model
OneSignalUserManagerImpl.sharedInstance.user.identityModel.removeAliases(Array(request.aliases.keys))
} else if responseType != .retryable {
// Fail, no retry, remove from cache and queue
self.addRequestQueue.removeAll(where: { $0 == request})
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self.addRequestQueue)
}
}
}
}
Expand All @@ -210,12 +231,15 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self.removeRequestQueue)
} onFailure: { error in
OneSignalLog.onesignalLog(.LL_ERROR, message: "OSIdentityOperationExecutor remove alias request failed with error: \(error.debugDescription)")
// TODO: Differentiate error cases
// If the error is not retryable, remove from cache and queue
if let nsError = error as? NSError,
nsError.code < 500 && nsError.code != 0 {
self.removeRequestQueue.removeAll(where: { $0 == request})
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self.removeRequestQueue)

if let nsError = error as? NSError {
let responseType = OSNetworkingUtils.getResponseStatusType(nsError.code)
if responseType != .retryable {
// Fail, no retry, remove from cache and queue
// A response of .missing could mean the alias doesn't exist on this user OR this user has been deleted
self.removeRequestQueue.removeAll(where: { $0 == request})
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self.removeRequestQueue)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,17 +135,30 @@ class OSPropertyOperationExecutor: OSOperationExecutor {

OneSignalClient.shared().execute(request) { _ in
// On success, remove request from cache, and we do need to hydrate
// TODO: We need to hydrate after all
// TODO: We need to hydrate after all ? What why ?
self.updateRequestQueue.removeAll(where: { $0 == request})
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_PROPERTIES_EXECUTOR_UPDATE_REQUEST_QUEUE_KEY, withValue: self.updateRequestQueue)
} onFailure: { error in
OneSignalLog.onesignalLog(.LL_ERROR, message: "OSPropertyOperationExecutor update properties request failed with error: \(error.debugDescription)")
// TODO: Differentiate error cases
// If the error is not retryable, remove from cache and queue
if let nsError = error as? NSError,
nsError.code < 500 && nsError.code != 0 {
self.updateRequestQueue.removeAll(where: { $0 == request})
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_PROPERTIES_EXECUTOR_UPDATE_REQUEST_QUEUE_KEY, withValue: self.updateRequestQueue)
if let nsError = error as? NSError {
let responseType = OSNetworkingUtils.getResponseStatusType(nsError.code)
if responseType == .missing {
// remove from cache and queue
self.updateRequestQueue.removeAll(where: { $0 == request})
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_PROPERTIES_EXECUTOR_UPDATE_REQUEST_QUEUE_KEY, withValue: self.updateRequestQueue)
// Logout if the user in the SDK is the same
guard OneSignalUserManagerImpl.sharedInstance.isCurrentUser(request.identityModel)
else {
return
}
// The subscription has been deleted along with the user, so remove the subscription_id but keep the same push subscription model
OneSignalUserManagerImpl.sharedInstance.pushSubscriptionModelStore.getModels()[OS_PUSH_SUBSCRIPTION_MODEL_KEY]?.subscriptionId = nil
OneSignalUserManagerImpl.sharedInstance._logout()
} else if responseType != .retryable {
// Fail, no retry, remove from cache and queue
self.updateRequestQueue.removeAll(where: { $0 == request})
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_PROPERTIES_EXECUTOR_UPDATE_REQUEST_QUEUE_KEY, withValue: self.updateRequestQueue)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,12 +246,24 @@ class OSSubscriptionOperationExecutor: OSOperationExecutor {
request.subscriptionModel.hydrate(response)
} onFailure: { error in
OneSignalLog.onesignalLog(.LL_ERROR, message: "OSSubscriptionOperationExecutor create subscription request failed with error: \(error.debugDescription)")
// TODO: Differentiate error cases
// If the error is not retryable, remove from cache and queue
if let nsError = error as? NSError,
nsError.code < 500 && nsError.code != 0 {
self.addRequestQueue.removeAll(where: { $0 == request})
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_SUBSCRIPTION_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self.addRequestQueue)
if let nsError = error as? NSError {
let responseType = OSNetworkingUtils.getResponseStatusType(nsError.code)
if responseType == .missing {
self.addRequestQueue.removeAll(where: { $0 == request})
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_SUBSCRIPTION_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self.addRequestQueue)
// Logout if the user in the SDK is the same
guard OneSignalUserManagerImpl.sharedInstance.isCurrentUser(request.identityModel)
else {
return
}
// The subscription has been deleted along with the user, so remove the subscription_id but keep the same push subscription model
OneSignalUserManagerImpl.sharedInstance.pushSubscriptionModelStore.getModels()[OS_PUSH_SUBSCRIPTION_MODEL_KEY]?.subscriptionId = nil
OneSignalUserManagerImpl.sharedInstance._logout()
} else if responseType != .retryable {
// Fail, no retry, remove from cache and queue
self.addRequestQueue.removeAll(where: { $0 == request})
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_SUBSCRIPTION_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self.addRequestQueue)
}
}
}
}
Expand All @@ -276,12 +288,14 @@ class OSSubscriptionOperationExecutor: OSOperationExecutor {

} onFailure: { error in
OneSignalLog.onesignalLog(.LL_ERROR, message: "OSSubscriptionOperationExecutor delete subscription request failed with error: \(error.debugDescription)")
// TODO: Differentiate error cases
// If the error is not retryable, remove from cache and queue
if let nsError = error as? NSError,
nsError.code < 500 && nsError.code != 0 {
self.removeRequestQueue.removeAll(where: { $0 == request})
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_SUBSCRIPTION_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self.removeRequestQueue)
if let nsError = error as? NSError {
let responseType = OSNetworkingUtils.getResponseStatusType(nsError.code)
if responseType != .retryable {
// Fail, no retry, remove from cache and queue
// If this request returns a missing status, that is ok as this is a delete request
self.removeRequestQueue.removeAll(where: { $0 == request})
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_SUBSCRIPTION_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self.removeRequestQueue)
}
}
}
}
Expand All @@ -306,12 +320,13 @@ class OSSubscriptionOperationExecutor: OSOperationExecutor {

} onFailure: { error in
OneSignalLog.onesignalLog(.LL_ERROR, message: "OSSubscriptionOperationExecutor update subscription request failed with error: \(error.debugDescription)")
// TODO: Differentiate error cases
// If the error is not retryable, remove from cache and queue
if let nsError = error as? NSError,
nsError.code < 500 && nsError.code != 0 {
self.updateRequestQueue.removeAll(where: { $0 == request})
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_SUBSCRIPTION_EXECUTOR_UPDATE_REQUEST_QUEUE_KEY, withValue: self.updateRequestQueue)
if let nsError = error as? NSError {
let responseType = OSNetworkingUtils.getResponseStatusType(nsError.code)
if responseType != .retryable {
// Fail, no retry, remove from cache and queue
self.updateRequestQueue.removeAll(where: { $0 == request})
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_SUBSCRIPTION_EXECUTOR_UPDATE_REQUEST_QUEUE_KEY, withValue: self.updateRequestQueue)
}
}
}
}
Expand Down
Loading

0 comments on commit b63e854

Please sign in to comment.