Skip to content

Commit 2a0f8ac

Browse files
authored
Merge pull request #154 from optimizely/yasir/decision-listener-new-changes
feat(decision-listener): Incorporated new decision notification listener changes.
2 parents d435d4f + ad354a2 commit 2a0f8ac

File tree

4 files changed

+172
-116
lines changed

4 files changed

+172
-116
lines changed

OptimizelySDK/Data Model/ProjectConfig.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class ProjectConfig : Codable {
2424
// NOTE: experiment.forcedVariations use [ExperimentKey: VariationKey] instead of ids
2525

2626
private var whitelistUsers = [String: [String: String]]()
27+
private var experimentFeatureMap = [String: [String]]()
2728

2829
init(datafile: Data) throws {
2930
do {
@@ -36,6 +37,7 @@ class ProjectConfig : Codable {
3637
if !isValidVersion(version: self.project.version) {
3738
throw OptimizelyError.dataFileVersionInvalid(self.project.version)
3839
}
40+
generateExperimentFeatureMap()
3941
}
4042

4143
convenience init(datafile: String) throws {
@@ -87,6 +89,20 @@ extension ProjectConfig {
8789
// old versions (< 4) of datafiles not supported
8890
return ["4"].contains(version)
8991
}
92+
93+
private func generateExperimentFeatureMap() {
94+
for feature in project.featureFlags {
95+
for id in feature.experimentIds {
96+
if var featureIdArray = experimentFeatureMap[id] {
97+
featureIdArray.append(feature.id)
98+
experimentFeatureMap[id] = featureIdArray
99+
}
100+
else {
101+
experimentFeatureMap[id] = [feature.id]
102+
}
103+
}
104+
}
105+
}
90106
}
91107

92108
// MARK: - Project Access
@@ -171,6 +187,13 @@ extension ProjectConfig {
171187
return project.getAudience(id: id)
172188
}
173189

190+
/**
191+
* Returns true if experiment belongs to any feature, false otherwise.
192+
*/
193+
func isFeatureExperiment(id: String) -> Bool {
194+
return experimentFeatureMap.keys.contains(id)
195+
}
196+
174197
/**
175198
* Get forced variation for a given experiment key and user id.
176199
*/

OptimizelySDK/Optimizely/OptimizelyManager.swift

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -292,21 +292,25 @@ open class OptimizelyManager: NSObject {
292292
throw OptimizelyError.experimentUnknown
293293
}
294294

295-
var args: Array<Any?> = (self.notificationCenter as! DefaultNotificationCenter).getArgumentsForDecisionListener(notificationType: Constants.DecisionTypeKeys.experiment, userId: userId, attributes: attributes)
295+
let decisionType = config.isFeatureExperiment(id: experiment.id) ? Constants.DecisionTypeKeys.featureTest : Constants.DecisionTypeKeys.abTest
296+
var args: Array<Any?> = (self.notificationCenter as! DefaultNotificationCenter).getArgumentsForDecisionListener(notificationType: decisionType, userId: userId, attributes: attributes)
296297

297298
var decisionInfo = [String:Any]()
298-
decisionInfo[Constants.NotificationKeys.experiment] = nil
299-
decisionInfo[Constants.NotificationKeys.variation] = nil
299+
var sourceInfo = [String:Any]()
300+
sourceInfo[Constants.ExperimentDecisionInfoKeys.experiment] = experiment.key
301+
sourceInfo[Constants.ExperimentDecisionInfoKeys.variation] = NSNull()
300302

301303
// fix DecisionService to throw error
302304
guard let variation = decisionService.getVariation(config: config, userId: userId, experiment: experiment, attributes: attributes ?? OptimizelyAttributes()) else {
305+
decisionInfo = sourceInfo
303306
args.append(decisionInfo)
304307
self.notificationCenter.sendNotifications(type: NotificationType.Decision.rawValue, args: args)
305308
throw OptimizelyError.variationUnknown
306309
}
307310

308-
decisionInfo[Constants.NotificationKeys.experiment] = experimentKey
309-
decisionInfo[Constants.NotificationKeys.variation] = variation.key
311+
sourceInfo[Constants.ExperimentDecisionInfoKeys.variation] = variation.key
312+
decisionInfo = sourceInfo
313+
310314
args.append(decisionInfo)
311315
self.notificationCenter.sendNotifications(type: NotificationType.Decision.rawValue, args: args)
312316

@@ -378,12 +382,13 @@ open class OptimizelyManager: NSObject {
378382
// fix DecisionService to throw error
379383
let pair = decisionService.getVariationForFeature(config: config, featureFlag: featureFlag, userId: userId, attributes: attributes ?? OptimizelyAttributes())
380384

381-
var args: Array<Any?> = (self.notificationCenter as! DefaultNotificationCenter).getArgumentsForDecisionListener(notificationType: Constants.DecisionTypeKeys.isFeatureEnabled, userId: userId, attributes: attributes)
385+
var args: Array<Any?> = (self.notificationCenter as! DefaultNotificationCenter).getArgumentsForDecisionListener(notificationType: Constants.DecisionTypeKeys.feature, userId: userId, attributes: attributes)
382386

383387
var decisionInfo = [String:Any]()
384388
decisionInfo[Constants.DecisionInfoKeys.feature] = featureKey
385-
decisionInfo[Constants.DecisionInfoKeys.source] = Constants.DecisionSource.Rollout
389+
decisionInfo[Constants.DecisionInfoKeys.source] = Constants.DecisionSource.rollout
386390
decisionInfo[Constants.DecisionInfoKeys.featureEnabled] = false
391+
decisionInfo[Constants.DecisionInfoKeys.sourceInfo] = [:]
387392

388393
guard let variation = pair?.variation else {
389394
args.append(decisionInfo)
@@ -396,8 +401,10 @@ open class OptimizelyManager: NSObject {
396401
// we came from an experiment if experiment is not nil
397402
if let experiment = pair?.experiment {
398403

399-
decisionInfo[Constants.DecisionInfoKeys.sourceExperiment] = experiment.key
400-
decisionInfo[Constants.DecisionInfoKeys.sourceVariation] = variation.key
404+
var sourceInfo = [String:Any]()
405+
sourceInfo[Constants.ExperimentDecisionInfoKeys.experiment] = experiment.key
406+
sourceInfo[Constants.ExperimentDecisionInfoKeys.variation] = variation.key
407+
decisionInfo[Constants.DecisionInfoKeys.sourceInfo] = sourceInfo
401408

402409
// TODO: fix to throw errors
403410
guard let body = BatchEventBuilder.createImpressionEvent(config: config,
@@ -427,7 +434,7 @@ open class OptimizelyManager: NSObject {
427434
}
428435

429436
decisionInfo[Constants.DecisionInfoKeys.featureEnabled] = featureEnabled
430-
decisionInfo[Constants.DecisionInfoKeys.source] = (pair?.experiment != nil ? Constants.DecisionSource.Experiment : Constants.DecisionSource.Rollout)
437+
decisionInfo[Constants.DecisionInfoKeys.source] = (pair?.experiment != nil ? Constants.DecisionSource.featureTest : Constants.DecisionSource.rollout)
431438
args.append(decisionInfo)
432439
self.notificationCenter.sendNotifications(type: NotificationType.Decision.rawValue, args: args)
433440

@@ -531,8 +538,7 @@ open class OptimizelyManager: NSObject {
531538
}
532539

533540
var decisionInfo = [String:Any]()
534-
decisionInfo[Constants.DecisionInfoKeys.sourceExperiment] = nil
535-
decisionInfo[Constants.DecisionInfoKeys.sourceVariation] = nil
541+
decisionInfo[Constants.DecisionInfoKeys.sourceInfo] = [:]
536542

537543
// TODO: [Jae] optional? fallback to empty string is OK?
538544
var featureValue = variable.defaultValue ?? ""
@@ -544,8 +550,10 @@ open class OptimizelyManager: NSObject {
544550
let decision = self.decisionService.getVariationForFeature(config: config, featureFlag: featureFlag, userId: userId, attributes: _attributes)
545551
if let decision = decision {
546552
if let experiment = decision.experiment {
547-
decisionInfo[Constants.DecisionInfoKeys.sourceExperiment] = experiment.key
548-
decisionInfo[Constants.DecisionInfoKeys.sourceVariation] = decision.variation?.key
553+
var sourceInfo = [String:Any]()
554+
sourceInfo[Constants.ExperimentDecisionInfoKeys.experiment] = experiment.key
555+
sourceInfo[Constants.ExperimentDecisionInfoKeys.variation] = decision.variation?.key
556+
decisionInfo[Constants.DecisionInfoKeys.sourceInfo] = sourceInfo
549557
}
550558
if let featureVariable = decision.variation?.variables?.filter({$0.id == variable.id}).first {
551559
if let featureEnabled = decision.variation?.featureEnabled, featureEnabled {
@@ -589,7 +597,7 @@ open class OptimizelyManager: NSObject {
589597
decisionInfo[Constants.DecisionInfoKeys.variable] = variableKey
590598
decisionInfo[Constants.DecisionInfoKeys.variableType] = typeName
591599
decisionInfo[Constants.DecisionInfoKeys.variableValue] = value
592-
decisionInfo[Constants.DecisionInfoKeys.source] = (decision?.experiment != nil ? Constants.DecisionSource.Experiment : Constants.DecisionSource.Rollout)
600+
decisionInfo[Constants.DecisionInfoKeys.source] = (decision?.experiment != nil ? Constants.DecisionSource.featureTest : Constants.DecisionSource.rollout)
593601
args.append(decisionInfo)
594602

595603
self.notificationCenter.sendNotifications(type: NotificationType.Decision.rawValue, args: args)

0 commit comments

Comments
 (0)