@@ -214,7 +214,6 @@ class DefaultDecisionService: OPTDecisionService {
214
214
user: OptimizelyUserContext ,
215
215
options: [ OptimizelyDecideOption ] ? = nil ) -> [ DecisionResponse < FeatureDecision > ] {
216
216
217
- let reasons = DecisionReasons ( options: options)
218
217
let userId = user. userId
219
218
let ignoreUPS = ( options ?? [ ] ) . contains ( . ignoreUserProfileService)
220
219
var profileTracker : UserProfileTracker ?
@@ -226,24 +225,8 @@ class DefaultDecisionService: OPTDecisionService {
226
225
var decisions = [ DecisionResponse < FeatureDecision > ] ( )
227
226
228
227
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)
247
230
}
248
231
249
232
// save profile
@@ -254,34 +237,66 @@ class DefaultDecisionService: OPTDecisionService {
254
237
return decisions
255
238
}
256
239
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
258
241
/// - Parameters:
259
242
/// - config: The project configuration.
260
243
/// - featureFlag: The feature flag to evaluate.
261
244
/// - user: The user context.
262
245
/// - userProfileTracker: Optional tracker for user profile data.
263
246
/// - options: Optional decision options.
264
247
/// - 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 > {
270
253
let reasons = DecisionReasons ( options: options)
271
254
272
255
let holdouts = config. getHoldoutForFlag ( id: featureFlag. id)
273
256
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 {
280
263
let featureDicision = FeatureDecision ( experiment: holdout, variation: variation, source: Constants . DecisionSource. holdout. rawValue)
281
264
return DecisionResponse ( result: featureDicision, reasons: reasons)
282
265
}
283
266
}
284
267
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
+
285
300
let experimentIds = featureFlag. experimentIds
286
301
if experimentIds. isEmpty {
287
302
let info = LogMessage . featureHasNoExperiments ( featureFlag. key)
0 commit comments