Skip to content

Commit a8a796b

Browse files
feat: Duplicate experiment key issue with multi feature flag (#267)
1 parent a436510 commit a8a796b

File tree

3 files changed

+89
-8
lines changed

3 files changed

+89
-8
lines changed

OptimizelySDK/Bucketing/Bucketer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ public virtual Result<Variation> Bucket(ProjectConfig config, Experiment experim
150150
}
151151

152152
// success!
153-
variation = config.GetVariationFromId(experiment.Key, variationId);
153+
variation = config.GetVariationFromIdByExperimentId(experiment.Id, variationId);
154154
message = $"User [{userId}] is in variation [{variation.Key}] of experiment [{experiment.Key}].";
155155
Logger.Log(LogLevel.INFO, reasons.AddInfo(message));
156156
return Result<Variation>.NewResult(variation, reasons);

OptimizelySDK/Config/DatafileProjectConfig.cs

Lines changed: 70 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,20 @@ private Dictionary<string, Dictionary<string, Variation>> _VariationKeyMap
125125
= new Dictionary<string, Dictionary<string, Variation>>();
126126
public Dictionary<string, Dictionary<string, Variation>> VariationKeyMap { get { return _VariationKeyMap; } }
127127

128+
/// <summary>
129+
/// Associative array of experiment ID to associative array of variation key to variations
130+
/// </summary>
131+
private Dictionary<string, Dictionary<string, Variation>> _VariationKeyMapByExperimentId
132+
= new Dictionary<string, Dictionary<string, Variation>>();
133+
public Dictionary<string, Dictionary<string, Variation>> VariationKeyMapByExperimentId { get { return _VariationKeyMapByExperimentId; } }
134+
135+
/// <summary>
136+
/// Associative array of experiment ID to associative array of variation key to variations
137+
/// </summary>
138+
private Dictionary<string, Dictionary<string, Variation>> _VariationIdMapByExperimentId
139+
= new Dictionary<string, Dictionary<string, Variation>>();
140+
public Dictionary<string, Dictionary<string, Variation>> VariationKeyIdByExperimentId { get { return _VariationIdMapByExperimentId; } }
141+
128142

129143
/// <summary>
130144
/// Associative array of experiment key to associative array of variation ID to variations
@@ -244,9 +258,10 @@ private void Initialize()
244258
TypedAudiences = TypedAudiences ?? new Audience[0];
245259
FeatureFlags = FeatureFlags ?? new FeatureFlag[0];
246260
Rollouts = Rollouts ?? new Rollout[0];
261+
_ExperimentKeyMap = new Dictionary<string, Experiment>();
247262

248263
_GroupIdMap = ConfigParser<Group>.GenerateMap(entities: Groups, getKey: g => g.Id.ToString(), clone: true);
249-
_ExperimentKeyMap = ConfigParser<Experiment>.GenerateMap(entities: Experiments, getKey: e => e.Key, clone: true);
264+
_ExperimentIdMap = ConfigParser<Experiment>.GenerateMap(entities: Experiments, getKey: e => e.Id, clone: true);
250265
_EventKeyMap = ConfigParser<Entity.Event>.GenerateMap(entities: Events, getKey: e => e.Key, clone: true);
251266
_AttributeKeyMap = ConfigParser<Attribute>.GenerateMap(entities: Attributes, getKey: a => a.Key, clone: true);
252267
_AudienceIdMap = ConfigParser<Audience>.GenerateMap(entities: Audiences, getKey: a => a.Id.ToString(), clone: true);
@@ -260,7 +275,7 @@ private void Initialize()
260275

261276
foreach (Group group in Groups)
262277
{
263-
var experimentsInGroup = ConfigParser<Experiment>.GenerateMap(group.Experiments, getKey: e => e.Key, clone: true);
278+
var experimentsInGroup = ConfigParser<Experiment>.GenerateMap(group.Experiments, getKey: e => e.Id, clone: true);
264279
foreach (Experiment experiment in experimentsInGroup.Values)
265280
{
266281
experiment.GroupId = group.Id;
@@ -269,22 +284,27 @@ private void Initialize()
269284

270285
// RJE: I believe that this is equivalent to this:
271286
// $this->_experimentKeyMap = array_merge($this->_experimentKeyMap, $experimentsInGroup);
272-
foreach (string key in experimentsInGroup.Keys)
273-
_ExperimentKeyMap[key] = experimentsInGroup[key];
287+
foreach (var experiment in experimentsInGroup.Values)
288+
_ExperimentIdMap[experiment.Id] = experiment;
274289
}
275290

276-
foreach (Experiment experiment in _ExperimentKeyMap.Values)
291+
foreach (Experiment experiment in _ExperimentIdMap.Values)
277292
{
278293
_VariationKeyMap[experiment.Key] = new Dictionary<string, Variation>();
279294
_VariationIdMap[experiment.Key] = new Dictionary<string, Variation>();
280-
_ExperimentIdMap[experiment.Id] = experiment;
295+
_VariationIdMapByExperimentId[experiment.Id] = new Dictionary<string, Variation>();
296+
_VariationKeyMapByExperimentId[experiment.Id] = new Dictionary<string, Variation>();
281297

298+
_ExperimentKeyMap[experiment.Key] = experiment;
299+
282300
if (experiment.Variations != null)
283301
{
284302
foreach (Variation variation in experiment.Variations)
285303
{
286304
_VariationKeyMap[experiment.Key][variation.Key] = variation;
287305
_VariationIdMap[experiment.Key][variation.Id] = variation;
306+
_VariationKeyMapByExperimentId[experiment.Id][variation.Key] = variation;
307+
_VariationIdMapByExperimentId[experiment.Id][variation.Id] = variation;
288308
}
289309
}
290310
}
@@ -296,13 +316,17 @@ private void Initialize()
296316
{
297317
_VariationKeyMap[rolloutRule.Key] = new Dictionary<string, Variation>();
298318
_VariationIdMap[rolloutRule.Key] = new Dictionary<string, Variation>();
319+
_VariationIdMapByExperimentId[rolloutRule.Id] = new Dictionary<string, Variation>();
320+
_VariationKeyMapByExperimentId[rolloutRule.Id] = new Dictionary<string, Variation>();
299321

300322
if (rolloutRule.Variations != null)
301323
{
302324
foreach (var variation in rolloutRule.Variations)
303325
{
304326
_VariationKeyMap[rolloutRule.Key][variation.Key] = variation;
305327
_VariationIdMap[rolloutRule.Key][variation.Id] = variation;
328+
_VariationKeyMapByExperimentId[rolloutRule.Id][variation.Key] = variation;
329+
_VariationIdMapByExperimentId[rolloutRule.Id][variation.Id] = variation;
306330
}
307331
}
308332
}
@@ -474,8 +498,28 @@ public Variation GetVariationFromKey(string experimentKey, string variationKey)
474498
return new Variation();
475499
}
476500

501+
477502
/// <summary>
478-
/// Get the Variation from the Key/ID
503+
/// Get the Variation from the keys
504+
/// </summary>
505+
/// <param name="experimentId">Id for Experiment</param>
506+
/// <param name="variationKey">key for Variation</param>
507+
/// <returns>Variation Entity corresponding to the provided experiment key and variation key or a dummy
508+
/// entity if keys are invalid</returns>
509+
public Variation GetVariationFromKeyByExperimentId(string experimentId, string variationKey)
510+
{
511+
if (_VariationKeyMapByExperimentId.ContainsKey(experimentId) &&
512+
_VariationKeyMapByExperimentId[experimentId].ContainsKey(variationKey))
513+
return _VariationKeyMapByExperimentId[experimentId][variationKey];
514+
515+
string message = $@"No variation key ""{variationKey}"" defined in datafile for experiment ""{experimentId}"".";
516+
Logger.Log(LogLevel.ERROR, message);
517+
ErrorHandler.HandleError(new Exceptions.InvalidVariationException("Provided variation is not in datafile."));
518+
return new Variation();
519+
}
520+
521+
/// <summary>
522+
/// Get the Variation from the Key/Id
479523
/// </summary>
480524
/// <param name="experimentKey">key for Experiment</param>
481525
/// <param name="variationId">ID for Variation</param>
@@ -493,6 +537,25 @@ public Variation GetVariationFromId(string experimentKey, string variationId)
493537
return new Variation();
494538
}
495539

