diff --git a/Sources/Implementation/DefaultDecisionService.swift b/Sources/Implementation/DefaultDecisionService.swift index 145702f0..eb590de0 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 { @@ -125,7 +126,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) } @@ -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 a75eaf11..fad9141e 100644 --- a/Sources/Optimizely+Decide/OptimizelyClient+Decide.swift +++ b/Sources/Optimizely+Decide/OptimizelyClient+Decide.swift @@ -297,6 +297,12 @@ extension OptimizelyClient { return OptimizelyDecision.errorDecision(key: flagKey, user: user, error: .featureKeyInvalid(flagKey)) } + let error = flagDecision?.error ?? false + + guard !error 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 f848dd71..02c54a46 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 d2b1e084..f9ccbca4 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." }