optimizely-sdk 5.0.0 → 5.1.0

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 (65) 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 +589 -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 +183 -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/user_profile_tracker.rb +64 -0
  63. data/lib/optimizely/version.rb +21 -21
  64. data/lib/optimizely.rb +1326 -1262
  65. metadata +8 -5
@@ -1,39 +1,39 @@
1
- # frozen_string_literal: true
2
-
3
- #
4
- # Copyright 2016-2017, 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
- module Optimizely
19
- class BaseErrorHandler
20
- # Class encapsulating exception handling functionality.
21
- # Override with your own exception handler providing a handle_error method.
22
-
23
- def handle_error(_error); end
24
- end
25
-
26
- class NoOpErrorHandler < BaseErrorHandler
27
- # Class providing handle_error method that suppresses errors.
28
-
29
- def handle_error(_error); end
30
- end
31
-
32
- class RaiseErrorHandler < BaseErrorHandler
33
- # Class providing a handle_error method that raises exceptions.
34
-
35
- def handle_error(error)
36
- raise error
37
- end
38
- end
39
- end
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright 2016-2017, 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
+ module Optimizely
19
+ class BaseErrorHandler
20
+ # Class encapsulating exception handling functionality.
21
+ # Override with your own exception handler providing a handle_error method.
22
+
23
+ def handle_error(_error); end
24
+ end
25
+
26
+ class NoOpErrorHandler < BaseErrorHandler
27
+ # Class providing handle_error method that suppresses errors.
28
+
29
+ def handle_error(_error); end
30
+ end
31
+
32
+ class RaiseErrorHandler < BaseErrorHandler
33
+ # Class providing a handle_error method that raises exceptions.
34
+
35
+ def handle_error(error)
36
+ raise error
37
+ end
38
+ end
39
+ end
@@ -1,235 +1,235 @@
1
- # frozen_string_literal: true
2
-
3
- #
4
- # Copyright 2019, 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
- require_relative 'event_processor'
19
- require_relative '../helpers/validator'
20
- module Optimizely
21
- class BatchEventProcessor < EventProcessor
22
- # BatchEventProcessor is a batched implementation of the Interface EventProcessor.
23
- # Events passed to the BatchEventProcessor are immediately added to an EventQueue.
24
- # The BatchEventProcessor maintains a single consumer thread that pulls events off of
25
- # the BlockingQueue and buffers them for either a configured batch size or for a
26
- # maximum duration before the resulting LogEvent is sent to the NotificationCenter.
27
-
28
- attr_reader :event_queue, :event_dispatcher, :current_batch, :started, :batch_size, :flush_interval
29
-
30
- DEFAULT_BATCH_SIZE = 10
31
- DEFAULT_BATCH_INTERVAL = 30_000 # interval in milliseconds
32
- DEFAULT_QUEUE_CAPACITY = 1000
33
- DEFAULT_TIMEOUT_INTERVAL = 5 # interval in seconds
34
-
35
- FLUSH_SIGNAL = 'FLUSH_SIGNAL'
36
- SHUTDOWN_SIGNAL = 'SHUTDOWN_SIGNAL'
37
-
38
- def initialize(
39
- event_queue: SizedQueue.new(DEFAULT_QUEUE_CAPACITY),
40
- event_dispatcher: nil,
41
- batch_size: DEFAULT_BATCH_SIZE,
42
- flush_interval: DEFAULT_BATCH_INTERVAL,
43
- logger: NoOpLogger.new,
44
- notification_center: nil
45
- )
46
- super()
47
- @event_queue = event_queue
48
- @logger = logger
49
- @event_dispatcher = event_dispatcher || EventDispatcher.new(logger: @logger)
50
- @batch_size = if (batch_size.is_a? Integer) && positive_number?(batch_size)
51
- batch_size
52
- else
53
- @logger.log(Logger::DEBUG, "Setting to default batch_size: #{DEFAULT_BATCH_SIZE}.")
54
- DEFAULT_BATCH_SIZE
55
- end
56
- @flush_interval = if positive_number?(flush_interval)
57
- flush_interval
58
- else
59
- @logger.log(Logger::DEBUG, "Setting to default flush_interval: #{DEFAULT_BATCH_INTERVAL} ms.")
60
- DEFAULT_BATCH_INTERVAL
61
- end
62
- @notification_center = notification_center
63
- @current_batch = []
64
- @started = false
65
- @stopped = false
66
- end
67
-
68
- def start!
69
- if @started == true
70
- @logger.log(Logger::WARN, 'Service already started.')
71
- return
72
- end
73
- @flushing_interval_deadline = Helpers::DateTimeUtils.create_timestamp + @flush_interval
74
- @logger.log(Logger::INFO, 'Starting scheduler.')
75
- if @wait_mutex.nil?
76
- @wait_mutex = Mutex.new
77
- @resource = ConditionVariable.new
78
- end
79
- @thread = Thread.new { run_queue }
80
- @started = true
81
- @stopped = false
82
- end
83
-
84
- def flush
85
- @event_queue << FLUSH_SIGNAL
86
- @wait_mutex.synchronize { @resource.signal }
87
- end
88
-
89
- def process(user_event)
90
- @logger.log(Logger::DEBUG, "Received userEvent: #{user_event}")
91
-
92
- # if the processor has been explicitly stopped. Don't accept tasks
93
- if @stopped
94
- @logger.log(Logger::WARN, 'Executor shutdown, not accepting tasks.')
95
- return
96
- end
97
-
98
- # start if the processor hasn't been started
99
- start! unless @started
100
-
101
- begin
102
- @event_queue.push(user_event, true)
103
- @wait_mutex.synchronize { @resource.signal }
104
- rescue => e
105
- @logger.log(Logger::WARN, "Payload not accepted by the queue: #{e.message}")
106
- nil
107
- end
108
- end
109
-
110
- def stop!
111
- return unless @started
112
-
113
- @logger.log(Logger::INFO, 'Stopping scheduler.')
114
- @event_queue << SHUTDOWN_SIGNAL
115
- @wait_mutex.synchronize { @resource.signal }
116
- @thread.join(DEFAULT_TIMEOUT_INTERVAL)
117
- @started = false
118
- @stopped = true
119
- end
120
-
121
- private
122
-
123
- def process_queue
124
- while @event_queue.length.positive?
125
- item = @event_queue.pop
126
- if item == SHUTDOWN_SIGNAL
127
- @logger.log(Logger::DEBUG, 'Received shutdown signal.')
128
- return false
129
- end
130
-
131
- if item == FLUSH_SIGNAL
132
- @logger.log(Logger::DEBUG, 'Received flush signal.')
133
- flush_queue!
134
- next
135
- end
136
-
137
- add_to_batch(item) if item.is_a? Optimizely::UserEvent
138
- end
139
- true
140
- end
141
-
142
- def run_queue
143
- loop do
144
- if Helpers::DateTimeUtils.create_timestamp >= @flushing_interval_deadline
145
- @logger.log(Logger::DEBUG, 'Deadline exceeded flushing current batch.')
146
-
147
- break unless process_queue
148
-
149
- flush_queue!
150
- @flushing_interval_deadline = Helpers::DateTimeUtils.create_timestamp + @flush_interval
151
- end
152
-
153
- break unless process_queue
154
-
155
- # what is the current interval to flush in seconds
156
- interval = (@flushing_interval_deadline - Helpers::DateTimeUtils.create_timestamp) * 0.001
157
-
158
- next unless interval.positive?
159
-
160
- @wait_mutex.synchronize { @resource.wait(@wait_mutex, interval) }
161
- end
162
- rescue SignalException
163
- @logger.log(Logger::ERROR, 'Interrupted while processing buffer.')
164
- rescue => e
165
- @logger.log(Logger::ERROR, "Uncaught exception processing buffer. #{e.message}")
166
- ensure
167
- @logger.log(Logger::INFO, 'Exiting processing loop. Attempting to flush pending events.')
168
- flush_queue!
169
- end
170
-
171
- def flush_queue!
172
- return if @current_batch.empty?
173
-
174
- log_event = Optimizely::EventFactory.create_log_event(@current_batch, @logger)
175
- begin
176
- @logger.log(
177
- Logger::INFO,
178
- 'Flushing Queue.'
179
- )
180
-
181
- @event_dispatcher.dispatch_event(log_event)
182
- @notification_center&.send_notifications(
183
- NotificationCenter::NOTIFICATION_TYPES[:LOG_EVENT],
184
- log_event
185
- )
186
- rescue StandardError => e
187
- @logger.log(Logger::ERROR, "Error dispatching event: #{log_event} #{e.message}.")
188
- end
189
- @current_batch = []
190
- end
191
-
192
- def add_to_batch(user_event)
193
- if should_split?(user_event)
194
- flush_queue!
195
- @current_batch = []
196
- end
197
-
198
- # Reset the deadline if starting a new batch.
199
- @flushing_interval_deadline = (Helpers::DateTimeUtils.create_timestamp + @flush_interval) if @current_batch.empty?
200
-
201
- @logger.log(Logger::DEBUG, "Adding user event: #{user_event} to batch.")
202
- @current_batch << user_event
203
- return unless @current_batch.length >= @batch_size
204
-
205
- @logger.log(Logger::DEBUG, 'Flushing on max batch size.')
206
- flush_queue!
207
- end
208
-
209
- def should_split?(user_event)
210
- return false if @current_batch.empty?
211
-
212
- current_context = @current_batch.last.event_context
213
- new_context = user_event.event_context
214
-
215
- # Revisions should match
216
- unless current_context[:revision] == new_context[:revision]
217
- @logger.log(Logger::DEBUG, 'Revisions mismatched: Flushing current batch.')
218
- return true
219
- end
220
-
221
- # Projects should match
222
- unless current_context[:project_id] == new_context[:project_id]
223
- @logger.log(Logger::DEBUG, 'Project Ids mismatched: Flushing current batch.')
224
- return true
225
- end
226
- false
227
- end
228
-
229
- def positive_number?(value)
230
- # Returns true if the given value is positive finite number.
231
- # false otherwise.
232
- Helpers::Validator.finite_number?(value) && value.positive?
233
- end
234
- end
235
- end
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright 2019, 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
+ require_relative 'event_processor'
19
+ require_relative '../helpers/validator'
20
+ module Optimizely
21
+ class BatchEventProcessor < EventProcessor
22
+ # BatchEventProcessor is a batched implementation of the Interface EventProcessor.
23
+ # Events passed to the BatchEventProcessor are immediately added to an EventQueue.
24
+ # The BatchEventProcessor maintains a single consumer thread that pulls events off of
25
+ # the BlockingQueue and buffers them for either a configured batch size or for a
26
+ # maximum duration before the resulting LogEvent is sent to the NotificationCenter.
27
+
28
+ attr_reader :event_queue, :event_dispatcher, :current_batch, :started, :batch_size, :flush_interval
29
+
30
+ DEFAULT_BATCH_SIZE = 10
31
+ DEFAULT_BATCH_INTERVAL = 30_000 # interval in milliseconds
32
+ DEFAULT_QUEUE_CAPACITY = 1000
33
+ DEFAULT_TIMEOUT_INTERVAL = 5 # interval in seconds
34
+
35
+ FLUSH_SIGNAL = 'FLUSH_SIGNAL'
36
+ SHUTDOWN_SIGNAL = 'SHUTDOWN_SIGNAL'
37
+
38
+ def initialize(
39
+ event_queue: SizedQueue.new(DEFAULT_QUEUE_CAPACITY),
40
+ event_dispatcher: nil,
41
+ batch_size: DEFAULT_BATCH_SIZE,
42
+ flush_interval: DEFAULT_BATCH_INTERVAL,
43
+ logger: NoOpLogger.new,
44
+ notification_center: nil
45
+ )
46
+ super()
47
+ @event_queue = event_queue
48
+ @logger = logger
49
+ @event_dispatcher = event_dispatcher || EventDispatcher.new(logger: @logger)
50
+ @batch_size = if (batch_size.is_a? Integer) && positive_number?(batch_size)
51
+ batch_size
52
+ else
53
+ @logger.log(Logger::DEBUG, "Setting to default batch_size: #{DEFAULT_BATCH_SIZE}.")
54
+ DEFAULT_BATCH_SIZE
55
+ end
56
+ @flush_interval = if positive_number?(flush_interval)
57
+ flush_interval
58
+ else
59
+ @logger.log(Logger::DEBUG, "Setting to default flush_interval: #{DEFAULT_BATCH_INTERVAL} ms.")
60
+ DEFAULT_BATCH_INTERVAL
61
+ end
62
+ @notification_center = notification_center
63
+ @current_batch = []
64
+ @started = false
65
+ @stopped = false
66
+ end
67
+
68
+ def start!
69
+ if @started == true
70
+ @logger.log(Logger::WARN, 'Service already started.')
71
+ return
72
+ end
73
+ @flushing_interval_deadline = Helpers::DateTimeUtils.create_timestamp + @flush_interval
74
+ @logger.log(Logger::INFO, 'Starting scheduler.')
75
+ if @wait_mutex.nil?
76
+ @wait_mutex = Mutex.new
77
+ @resource = ConditionVariable.new
78
+ end
79
+ @thread = Thread.new { run_queue }
80
+ @started = true
81
+ @stopped = false
82
+ end
83
+
84
+ def flush
85
+ @event_queue << FLUSH_SIGNAL
86
+ @wait_mutex.synchronize { @resource.signal }
87
+ end
88
+
89
+ def process(user_event)
90
+ @logger.log(Logger::DEBUG, "Received userEvent: #{user_event}")
91
+
92
+ # if the processor has been explicitly stopped. Don't accept tasks
93
+ if @stopped
94
+ @logger.log(Logger::WARN, 'Executor shutdown, not accepting tasks.')
95
+ return
96
+ end
97
+
98
+ # start if the processor hasn't been started
99
+ start! unless @started
100
+
101
+ begin
102
+ @event_queue.push(user_event, true)
103
+ @wait_mutex.synchronize { @resource.signal }
104
+ rescue => e
105
+ @logger.log(Logger::WARN, "Payload not accepted by the queue: #{e.message}")
106
+ nil
107
+ end
108
+ end
109
+
110
+ def stop!
111
+ return unless @started
112
+
113
+ @logger.log(Logger::INFO, 'Stopping scheduler.')
114
+ @event_queue << SHUTDOWN_SIGNAL
115
+ @wait_mutex.synchronize { @resource.signal }
116
+ @thread.join(DEFAULT_TIMEOUT_INTERVAL)
117
+ @started = false
118
+ @stopped = true
119
+ end
120
+
121
+ private
122
+
123
+ def process_queue
124
+ while @event_queue.length.positive?
125
+ item = @event_queue.pop
126
+ if item == SHUTDOWN_SIGNAL
127
+ @logger.log(Logger::DEBUG, 'Received shutdown signal.')
128
+ return false
129
+ end
130
+
131
+ if item == FLUSH_SIGNAL
132
+ @logger.log(Logger::DEBUG, 'Received flush signal.')
133
+ flush_queue!
134
+ next
135
+ end
136
+
137
+ add_to_batch(item) if item.is_a? Optimizely::UserEvent
138
+ end
139
+ true
140
+ end
141
+
142
+ def run_queue
143
+ loop do
144
+ if Helpers::DateTimeUtils.create_timestamp >= @flushing_interval_deadline
145
+ @logger.log(Logger::DEBUG, 'Deadline exceeded flushing current batch.')
146
+
147
+ break unless process_queue
148
+
149
+ flush_queue!
150
+ @flushing_interval_deadline = Helpers::DateTimeUtils.create_timestamp + @flush_interval
151
+ end
152
+
153
+ break unless process_queue
154
+
155
+ # what is the current interval to flush in seconds
156
+ interval = (@flushing_interval_deadline - Helpers::DateTimeUtils.create_timestamp) * 0.001
157
+
158
+ next unless interval.positive?
159
+
160
+ @wait_mutex.synchronize { @resource.wait(@wait_mutex, interval) }
161
+ end
162
+ rescue SignalException
163
+ @logger.log(Logger::ERROR, 'Interrupted while processing buffer.')
164
+ rescue => e
165
+ @logger.log(Logger::ERROR, "Uncaught exception processing buffer. #{e.message}")
166
+ ensure
167
+ @logger.log(Logger::INFO, 'Exiting processing loop. Attempting to flush pending events.')
168
+ flush_queue!
169
+ end
170
+
171
+ def flush_queue!
172
+ return if @current_batch.empty?
173
+
174
+ log_event = Optimizely::EventFactory.create_log_event(@current_batch, @logger)
175
+ begin
176
+ @logger.log(
177
+ Logger::INFO,
178
+ 'Flushing Queue.'
179
+ )
180
+
181
+ @event_dispatcher.dispatch_event(log_event)
182
+ @notification_center&.send_notifications(
183
+ NotificationCenter::NOTIFICATION_TYPES[:LOG_EVENT],
184
+ log_event
185
+ )
186
+ rescue StandardError => e
187
+ @logger.log(Logger::ERROR, "Error dispatching event: #{log_event} #{e.message}.")
188
+ end
189
+ @current_batch = []
190
+ end
191
+
192
+ def add_to_batch(user_event)
193
+ if should_split?(user_event)
194
+ flush_queue!
195
+ @current_batch = []
196
+ end
197
+
198
+ # Reset the deadline if starting a new batch.
199
+ @flushing_interval_deadline = (Helpers::DateTimeUtils.create_timestamp + @flush_interval) if @current_batch.empty?
200
+
201
+ @logger.log(Logger::DEBUG, "Adding user event: #{user_event} to batch.")
202
+ @current_batch << user_event
203
+ return unless @current_batch.length >= @batch_size
204
+
205
+ @logger.log(Logger::DEBUG, 'Flushing on max batch size.')
206
+ flush_queue!
207
+ end
208
+
209
+ def should_split?(user_event)
210
+ return false if @current_batch.empty?
211
+
212
+ current_context = @current_batch.last.event_context
213
+ new_context = user_event.event_context
214
+
215
+ # Revisions should match
216
+ unless current_context[:revision] == new_context[:revision]
217
+ @logger.log(Logger::DEBUG, 'Revisions mismatched: Flushing current batch.')
218
+ return true
219
+ end
220
+
221
+ # Projects should match
222
+ unless current_context[:project_id] == new_context[:project_id]
223
+ @logger.log(Logger::DEBUG, 'Project Ids mismatched: Flushing current batch.')
224
+ return true
225
+ end
226
+ false
227
+ end
228
+
229
+ def positive_number?(value)
230
+ # Returns true if the given value is positive finite number.
231
+ # false otherwise.
232
+ Helpers::Validator.finite_number?(value) && value.positive?
233
+ end
234
+ end
235
+ end
@@ -1,44 +1,44 @@
1
- # frozen_string_literal: true
2
-
3
- #
4
- # Copyright 2019, 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
- require_relative 'user_event'
19
- require 'optimizely/helpers/date_time_utils'
20
- module Optimizely
21
- class ConversionEvent < UserEvent
22
- # Represents conversion event
23
- attr_reader :event, :user_id, :visitor_attributes, :tags, :bot_filtering
24
-
25
- def initialize(
26
- event_context:,
27
- event:,
28
- user_id:,
29
- visitor_attributes:,
30
- tags:,
31
- bot_filtering:
32
- )
33
- super()
34
- @event_context = event_context
35
- @uuid = SecureRandom.uuid
36
- @timestamp = Helpers::DateTimeUtils.create_timestamp
37
- @event = event
38
- @user_id = user_id
39
- @visitor_attributes = visitor_attributes
40
- @tags = tags
41
- @bot_filtering = bot_filtering
42
- end
43
- end
44
- end
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright 2019, 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
+ require_relative 'user_event'
19
+ require 'optimizely/helpers/date_time_utils'
20
+ module Optimizely
21
+ class ConversionEvent < UserEvent
22
+ # Represents conversion event
23
+ attr_reader :event, :user_id, :visitor_attributes, :tags, :bot_filtering
24
+
25
+ def initialize(
26
+ event_context:,
27
+ event:,
28
+ user_id:,
29
+ visitor_attributes:,
30
+ tags:,
31
+ bot_filtering:
32
+ )
33
+ super()
34
+ @event_context = event_context
35
+ @uuid = SecureRandom.uuid
36
+ @timestamp = Helpers::DateTimeUtils.create_timestamp
37
+ @event = event
38
+ @user_id = user_id
39
+ @visitor_attributes = visitor_attributes
40
+ @tags = tags
41
+ @bot_filtering = bot_filtering
42
+ end
43
+ end
44
+ end