Skip to content

Commit c3ed2ab

Browse files
rashidspaliabbasrizvi
authored andcommitted
feat(DecisionListener): Adds experiment decision listener. (#159)
1 parent ca0a3fe commit c3ed2ab

File tree

4 files changed

+77
-7
lines changed

4 files changed

+77
-7
lines changed

lib/optimizely.rb

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,17 @@ def get_variation(experiment_key, user_id, attributes = nil)
143143
end
144144

145145
variation_id = @decision_service.get_variation(experiment_key, user_id, attributes)
146+
variation = @config.get_variation_from_id(experiment_key, variation_id) unless variation_id.nil?
147+
variation_key = variation['key'] if variation
146148

147-
unless variation_id.nil?
148-
variation = @config.get_variation_from_id(experiment_key, variation_id)
149-
return variation['key'] if variation
150-
end
151-
nil
149+
@notification_center.send_notifications(
150+
NotificationCenter::NOTIFICATION_TYPES[:DECISION],
151+
Helpers::Constants::DECISION_INFO_TYPES['EXPERIMENT'], user_id, (attributes || {}),
152+
experiment_key: experiment_key,
153+
variation_key: variation_key
154+
)
155+
156+
variation_key
152157
end
153158

154159
# Force a user into a variation for a given experiment.

lib/optimizely/helpers/constants.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,12 @@ module Constants
352352
'UNKNOWN_MATCH_TYPE' => 'Audience condition %s uses an unknown match type. You may need ' \
353353
'to upgrade to a newer release of the Optimizely SDK.'
354354
}.freeze
355+
356+
DECISION_INFO_TYPES = {
357+
'EXPERIMENT' => 'experiment',
358+
'FEATURE' => 'feature',
359+
'FEATURE_VARIABLE' => 'feature_variable'
360+
}.freeze
355361
end
356362
end
357363
end

lib/optimizely/notification_center.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# frozen_string_literal: true
22

33
#
4-
# Copyright 2017-2018, Optimizely and contributors
4+
# Copyright 2017-2019, Optimizely and contributors
55
#
66
# Licensed under the Apache License, Version 2.0 (the "License");
77
# you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@ class NotificationCenter
2222

2323
NOTIFICATION_TYPES = {
2424
ACTIVATE: 'ACTIVATE: experiment, user_id, attributes, variation, event',
25+
DECISION: 'DECISION: type, user_id, attributes, decision_info',
2526
TRACK: 'TRACK: event_key, user_id, attributes, event_tags, event'
2627
}.freeze
2728

spec/project_spec.rb

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,11 +592,17 @@ class InvalidErrorHandler; end
592592
.with('test_experiment')
593593
.and_return([])
594594
experiment = project_instance.config.get_experiment_from_key('test_experiment')
595+
596+
# Decision listener
597+
expect(project_instance.notification_center).to receive(:send_notifications).ordered
598+
599+
# Activate listener
595600
expect(project_instance.notification_center).to receive(:send_notifications).with(
596601
Optimizely::NotificationCenter::NOTIFICATION_TYPES[:ACTIVATE],
597602
experiment, 'test_user', nil, variation_to_return,
598603
instance_of(Optimizely::Event)
599-
)
604+
).ordered
605+
600606
project_instance.activate('test_experiment', 'test_user')
601607

602608
expect(spy_logger).to have_received(:log).once.with(Logger::INFO, include('Dispatching impression event to' \
@@ -649,6 +655,36 @@ class InvalidErrorHandler; end
649655
invalid_project = Optimizely::Project.new('invalid')
650656
invalid_project.activate('test_exp', 'test_user')
651657
end
658+
659+
describe '.decision listener' do
660+
it 'should call decision listener when user not in experiment' do
661+
expect(project_instance.notification_center).to receive(:send_notifications).with(
662+
Optimizely::NotificationCenter::NOTIFICATION_TYPES[:DECISION],
663+
'experiment', 'test_user', {},
664+
experiment_key: 'test_experiment_with_audience', variation_key: nil
665+
)
666+
667+
project_instance.activate('test_experiment_with_audience', 'test_user')
668+
end
669+
670+
it 'should call decision listener when user in experiment' do
671+
variation_to_return = project_instance.config.get_variation_from_id('test_experiment', '111128')
672+
allow(project_instance.decision_service.bucketer).to receive(:bucket).and_return(variation_to_return)
673+
expect(project_instance.event_dispatcher).to receive(:dispatch_event).with(instance_of(Optimizely::Event))
674+
675+
# Decision listener
676+
expect(project_instance.notification_center).to receive(:send_notifications).with(
677+
Optimizely::NotificationCenter::NOTIFICATION_TYPES[:DECISION],
678+
'experiment', 'test_user', {},
679+
experiment_key: 'test_experiment', variation_key: 'control'
680+
).ordered
681+
682+
# Activate listener
683+
expect(project_instance.notification_center).to receive(:send_notifications).ordered
684+
685+
project_instance.activate('test_experiment', 'test_user')
686+
end
687+
end
652688
end
653689

654690
describe '#track' do
@@ -1066,6 +1102,28 @@ class InvalidErrorHandler; end
10661102
invalid_project = Optimizely::Project.new('invalid')
10671103
invalid_project.get_variation('test_exp', 'test_user')
10681104
end
1105+
1106+
describe '.decision listener' do
1107+
it 'should call decision listener when user in experiment' do
1108+
expect(project_instance.notification_center).to receive(:send_notifications).with(
1109+
Optimizely::NotificationCenter::NOTIFICATION_TYPES[:DECISION],
1110+
'experiment', 'test_user', {'browser_type' => 'firefox'},
1111+
experiment_key: 'test_experiment_with_audience', variation_key: 'control_with_audience'
1112+
)
1113+
1114+
project_instance.get_variation('test_experiment_with_audience', 'test_user', 'browser_type' => 'firefox')
1115+
end
1116+
1117+
it 'should call decision listener when user not in experiment' do
1118+
expect(project_instance.notification_center).to receive(:send_notifications).with(
1119+
Optimizely::NotificationCenter::NOTIFICATION_TYPES[:DECISION],
1120+
'experiment', 'test_user', {'browser_type' => 'chrome'},
1121+
experiment_key: 'test_experiment_with_audience', variation_key: nil
1122+
)
1123+
1124+
project_instance.get_variation('test_experiment_with_audience', 'test_user', 'browser_type' => 'chrome')
1125+
end
1126+
end
10691127
end
10701128

10711129
describe '#is_feature_enabled' do

0 commit comments

Comments
 (0)