optimizely-sdk 5.0.0 → 5.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +202 -202
  3. data/lib/optimizely/audience.rb +127 -127
  4. data/lib/optimizely/bucketer.rb +156 -156
  5. data/lib/optimizely/condition_tree_evaluator.rb +123 -123
  6. data/lib/optimizely/config/datafile_project_config.rb +558 -558
  7. data/lib/optimizely/config/proxy_config.rb +34 -34
  8. data/lib/optimizely/config_manager/async_scheduler.rb +95 -95
  9. data/lib/optimizely/config_manager/http_project_config_manager.rb +340 -340
  10. data/lib/optimizely/config_manager/project_config_manager.rb +25 -25
  11. data/lib/optimizely/config_manager/static_project_config_manager.rb +55 -55
  12. data/lib/optimizely/decide/optimizely_decide_option.rb +28 -28
  13. data/lib/optimizely/decide/optimizely_decision.rb +60 -60
  14. data/lib/optimizely/decide/optimizely_decision_message.rb +26 -26
  15. data/lib/optimizely/decision_service.rb +563 -563
  16. data/lib/optimizely/error_handler.rb +39 -39
  17. data/lib/optimizely/event/batch_event_processor.rb +235 -235
  18. data/lib/optimizely/event/entity/conversion_event.rb +44 -44
  19. data/lib/optimizely/event/entity/decision.rb +38 -38
  20. data/lib/optimizely/event/entity/event_batch.rb +86 -86
  21. data/lib/optimizely/event/entity/event_context.rb +50 -50
  22. data/lib/optimizely/event/entity/impression_event.rb +48 -48
  23. data/lib/optimizely/event/entity/snapshot.rb +33 -33
  24. data/lib/optimizely/event/entity/snapshot_event.rb +48 -48
  25. data/lib/optimizely/event/entity/user_event.rb +22 -22
  26. data/lib/optimizely/event/entity/visitor.rb +36 -36
  27. data/lib/optimizely/event/entity/visitor_attribute.rb +38 -38
  28. data/lib/optimizely/event/event_factory.rb +156 -156
  29. data/lib/optimizely/event/event_processor.rb +25 -25
  30. data/lib/optimizely/event/forwarding_event_processor.rb +44 -44
  31. data/lib/optimizely/event/user_event_factory.rb +88 -88
  32. data/lib/optimizely/event_builder.rb +221 -221
  33. data/lib/optimizely/event_dispatcher.rb +69 -69
  34. data/lib/optimizely/exceptions.rb +193 -193
  35. data/lib/optimizely/helpers/constants.rb +459 -459
  36. data/lib/optimizely/helpers/date_time_utils.rb +30 -30
  37. data/lib/optimizely/helpers/event_tag_utils.rb +132 -132
  38. data/lib/optimizely/helpers/group.rb +31 -31
  39. data/lib/optimizely/helpers/http_utils.rb +68 -68
  40. data/lib/optimizely/helpers/sdk_settings.rb +61 -61
  41. data/lib/optimizely/helpers/validator.rb +236 -236
  42. data/lib/optimizely/helpers/variable_type.rb +67 -67
  43. data/lib/optimizely/logger.rb +46 -46
  44. data/lib/optimizely/notification_center.rb +174 -174
  45. data/lib/optimizely/notification_center_registry.rb +71 -71
  46. data/lib/optimizely/odp/lru_cache.rb +114 -114
  47. data/lib/optimizely/odp/odp_config.rb +102 -102
  48. data/lib/optimizely/odp/odp_event.rb +75 -75
  49. data/lib/optimizely/odp/odp_event_api_manager.rb +70 -70
  50. data/lib/optimizely/odp/odp_event_manager.rb +286 -286
  51. data/lib/optimizely/odp/odp_manager.rb +159 -159
  52. data/lib/optimizely/odp/odp_segment_api_manager.rb +122 -122
  53. data/lib/optimizely/odp/odp_segment_manager.rb +97 -97
  54. data/lib/optimizely/optimizely_config.rb +273 -273
  55. data/lib/optimizely/optimizely_factory.rb +184 -184
  56. data/lib/optimizely/optimizely_user_context.rb +238 -238
  57. data/lib/optimizely/params.rb +31 -31
  58. data/lib/optimizely/project_config.rb +99 -99
  59. data/lib/optimizely/semantic_version.rb +166 -166
  60. data/lib/optimizely/user_condition_evaluator.rb +391 -391
  61. data/lib/optimizely/user_profile_service.rb +35 -35
  62. data/lib/optimizely/version.rb +21 -21
  63. data/lib/optimizely.rb +1262 -1262
  64. metadata +7 -5
