Skip to content

Commit 105a47c

Browse files
authored
Parse rollouts from datafile (#53)
1 parent a2a22e8 commit 105a47c

File tree

3 files changed

+235
-14
lines changed

3 files changed

+235
-14
lines changed

lib/optimizely/project_config.rb

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,17 @@ class ProjectConfig
2929
attr_reader :error_handler
3030
attr_reader :logger
3131

32-
attr_reader :parsing_succeeded
33-
attr_reader :version
3432
attr_reader :account_id
35-
attr_reader :project_id
3633
attr_reader :attributes
34+
attr_reader :audiences
3735
attr_reader :events
3836
attr_reader :experiments
3937
attr_reader :groups
38+
attr_reader :parsing_succeeded
39+
attr_reader :project_id
4040
attr_reader :revision
41-
attr_reader :audiences
41+
attr_reader :rollouts
42+
attr_reader :version
4243

4344
attr_reader :attribute_key_map
4445
attr_reader :audience_id_map
@@ -47,7 +48,8 @@ class ProjectConfig
4748
attr_reader :experiment_key_map
4849
attr_reader :feature_flag_key_map
4950
attr_reader :group_key_map
50-
attr_reader :audience_id_map
51+
attr_reader :rollout_id_map
52+
attr_reader :rollout_experiment_id_map
5153
attr_reader :variation_id_map
5254
attr_reader :variation_id_to_variable_usage_map
5355
attr_reader :variation_key_map
@@ -69,14 +71,15 @@ def initialize(datafile, logger, error_handler)
6971
end
7072

7173
@account_id = config['accountId']
72-
@project_id = config['projectId']
73-
@attributes = config['attributes']
74-
@events = config['events']
74+
@attributes = config.fetch('attributes', [])
75+
@audiences = config.fetch('audiences', [])
76+
@events = config.fetch('events', [])
7577
@experiments = config['experiments']
7678
@feature_flags = config.fetch('featureFlags', [])
77-
@revision = config['revision']
78-
@audiences = config['audiences']
7979
@groups = config.fetch('groups', [])
80+
@project_id = config['projectId']
81+
@revision = config['revision']
82+
@rollouts = config.fetch('rollouts', [])
8083

8184
# Utility maps for quick lookup
8285
@attribute_key_map = generate_key_map(@attributes, 'key')
@@ -94,7 +97,15 @@ def initialize(datafile, logger, error_handler)
9497
@variation_id_map = {}
9598
@variation_key_map = {}
9699
@variation_id_to_variable_usage_map = {}
97-
@experiment_key_map.each do |key, exp|
100+
@rollout_id_map = generate_key_map(@rollouts, 'id')
101+
# split out the experiment id map for rollouts
102+
@rollout_experiment_id_map = {}
103+
@rollout_id_map.each do |id, rollout|
104+
exps = rollout.fetch('experiments')
105+
@rollout_experiment_id_map = @rollout_experiment_id_map.merge(generate_key_map(exps, 'id'))
106+
end
107+
@all_experiments = @experiment_key_map.merge(@rollout_experiment_id_map)
108+
@all_experiments.each do |key, exp|
98109
variations = exp.fetch('variations')
99110
@variation_id_map[key] = generate_key_map(variations, 'id')
100111
@variation_key_map[key] = generate_key_map(variations, 'key')

spec/project_config_spec.rb

Lines changed: 149 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@
7979
'group1_exp1' => config_body['groups'][0]['experiments'][0].merge('groupId' => '101'),
8080
'group1_exp2' => config_body['groups'][0]['experiments'][1].merge('groupId' => '101'),
8181
'group2_exp1' => config_body['groups'][1]['experiments'][0].merge('groupId' => '102'),
82-
'group2_exp2' => config_body['groups'][1]['experiments'][1].merge('groupId' => '102')
82+
'group2_exp2' => config_body['groups'][1]['experiments'][1].merge('groupId' => '102'),
8383
}
8484

8585
expected_variation_id_map = {
@@ -234,6 +234,36 @@
234234
'key' => 'g2_e2_v2',
235235
'id' => '144446'
236236
}
237+
},
238+
'177770' => {
239+
'177771' => {
240+
'id' => '177771',
241+
'key' => '177771',
242+
'variables' => [
243+
{
244+
'id' => '155556',
245+
'value' => 'true'
246+
}
247+
]
248+
}
249+
},
250+
'177772' => {
251+
'177773' => {
252+
'id' => '177773',
253+
'key' => '177773',
254+
'variables' => [
255+
{
256+
'id' => '155556',
257+
'value' => 'false'
258+
}
259+
]
260+
}
261+
},
262+
'177774' => {
263+
'177775' => {
264+
'id' => '177775',
265+
'key' => '177775',
266+
}
237267
}
238268
}
239269

@@ -389,6 +419,36 @@
389419
'key' => 'g2_e2_v2',
390420
'id' => '144446'
391421
}
422+
},
423+
'177770' => {
424+
'177771' => {
425+
'id' => '177771',
426+
'key' => '177771',
427+
'variables' => [
428+
{
429+
'id' => '155556',
430+
'value' => 'true'
431+
}
432+
]
433+
}
434+
},
435+
'177772' => {
436+
'177773' => {
437+
'id' => '177773',
438+
'key' => '177773',
439+
'variables' => [
440+
{
441+
'id' => '155556',
442+
'value' => 'false'
443+
}
444+
]
445+
}
446+
},
447+
'177774' => {
448+
'177775' => {
449+
'id' => '177775',
450+
'key' => '177775',
451+
}
392452
}
393453
}
394454

