optimizely-sdk 3.9.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +202 -202
  3. data/lib/optimizely/audience.rb +127 -97
  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 +539 -508
  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 +330 -321
  10. data/lib/optimizely/config_manager/project_config_manager.rb +24 -24
  11. data/lib/optimizely/config_manager/static_project_config_manager.rb +53 -47
  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 -500
  16. data/lib/optimizely/error_handler.rb +39 -39
  17. data/lib/optimizely/event/batch_event_processor.rb +235 -234
  18. data/lib/optimizely/event/entity/conversion_event.rb +44 -43
  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 -47
  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 -35
  27. data/lib/optimizely/event/entity/visitor_attribute.rb +38 -37
  28. data/lib/optimizely/event/event_factory.rb +156 -155
  29. data/lib/optimizely/event/event_processor.rb +25 -25
  30. data/lib/optimizely/event/forwarding_event_processor.rb +44 -43
  31. data/lib/optimizely/event/user_event_factory.rb +88 -88
  32. data/lib/optimizely/event_builder.rb +221 -228
  33. data/lib/optimizely/event_dispatcher.rb +71 -71
  34. data/lib/optimizely/exceptions.rb +135 -139
  35. data/lib/optimizely/helpers/constants.rb +415 -397
  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 +65 -64
  40. data/lib/optimizely/helpers/validator.rb +183 -183
  41. data/lib/optimizely/helpers/variable_type.rb +67 -67
  42. data/lib/optimizely/logger.rb +46 -45
  43. data/lib/optimizely/notification_center.rb +174 -176
  44. data/lib/optimizely/optimizely_config.rb +271 -272
  45. data/lib/optimizely/optimizely_factory.rb +181 -181
  46. data/lib/optimizely/optimizely_user_context.rb +204 -107
  47. data/lib/optimizely/params.rb +31 -31
  48. data/lib/optimizely/project_config.rb +99 -91
  49. data/lib/optimizely/semantic_version.rb +166 -166
  50. data/lib/optimizely/{custom_attribute_condition_evaluator.rb → user_condition_evaluator.rb} +391 -369
  51. data/lib/optimizely/user_profile_service.rb +35 -35
  52. data/lib/optimizely/version.rb +21 -21
  53. data/lib/optimizely.rb +1130 -1117
  54. metadata +13 -13
