optimizely-sdk 5.0.0 → 5.0.1

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.
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