540+
/// <summary>
541+
/// Get the Variation from the expId/varId
542+
/// </summary>
543+
/// <param name="experimentId">ID for Experiment</param>
544+
/// <param name="variationId">ID for Variation</param>
545+
/// <returns>Variation Entity corresponding to the provided experiment key and variation ID or a dummy
546+
/// entity if experiment ID or variation ID is invalid</returns>
547+
public Variation GetVariationFromIdByExperimentId(string experimentId, string variationId)
548+
{
549+
if (_VariationIdMapByExperimentId.ContainsKey(experimentId) &&
550+
_VariationIdMapByExperimentId[experimentId].ContainsKey(variationId))
551+
return _VariationIdMapByExperimentId[experimentId][variationId];
552+
553+
string message = $@"No variation ID ""{variationId}"" defined in datafile for experiment ""{experimentId}"".";
554+
Logger.Log(LogLevel.ERROR, message);
555+
ErrorHandler.HandleError(new Exceptions.InvalidVariationException("Provided variation is not in datafile."));
556+
return new Variation();
557+
}
558+
496559
/// <summary>
497560
/// Get the feature from the key
498561
/// </summary>

OptimizelySDK/ProjectConfig.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,15 @@ public interface ProjectConfig
209209
/// entity if keys are invalid</returns>
210210
Variation GetVariationFromKey(string experimentKey, string variationKey);
211211

212+
/// <summary>
213+
/// Get the Variation from the keys
214+
/// </summary>
215+
/// <param name="experimentId">ID for Experiment</param>
216+
/// <param name="variationKey">key for Variation</param>
217+
/// <returns>Variation Entity corresponding to the provided experiment key and variation key or a dummy
218+
/// entity if keys are invalid</returns>
219+
Variation GetVariationFromKeyByExperimentId(string experimentId, string variationKey);
220+
212221
/// <summary>
213222
/// Get the Variation from the Key/ID
214223
/// </summary>
@@ -218,6 +227,15 @@ public interface ProjectConfig
218227
/// entity if key or ID is invalid</returns>
219228
Variation GetVariationFromId(string experimentKey, string variationId);
220229

230+
/// <summary>
231+
/// Get the Variation from the Key/ID
232+
/// </summary>
233+
/// <param name="experimentId">ID for Experiment</param>
234+
/// <param name="variationId">ID for Variation</param>
235+
/// <returns>Variation Entity corresponding to the provided experiment key and variation ID or a dummy
236+
/// entity if key or ID is invalid</returns>
237+
Variation GetVariationFromIdByExperimentId(string experimentId, string variationId);
238+
221239
/// <summary>
222240
/// Get the feature from the key
223241
/// </summary>

0 commit comments

Comments
 (0)