optimizely-sdk 1.5.0 → 2.0.0.beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/optimizely.rb +0 -47
- data/lib/optimizely/bucketer.rb +16 -18
- data/lib/optimizely/decision_service.rb +120 -135
- data/lib/optimizely/event_builder.rb +142 -158
- data/lib/optimizely/exceptions.rb +0 -9
- data/lib/optimizely/helpers/event_tag_utils.rb +5 -66
- data/lib/optimizely/helpers/validator.rb +0 -5
- data/lib/optimizely/project_config.rb +4 -107
- data/lib/optimizely/version.rb +1 -4
- metadata +7 -6
- data/lib/optimizely/notification_center.rb +0 -148
@@ -38,8 +38,6 @@ module Optimizely
|
|
38
38
|
attr_reader :groups
|
39
39
|
attr_reader :parsing_succeeded
|
40
40
|
attr_reader :project_id
|
41
|
-
# Boolean - denotes if Optimizely should remove the last block of visitors' IP address before storing event data
|
42
|
-
attr_reader :anonymize_ip
|
43
41
|
attr_reader :revision
|
44
42
|
attr_reader :rollouts
|
45
43
|
attr_reader :version
|
@@ -58,12 +56,6 @@ module Optimizely
|
|
58
56
|
attr_reader :variation_id_to_variable_usage_map
|
59
57
|
attr_reader :variation_key_map
|
60
58
|
|
61
|
-
# Hash of user IDs to a Hash
|
62
|
-
# of experiments to variations. This contains all the forced variations
|
63
|
-
# set by the user by calling setForcedVariation (it is not the same as the
|
64
|
-
# whitelisting forcedVariations data structure in the Experiments class).
|
65
|
-
attr_reader :forced_variation_map
|
66
|
-
|
67
59
|
def initialize(datafile, logger, error_handler)
|
68
60
|
# ProjectConfig init method to fetch and set project config data
|
69
61
|
#
|
@@ -88,7 +80,6 @@ module Optimizely
|
|
88
80
|
@feature_flags = config.fetch('featureFlags', [])
|
89
81
|
@groups = config.fetch('groups', [])
|
90
82
|
@project_id = config['projectId']
|
91
|
-
@anonymize_ip = (config.has_key? 'anonymizeIP')? config['anonymizeIP'] :false
|
92
83
|
@revision = config['revision']
|
93
84
|
@rollouts = config.fetch('rollouts', [])
|
94
85
|
|
@@ -107,7 +98,6 @@ module Optimizely
|
|
107
98
|
@audience_id_map = generate_key_map(@audiences, 'id')
|
108
99
|
@variation_id_map = {}
|
109
100
|
@variation_key_map = {}
|
110
|
-
@forced_variation_map = {}
|
111
101
|
@variation_id_to_variable_usage_map = {}
|
112
102
|
@variation_id_to_experiment_map = {}
|
113
103
|
@experiment_key_map.each do |key, exp|
|
@@ -256,12 +246,12 @@ module Optimizely
|
|
256
246
|
nil
|
257
247
|
end
|
258
248
|
|
259
|
-
def
|
260
|
-
# Retrieves
|
249
|
+
def get_forced_variations(experiment_key)
|
250
|
+
# Retrieves forced variations for a given experiment Key
|
261
251
|
#
|
262
252
|
# experiment_key - String Key representing the experiment
|
263
253
|
#
|
264
|
-
# Returns
|
254
|
+
# Returns forced variations for the experiment or nil
|
265
255
|
|
266
256
|
experiment = @experiment_key_map[experiment_key]
|
267
257
|
return experiment['forcedVariations'] if experiment
|
@@ -269,100 +259,6 @@ module Optimizely
|
|
269
259
|
@error_handler.handle_error InvalidExperimentError
|
270
260
|
end
|
271
261
|
|
272
|
-
def get_forced_variation(experiment_key, user_id)
|
273
|
-
# Gets the forced variation for the given user and experiment.
|
274
|
-
#
|
275
|
-
# experiment_key - String Key for experiment.
|
276
|
-
# user_id - String ID for user
|
277
|
-
#
|
278
|
-
# Returns Variation The variation which the given user and experiment should be forced into.
|
279
|
-
|
280
|
-
# check for nil and empty string user ID
|
281
|
-
if user_id.nil? or user_id.empty?
|
282
|
-
@logger.log(Logger::DEBUG, "User ID is invalid")
|
283
|
-
return nil
|
284
|
-
end
|
285
|
-
|
286
|
-
unless @forced_variation_map.has_key? (user_id)
|
287
|
-
@logger.log(Logger::DEBUG, "User '#{user_id}' is not in the forced variation map.")
|
288
|
-
return nil
|
289
|
-
end
|
290
|
-
|
291
|
-
experimentToVariationMap = @forced_variation_map[user_id]
|
292
|
-
experiment = get_experiment_from_key(experiment_key)
|
293
|
-
experiment_id = experiment["id"] if experiment
|
294
|
-
# check for nil and empty string experiment ID
|
295
|
-
if experiment_id.nil? or experiment_id.empty?
|
296
|
-
# this case is logged in get_experiment_from_key
|
297
|
-
return nil
|
298
|
-
end
|
299
|
-
|
300
|
-
unless experimentToVariationMap.has_key? (experiment_id)
|
301
|
-
@logger.log(Logger::DEBUG, "No experiment '#{experiment_key}' mapped to user '#{user_id}' in the forced variation map.")
|
302
|
-
return nil
|
303
|
-
end
|
304
|
-
|
305
|
-
variation_id = experimentToVariationMap[experiment_id]
|
306
|
-
variation_key = ""
|
307
|
-
variation = get_variation_from_id(experiment_key,variation_id)
|
308
|
-
variation_key = variation["key"] if variation
|
309
|
-
|
310
|
-
# check if the variation exists in the datafile
|
311
|
-
if variation_key.empty?
|
312
|
-
# this case is logged in get_variation_from_id
|
313
|
-
return nil
|
314
|
-
end
|
315
|
-
|
316
|
-
@logger.log(Logger::DEBUG, "Variation '#{variation_key}' is mapped to experiment '#{experiment_key}' and user '#{user_id}' in the forced variation map")
|
317
|
-
|
318
|
-
variation
|
319
|
-
end
|
320
|
-
|
321
|
-
def set_forced_variation(experiment_key, user_id, variation_key)
|
322
|
-
# Sets a Hash of user IDs to a Hash of experiments to forced variations.
|
323
|
-
#
|
324
|
-
# experiment_key - String Key for experiment.
|
325
|
-
# user_id - String ID for user.
|
326
|
-
# variation_key - String Key for variation. If null, then clear the existing experiment-to-variation mapping.
|
327
|
-
#
|
328
|
-
# Returns a boolean value that indicates if the set completed successfully.
|
329
|
-
|
330
|
-
# check for null and empty string user ID
|
331
|
-
if user_id.nil? or user_id.empty?
|
332
|
-
@logger.log(Logger::DEBUG, "User ID is invalid")
|
333
|
-
return false
|
334
|
-
end
|
335
|
-
|
336
|
-
experiment = get_experiment_from_key(experiment_key)
|
337
|
-
experiment_id = experiment["id"] if experiment
|
338
|
-
# check if the experiment exists in the datafile
|
339
|
-
if experiment_id.nil? or experiment_id.empty?
|
340
|
-
return false
|
341
|
-
end
|
342
|
-
|
343
|
-
# clear the forced variation if the variation key is null
|
344
|
-
if variation_key.nil? or variation_key.empty?
|
345
|
-
@forced_variation_map[user_id].delete(experiment_id) if @forced_variation_map.has_key? (user_id)
|
346
|
-
@logger.log(Logger::DEBUG, "Variation mapped to experiment '#{experiment_key}' has been removed for user '#{user_id}'.")
|
347
|
-
return true
|
348
|
-
end
|
349
|
-
|
350
|
-
variation_id = get_variation_id_from_key(experiment_key, variation_key)
|
351
|
-
|
352
|
-
# check if the variation exists in the datafile
|
353
|
-
unless variation_id
|
354
|
-
# this case is logged in get_variation_id_from_key
|
355
|
-
return false
|
356
|
-
end
|
357
|
-
|
358
|
-
unless @forced_variation_map.has_key? user_id
|
359
|
-
@forced_variation_map[user_id] = {}
|
360
|
-
end
|
361
|
-
@forced_variation_map[user_id][experiment_id] = variation_id
|
362
|
-
@logger.log(Logger::DEBUG, "Set variation '#{variation_id}' for experiment '#{experiment_id}' and user '#{user_id}' in the forced variation map.")
|
363
|
-
return true
|
364
|
-
end
|
365
|
-
|
366
262
|
def get_attribute_id(attribute_key)
|
367
263
|
attribute = @attribute_key_map[attribute_key]
|
368
264
|
return attribute['id'] if attribute
|
@@ -394,6 +290,7 @@ module Optimizely
|
|
394
290
|
return true if variation
|
395
291
|
@logger.log Logger::ERROR, "Variation ID '#{variation_id}' is not in datafile."
|
396
292
|
@error_handler.handle_error InvalidVariationError
|
293
|
+
return false
|
397
294
|
end
|
398
295
|
|
399
296
|
false
|
data/lib/optimizely/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: optimizely-sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0.beta
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
+
- Andrew Delikat
|
8
|
+
- Haley Bash
|
7
9
|
- Optimizely
|
8
10
|
autorequire:
|
9
11
|
bindir: bin
|
10
12
|
cert_chain: []
|
11
|
-
date: 2017-
|
13
|
+
date: 2017-09-08 00:00:00.000000000 Z
|
12
14
|
dependencies:
|
13
15
|
- !ruby/object:Gem::Dependency
|
14
16
|
name: bundler
|
@@ -130,7 +132,6 @@ files:
|
|
130
132
|
- lib/optimizely/helpers/validator.rb
|
131
133
|
- lib/optimizely/helpers/variable_type.rb
|
132
134
|
- lib/optimizely/logger.rb
|
133
|
-
- lib/optimizely/notification_center.rb
|
134
135
|
- lib/optimizely/params.rb
|
135
136
|
- lib/optimizely/project_config.rb
|
136
137
|
- lib/optimizely/user_profile_service.rb
|
@@ -150,12 +151,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
150
151
|
version: '0'
|
151
152
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
152
153
|
requirements:
|
153
|
-
- - "
|
154
|
+
- - ">"
|
154
155
|
- !ruby/object:Gem::Version
|
155
|
-
version:
|
156
|
+
version: 1.3.1
|
156
157
|
requirements: []
|
157
158
|
rubyforge_project:
|
158
|
-
rubygems_version: 2.
|
159
|
+
rubygems_version: 2.6.6
|
159
160
|
signing_key:
|
160
161
|
specification_version: 4
|
161
162
|
summary: Ruby SDK for Optimizely's testing framework
|
@@ -1,148 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Copyright 2017, Optimizely and contributors
|
3
|
-
#
|
4
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
-
# you may not use this file except in compliance with the License.
|
6
|
-
# You may obtain a copy of the License at
|
7
|
-
#
|
8
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
-
#
|
10
|
-
# Unless required by applicable law or agreed to in writing, software
|
11
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
-
# See the License for the specific language governing permissions and
|
14
|
-
# limitations under the License.
|
15
|
-
#
|
16
|
-
module Optimizely
|
17
|
-
class NotificationCenter
|
18
|
-
attr_reader :notifications
|
19
|
-
attr_reader :notification_id
|
20
|
-
|
21
|
-
NOTIFICATION_TYPES = {
|
22
|
-
ACTIVATE: 'ACTIVATE: experiment, user_id, attributes, variation, event',
|
23
|
-
TRACK: 'TRACK: event_key, user_id, attributes, event_tags, event'
|
24
|
-
}.freeze
|
25
|
-
|
26
|
-
def initialize(logger, error_handler)
|
27
|
-
@notification_id = 1
|
28
|
-
@notifications = {}
|
29
|
-
NOTIFICATION_TYPES.values.each { |value| @notifications[value] = [] }
|
30
|
-
@logger = logger
|
31
|
-
@error_handler = error_handler
|
32
|
-
end
|
33
|
-
|
34
|
-
def add_notification_listener(notification_type, notification_callback)
|
35
|
-
# Adds notification callback to the notification center
|
36
|
-
|
37
|
-
# Args:
|
38
|
-
# notification_type: one of the constants in NOTIFICATION_TYPES
|
39
|
-
# notification_callback: function to call when the event is sent
|
40
|
-
|
41
|
-
# Returns:
|
42
|
-
# notification ID used to remove the notification
|
43
|
-
|
44
|
-
return nil unless notification_type_valid?(notification_type)
|
45
|
-
|
46
|
-
unless notification_callback
|
47
|
-
@logger.log Logger::ERROR, 'Callback can not be empty.'
|
48
|
-
return nil
|
49
|
-
end
|
50
|
-
|
51
|
-
unless notification_callback.is_a? Method
|
52
|
-
@logger.log Logger::ERROR, 'Invalid notification callback given.'
|
53
|
-
return nil
|
54
|
-
end
|
55
|
-
|
56
|
-
@notifications[notification_type].each do |notification|
|
57
|
-
return -1 if notification[:callback] == notification_callback
|
58
|
-
end
|
59
|
-
@notifications[notification_type].push(notification_id: @notification_id, callback: notification_callback)
|
60
|
-
notification_id = @notification_id
|
61
|
-
@notification_id += 1
|
62
|
-
notification_id
|
63
|
-
end
|
64
|
-
|
65
|
-
def remove_notification_listener(notification_id)
|
66
|
-
# Removes previously added notification callback
|
67
|
-
|
68
|
-
# Args:
|
69
|
-
# notification_id:
|
70
|
-
# Returns:
|
71
|
-
# The function returns true if found and removed, false otherwise
|
72
|
-
unless notification_id
|
73
|
-
@logger.log Logger::ERROR, 'Notification ID can not be empty.'
|
74
|
-
return nil
|
75
|
-
end
|
76
|
-
@notifications.each do |key, _array|
|
77
|
-
@notifications[key].each do |notification|
|
78
|
-
if notification_id == notification[:notification_id]
|
79
|
-
@notifications[key].delete(notification_id: notification_id, callback: notification[:callback])
|
80
|
-
return true
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
false
|
85
|
-
end
|
86
|
-
|
87
|
-
def clear_notifications(notification_type)
|
88
|
-
# Removes notifications for a certain notification type
|
89
|
-
#
|
90
|
-
# Args:
|
91
|
-
# notification_type: one of the constants in NOTIFICATION_TYPES
|
92
|
-
|
93
|
-
return nil unless notification_type_valid?(notification_type)
|
94
|
-
|
95
|
-
@notifications[notification_type] = []
|
96
|
-
@logger.log Logger::INFO, "All callbacks for notification type #{notification_type} have been removed."
|
97
|
-
end
|
98
|
-
|
99
|
-
def clean_all_notifications
|
100
|
-
# Removes all notifications
|
101
|
-
@notifications.keys.each { |key| @notifications[key] = [] }
|
102
|
-
end
|
103
|
-
|
104
|
-
def send_notifications(notification_type, *args)
|
105
|
-
# Sends off the notification for the specific event. Uses var args to pass in a
|
106
|
-
# arbitrary list of parameters according to which notification type was sent
|
107
|
-
|
108
|
-
# Args:
|
109
|
-
# notification_type: one of the constants in NOTIFICATION_TYPES
|
110
|
-
# args: list of arguments to the callback
|
111
|
-
return nil unless notification_type_valid?(notification_type)
|
112
|
-
|
113
|
-
@notifications[notification_type].each do |notification|
|
114
|
-
begin
|
115
|
-
notification_callback = notification[:callback]
|
116
|
-
notification_callback.call(*args)
|
117
|
-
@logger.log Logger::INFO, "Notification #{notification_type} sent successfully."
|
118
|
-
rescue => e
|
119
|
-
@logger.log(Logger::ERROR, "Problem calling notify callback. Error: #{e}")
|
120
|
-
return nil
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
private
|
126
|
-
|
127
|
-
def notification_type_valid?(notification_type)
|
128
|
-
# Validates notification type
|
129
|
-
|
130
|
-
# Args:
|
131
|
-
# notification_type: one of the constants in NOTIFICATION_TYPES
|
132
|
-
|
133
|
-
# Returns true if notification_type is valid, false otherwise
|
134
|
-
|
135
|
-
unless notification_type
|
136
|
-
@logger.log Logger::ERROR, 'Notification type can not be empty.'
|
137
|
-
return false
|
138
|
-
end
|
139
|
-
|
140
|
-
unless @notifications.include?(notification_type)
|
141
|
-
@logger.log Logger::ERROR, 'Invalid notification type.'
|
142
|
-
@error_handler.handle_error InvalidNotificationType
|
143
|
-
return false
|
144
|
-
end
|
145
|
-
true
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|