Skip to content

Commit 015355c

Browse files
Merge branch 'muzahid/FSSDK-11373' into muzahid/FSSDK-11374
* muzahid/FSSDK-11373: wip: add code doc wip: fix flag decision logic wip: add flag decision method
2 parents 5d4b97a + 557f6ea commit 015355c

File tree

4 files changed

+50
-36
lines changed

4 files changed

+50
-36
lines changed

Sources/Implementation/DefaultDecisionService.swift

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,6 @@ class DefaultDecisionService: OPTDecisionService {
214214
user: OptimizelyUserContext,
215215
options: [OptimizelyDecideOption]? = nil) -> [DecisionResponse<FeatureDecision>] {
216216

217-
let reasons = DecisionReasons(options: options)
218217
let userId = user.userId
219218
let ignoreUPS = (options ?? []).contains(.ignoreUserProfileService)
220219
var profileTracker: UserProfileTracker?
@@ -226,24 +225,8 @@ class DefaultDecisionService: OPTDecisionService {
226225
var decisions = [DecisionResponse<FeatureDecision>]()
227226

228227
for featureFlag in featureFlags {
229-
var decisionResponse = getVariationForFeature(config: config, featureFlag: featureFlag, user: user, userProfileTracker: profileTracker)
230-
231-
reasons.merge(decisionResponse.reasons)
232-
233-
if let decision = decisionResponse.result {
234-
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))
246-
}
228+
let flagDecisionResponse = getDecisionForFlag(config: config, featureFlag: featureFlag, user: user, userProfileTracker: profileTracker)
229+
decisions.append(flagDecisionResponse)
247230
}
248231

249232
// save profile
@@ -254,34 +237,66 @@ class DefaultDecisionService: OPTDecisionService {
254237
return decisions
255238
}
256239

257-
/// Determines the feature decision for a feature flag, considering experiments and holdouts.
240+
/// Determines the feature decision for a feature flag, considering holdout, experiment and rollout
258241
/// - Parameters:
259242
/// - config: The project configuration.
260243
/// - featureFlag: The feature flag to evaluate.
261244
/// - user: The user context.
262245
/// - userProfileTracker: Optional tracker for user profile data.
263246
/// - options: Optional decision options.
264247
/// - Returns: A `DecisionResponse` with the feature decision (if any) and reasons.
265-
func getVariationForFeature(config: ProjectConfig,
266-
featureFlag: FeatureFlag,
267-
user: OptimizelyUserContext,
268-
userProfileTracker: UserProfileTracker? = nil,
269-
options: [OptimizelyDecideOption]? = nil) -> DecisionResponse<FeatureDecision> {
248+
func getDecisionForFlag(config: ProjectConfig,
249+
featureFlag: FeatureFlag,
250+
user: OptimizelyUserContext,
251+
userProfileTracker: UserProfileTracker? = nil,
252+
options: [OptimizelyDecideOption]? = nil) -> DecisionResponse<FeatureDecision> {
270253
let reasons = DecisionReasons(options: options)
271254

272255
let holdouts = config.getHoldoutForFlag(id: featureFlag.id)
273256
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 {
257+
let holdoutDecision = getVariationForHoldout(config: config,
258+
flagKey: featureFlag.key,
259+
holdout: holdout,
260+
user: user)
261+
reasons.merge(holdoutDecision.reasons)
262+
if let variation = holdoutDecision.result {
280263
let featureDicision = FeatureDecision(experiment: holdout, variation: variation, source: Constants.DecisionSource.holdout.rawValue)
281264
return DecisionResponse(result: featureDicision, reasons: reasons)
282265
}
283266
}
284267

268+
let flagExpDecision = getVariationForFeatureExperiments(config: config, featureFlag: featureFlag, user: user, userProfileTracker: userProfileTracker)
269+
reasons.merge(flagExpDecision.reasons)
270+
271+
if let decision = flagExpDecision.result {
272+
return DecisionResponse(result: decision, reasons: reasons)
273+
}
274+
275+
let rolloutDecision = getVariationForFeatureRollout(config: config, featureFlag: featureFlag, user: user)
276+
reasons.merge(rolloutDecision.reasons)
277+
278+
if let decision = rolloutDecision.result {
279+
return DecisionResponse(result: decision, reasons: reasons)
280+
} else {
281+
return DecisionResponse(result: nil, reasons: reasons)
282+
}
283+
}
284+
285+
/// Determines the feature decision for a feature flag, considering experiments
286+
/// - Parameters:
287+
/// - config: The project configuration.
288+
/// - featureFlag: The feature flag to evaluate.
289+
/// - user: The user context.
290+
/// - userProfileTracker: Optional tracker for user profile data.
291+
/// - options: Optional decision options.
292+
/// - Returns: A `DecisionResponse` with the feature decision (if any) and reasons.
293+
func getVariationForFeatureExperiments(config: ProjectConfig,
294+
featureFlag: FeatureFlag,
295+
user: OptimizelyUserContext,
296+
userProfileTracker: UserProfileTracker? = nil,
297+
options: [OptimizelyDecideOption]? = nil) -> DecisionResponse<FeatureDecision> {
298+
let reasons = DecisionReasons(options: options)
299+
285300
let experimentIds = featureFlag.experimentIds
286301
if experimentIds.isEmpty {
287302
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)