@@ -1,397 +1,415 @@
1
- # frozen_string_literal: true
2
-
3
- #
4
- # Copyright 2016-2020, 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
- },
290
- 'required' => %w[
291
- projectId
292
- accountId
293
- experiments
294
- events
295
- groups
296
- audiences
297
- attributes
298
- version
299
- revision
300
- ]
301
- }.freeze
302
-
303
- VARIABLE_TYPES = {
304
- 'BOOLEAN' => 'boolean',
305
- 'DOUBLE' => 'double',
306
- 'INTEGER' => 'integer',
307
- 'STRING' => 'string',
308
- 'JSON' => 'json'
309
- }.freeze
310
-
311
- INPUT_VARIABLES = {
312
- 'FEATURE_FLAG_KEY' => 'Feature flag key',
313
- 'EXPERIMENT_KEY' => 'Experiment key',
314
- 'USER_ID' => 'User ID',
315
- 'VARIATION_KEY' => 'Variation key',
316
- 'VARIABLE_KEY' => 'Variable key',
317
- 'VARIABLE_TYPE' => 'Variable type'
318
- }.freeze
319
-
320
- CONTROL_ATTRIBUTES = {
321
- 'BOT_FILTERING' => '$opt_bot_filtering',
322
- 'BUCKETING_ID' => '$opt_bucketing_id',
323
- 'USER_AGENT' => '$opt_user_agent'
324
- }.freeze
325
-
326
- SUPPORTED_VERSIONS = {
327
- 'v2' => '2',
328
- 'v3' => '3',
329
- 'v4' => '4'
330
- }.freeze
331
-
332
- ATTRIBUTE_VALID_TYPES = [FalseClass, Float, Integer, String, TrueClass].freeze
333
-
334
- FINITE_NUMBER_LIMIT = 2**53
335
-
336
- AUDIENCE_EVALUATION_LOGS = {
337
- 'AUDIENCE_EVALUATION_RESULT' => "Audience '%s' evaluated to %s.",
338
- 'EVALUATING_AUDIENCE' => "Starting to evaluate audience '%s' with conditions: %s.",
339
- 'INFINITE_ATTRIBUTE_VALUE' => 'Audience condition %s evaluated to UNKNOWN because the number value ' \
340
- "for user attribute '%s' is not in the range [-2^53, +2^53].",
341
- 'INVALID_SEMANTIC_VERSION' => 'Audience condition %s evaluated as UNKNOWN because an invalid semantic version ' \
342
- "was passed for user attribute '%s'.",
343
- 'MISSING_ATTRIBUTE_VALUE' => 'Audience condition %s evaluated as UNKNOWN because no value ' \
344
- "was passed for user attribute '%s'.",
345
- 'NULL_ATTRIBUTE_VALUE' => 'Audience condition %s evaluated to UNKNOWN because a nil value was passed ' \
346
- "for user attribute '%s'.",
347
- 'UNEXPECTED_TYPE' => "Audience condition %s evaluated as UNKNOWN because a value of type '%s' " \
348
- "was passed for user attribute '%s'.",
349
- 'UNKNOWN_CONDITION_TYPE' => 'Audience condition %s uses an unknown condition type. You may need ' \
350
- 'to upgrade to a newer release of the Optimizely SDK.',
351
- 'UNKNOWN_CONDITION_VALUE' => 'Audience condition %s has an unsupported condition value. You may need ' \
352
- 'to upgrade to a newer release of the Optimizely SDK.',
353
- 'UNKNOWN_MATCH_TYPE' => 'Audience condition %s uses an unknown match type. You may need ' \
354
- 'to upgrade to a newer release of the Optimizely SDK.'
355
- }.freeze
356
-
357
- EXPERIMENT_AUDIENCE_EVALUATION_LOGS = {
358
- 'AUDIENCE_EVALUATION_RESULT_COMBINED' => "Audiences for experiment '%s' collectively evaluated to %s.",
359
- 'EVALUATING_AUDIENCES_COMBINED' => "Evaluating audiences for experiment '%s': %s."
360
- }.merge(AUDIENCE_EVALUATION_LOGS).freeze
361
-
362
- ROLLOUT_AUDIENCE_EVALUATION_LOGS = {
363
- 'AUDIENCE_EVALUATION_RESULT_COMBINED' => "Audiences for rule '%s' collectively evaluated to %s.",
364
- 'EVALUATING_AUDIENCES_COMBINED' => "Evaluating audiences for rule '%s': %s."
365
- }.merge(AUDIENCE_EVALUATION_LOGS).freeze
366
-
367
- DECISION_NOTIFICATION_TYPES = {
368
- 'AB_TEST' => 'ab-test',
369
- 'FEATURE' => 'feature',
370
- 'FEATURE_TEST' => 'feature-test',
371
- 'FEATURE_VARIABLE' => 'feature-variable',
372
- 'FLAG' => 'flag',
373
- 'ALL_FEATURE_VARIABLES' => 'all-feature-variables'
374
- }.freeze
375
-
376
- CONFIG_MANAGER = {
377
- 'DATAFILE_URL_TEMPLATE' => 'https://cdn.optimizely.com/datafiles/%s.json',
378
- 'AUTHENTICATED_DATAFILE_URL_TEMPLATE' => 'https://config.optimizely.com/datafiles/auth/%s.json',
379
- # Default time in seconds to block the 'config' method call until 'config' instance has been initialized.
380
- 'DEFAULT_BLOCKING_TIMEOUT' => 15,
381
- # Default config update interval of 5 minutes
382
- 'DEFAULT_UPDATE_INTERVAL' => 5 * 60,
383
- # Maximum update interval or blocking timeout: 30 days
384
- 'MAX_SECONDS_LIMIT' => 2_592_000,
385
- # Minimum update interval or blocking timeout: 1 second
386
- 'MIN_SECONDS_LIMIT' => 1,
387
- # Time in seconds before which request for datafile times out
388
- 'REQUEST_TIMEOUT' => 10
389
- }.freeze
390
-
391
- HTTP_HEADERS = {
392
- 'IF_MODIFIED_SINCE' => 'If-Modified-Since',
393
- 'LAST_MODIFIED' => 'Last-Modified'
394
- }.freeze
395
- end
396
- end
397
- end
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright 2016-2020, 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
+ DECISION_NOTIFICATION_TYPES = {
386
+ 'AB_TEST' => 'ab-test',
387
+ 'FEATURE' => 'feature',
388
+ 'FEATURE_TEST' => 'feature-test',
389
+ 'FEATURE_VARIABLE' => 'feature-variable',
390
+ 'FLAG' => 'flag',
391
+ 'ALL_FEATURE_VARIABLES' => 'all-feature-variables'
392
+ }.freeze
393
+
394
+ CONFIG_MANAGER = {
395
+ 'DATAFILE_URL_TEMPLATE' => 'https://cdn.optimizely.com/datafiles/%s.json',
396
+ 'AUTHENTICATED_DATAFILE_URL_TEMPLATE' => 'https://config.optimizely.com/datafiles/auth/%s.json',
397
+ # Default time in seconds to block the 'config' method call until 'config' instance has been initialized.
398
+ 'DEFAULT_BLOCKING_TIMEOUT' => 15,
399
+ # Default config update interval of 5 minutes
400
+ 'DEFAULT_UPDATE_INTERVAL' => 5 * 60,
401
+ # Maximum update interval or blocking timeout: 30 days
402
+ 'MAX_SECONDS_LIMIT' => 2_592_000,
403
+ # Minimum update interval or blocking timeout: 1 second
404
+ 'MIN_SECONDS_LIMIT' => 1,
405
+ # Time in seconds before which request for datafile times out
406
+ 'REQUEST_TIMEOUT' => 10
407
+ }.freeze
408
+
409
+ HTTP_HEADERS = {
410
+ 'IF_MODIFIED_SINCE' => 'If-Modified-Since',
411
+ 'LAST_MODIFIED' => 'Last-Modified'
412
+ }.freeze
413
+ end
414
+ end
415
+ end