From 6d95172ce6dba42063e117cde8757eafe59810bb Mon Sep 17 00:00:00 2001 From: muzahidul-opti Date: Tue, 14 Oct 2025 23:18:17 +0600 Subject: [PATCH 1/2] fix: fix typo in log message - Update log message to remove unnecessary punctuation - Correct typo in log message for failed CMAB data fetch in experiment --- Sources/Implementation/DefaultDecisionService.swift | 2 +- .../Optimizely+Decide/OptimizelyClient+Decide.swift | 4 ++++ Sources/Optimizely+Decide/OptimizelyDecision.swift | 10 ++++++++++ Sources/Utils/LogMessage.swift | 2 +- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Sources/Implementation/DefaultDecisionService.swift b/Sources/Implementation/DefaultDecisionService.swift index 145702f05..99e25b88a 100644 --- a/Sources/Implementation/DefaultDecisionService.swift +++ b/Sources/Implementation/DefaultDecisionService.swift @@ -125,7 +125,7 @@ class DefaultDecisionService: OPTDecisionService { case .failure: let info = LogMessage.cmabFetchFailed(experiment.key) self.logger.e(info) - reasons.addInfo(info) + reasons.addError(info) let nilVariation = VariationDecision(variation: nil, cmabError: true, cmabUUID: nil) return DecisionResponse(result: nilVariation, reasons: reasons) } diff --git a/Sources/Optimizely+Decide/OptimizelyClient+Decide.swift b/Sources/Optimizely+Decide/OptimizelyClient+Decide.swift index a75eaf11a..4dfb7788c 100644 --- a/Sources/Optimizely+Decide/OptimizelyClient+Decide.swift +++ b/Sources/Optimizely+Decide/OptimizelyClient+Decide.swift @@ -297,6 +297,10 @@ extension OptimizelyClient { return OptimizelyDecision.errorDecision(key: flagKey, user: user, error: .featureKeyInvalid(flagKey)) } + guard flagDecision?.variation != nil else { + return OptimizelyDecision.errorDecision(key: flagKey, user: user, reasons: decisionReasons.toReport()) + } + let userId = user.userId let attributes = user.attributes let flagEnabled = flagDecision?.variation?.featureEnabled ?? false diff --git a/Sources/Optimizely+Decide/OptimizelyDecision.swift b/Sources/Optimizely+Decide/OptimizelyDecision.swift index f848dd719..02c54a46b 100644 --- a/Sources/Optimizely+Decide/OptimizelyDecision.swift +++ b/Sources/Optimizely+Decide/OptimizelyDecision.swift @@ -52,6 +52,16 @@ extension OptimizelyDecision { reasons: [error.reason]) } + static func errorDecision(key: String, user: OptimizelyUserContext, reasons: [String]) -> OptimizelyDecision { + return OptimizelyDecision(variationKey: nil, + enabled: false, + variables: OptimizelyJSON.createEmpty(), + ruleKey: nil, + flagKey: key, + userContext: user, + reasons: reasons) + } + var hasFailed: Bool { return variationKey == nil } diff --git a/Sources/Utils/LogMessage.swift b/Sources/Utils/LogMessage.swift index d2b1e0847..f9ccbca45 100644 --- a/Sources/Utils/LogMessage.swift +++ b/Sources/Utils/LogMessage.swift @@ -148,7 +148,7 @@ extension LogMessage: CustomStringConvertible { case .failedToAssignValue: message = "Value for path could not be assigned to provided type." case .valueForKeyNotFound(let key): message = "Value for JSON key (\(key)) not found." case .lowPeriodicDownloadInterval: message = "Polling intervals below 30 seconds are not recommended." - case .cmabFetchFailed(let key): message = "Failed to fetch CMAB data for experiment: \(key)." + case .cmabFetchFailed(let key): message = "Failed to fetch CMAB data for experiment \(key)." case .cmabNotSupportedInSyncMode: message = "CMAB is not supported in sync mode." } From 57b694df1727c51e51ae38185fd205161aecf561 Mon Sep 17 00:00:00 2001 From: muzahidul-opti Date: Tue, 14 Oct 2025 23:31:45 +0600 Subject: [PATCH 2/2] fix: correct error handling logic - Update FeatureDecision struct to include 'error' property - Update handling of errors in OptimizelyClient+Decide.swift - Adjust guard clause to properly check for errors before decision making --- Sources/Implementation/DefaultDecisionService.swift | 3 ++- Sources/Optimizely+Decide/OptimizelyClient+Decide.swift | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Sources/Implementation/DefaultDecisionService.swift b/Sources/Implementation/DefaultDecisionService.swift index 99e25b88a..eb590de03 100644 --- a/Sources/Implementation/DefaultDecisionService.swift +++ b/Sources/Implementation/DefaultDecisionService.swift @@ -21,6 +21,7 @@ struct FeatureDecision { let variation: Variation? let source: String var cmabUUID: String? + var error = false } struct VariationDecision { @@ -457,7 +458,7 @@ class DefaultDecisionService: OPTDecisionService { if result.cmabError { // For CMAB - we're supposed to get decision from the server. // If failed, return decision with nil variation, so the client can take care of them. - let featureDecision = FeatureDecision(experiment: experiment, variation: nil, source: Constants.DecisionSource.featureTest.rawValue) + let featureDecision = FeatureDecision(experiment: experiment, variation: nil, source: Constants.DecisionSource.featureTest.rawValue, error: true) return DecisionResponse(result: featureDecision, reasons: reasons) } else if let variation = result.variation { let featureDecision = FeatureDecision(experiment: experiment, variation: variation, source: Constants.DecisionSource.featureTest.rawValue, cmabUUID: result.cmabUUID) diff --git a/Sources/Optimizely+Decide/OptimizelyClient+Decide.swift b/Sources/Optimizely+Decide/OptimizelyClient+Decide.swift index 4dfb7788c..fad9141ee 100644 --- a/Sources/Optimizely+Decide/OptimizelyClient+Decide.swift +++ b/Sources/Optimizely+Decide/OptimizelyClient+Decide.swift @@ -297,7 +297,9 @@ extension OptimizelyClient { return OptimizelyDecision.errorDecision(key: flagKey, user: user, error: .featureKeyInvalid(flagKey)) } - guard flagDecision?.variation != nil else { + let error = flagDecision?.error ?? false + + guard !error else { return OptimizelyDecision.errorDecision(key: flagKey, user: user, reasons: decisionReasons.toReport()) }