@@ -431,7 +491,7 @@
431491
'boolean_single_variable_feature' => {
432492
'id'=> '155554',
433493
'key'=> 'boolean_single_variable_feature',
434-
'rolloutId'=> '',
494+
'rolloutId'=> '166660',
435495
'experimentIds'=> [],
436496
'variables'=> [
437497
{
@@ -556,9 +616,94 @@
556616
'id' => '155563',
557617
'value' => 'groupie_2_v2'
558618
}
619+
},
620+
'177771' => {
621+
'155556' =>{
622+
'id' => '155556',
623+
'value' => 'true'
624+
}
625+
},
626+
'177773' => {
627+
'155556' =>{
628+
'id' => '155556',
629+
'value' => 'false'
630+
}
559631
}
560632
}
561633

634+
expected_rollout_id_map = {
635+
'166660' => {
636+
'id' => '166660',
637+
'policy' => 'rollout',
638+
'experiments' => [{
639+
'id' => '177770',
640+
'key' => '177770',
641+
'status' => 'Running',
642+
'layerId' => '166660',
643+
'audienceIds' => ['11154'],
644+
'variations' => [{
645+
'id' => '177771',
646+
'key' => '177771',
647+
'variables' => [
648+
{
649+
'id' => '155556',
650+
'value' => 'true'
651+
}
652+
]
653+
}],
654+
'trafficAllocation' => [{
655+
'entityId' => '177771',
656+
'endOfRange' => 1000
657+
}]
658+
}, {
659+
'id' => '177772',
660+
'key' => '177772',
661+
'status' => 'Running',
662+
'layerId' => '166660',
663+
'audienceIds' => [],
664+
'variations' => [{
665+
'id' => '177773',
666+
'key' => '177773',
667+
'variables' => [
668+
{
669+
'id' => '155556',
670+
'value' => 'false'
671+
}
672+
]
673+
}],
674+
'trafficAllocation' => [{
675+
'entityId' => '177773',
676+
'endOfRange' => 10000
677+
}]
678+
}]
679+
},
680+
'166661' => {
681+
'id' => '166661',
682+
'policy' => 'rollout',
683+
'experiments' => [{
684+
'id' => '177774',
685+
'key' => '177774',
686+
'status' => 'Running',
687+
'layerId' => '166661',
688+
'audienceIds' => [],
689+
'variations' => [{
690+
'id' => '177775',
691+
'key' => '177775'
692+
}],
693+
'trafficAllocation' => [{
694+
'entityId' => '177775',
695+
'endOfRange' => 1500
696+
}]
697+
}]
698+
}
699+
}
700+
701+
expected_rollout_experiment_id_map = {
702+
'177770' => config_body['rollouts'][0]['experiments'][0],
703+
'177772' => config_body['rollouts'][0]['experiments'][1],
704+
'177774' => config_body['rollouts'][1]['experiments'][0],
705+
}
706+
562707
expect(project_config.attribute_key_map).to eq(expected_attribute_key_map)
563708
expect(project_config.audience_id_map).to eq(expected_audience_id_map)
564709
expect(project_config.event_key_map).to eq(expected_event_key_map)
@@ -567,6 +712,8 @@
567712
expect(project_config.variation_key_map).to eq(expected_variation_key_map)
568713
expect(project_config.feature_flag_key_map).to eq(expected_feature_flag_key_map)
569714
expect(project_config.variation_id_to_variable_usage_map).to eq(expected_variation_id_to_variable_usage_map)
715+
expect(project_config.rollout_id_map).to eq(expected_rollout_id_map)
716+
expect(project_config.rollout_experiment_id_map).to eq(expected_rollout_experiment_id_map)
570717
end
571718
end
572719

spec/spec_params.rb

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ module OptimizelySpec
361361
}, {
362362
'id'=> '155554',
363363
'key'=> 'boolean_single_variable_feature',
364-
'rolloutId'=> '',
364+
'rolloutId'=> '166660',
365365
'experimentIds'=> [],
366366
'variables'=> [
367367
{
@@ -416,6 +416,69 @@ module OptimizelySpec
416416
'defaultValue'=> 'null'
417417
}
418418
]
419+
}],
420+
'rollouts' => [{
421+
'id' => '166660',
422+
'policy' => 'rollout',
423+
'experiments' => [{
424+
'id' => '177770',
425+
'key' => '177770',
426+
'status' => 'Running',
427+
'layerId' => '166660',
428+
'audienceIds' => ['11154'],
429+
'variations' => [{
430+
'id' => '177771',
431+
'key' => '177771',
432+
'variables' => [
433+
{
434+
'id' => '155556',
435+
'value' => 'true'
436+
}
437+
]
438+
}],
439+
'trafficAllocation' => [{
440+
'entityId' => '177771',
441+
'endOfRange' => 1000
442+
}]
443+
}, {
444+
'id' => '177772',
445+
'key' => '177772',
446+
'status' => 'Running',
447+
'layerId' => '166660',
448+
'audienceIds' => [],
449+
'variations' => [{
450+
'id' => '177773',
451+
'key' => '177773',
452+
'variables' => [
453+
{
454+
'id' => '155556',
455+
'value' => 'false'
456+
}
457+
]
458+
}],
459+
'trafficAllocation' => [{
460+
'entityId' => '177773',
461+
'endOfRange' => 10000
462+
}]
463+
}]
464+
}, {
465+
'id' => '166661',
466+
'policy' => 'rollout',
467+
'experiments' => [{
468+
'id' => '177774',
469+
'key' => '177774',
470+
'status' => 'Running',
471+
'layerId' => '166661',
472+
'audienceIds' => [],
473+
'variations' => [{
474+
'id' => '177775',
475+
'key' => '177775'
476+
}],
477+
'trafficAllocation' => [{
478+
'entityId' => '177775',
479+
'endOfRange' => 1500
480+
}]
481+
}]
419482
}]
420483
}
421484

0 commit comments

Comments
 (0)