Skip to content

Commit 90b46c9

Browse files
wip: add flag decision method
1 parent b3e855e commit 90b46c9

File tree

4 files changed

+45
-34
lines changed

4 files changed

+45
-34
lines changed

Sources/Implementation/DefaultDecisionService.swift

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -226,23 +226,11 @@ class DefaultDecisionService: OPTDecisionService {
226226
var decisions = [DecisionResponse<FeatureDecision>]()
227227

228228
for featureFlag in featureFlags {
229-
var decisionResponse = getVariationForFeature(config: config, featureFlag: featureFlag, user: user, userProfileTracker: profileTracker)
229+
let flagDecisionResponse = getDecisionForFlag(config: config, featureFlag: featureFlag, user: user, userProfileTracker: profileTracker)
230+
reasons.merge(flagDecisionResponse.reasons)
230231

231-
reasons.merge(decisionResponse.reasons)
232-
233-
if let decision = decisionResponse.result {
232+
if let decision = flagDecisionResponse.result {
234233
decisions.append(DecisionResponse(result: decision, reasons: reasons))
235-
continue
236-
}
237-
238-
decisionResponse = getVariationForFeatureRollout(config: config, featureFlag: featureFlag, user: user)
239-
240-
reasons.merge(decisionResponse.reasons)
241-
242-
if let decision = decisionResponse.result {
243-
decisions.append(DecisionResponse(result: decision, reasons: reasons))
244-
} else {
245-
decisions.append(DecisionResponse(result: nil, reasons: reasons))
246234
}
247235
}
248236

@@ -254,6 +242,43 @@ class DefaultDecisionService: OPTDecisionService {
254242
return decisions
255243
}
256244

245+
func getDecisionForFlag(config: ProjectConfig,
246+
featureFlag: FeatureFlag,
247+
user: OptimizelyUserContext,
248+
userProfileTracker: UserProfileTracker? = nil,
249+
options: [OptimizelyDecideOption]? = nil) -> DecisionResponse<FeatureDecision> {
250+
let reasons = DecisionReasons(options: options)
251+
252+
let holdouts = config.getHoldoutForFlag(id: featureFlag.id)
253+
for holdout in holdouts {
254+
let holdoutDecision = getVariationForHoldout(config: config,
255+
flagKey: featureFlag.key,
256+
holdout: holdout,
257+
user: user)
258+
reasons.merge(holdoutDecision.reasons)
259+
if let variation = holdoutDecision.result {
260+
let featureDicision = FeatureDecision(experiment: holdout, variation: variation, source: Constants.DecisionSource.holdout.rawValue)
261+
return DecisionResponse(result: featureDicision, reasons: reasons)
262+
}
263+
}
264+
265+
let flagExpDecision = getVariationForFeatureExperiments(config: config, featureFlag: featureFlag, user: user, userProfileTracker: userProfileTracker)
266+
reasons.merge(flagExpDecision.reasons)
267+
268+
if let decision = flagExpDecision.result {
269+
return DecisionResponse(result: decision, reasons: reasons)
270+
}
271+
272+
let rolloutDecision = getVariationForFeatureRollout(config: config, featureFlag: featureFlag, user: user)
273+
reasons.merge(rolloutDecision.reasons)
274+
275+
if let decision = rolloutDecision.result {
276+
return DecisionResponse(result: decision, reasons: reasons)
277+
} else {
278+
return DecisionResponse(result: nil, reasons: reasons)
279+
}
280+
}
281+
257282
/// Determines the feature decision for a feature flag, considering experiments and holdouts.
258283
/// - Parameters:
259284
/// - config: The project configuration.
@@ -262,26 +287,13 @@ class DefaultDecisionService: OPTDecisionService {
262287
/// - userProfileTracker: Optional tracker for user profile data.
263288
/// - options: Optional decision options.
264289
/// - Returns: A `DecisionResponse` with the feature decision (if any) and reasons.
265-
func getVariationForFeature(config: ProjectConfig,
290+
func getVariationForFeatureExperiments(config: ProjectConfig,
266291
featureFlag: FeatureFlag,
267292
user: OptimizelyUserContext,
268293
userProfileTracker: UserProfileTracker? = nil,
269294
options: [OptimizelyDecideOption]? = nil) -> DecisionResponse<FeatureDecision> {
270295
let reasons = DecisionReasons(options: options)
271296

272-
let holdouts = config.getHoldoutForFlag(id: featureFlag.id)
273-
for holdout in holdouts {
274-
let dicisionResponse = getVariationForHoldout(config: config,
275-
flagKey: featureFlag.key,
276-
holdout: holdout,
277-
user: user)
278-
reasons.merge(dicisionResponse.reasons)
279-
if let variation = dicisionResponse.result {
280-
let featureDicision = FeatureDecision(experiment: holdout, variation: variation, source: Constants.DecisionSource.holdout.rawValue)
281-
return DecisionResponse(result: featureDicision, reasons: reasons)
282-
}
283-
}
284-
285297
let experimentIds = featureFlag.experimentIds
286298
if experimentIds.isEmpty {
287299
let info = LogMessage.featureHasNoExperiments(featureFlag.key)

Tests/OptimizelyTests-Common/DecisionListenerTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1263,7 +1263,7 @@ class FakeDecisionService: DefaultDecisionService {
12631263
return DecisionResponse.responseNoReasons(result: featureDecision)
12641264
}
12651265

1266-
override func getVariationForFeature(config: ProjectConfig, featureFlag: FeatureFlag, user: OptimizelyUserContext, userProfileTracker: UserProfileTracker? = nil, options: [OptimizelyDecideOption]? = nil) -> DecisionResponse<FeatureDecision> {
1266+
override func getVariationForFeatureExperiments(config: ProjectConfig, featureFlag: FeatureFlag, user: OptimizelyUserContext, userProfileTracker: UserProfileTracker? = nil, options: [OptimizelyDecideOption]? = nil) -> DecisionResponse<FeatureDecision> {
12671267
guard let experiment = self.experiment, let tmpVariation = self.variation else {
12681268
return DecisionResponse.nilNoReasons()
12691269
}

Tests/OptimizelyTests-Common/DecisionServiceTests_Features.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ class DecisionServiceTests_Features: XCTestCase {
258258
extension DecisionServiceTests_Features {
259259

260260
func testGetVariationForFeatureExperimentWhenMatched() {
261-
let pair = self.decisionService.getVariationForFeature(config: config,
261+
let pair = self.decisionService.getVariationForFeatureExperiments(config: config,
262262
featureFlag: featureFlag,
263263
user: optimizely.createUserContext(userId: kUserId,
264264
attributes: kAttributesCountryMatch)).result
@@ -268,7 +268,7 @@ extension DecisionServiceTests_Features {
268268
}
269269

270270
func testGetVariationForFeatureExperimentWhenNotMatched() {
271-
let pair = self.decisionService.getVariationForFeature(config: config,
271+
let pair = self.decisionService.getVariationForFeatureExperiments(config: config,
272272
featureFlag: featureFlag,
273273
user: optimizely.createUserContext(userId: kUserId,
274274
attributes: kAttributesCountryNotMatch)).result
@@ -280,7 +280,7 @@ extension DecisionServiceTests_Features {
280280
featureFlag.experimentIds = ["99999"] // not-existing experiment
281281
self.config.project.featureFlags = [featureFlag]
282282

283-
let pair = self.decisionService.getVariationForFeature(config: config,
283+
let pair = self.decisionService.getVariationForFeatureExperiments(config: config,
284284
featureFlag: featureFlag,
285285
user: optimizely.createUserContext(userId: kUserId,
286286
attributes: kAttributesCountryMatch)).result

Tests/OptimizelyTests-Common/OptimizelyUserContextTests_Decide_Reasons.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import XCTest
1818

1919
class OptimizelyUserContextTests_Decide_Reasons: XCTestCase {
20-
/// Need to add testcases for holdout
2120
let kUserId = "tester"
2221

2322
var optimizely: OptimizelyClient!

0 commit comments

Comments
 (0)