optimizely-sdk 5.0.0.pre.beta → 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 +48 -32
  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 -338
  10. data/lib/optimizely/config_manager/project_config_manager.rb +25 -25
  11. data/lib/optimizely/config_manager/static_project_config_manager.rb +55 -54
  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 -149
  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 -238
  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 -271
  55. data/lib/optimizely/optimizely_factory.rb +184 -186
  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 +12 -10
@@ -1,459 +1,459 @@
1
- # frozen_string_literal: true
2
-
3
- #
4
- # Copyright 2016-2020, 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
- module Optimizely
19
- module Helpers
20
- module Constants
21
- JSON_SCHEMA_V2 = {
22
- 'type' => 'object',
23
- 'properties' => {
24
- 'projectId' => {
25
- 'type' => 'string'
26
- },
27
- 'accountId' => {
28
- 'type' => 'string'
29
- },
30
- 'groups' => {
31
- 'type' => 'array',
32
- 'items' => {
33
- 'type' => 'object',
34
- 'properties' => {
35
- 'id' => {
36
- 'type' => 'string'
37
- },
38
- 'policy' => {
39
- 'type' => 'string'
40
- },
41
- 'trafficAllocation' => {
42
- 'type' => 'array',
43
- 'items' => {
44
- 'type' => 'object',
45
- 'properties' => {
46
- 'entityId' => {
47
- 'type' => 'string'
48
- },
49
- 'endOfRange' => {
50
- 'type' => 'integer'
51
- }
52
- },
53
- 'required' => %w[
54
- entityId
55
- endOfRange
56
- ]
57
- }
58
- },
59
- 'experiments' => {
60
- 'type' => 'array',
61
- 'items' => {
62
- 'type' => 'object',
63
- 'properties' => {
64
- 'id' => {
65
- 'type' => 'string'
66
- },
67
- 'layerId' => {
68
- 'type' => 'string'
69
- },
70
- 'key' => {
71
- 'type' => 'string'
72
- },
73
- 'status' => {
74
- 'type' => 'string'
75
- },
76
- 'variations' => {
77
- 'type' => 'array',
78
- 'items' => {
79
- 'type' => 'object',
80
- 'properties' => {
81
- 'id' => {
82
- 'type' => 'string'
83
- },
84
- 'key' => {
85
- 'type' => 'string'
86
- }
87
- },
88
- 'required' => %w[
89
- id
90
- key
91
- ]
92
- }
93
- },
94
- 'trafficAllocation' => {
95
- 'type' => 'array',
96
- 'items' => {
97
- 'type' => 'object',
98
- 'properties' => {
99
- 'entityId' => {
100
- 'type' => 'string'
101
- },
102
- 'endOfRange' => {
103
- 'type' => 'integer'
104
- }
105
- },
106
- 'required' => %w[
107
- entityId
108
- endOfRange
109
- ]
110
- }
111
- },
112
- 'audienceIds' => {
113
- 'type' => 'array',
114
- 'items' => {
115
- 'type' => 'string'
116
- }
117
- },
118
- 'forcedVariations' => {
119
- 'type' => 'object'
120
- }
121
- },
122
- 'required' => %w[
123
- id
124
- layerId
125
- key
126
- status
127
- variations
128
- trafficAllocation
129
- audienceIds
130
- forcedVariations
131
- ]
132
- }
133
- }
134
- },
135
- 'required' => %w[
136
- id
137
- policy
138
- trafficAllocation
139
- experiments
140
- ]
141
- }
142
- },
143
- 'experiments' => {
144
- 'type' => 'array',
145
- 'items' => {
146
- 'type' => 'object',
147
- 'properties' => {
148
- 'id' => {
149
- 'type' => 'string'
150
- },
151
- 'key' => {
152
- 'type' => 'string'
153
- },
154
- 'status' => {
155
- 'type' => 'string'
156
- },
157
- 'layerId' => {
158
- 'type' => 'string'
159
- },
160
- 'variations' => {
161
- 'type' => 'array',
162
- 'items' => {
163
- 'type' => 'object',
164
- 'properties' => {
165
- 'id' => {
166
- 'type' => 'string'
167
- },
168
- 'key' => {
169
- 'type' => 'string'
170
- }
171
- },
172
- 'required' => %w[
173
- id
174
- key
175
- ]
176
- }
177
- },
178
- 'trafficAllocation' => {
179
- 'type' => 'array',
180
- 'items' => {
181
- 'type' => 'object',
182
- 'properties' => {
183
- 'entityId' => {
184
- 'type' => 'string'
185
- },
186
- 'endOfRange' => {
187
- 'type' => 'integer'
188
- }
189
- },
190
- 'required' => %w[
191
- entityId
192
- endOfRange
193
- ]
194
- }
195
- },
196
- 'audienceIds' => {
197
- 'type' => 'array',
198
- 'items' => {
199
- 'type' => 'string'
200
- }
201
- },
202
- 'forcedVariations' => {
203
- 'type' => 'object'
204
- }
205
- },
206
- 'required' => %w[
207
- id
208
- key
209
- variations
210
- trafficAllocation
211
- audienceIds
212
- forcedVariations
213
- status
214
- layerId
215
- ]
216
- }
217
- },
218
- 'events' => {
219
- 'type' => 'array',
220
- 'items' => {
221
- 'type' => 'object',
222
- 'properties' => {
223
- 'key' => {
224
- 'type' => 'string'
225
- },
226
- 'experimentIds' => {
227
- 'type' => 'array',
228
- 'items' => {
229
- 'type' => 'string'
230
- }
231
- },
232
- 'id' => {
233
- 'type' => 'string'
234
- }
235
- },
236
- 'required' => %w[
237
- key
238
- experimentIds
239
- id
240
- ]
241
- }
242
- },
243
- 'audiences' => {
244
- 'type' => 'array',
245
- 'items' => {
246
- 'type' => 'object',
247
- 'properties' => {
248
- 'id' => {
249
- 'type' => 'string'
250
- },
251
- 'name' => {
252
- 'type' => 'string'
253
- },
254
- 'conditions' => {
255
- 'type' => 'string'
256
- }
257
- },
258
- 'required' => %w[
259
- id
260
- name
261
- conditions
262
- ]
263
- }
264
- },
265
- 'attributes' => {
266
- 'type' => 'array',
267
- 'items' => {
268
- 'type' => 'object',
269
- 'properties' => {
270
- 'id' => {
271
- 'type' => 'string'
272
- },
273
- 'key' => {
274
- 'type' => 'string'
275
- }
276
- },
277
- 'required' => %w[
278
- id
279
- key
280
- ]
281
- }
282
- },
283
- 'version' => {
284
- 'type' => 'string'
285
- },
286
- 'revision' => {
287
- 'type' => 'string'
288
- },
289
- 'integrations' => {
290
- 'type' => 'array',
291
- 'items' => {
292
- 'type' => 'object',
293
- 'properties' => {
294
- 'key' => {
295
- 'type' => 'string'
296
- },
297
- 'host' => {
298
- 'type' => 'string'
299
- },
300
- 'publicKey' => {
301
- 'type' => 'string'
302
- }
303
- },
304
- 'required' => %w[key]
305
- }
306
- }
307
- },
308
- 'required' => %w[
309
- projectId
310
- accountId
311
- experiments
312
- events
313
- groups
314
- audiences
315
- attributes
316
- version
317
- revision
318
- ]
319
- }.freeze
320
-
321
- VARIABLE_TYPES = {
322
- 'BOOLEAN' => 'boolean',
323
- 'DOUBLE' => 'double',
324
- 'INTEGER' => 'integer',
325
- 'STRING' => 'string',
326
- 'JSON' => 'json'
327
- }.freeze
328
-
329
- INPUT_VARIABLES = {
330
- 'FEATURE_FLAG_KEY' => 'Feature flag key',
331
- 'EXPERIMENT_KEY' => 'Experiment key',
332
- 'USER_ID' => 'User ID',
333
- 'VARIATION_KEY' => 'Variation key',
334
- 'VARIABLE_KEY' => 'Variable key',
335
- 'VARIABLE_TYPE' => 'Variable type'
336
- }.freeze
337
-
338
- CONTROL_ATTRIBUTES = {
339
- 'BOT_FILTERING' => '$opt_bot_filtering',
340
- 'BUCKETING_ID' => '$opt_bucketing_id',
341
- 'USER_AGENT' => '$opt_user_agent'
342
- }.freeze
343
-
344
- SUPPORTED_VERSIONS = {
345
- 'v2' => '2',
346
- 'v3' => '3',
347
- 'v4' => '4'
348
- }.freeze
349
-
350
- ATTRIBUTE_VALID_TYPES = [FalseClass, Float, Integer, String, TrueClass].freeze
351
-
352
- FINITE_NUMBER_LIMIT = 2**53
353
-
354
- AUDIENCE_EVALUATION_LOGS = {
355
- 'AUDIENCE_EVALUATION_RESULT' => "Audience '%s' evaluated to %s.",
356
- 'EVALUATING_AUDIENCE' => "Starting to evaluate audience '%s' with conditions: %s.",
357
- 'INFINITE_ATTRIBUTE_VALUE' => 'Audience condition %s evaluated to UNKNOWN because the number value ' \
358
- "for user attribute '%s' is not in the range [-2^53, +2^53].",
359
- 'INVALID_SEMANTIC_VERSION' => 'Audience condition %s evaluated as UNKNOWN because an invalid semantic version ' \
360
- "was passed for user attribute '%s'.",
361
- 'MISSING_ATTRIBUTE_VALUE' => 'Audience condition %s evaluated as UNKNOWN because no value ' \
362
- "was passed for user attribute '%s'.",
363
- 'NULL_ATTRIBUTE_VALUE' => 'Audience condition %s evaluated to UNKNOWN because a nil value was passed ' \
364
- "for user attribute '%s'.",
365
- 'UNEXPECTED_TYPE' => "Audience condition %s evaluated as UNKNOWN because a value of type '%s' " \
366
- "was passed for user attribute '%s'.",
367
- 'UNKNOWN_CONDITION_TYPE' => 'Audience condition %s uses an unknown condition type. You may need ' \
368
- 'to upgrade to a newer release of the Optimizely SDK.',
369
- 'UNKNOWN_CONDITION_VALUE' => 'Audience condition %s has an unsupported condition value. You may need ' \
370
- 'to upgrade to a newer release of the Optimizely SDK.',
371
- 'UNKNOWN_MATCH_TYPE' => 'Audience condition %s uses an unknown match type. You may need ' \
372
- 'to upgrade to a newer release of the Optimizely SDK.'
373
- }.freeze
374
-
375
- EXPERIMENT_AUDIENCE_EVALUATION_LOGS = {
376
- 'AUDIENCE_EVALUATION_RESULT_COMBINED' => "Audiences for experiment '%s' collectively evaluated to %s.",
377
- 'EVALUATING_AUDIENCES_COMBINED' => "Evaluating audiences for experiment '%s': %s."
378
- }.merge(AUDIENCE_EVALUATION_LOGS).freeze
379
-
380
- ROLLOUT_AUDIENCE_EVALUATION_LOGS = {
381
- 'AUDIENCE_EVALUATION_RESULT_COMBINED' => "Audiences for rule '%s' collectively evaluated to %s.",
382
- 'EVALUATING_AUDIENCES_COMBINED' => "Evaluating audiences for rule '%s': %s."
383
- }.merge(AUDIENCE_EVALUATION_LOGS).freeze
384
-
385
- ODP_LOGS = {
386
- FETCH_SEGMENTS_FAILED: 'Audience segments fetch failed (%s).',
387
- ODP_EVENT_FAILED: 'ODP event send failed (%s).',
388
- ODP_NOT_ENABLED: 'ODP is not enabled.',
389
- ODP_NOT_INTEGRATED: 'ODP is not integrated.',
390
- ODP_INVALID_DATA: 'ODP data is not valid.',
391
- ODP_INVALID_ACTION: 'ODP action is not valid (cannot be empty).'
392
- }.freeze
393
-
394
- DECISION_NOTIFICATION_TYPES = {
395
- 'AB_TEST' => 'ab-test',
396
- 'FEATURE' => 'feature',
397
- 'FEATURE_TEST' => 'feature-test',
398
- 'FEATURE_VARIABLE' => 'feature-variable',
399
- 'FLAG' => 'flag',
400
- 'ALL_FEATURE_VARIABLES' => 'all-feature-variables'
401
- }.freeze
402
-
403
- CONFIG_MANAGER = {
404
- 'DATAFILE_URL_TEMPLATE' => 'https://cdn.optimizely.com/datafiles/%s.json',
405
- 'AUTHENTICATED_DATAFILE_URL_TEMPLATE' => 'https://config.optimizely.com/datafiles/auth/%s.json',
406
- # Default time in seconds to block the 'config' method call until 'config' instance has been initialized.
407
- 'DEFAULT_BLOCKING_TIMEOUT' => 15,
408
- # Default config update interval of 5 minutes
409
- 'DEFAULT_UPDATE_INTERVAL' => 5 * 60,
410
- # Maximum update interval or blocking timeout: 30 days
411
- 'MAX_SECONDS_LIMIT' => 2_592_000,
412
- # Minimum update interval or blocking timeout: 1 second
413
- 'MIN_SECONDS_LIMIT' => 1,
414
- # Time in seconds before which request for datafile times out
415
- 'REQUEST_TIMEOUT' => 10
416
- }.freeze
417
-
418
- EVENT_DISPATCH_CONFIG = {
419
- REQUEST_TIMEOUT: 10
420
- }.freeze
421
-
422
- ODP_GRAPHQL_API_CONFIG = {
423
- REQUEST_TIMEOUT: 10
424
- }.freeze
425
-
426
- ODP_REST_API_CONFIG = {
427
- REQUEST_TIMEOUT: 10
428
- }.freeze
429
-
430
- ODP_SEGMENTS_CACHE_CONFIG = {
431
- DEFAULT_CAPACITY: 10_000,
432
- DEFAULT_TIMEOUT_SECONDS: 600
433
- }.freeze
434
-
435
- ODP_MANAGER_CONFIG = {
436
- KEY_FOR_USER_ID: 'fs_user_id',
437
- EVENT_TYPE: 'fullstack'
438
- }.freeze
439
-
440
- ODP_CONFIG_STATE = {
441
- UNDETERMINED: 'UNDETERMINED',
442
- INTEGRATED: 'INTEGRATED',
443
- NOT_INTEGRATED: 'NOT_INTEGRATED'
444
- }.freeze
445
-
446
- ODP_EVENT_MANAGER = {
447
- DEFAULT_QUEUE_CAPACITY: 10_000,
448
- DEFAULT_BATCH_SIZE: 10,
449
- DEFAULT_FLUSH_INTERVAL_SECONDS: 1,
450
- DEFAULT_RETRY_COUNT: 3
451
- }.freeze
452
-
453
- HTTP_HEADERS = {
454
- 'IF_MODIFIED_SINCE' => 'If-Modified-Since',
455
- 'LAST_MODIFIED' => 'Last-Modified'
456
- }.freeze
457
- end
458
- end
459
- end
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright 2016-2020, 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
+ module Optimizely
19
+ module Helpers
20
+ module Constants
21
+ JSON_SCHEMA_V2 = {
22
+ 'type' => 'object',
23
+ 'properties' => {
24
+ 'projectId' => {
25
+ 'type' => 'string'
26
+ },
27
+ 'accountId' => {
28
+ 'type' => 'string'
29
+ },
30
+ 'groups' => {
31
+ 'type' => 'array',
32
+ 'items' => {
33
+ 'type' => 'object',
34
+ 'properties' => {
35
+ 'id' => {
36
+ 'type' => 'string'
37
+ },
38
+ 'policy' => {
39
+ 'type' => 'string'
40
+ },
41
+ 'trafficAllocation' => {
42
+ 'type' => 'array',
43
+ 'items' => {
44
+ 'type' => 'object',
45
+ 'properties' => {
46
+ 'entityId' => {
47
+ 'type' => 'string'
48
+ },
49
+ 'endOfRange' => {
50
+ 'type' => 'integer'
51
+ }
52
+ },
53
+ 'required' => %w[
54
+ entityId
55
+ endOfRange
56
+ ]
57
+ }
58
+ },
59
+ 'experiments' => {
60
+ 'type' => 'array',
61
+ 'items' => {
62
+ 'type' => 'object',
63
+ 'properties' => {
64
+ 'id' => {
65
+ 'type' => 'string'
66
+ },
67
+ 'layerId' => {
68
+ 'type' => 'string'
69
+ },
70
+ 'key' => {
71
+ 'type' => 'string'
72
+ },
73
+ 'status' => {
74
+ 'type' => 'string'
75
+ },
76
+ 'variations' => {
77
+ 'type' => 'array',
78
+ 'items' => {
79
+ 'type' => 'object',
80
+ 'properties' => {
81
+ 'id' => {
82
+ 'type' => 'string'
83
+ },
84
+ 'key' => {
85
+ 'type' => 'string'
86
+ }
87
+ },
88
+ 'required' => %w[
89
+ id
90
+ key
91
+ ]
92
+ }
93
+ },
94
+ 'trafficAllocation' => {
95
+ 'type' => 'array',
96
+ 'items' => {
97
+ 'type' => 'object',
98
+ 'properties' => {
99
+ 'entityId' => {
100
+ 'type' => 'string'
101
+ },
102
+ 'endOfRange' => {
103
+ 'type' => 'integer'
104
+ }
105
+ },
106
+ 'required' => %w[
107
+ entityId
108
+ endOfRange
109
+ ]
110
+ }
111
+ },
112
+ 'audienceIds' => {
113
+ 'type' => 'array',
114
+ 'items' => {
115
+ 'type' => 'string'
116
+ }
117
+ },
118
+ 'forcedVariations' => {
119
+ 'type' => 'object'
120
+ }
121
+ },
122
+ 'required' => %w[
123
+ id
124
+ layerId
125
+ key
126
+ status
127
+ variations
128
+ trafficAllocation
129
+ audienceIds
130
+ forcedVariations
131
+ ]
132
+ }
133
+ }
134
+ },
135
+ 'required' => %w[
136
+ id
137
+ policy
138
+ trafficAllocation
139
+ experiments
140
+ ]
141
+ }
142
+ },
143
+ 'experiments' => {
144
+ 'type' => 'array',
145
+ 'items' => {
146
+ 'type' => 'object',
147
+ 'properties' => {
148
+ 'id' => {
149
+ 'type' => 'string'
150
+ },
151
+ 'key' => {
152
+ 'type' => 'string'
153
+ },
154
+ 'status' => {
155
+ 'type' => 'string'
156
+ },
157
+ 'layerId' => {
158
+ 'type' => 'string'
159
+ },
160
+ 'variations' => {
161
+ 'type' => 'array',
162
+ 'items' => {
163
+ 'type' => 'object',
164
+ 'properties' => {
165
+ 'id' => {
166
+ 'type' => 'string'
167
+ },
168
+ 'key' => {
169
+ 'type' => 'string'
170
+ }
171
+ },
172
+ 'required' => %w[
173
+ id
174
+ key
175
+ ]
176
+ }
177
+ },
178
+ 'trafficAllocation' => {
179
+ 'type' => 'array',
180
+ 'items' => {
181
+ 'type' => 'object',
182
+ 'properties' => {
183
+ 'entityId' => {
184
+ 'type' => 'string'
185
+ },
186
+ 'endOfRange' => {
187
+ 'type' => 'integer'
188
+ }
189
+ },
190
+ 'required' => %w[
191
+ entityId
192
+ endOfRange
193
+ ]
194
+ }
195
+ },
196
+ 'audienceIds' => {
197
+ 'type' => 'array',
198
+ 'items' => {
199
+ 'type' => 'string'
200
+ }
201
+ },
202
+ 'forcedVariations' => {
203
+ 'type' => 'object'
204
+ }
205
+ },
206
+ 'required' => %w[
207
+ id
208
+ key
209
+ variations
210
+ trafficAllocation
211
+ audienceIds
212
+ forcedVariations
213
+ status
214
+ layerId
215
+ ]
216
+ }
217
+ },
218
+ 'events' => {
219
+ 'type' => 'array',
220
+ 'items' => {
221
+ 'type' => 'object',
222
+ 'properties' => {
223
+ 'key' => {
224
+ 'type' => 'string'
225
+ },
226
+ 'experimentIds' => {
227
+ 'type' => 'array',
228
+ 'items' => {
229
+ 'type' => 'string'
230
+ }
231
+ },
232
+ 'id' => {
233
+ 'type' => 'string'
234
+ }
235
+ },
236
+ 'required' => %w[
237
+ key
238
+ experimentIds
239
+ id
240
+ ]
241
+ }
242
+ },
243
+ 'audiences' => {
244
+ 'type' => 'array',
245
+ 'items' => {
246
+ 'type' => 'object',
247
+ 'properties' => {
248
+ 'id' => {
249
+ 'type' => 'string'
250
+ },
251
+ 'name' => {
252
+ 'type' => 'string'
253
+ },
254
+ 'conditions' => {
255
+ 'type' => 'string'
256
+ }
257
+ },
258
+ 'required' => %w[
259
+ id
260
+ name
261
+ conditions
262
+ ]
263
+ }
264
+ },
265
+ 'attributes' => {
266
+ 'type' => 'array',
267
+ 'items' => {
268
+ 'type' => 'object',
269
+ 'properties' => {
270
+ 'id' => {
271
+ 'type' => 'string'
272
+ },
273
+ 'key' => {
274
+ 'type' => 'string'
275
+ }
276
+ },
277
+ 'required' => %w[
278
+ id
279
+ key
280
+ ]
281
+ }
282
+ },
283
+ 'version' => {
284
+ 'type' => 'string'
285
+ },
286
+ 'revision' => {
287
+ 'type' => 'string'
288
+ },
289
+ 'integrations' => {
290
+ 'type' => 'array',
291
+ 'items' => {
292
+ 'type' => 'object',
293
+ 'properties' => {
294
+ 'key' => {
295
+ 'type' => 'string'
296
+ },
297
+ 'host' => {
298
+ 'type' => 'string'
299
+ },
300
+ 'publicKey' => {
301
+ 'type' => 'string'
302
+ }
303
+ },
304
+ 'required' => %w[key]
305
+ }
306
+ }
307
+ },
308
+ 'required' => %w[
309
+ projectId
310
+ accountId
311
+ experiments
312
+ events
313
+ groups
314
+ audiences
315
+ attributes
316
+ version
317
+ revision
318
+ ]
319
+ }.freeze
320
+
321
+ VARIABLE_TYPES = {
322
+ 'BOOLEAN' => 'boolean',
323
+ 'DOUBLE' => 'double',
324
+ 'INTEGER' => 'integer',
325
+ 'STRING' => 'string',
326
+ 'JSON' => 'json'
327
+ }.freeze
328
+
329
+ INPUT_VARIABLES = {
330
+ 'FEATURE_FLAG_KEY' => 'Feature flag key',
331
+ 'EXPERIMENT_KEY' => 'Experiment key',
332
+ 'USER_ID' => 'User ID',
333
+ 'VARIATION_KEY' => 'Variation key',
334
+ 'VARIABLE_KEY' => 'Variable key',
335
+ 'VARIABLE_TYPE' => 'Variable type'
336
+ }.freeze
337
+
338
+ CONTROL_ATTRIBUTES = {
339
+ 'BOT_FILTERING' => '$opt_bot_filtering',
340
+ 'BUCKETING_ID' => '$opt_bucketing_id',
341
+ 'USER_AGENT' => '$opt_user_agent'
342
+ }.freeze
343
+
344
+ SUPPORTED_VERSIONS = {
345
+ 'v2' => '2',
346
+ 'v3' => '3',
347
+ 'v4' => '4'
348
+ }.freeze
349
+
350
+ ATTRIBUTE_VALID_TYPES = [FalseClass, Float, Integer, String, TrueClass].freeze
351
+
352
+ FINITE_NUMBER_LIMIT = 2**53
353
+
354
+ AUDIENCE_EVALUATION_LOGS = {
355
+ 'AUDIENCE_EVALUATION_RESULT' => "Audience '%s' evaluated to %s.",
356
+ 'EVALUATING_AUDIENCE' => "Starting to evaluate audience '%s' with conditions: %s.",
357
+ 'INFINITE_ATTRIBUTE_VALUE' => 'Audience condition %s evaluated to UNKNOWN because the number value ' \
358
+ "for user attribute '%s' is not in the range [-2^53, +2^53].",
359
+ 'INVALID_SEMANTIC_VERSION' => 'Audience condition %s evaluated as UNKNOWN because an invalid semantic version ' \
360
+ "was passed for user attribute '%s'.",
361
+ 'MISSING_ATTRIBUTE_VALUE' => 'Audience condition %s evaluated as UNKNOWN because no value ' \
362
+ "was passed for user attribute '%s'.",
363
+ 'NULL_ATTRIBUTE_VALUE' => 'Audience condition %s evaluated to UNKNOWN because a nil value was passed ' \
364
+ "for user attribute '%s'.",
365
+ 'UNEXPECTED_TYPE' => "Audience condition %s evaluated as UNKNOWN because a value of type '%s' " \
366
+ "was passed for user attribute '%s'.",
367
+ 'UNKNOWN_CONDITION_TYPE' => 'Audience condition %s uses an unknown condition type. You may need ' \
368
+ 'to upgrade to a newer release of the Optimizely SDK.',
369
+ 'UNKNOWN_CONDITION_VALUE' => 'Audience condition %s has an unsupported condition value. You may need ' \
370
+ 'to upgrade to a newer release of the Optimizely SDK.',
371
+ 'UNKNOWN_MATCH_TYPE' => 'Audience condition %s uses an unknown match type. You may need ' \
372
+ 'to upgrade to a newer release of the Optimizely SDK.'
373
+ }.freeze
374
+
375
+ EXPERIMENT_AUDIENCE_EVALUATION_LOGS = {
376
+ 'AUDIENCE_EVALUATION_RESULT_COMBINED' => "Audiences for experiment '%s' collectively evaluated to %s.",
377
+ 'EVALUATING_AUDIENCES_COMBINED' => "Evaluating audiences for experiment '%s': %s."
378
+ }.merge(AUDIENCE_EVALUATION_LOGS).freeze
379
+
380
+ ROLLOUT_AUDIENCE_EVALUATION_LOGS = {
381
+ 'AUDIENCE_EVALUATION_RESULT_COMBINED' => "Audiences for rule '%s' collectively evaluated to %s.",
382
+ 'EVALUATING_AUDIENCES_COMBINED' => "Evaluating audiences for rule '%s': %s."
383
+ }.merge(AUDIENCE_EVALUATION_LOGS).freeze
384
+
385
+ ODP_LOGS = {
386
+ FETCH_SEGMENTS_FAILED: 'Audience segments fetch failed (%s).',
387
+ ODP_EVENT_FAILED: 'ODP event send failed (%s).',
388
+ ODP_NOT_ENABLED: 'ODP is not enabled.',
389
+ ODP_NOT_INTEGRATED: 'ODP is not integrated.',
390
+ ODP_INVALID_DATA: 'ODP data is not valid.',
391
+ ODP_INVALID_ACTION: 'ODP action is not valid (cannot be empty).'
392
+ }.freeze
393
+
394
+ DECISION_NOTIFICATION_TYPES = {
395
+ 'AB_TEST' => 'ab-test',
396
+ 'FEATURE' => 'feature',
397
+ 'FEATURE_TEST' => 'feature-test',
398
+ 'FEATURE_VARIABLE' => 'feature-variable',
399
+ 'FLAG' => 'flag',
400
+ 'ALL_FEATURE_VARIABLES' => 'all-feature-variables'
401
+ }.freeze
402
+
403
+ CONFIG_MANAGER = {
404
+ 'DATAFILE_URL_TEMPLATE' => 'https://cdn.optimizely.com/datafiles/%s.json',
405
+ 'AUTHENTICATED_DATAFILE_URL_TEMPLATE' => 'https://config.optimizely.com/datafiles/auth/%s.json',
406
+ # Default time in seconds to block the 'config' method call until 'config' instance has been initialized.
407
+ 'DEFAULT_BLOCKING_TIMEOUT' => 15,
408
+ # Default config update interval of 5 minutes
409
+ 'DEFAULT_UPDATE_INTERVAL' => 5 * 60,
410
+ # Maximum update interval or blocking timeout: 30 days
411
+ 'MAX_SECONDS_LIMIT' => 2_592_000,
412
+ # Minimum update interval or blocking timeout: 1 second
413
+ 'MIN_SECONDS_LIMIT' => 1,
414
+ # Time in seconds before which request for datafile times out
415
+ 'REQUEST_TIMEOUT' => 10
416
+ }.freeze
417
+
418
+ EVENT_DISPATCH_CONFIG = {
419
+ REQUEST_TIMEOUT: 10
420
+ }.freeze
421
+
422
+ ODP_GRAPHQL_API_CONFIG = {
423
+ REQUEST_TIMEOUT: 10
424
+ }.freeze
425
+
426
+ ODP_REST_API_CONFIG = {
427
+ REQUEST_TIMEOUT: 10
428
+ }.freeze
429
+
430
+ ODP_SEGMENTS_CACHE_CONFIG = {
431
+ DEFAULT_CAPACITY: 10_000,
432
+ DEFAULT_TIMEOUT_SECONDS: 600
433
+ }.freeze
434
+
435
+ ODP_MANAGER_CONFIG = {
436
+ KEY_FOR_USER_ID: 'fs_user_id',
437
+ EVENT_TYPE: 'fullstack'
438
+ }.freeze
439
+
440
+ ODP_CONFIG_STATE = {
441
+ UNDETERMINED: 'UNDETERMINED',
442
+ INTEGRATED: 'INTEGRATED',
443
+ NOT_INTEGRATED: 'NOT_INTEGRATED'
444
+ }.freeze
445
+
446
+ ODP_EVENT_MANAGER = {
447
+ DEFAULT_QUEUE_CAPACITY: 10_000,
448
+ DEFAULT_BATCH_SIZE: 10,
449
+ DEFAULT_FLUSH_INTERVAL_SECONDS: 1,
450
+ DEFAULT_RETRY_COUNT: 3
451
+ }.freeze
452
+
453
+ HTTP_HEADERS = {
454
+ 'IF_MODIFIED_SINCE' => 'If-Modified-Since',
455
+ 'LAST_MODIFIED' => 'Last-Modified'
456
+ }.freeze
457
+ end
458
+ end
459
+ end