diff --git a/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/OSDelta.swift b/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/OSDelta.swift index 5eb03c73c..39220214d 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/OSDelta.swift +++ b/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/OSDelta.swift @@ -39,7 +39,7 @@ open class OSDelta: NSObject, NSCoding { public let value: Any override open var description: String { - return "OSDelta \(name) with property: \(property) value: \(value)" + return "" } public init(name: String, model: OSModel, property: String, value: Any) { diff --git a/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/OSOperationExecutor.swift b/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/OSOperationExecutor.swift index db3aee576..63c5e7a5d 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/OSOperationExecutor.swift +++ b/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/OSOperationExecutor.swift @@ -27,8 +27,9 @@ import OneSignalCore -// TODO: Concrete executors drop OSDeltas and Requests when initializing from the cache, when they cannot be connected to their respective models anymore. Revisit this behavior of dropping. - +/** + Concrete executors drop OSDeltas and Requests when initializing from the cache, when they cannot be connected to their respective models anymore. These cannot be sent, so they are dropped.. + */ public protocol OSOperationExecutor { var supportedDeltas: [String] { get } var deltaQueue: [OSDelta] { get } diff --git a/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/OSOperationRepo.swift b/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/OSOperationRepo.swift index 6da7b4553..5a9fd5d58 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/OSOperationRepo.swift +++ b/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/OSOperationRepo.swift @@ -71,8 +71,9 @@ public class OSOperationRepo: NSObject { // Read the Deltas from cache, if any... if let deltaQueue = OneSignalUserDefaults.initShared().getSavedCodeableData(forKey: OS_OPERATION_REPO_DELTA_QUEUE_KEY, defaultValue: []) as? [OSDelta] { self.deltaQueue = deltaQueue + OneSignalLog.onesignalLog(.LL_VERBOSE, message: "OSOperationRepo.start() with deltaQueue: \(deltaQueue)") } else { - // log error + OneSignalLog.onesignalLog(.LL_ERROR, message: "OSOperationRepo.start() is unable to uncache the OSDelta queue.") } pollFlushQueue() diff --git a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSIdentityOperationExecutor.swift b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSIdentityOperationExecutor.swift index 9d6e95772..06cfe3175 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSIdentityOperationExecutor.swift +++ b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSIdentityOperationExecutor.swift @@ -49,6 +49,7 @@ class OSIdentityOperationExecutor: OSOperationExecutor { } } self.deltaQueue = deltaQueue + OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_IDENTITY_EXECUTOR_DELTA_QUEUE_KEY, withValue: self.deltaQueue) } else { OneSignalLog.onesignalLog(.LL_ERROR, message: "OSIdentityOperationExecutor error encountered reading from cache for \(OS_IDENTITY_EXECUTOR_DELTA_QUEUE_KEY)") } @@ -70,6 +71,7 @@ class OSIdentityOperationExecutor: OSOperationExecutor { } } self.addRequestQueue = addRequestQueue + OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self.addRequestQueue) } else { OneSignalLog.onesignalLog(.LL_ERROR, message: "OSIdentityOperationExecutor error encountered reading from cache for \(OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY)") } @@ -89,6 +91,7 @@ class OSIdentityOperationExecutor: OSOperationExecutor { } } self.removeRequestQueue = removeRequestQueue + OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self.removeRequestQueue) } else { OneSignalLog.onesignalLog(.LL_ERROR, message: "OSIdentityOperationExecutor error encountered reading from cache for \(OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY)") } diff --git a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSPropertyOperationExecutor.swift b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSPropertyOperationExecutor.swift index fe83f5c81..eea593d9e 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSPropertyOperationExecutor.swift +++ b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSPropertyOperationExecutor.swift @@ -47,10 +47,12 @@ class OSPropertyOperationExecutor: OSOperationExecutor { delta.model = modelInStore } else { // 2. The model does not exist, drop this Delta + OneSignalLog.onesignalLog(.LL_WARN, message: "OSPropertyOperationExecutor.init dropped: \(delta)") deltaQueue.remove(at: index) } } self.deltaQueue = deltaQueue + OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_PROPERTIES_EXECUTOR_DELTA_QUEUE_KEY, withValue: self.deltaQueue) } else { OneSignalLog.onesignalLog(.LL_ERROR, message: "OSPropertyOperationExecutor error encountered reading from cache for \(OS_PROPERTIES_EXECUTOR_DELTA_QUEUE_KEY)") } @@ -71,10 +73,12 @@ class OSPropertyOperationExecutor: OSOperationExecutor { request.identityModel = identityModel } else if !request.prepareForExecution() { // 3. The identitymodel do not exist AND this request cannot be sent, drop this Request + OneSignalLog.onesignalLog(.LL_WARN, message: "OSPropertyOperationExecutor.init dropped: \(request)") updateRequestQueue.remove(at: index) } } self.updateRequestQueue = updateRequestQueue + OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_PROPERTIES_EXECUTOR_UPDATE_REQUEST_QUEUE_KEY, withValue: self.updateRequestQueue) } else { OneSignalLog.onesignalLog(.LL_ERROR, message: "OSPropertyOperationExecutor error encountered reading from cache for \(OS_PROPERTIES_EXECUTOR_UPDATE_REQUEST_QUEUE_KEY)") } diff --git a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSSubscriptionOperationExecutor.swift b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSSubscriptionOperationExecutor.swift index c7755bab1..499705bad 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSSubscriptionOperationExecutor.swift +++ b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSSubscriptionOperationExecutor.swift @@ -51,6 +51,7 @@ class OSSubscriptionOperationExecutor: OSOperationExecutor { } } self.deltaQueue = deltaQueue + OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_SUBSCRIPTION_EXECUTOR_DELTA_QUEUE_KEY, withValue: self.deltaQueue) } else { OneSignalLog.onesignalLog(.LL_ERROR, message: "OSSubscriptionOperationExecutor error encountered reading from cache for \(OS_SUBSCRIPTION_EXECUTOR_DELTA_QUEUE_KEY)") } @@ -87,6 +88,7 @@ class OSSubscriptionOperationExecutor: OSOperationExecutor { requestQueue.append(request) } self.addRequestQueue = requestQueue + OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_SUBSCRIPTION_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self.addRequestQueue) } else { OneSignalLog.onesignalLog(.LL_ERROR, message: "OSSubscriptionOperationExecutor error encountered reading from cache for \(OS_SUBSCRIPTION_EXECUTOR_ADD_REQUEST_QUEUE_KEY)") } @@ -106,6 +108,7 @@ class OSSubscriptionOperationExecutor: OSOperationExecutor { } } self.removeRequestQueue = removeRequestQueue + OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_SUBSCRIPTION_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self.removeRequestQueue) } else { OneSignalLog.onesignalLog(.LL_ERROR, message: "OSSubscriptionOperationExecutor error encountered reading from cache for \(OS_SUBSCRIPTION_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY)") } @@ -125,6 +128,7 @@ class OSSubscriptionOperationExecutor: OSOperationExecutor { } } self.updateRequestQueue = updateRequestQueue + OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_SUBSCRIPTION_EXECUTOR_UPDATE_REQUEST_QUEUE_KEY, withValue: self.updateRequestQueue) } else { OneSignalLog.onesignalLog(.LL_ERROR, message: "OSSubscriptionOperationExecutor error encountered reading from cache for \(OS_SUBSCRIPTION_EXECUTOR_UPDATE_REQUEST_QUEUE_KEY)") } diff --git a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSUserExecutor.swift b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSUserExecutor.swift index c8b2d5e78..be0758ebc 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSUserExecutor.swift +++ b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSUserExecutor.swift @@ -91,6 +91,12 @@ class OSUserExecutor { identityModels[req.identityModelToUpdate.modelId] = req.identityModelToUpdate } else { // 4. Both models don't exist yet + // Drop the request if the identityModelToIdentify does not already exist AND the request is missing OSID + // Otherwise, this request will forever fail `prepareForExecution` and block pending requests such as recovery calls to `logout` or `login` + guard request.prepareForExecution() else { + OneSignalLog.onesignalLog(.LL_ERROR, message: "OSUserExecutor.start() dropped: \(request)") + continue + } identityModels[req.identityModelToIdentify.modelId] = req.identityModelToIdentify identityModels[req.identityModelToUpdate.modelId] = req.identityModelToUpdate } @@ -99,7 +105,7 @@ class OSUserExecutor { } } self.userRequestQueue = userRequestQueue - + OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_USER_EXECUTOR_USER_REQUEST_QUEUE_KEY, withValue: self.userRequestQueue) // Read unfinished Transfer Subscription requests from cache, if any... if let transferSubscriptionRequestQueue = OneSignalUserDefaults.initShared().getSavedCodeableData(forKey: OS_USER_EXECUTOR_TRANSFER_SUBSCRIPTION_REQUEST_QUEUE_KEY, defaultValue: []) as? [OSRequestTransferSubscription] { // We only care about the last transfer subscription request @@ -111,14 +117,14 @@ class OSUserExecutor { self.transferSubscriptionRequestQueue = [request] } else if !request.prepareForExecution() { // The model do not exist AND this request cannot be sent, drop this Request - OneSignalLog.onesignalLog(.LL_ERROR, message: "OSUserExecutor.start() reading request \(request) from cache failed. Dropping request.") + OneSignalLog.onesignalLog(.LL_ERROR, message: "OSUserExecutor.start() dropped: \(request)") self.transferSubscriptionRequestQueue = [] } } } else { OneSignalLog.onesignalLog(.LL_ERROR, message: "OSUserExecutor error encountered reading from cache for \(OS_USER_EXECUTOR_TRANSFER_SUBSCRIPTION_REQUEST_QUEUE_KEY)") } - + OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_USER_EXECUTOR_TRANSFER_SUBSCRIPTION_REQUEST_QUEUE_KEY, withValue: self.transferSubscriptionRequestQueue) executePendingRequests() } @@ -144,6 +150,7 @@ class OSUserExecutor { static func executePendingRequests() { let requestQueue: [OSUserRequest] = userRequestQueue + transferSubscriptionRequestQueue + OneSignalLog.onesignalLog(.LL_VERBOSE, message: "OSUserExecutor.executePendingRequests called with queue \(requestQueue)") if requestQueue.isEmpty { return @@ -155,6 +162,7 @@ class OSUserExecutor { }) { // Return as soon as we reach an un-executable request if !request.prepareForExecution() { + OneSignalLog.onesignalLog(.LL_WARN, message: "OSUserExecutor.executePendingRequests() is blocked by unexecutable request \(request)") return } @@ -388,10 +396,7 @@ class OSUserExecutor { request.sentToClient = true OneSignalCoreImpl.sharedClient().execute(request) { _ in removeFromQueue(request) - - // TODO: ... hydrate with returned identity object? executePendingRequests() - } onFailure: { error in OneSignalLog.onesignalLog(.LL_ERROR, message: "OSUserExecutor executeTransferPushSubscriptionRequest failed with error: \(error.debugDescription)") if let nsError = error as? NSError { diff --git a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/OneSignalUserManagerImpl.swift b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/OneSignalUserManagerImpl.swift index e63b4da46..92d161abd 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/OneSignalUserManagerImpl.swift +++ b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/OneSignalUserManagerImpl.swift @@ -260,7 +260,7 @@ public class OneSignalUserManagerImpl: NSObject, OneSignalUserManager { } start() guard externalId != "" else { - // Log error + OneSignalLog.onesignalLog(.LL_ERROR, message: "OneSignal.User login called with empty externalId. This is not allowed.") return } OneSignalLog.onesignalLog(.LL_VERBOSE, message: "OneSignal.User login called with externalId: \(externalId)") @@ -539,7 +539,7 @@ extension OneSignalUserManagerImpl { @objc public func startNewSession() { OneSignalLog.onesignalLog(.LL_VERBOSE, message: "OneSignalUserManagerImpl starting new session") - guard !OneSignalConfigManager.shouldAwaitAppIdAndLogMissingPrivacyConsent(forMethod: nil) else { + guard !OneSignalConfigManager.shouldAwaitAppIdAndLogMissingPrivacyConsent(forMethod: "_startNewSession") else { return } start() @@ -549,9 +549,12 @@ extension OneSignalUserManagerImpl { updateSession(sessionCount: 1, sessionTime: nil, refreshDeviceMetadata: true) // Fetch the user's data if there is a onesignal_id - // TODO: What if onesignal_id is missing, because we may init a user from cache but it may be missing onesignal_id. Is this ok. if let onesignalId = onesignalId { OSUserExecutor.fetchUser(aliasLabel: OS_ONESIGNAL_ID, aliasId: onesignalId, identityModel: user.identityModel, onNewSession: true) + } else { + // It is possible to init a user from cache who is missing the onesignalId + // This can happen if any createUser or identifyUser requests are cached + OneSignalLog.onesignalLog(.LL_WARN, message: "OneSignalUserManagerImpl.startNewSession() is unable to fetch user with External ID \(externalId ?? "nil") due to null OneSignal ID") } } diff --git a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Requests/OSRequestCreateUser.swift b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Requests/OSRequestCreateUser.swift index b52fb2195..b356bcd49 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Requests/OSRequestCreateUser.swift +++ b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Requests/OSRequestCreateUser.swift @@ -66,7 +66,7 @@ class OSRequestCreateUser: OneSignalRequest, OSUserRequest { self.identityModel = identityModel self.pushSubscriptionModel = pushSubscriptionModel self.originalPushToken = originalPushToken - self.stringDescription = "OSRequestCreateUser" + self.stringDescription = "" super.init() var params: [String: Any] = [:] @@ -114,7 +114,7 @@ class OSRequestCreateUser: OneSignalRequest, OSUserRequest { self.identityModel = identityModel self.pushSubscriptionModel = pushSubscriptionModel self.originalPushToken = coder.decodeObject(forKey: "originalPushToken") as? String - self.stringDescription = "OSRequestCreateUser" + self.stringDescription = "" super.init() self.parameters = parameters self.method = HTTPMethod(rawValue: rawMethod) diff --git a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Requests/OSRequestIdentifyUser.swift b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Requests/OSRequestIdentifyUser.swift index 02aa0e318..90dcb0ea0 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Requests/OSRequestIdentifyUser.swift +++ b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Requests/OSRequestIdentifyUser.swift @@ -55,6 +55,7 @@ class OSRequestIdentifyUser: OneSignalRequest, OSUserRequest { } else { // self.path is non-nil, so set to empty string self.path = "" + OneSignalLog.onesignalLog(.LL_DEBUG, message: "Cannot generate the Identify User request due to null app ID or null OneSignal ID.") return false } } @@ -71,7 +72,7 @@ class OSRequestIdentifyUser: OneSignalRequest, OSUserRequest { self.identityModelToUpdate = identityModelToUpdate self.aliasLabel = aliasLabel self.aliasId = aliasId - self.stringDescription = "OSRequestIdentifyUser with aliasLabel: \(aliasLabel) aliasId: \(aliasId)" + self.stringDescription = "" super.init() self.parameters = ["identity": [aliasLabel: aliasId]] self.method = PATCH @@ -105,7 +106,7 @@ class OSRequestIdentifyUser: OneSignalRequest, OSUserRequest { self.identityModelToUpdate = identityModelToUpdate self.aliasLabel = aliasLabel self.aliasId = aliasId - self.stringDescription = "OSRequestIdentifyUser with aliasLabel: \(aliasLabel) aliasId: \(aliasId)" + self.stringDescription = "" super.init() self.timestamp = timestamp self.parameters = parameters diff --git a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Requests/OSRequestUpdateProperties.swift b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Requests/OSRequestUpdateProperties.swift index dcbdeda34..1ad4b1de1 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Requests/OSRequestUpdateProperties.swift +++ b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Requests/OSRequestUpdateProperties.swift @@ -58,7 +58,7 @@ class OSRequestUpdateProperties: OneSignalRequest, OSUserRequest { init(properties: [String: Any], deltas: [String: Any]?, refreshDeviceMetadata: Bool?, modelToUpdate: OSPropertiesModel, identityModel: OSIdentityModel) { self.modelToUpdate = modelToUpdate self.identityModel = identityModel - self.stringDescription = "OSRequestUpdateProperties with properties: \(properties) deltas: \(String(describing: deltas)) refreshDeviceMetadata: \(String(describing: refreshDeviceMetadata))" + self.stringDescription = "" super.init() var propertiesObject = properties @@ -99,7 +99,7 @@ class OSRequestUpdateProperties: OneSignalRequest, OSUserRequest { } self.modelToUpdate = modelToUpdate self.identityModel = identityModel - self.stringDescription = "OSRequestUpdateProperties with parameters: \(parameters)" + self.stringDescription = "" super.init() self.parameters = parameters self.method = HTTPMethod(rawValue: rawMethod) diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignal.m b/iOS_SDK/OneSignalSDK/Source/OneSignal.m index 304d42a2e..b6f7531fc 100755 --- a/iOS_SDK/OneSignalSDK/Source/OneSignal.m +++ b/iOS_SDK/OneSignalSDK/Source/OneSignal.m @@ -357,7 +357,7 @@ + (void)startNewSession:(BOOL)fromInit { return; } - [OneSignalLog onesignalLog:ONE_S_LL_VERBOSE message:@"startNewSession"]; + [OneSignalLog onesignalLog:ONE_S_LL_VERBOSE message:@"OneSignal.startNewSession"]; // Run on the main queue as it is possible for this to be called from multiple queues. // Also some of the code in the method is not thread safe such as _outcomeEventsController. @@ -367,7 +367,7 @@ + (void)startNewSession:(BOOL)fromInit { } + (void)startNewSessionInternal { - [OneSignalLog onesignalLog:ONE_S_LL_VERBOSE message:@"startNewSessionInternal"]; + [OneSignalLog onesignalLog:ONE_S_LL_VERBOSE message:@"OneSignal.startNewSessionInternal"]; // return if the user has not granted privacy permissions if ([OSPrivacyConsentController shouldLogMissingPrivacyConsentErrorWithMethodName:nil])