@@ -1,114 +1,114 @@
1
- # frozen_string_literal: true
2
-
3
- #
4
- # Copyright 2022, Optimizely and contributors
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
-
19
- module Optimizely
20
- class LRUCache
21
- # Least Recently Used cache that invalidates entries older than the timeout.
22
-
23
- attr_reader :capacity, :timeout
24
-
25
- def initialize(capacity, timeout_in_secs)
26
- # @param capacity - The max size of the cache. If set <= 0, caching is disabled.
27
- # @param timeout_in_secs - Seconds until a cache item is considered stale.
28
- # If set <= 0, items never expire.
29
- @cache_mutex = Mutex.new
30
- @map = {}
31
- @capacity = capacity
32
- @timeout = timeout_in_secs
33
- end
34
-
35
- # Retrieve the non stale value from the cache corresponding to the provided key
36
- # or nil if key is not found
37
- # Moves the key/value pair to the end of the cache
38
- #
39
- # @param key - The key to retrieve
40
-
41
- def lookup(key)
42
- return nil if @capacity <= 0
43
-
44
- @cache_mutex.synchronize do
45
- return nil unless @map.include?(key)
46
-
47
- element = @map.delete(key)
48
- return nil if element.stale?(@timeout)
49
-
50
- @map[key] = element
51
-
52
- element.value
53
- end
54
- end
55
-
56
- # Save a key/value pair into the cache
57
- # Moves the key/value pair to the end of the cache
58
- #
59
- # @param key - A user key
60
- # @param value - A user value
61
-
62
- def save(key, value)
63
- return if @capacity <= 0
64
-
65
- @cache_mutex.synchronize do
66
- @map.delete(key) if @map.key?(key)
67
-
68
- @map[key] = CacheElement.new(value)
69
-
70
- @map.delete(@map.first[0]) if @map.size > @capacity
71
- nil
72
- end
73
- end
74
-
75
- # Clears the cache
76
-
77
- def reset
78
- return if @capacity <= 0
79
-
80
- @cache_mutex.synchronize { @map.clear }
81
- nil
82
- end
83
-
84
- # Retrieve a value from the cache for a given key or nil if key is not found
85
- # Doesn't update the cache
86
- #
87
- # @param key - The key to retrieve
88
-
89
- def peek(key)
90
- return nil if @capacity <= 0
91
-
92
- @cache_mutex.synchronize { @map[key]&.value }
93
- end
94
- end
95
-
96
- class CacheElement
97
- # Individual element for the LRUCache.
98
- attr_reader :value, :timestamp
99
-
100
- def initialize(value)
101
- @value = value
102
- @timestamp = Time.new
103
- end
104
-
105
- def stale?(timeout)
106
- # Returns true if the provided timeout has passed since the element's timestamp.
107
- #
108
- # @param timeout - The duration to check against
109
- return false if timeout <= 0
110
-
111
- Time.new - @timestamp >= timeout
112
- end
113
- end
114
- end
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright 2022, Optimizely and contributors
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ module Optimizely
20
+ class LRUCache
21
+ # Least Recently Used cache that invalidates entries older than the timeout.
22
+
23
+ attr_reader :capacity, :timeout
24
+
25
+ def initialize(capacity, timeout_in_secs)
26
+ # @param capacity - The max size of the cache. If set <= 0, caching is disabled.
27
+ # @param timeout_in_secs - Seconds until a cache item is considered stale.
28
+ # If set <= 0, items never expire.
29
+ @cache_mutex = Mutex.new
30
+ @map = {}
31
+ @capacity = capacity
32
+ @timeout = timeout_in_secs
33
+ end
34
+
35
+ # Retrieve the non stale value from the cache corresponding to the provided key
36
+ # or nil if key is not found
37
+ # Moves the key/value pair to the end of the cache
38
+ #
39
+ # @param key - The key to retrieve
40
+
41
+ def lookup(key)
42
+ return nil if @capacity <= 0
43
+
44
+ @cache_mutex.synchronize do
45
+ return nil unless @map.include?(key)
46
+
47
+ element = @map.delete(key)
48
+ return nil if element.stale?(@timeout)
49
+
50
+ @map[key] = element
51
+
52
+ element.value
53
+ end
54
+ end
55
+
56
+ # Save a key/value pair into the cache
57
+ # Moves the key/value pair to the end of the cache
58
+ #
59
+ # @param key - A user key
60
+ # @param value - A user value
61
+
62
+ def save(key, value)
63
+ return if @capacity <= 0
64
+
65
+ @cache_mutex.synchronize do
66
+ @map.delete(key) if @map.key?(key)
67
+
68
+ @map[key] = CacheElement.new(value)
69
+
70
+ @map.delete(@map.first[0]) if @map.size > @capacity
71
+ nil
72
+ end
73
+ end
74
+
75
+ # Clears the cache
76
+
77
+ def reset
78
+ return if @capacity <= 0
79
+
80
+ @cache_mutex.synchronize { @map.clear }
81
+ nil
82
+ end
83
+
84
+ # Retrieve a value from the cache for a given key or nil if key is not found
85
+ # Doesn't update the cache
86
+ #
87
+ # @param key - The key to retrieve
88
+
89
+ def peek(key)
90
+ return nil if @capacity <= 0
91
+
92
+ @cache_mutex.synchronize { @map[key]&.value }
93
+ end
94
+ end
95
+
96
+ class CacheElement
97
+ # Individual element for the LRUCache.
98
+ attr_reader :value, :timestamp
99
+
100
+ def initialize(value)
101
+ @value = value
102
+ @timestamp = Time.new
103
+ end
104
+
105
+ def stale?(timeout)
106
+ # Returns true if the provided timeout has passed since the element's timestamp.
107
+ #
108
+ # @param timeout - The duration to check against
109
+ return false if timeout <= 0
110
+
111
+ Time.new - @timestamp >= timeout
112
+ end
113
+ end
114
+ end
@@ -1,102 +1,102 @@
1
- # frozen_string_literal: true
2
-
3
- #
4
- # Copyright 2022, Optimizely and contributors
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
-
19
- require 'optimizely/logger'
20
- require_relative '../helpers/constants'
21
-
22
- module Optimizely
23
- class OdpConfig
24
- ODP_CONFIG_STATE = Helpers::Constants::ODP_CONFIG_STATE
25
- # Contains configuration used for ODP integration.
26
- #
27
- # @param api_host - The host URL for the ODP audience segments API (optional).
28
- # @param api_key - The public API key for the ODP account from which the audience segments will be fetched (optional).
29
- # @param segments_to_check - An array of all ODP segments used in the current datafile (associated with api_host/api_key).
30
- def initialize(api_key = nil, api_host = nil, segments_to_check = [])
31
- @api_key = api_key
32
- @api_host = api_host
33
- @segments_to_check = segments_to_check
34
- @mutex = Mutex.new
35
- @odp_state = @api_host.nil? || @api_key.nil? ? ODP_CONFIG_STATE[:UNDETERMINED] : ODP_CONFIG_STATE[:INTEGRATED]
36
- end
37
-
38
- # Replaces the existing configuration
39
- #
40
- # @param api_host - The host URL for the ODP audience segments API (optional).
41
- # @param api_key - The public API key for the ODP account from which the audience segments will be fetched (optional).
42
- # @param segments_to_check - An array of all ODP segments used in the current datafile (associated with api_host/api_key).
43
- #
44
- # @return - True if the provided values were different than the existing values.
45
-
46
- def update(api_key = nil, api_host = nil, segments_to_check = [])
47
- updated = false
48
- @mutex.synchronize do
49
- @odp_state = api_host.nil? || api_key.nil? ? ODP_CONFIG_STATE[:NOT_INTEGRATED] : ODP_CONFIG_STATE[:INTEGRATED]
50
-
51
- if @api_key != api_key || @api_host != api_host || @segments_to_check != segments_to_check
52
- @api_key = api_key
53
- @api_host = api_host
54
- @segments_to_check = segments_to_check
55
- updated = true
56
- end
57
- end
58
-
59
- updated
60
- end
61
-
62
- # Returns the api host for odp connections
63
- #
64
- # @return - The api host.
65
-
66
- def api_host
67
- @mutex.synchronize { @api_host.clone }
68
- end
69
-
70
- # Returns the api key for odp connections
71
- #
72
- # @return - The api key.
73
-
74
- def api_key
75
- @mutex.synchronize { @api_key.clone }
76
- end
77
-
78
- # Returns An array of qualified segments for this user
79
- #
80
- # @return - An array of segments names.
81
-
82
- def segments_to_check
83
- @mutex.synchronize { @segments_to_check.clone }
84
- end
85
-
86
- # Replace qualified segments with provided segments
87
- #
88
- # @param segments - An array of segment names
89
-
90
- def segments_to_check=(segments_to_check)
91
- @mutex.synchronize { @segments_to_check = segments_to_check.clone }
92
- end
93
-
94
- # Returns the state of odp integration (UNDETERMINED, INTEGRATED, NOT_INTEGRATED)
95
- #
96
- # @return - string
97
-
98
- def odp_state
99
- @mutex.synchronize { @odp_state }
100
- end
101
- end
102
- end
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright 2022, Optimizely and contributors
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'optimizely/logger'
20
+ require_relative '../helpers/constants'
21
+
22
+ module Optimizely
23
+ class OdpConfig
24
+ ODP_CONFIG_STATE = Helpers::Constants::ODP_CONFIG_STATE
25
+ # Contains configuration used for ODP integration.
26
+ #
27
+ # @param api_host - The host URL for the ODP audience segments API (optional).
28
+ # @param api_key - The public API key for the ODP account from which the audience segments will be fetched (optional).
29
+ # @param segments_to_check - An array of all ODP segments used in the current datafile (associated with api_host/api_key).
30
+ def initialize(api_key = nil, api_host = nil, segments_to_check = [])
31
+ @api_key = api_key
32
+ @api_host = api_host
33
+ @segments_to_check = segments_to_check
34
+ @mutex = Mutex.new
35
+ @odp_state = @api_host.nil? || @api_key.nil? ? ODP_CONFIG_STATE[:UNDETERMINED] : ODP_CONFIG_STATE[:INTEGRATED]
36
+ end
37
+
38
+ # Replaces the existing configuration
39
+ #
40
+ # @param api_host - The host URL for the ODP audience segments API (optional).
41
+ # @param api_key - The public API key for the ODP account from which the audience segments will be fetched (optional).
42
+ # @param segments_to_check - An array of all ODP segments used in the current datafile (associated with api_host/api_key).
43
+ #
44
+ # @return - True if the provided values were different than the existing values.
45
+
46
+ def update(api_key = nil, api_host = nil, segments_to_check = [])
47
+ updated = false
48
+ @mutex.synchronize do
49
+ @odp_state = api_host.nil? || api_key.nil? ? ODP_CONFIG_STATE[:NOT_INTEGRATED] : ODP_CONFIG_STATE[:INTEGRATED]
50
+
51
+ if @api_key != api_key || @api_host != api_host || @segments_to_check != segments_to_check
52
+ @api_key = api_key
53
+ @api_host = api_host
54
+ @segments_to_check = segments_to_check
55
+ updated = true
56
+ end
57
+ end
58
+
59
+ updated
60
+ end
61
+
62
+ # Returns the api host for odp connections
63
+ #
64
+ # @return - The api host.
65
+
66
+ def api_host
67
+ @mutex.synchronize { @api_host.clone }
68
+ end
69
+
70
+ # Returns the api key for odp connections
71
+ #
72
+ # @return - The api key.
73
+
74
+ def api_key
75
+ @mutex.synchronize { @api_key.clone }
76
+ end
77
+
78
+ # Returns An array of qualified segments for this user
79
+ #
80
+ # @return - An array of segments names.
81
+
82
+ def segments_to_check
83
+ @mutex.synchronize { @segments_to_check.clone }
84
+ end
85
+
86
+ # Replace qualified segments with provided segments
87
+ #
88
+ # @param segments - An array of segment names
89
+
90
+ def segments_to_check=(segments_to_check)
91
+ @mutex.synchronize { @segments_to_check = segments_to_check.clone }
92
+ end
93
+
94
+ # Returns the state of odp integration (UNDETERMINED, INTEGRATED, NOT_INTEGRATED)
95
+ #
96
+ # @return - string
97
+
98
+ def odp_state
99
+ @mutex.synchronize { @odp_state }
100
+ end
101
+ end
102
+ end
@@ -1,75 +1,75 @@
1
- # frozen_string_literal: true
2
-
3
- #
4
- # Copyright 2022, Optimizely and contributors
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
-
19
- require 'json'
20
- require_relative '../helpers/constants'
21
-
22
- module Optimizely
23
- class OdpEvent
24
- # Representation of an odp event which can be sent to the Optimizely odp platform.
25
-
26
- KEY_FOR_USER_ID = Helpers::Constants::ODP_MANAGER_CONFIG[:KEY_FOR_USER_ID]
27
-
28
- def initialize(type:, action:, identifiers:, data:)
29
- @type = type
30
- @action = action
31
- @identifiers = convert_identifiers(identifiers)
32
- @data = add_common_event_data(data)
33
- end
34
-
35
- def add_common_event_data(custom_data)
36
- data = {
37
- idempotence_id: SecureRandom.uuid,
38
- data_source_type: 'sdk',
39
- data_source: 'ruby-sdk',
40
- data_source_version: VERSION
41
- }
42
- data.update(custom_data)
43
- data
44
- end
45
-
46
- def convert_identifiers(identifiers)
47
- # Convert incorrect case/separator of identifier key `fs_user_id`
48
- # (ie. `fs-user-id`, `FS_USER_ID`).
49
-
50
- identifiers.clone.each_key do |key|
51
- break if key == KEY_FOR_USER_ID
52
-
53
- if ['fs-user-id', KEY_FOR_USER_ID].include?(key.downcase)
54
- identifiers[KEY_FOR_USER_ID] = identifiers.delete(key)
55
- break
56
- end
57
- end
58
-
59
- identifiers
60
- end
61
-
62
- def to_json(*_args)
63
- {
64
- type: @type,
65
- action: @action,
66
- identifiers: @identifiers,
67
- data: @data
68
- }.to_json
69
- end
70
-
71
- def ==(other)
72
- to_json == other.to_json
73
- end
74
- end
75
- end
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright 2022, Optimizely and contributors
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'json'
20
+ require_relative '../helpers/constants'
21
+
22
+ module Optimizely
23
+ class OdpEvent
24
+ # Representation of an odp event which can be sent to the Optimizely odp platform.
25
+
26
+ KEY_FOR_USER_ID = Helpers::Constants::ODP_MANAGER_CONFIG[:KEY_FOR_USER_ID]
27
+
28
+ def initialize(type:, action:, identifiers:, data:)
29
+ @type = type
30
+ @action = action
31
+ @identifiers = convert_identifiers(identifiers)
32
+ @data = add_common_event_data(data)
33
+ end
34
+
35
+ def add_common_event_data(custom_data)
36
+ data = {
37
+ idempotence_id: SecureRandom.uuid,
38
+ data_source_type: 'sdk',
39
+ data_source: 'ruby-sdk',
40
+ data_source_version: VERSION
41
+ }
42
+ data.update(custom_data)
43
+ data
44
+ end
45
+
46
+ def convert_identifiers(identifiers)
47
+ # Convert incorrect case/separator of identifier key `fs_user_id`
48
+ # (ie. `fs-user-id`, `FS_USER_ID`).
49
+
50
+ identifiers.clone.each_key do |key|
51
+ break if key == KEY_FOR_USER_ID
52
+
53
+ if ['fs-user-id', KEY_FOR_USER_ID].include?(key.downcase)
54
+ identifiers[KEY_FOR_USER_ID] = identifiers.delete(key)
55
+ break
56
+ end
57
+ end
58
+
59
+ identifiers
60
+ end
61
+
62
+ def to_json(*_args)
63
+ {
64
+ type: @type,
65
+ action: @action,
66
+ identifiers: @identifiers,
67
+ data: @data
68
+ }.to_json
69
+ end
70
+
71
+ def ==(other)
72
+ to_json == other.to_json
73
+ end
74
+ end
75
+ end