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