vwo-sdk 1.15.0 → 1.23.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.
- checksums.yaml +4 -4
- data/lib/vwo/constants.rb +5 -2
- data/lib/vwo/core/bucketer.rb +33 -5
- data/lib/vwo/core/variation_decider.rb +418 -133
- data/lib/vwo/enums.rb +8 -3
- data/lib/vwo/logger.rb +4 -2
- data/lib/vwo/schemas/settings_file.rb +32 -1
- data/lib/vwo/services/operand_evaluator.rb +2 -3
- data/lib/vwo/services/segment_evaluator.rb +4 -2
- data/lib/vwo/utils/campaign.rb +58 -0
- data/lib/vwo/utils/feature.rb +2 -0
- data/lib/vwo/utils/utility.rb +40 -0
- data/lib/vwo.rb +90 -78
- metadata +3 -2
@@ -66,6 +66,8 @@ class VWO
|
|
66
66
|
|
67
67
|
return unless campaign
|
68
68
|
|
69
|
+
is_campaign_part_of_group = @settings_file && is_part_of_group(@settings_file, campaign["id"])
|
70
|
+
|
69
71
|
@has_stored_variation = false
|
70
72
|
decision = {
|
71
73
|
:campaign_id => campaign['id'],
|
@@ -93,62 +95,17 @@ class VWO
|
|
93
95
|
:vwo_user_id => generator_for(user_id, @settings_file['accountId'])
|
94
96
|
}
|
95
97
|
|
96
|
-
if
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
campaign_key,
|
102
|
-
variation_targeting_variables
|
103
|
-
)
|
104
|
-
status = if variation
|
105
|
-
StatusEnum::PASSED
|
106
|
-
else
|
107
|
-
StatusEnum::FAILED
|
108
|
-
end
|
109
|
-
|
110
|
-
@logger.log(
|
111
|
-
LogLevelEnum::INFO,
|
112
|
-
format(
|
113
|
-
LogMessageEnum::InfoMessages::SEGMENTATION_STATUS,
|
114
|
-
file: FILE,
|
115
|
-
campaign_key: campaign_key,
|
116
|
-
user_id: user_id,
|
117
|
-
status: status,
|
118
|
-
custom_variables: variation_targeting_variables,
|
119
|
-
variation_name: status == StatusEnum::PASSED ? "and #{variation['name']} is Assigned" : ' ',
|
120
|
-
segmentation_type: SegmentationTypeEnum::WHITELISTING,
|
121
|
-
api_name: api_name
|
122
|
-
)
|
123
|
-
)
|
124
|
-
|
125
|
-
if variation
|
126
|
-
if campaign['type'] == CampaignTypes::VISUAL_AB || campaign['type'] == CampaignTypes::FEATURE_TEST
|
127
|
-
decision[:variation_name] = variation['name']
|
128
|
-
decision[:variation_id] = variation['id']
|
129
|
-
if campaign['type'] == CampaignTypes::FEATURE_TEST
|
130
|
-
decision[:is_feature_enabled] = variation['isFeatureEnabled']
|
131
|
-
elsif campaign['type'] == CampaignTypes::VISUAL_AB
|
132
|
-
decision[:is_user_whitelisted] = !!variation['name']
|
133
|
-
end
|
134
|
-
end
|
135
|
-
@hooks_manager.execute(decision)
|
136
|
-
end
|
137
|
-
|
138
|
-
return variation if variation && variation['name']
|
139
|
-
else
|
140
|
-
@logger.log(
|
141
|
-
LogLevelEnum::INFO,
|
142
|
-
format(
|
143
|
-
LogMessageEnum::InfoMessages::WHITELISTING_SKIPPED,
|
144
|
-
file: FILE,
|
145
|
-
campaign_key: campaign_key,
|
146
|
-
user_id: user_id,
|
147
|
-
api_name: api_name
|
148
|
-
)
|
149
|
-
)
|
98
|
+
if is_campaign_part_of_group
|
99
|
+
group_id = @settings_file["campaignGroups"][campaign["id"].to_s]
|
100
|
+
decision[:group_id] = group_id
|
101
|
+
group_name = @settings_file["groups"][group_id.to_s]["name"]
|
102
|
+
decision[:group_name] = group_name
|
150
103
|
end
|
151
104
|
|
105
|
+
# evaluate whitelisting
|
106
|
+
variation = get_variation_if_whitelisting_passed(user_id, campaign, variation_targeting_variables, api_name, decision, true)
|
107
|
+
return variation if variation && variation['name']
|
108
|
+
|
152
109
|
user_campaign_map = get_user_storage(user_id, campaign_key)
|
153
110
|
variation = get_stored_variation(user_id, campaign_key, user_campaign_map) if valid_hash?(user_campaign_map)
|
154
111
|
|
@@ -194,8 +151,7 @@ class VWO
|
|
194
151
|
)
|
195
152
|
)
|
196
153
|
|
197
|
-
if ([ApiMethods::TRACK, ApiMethods::GET_VARIATION_NAME, ApiMethods::GET_FEATURE_VARIABLE_VALUE].include? api_name) &&
|
198
|
-
@user_storage_service && campaign['type'] != CampaignTypes::FEATURE_ROLLOUT
|
154
|
+
if ([ApiMethods::TRACK, ApiMethods::GET_VARIATION_NAME, ApiMethods::GET_FEATURE_VARIABLE_VALUE].include? api_name) && @user_storage_service
|
199
155
|
@logger.log(
|
200
156
|
LogLevelEnum::DEBUG,
|
201
157
|
format(
|
@@ -223,82 +179,106 @@ class VWO
|
|
223
179
|
end
|
224
180
|
|
225
181
|
# Pre-segmentation
|
182
|
+
is_presegmentation = check_presegmentation(campaign, user_id, custom_variables, api_name)
|
183
|
+
is_presegmentation_and_traffic_passed = is_presegmentation && @bucketer.user_part_of_campaign?(user_id, campaign)
|
184
|
+
unless is_presegmentation_and_traffic_passed
|
185
|
+
return nil
|
186
|
+
end
|
226
187
|
|
227
|
-
|
228
|
-
|
188
|
+
if is_presegmentation_and_traffic_passed && is_campaign_part_of_group
|
189
|
+
group_campaigns = get_group_campaigns(@settings_file, group_id)
|
190
|
+
|
191
|
+
if group_campaigns
|
192
|
+
is_any_campaign_whitelisted_or_stored = check_whitelisting_or_storage_for_grouped_campaigns(user_id, campaign, group_campaigns, group_name, variation_targeting_variables, true)
|
193
|
+
|
194
|
+
if is_any_campaign_whitelisted_or_stored
|
195
|
+
@logger.log(
|
196
|
+
LogLevelEnum::INFO,
|
197
|
+
format(
|
198
|
+
LogMessageEnum::InfoMessages::CALLED_CAMPAIGN_NOT_WINNER,
|
199
|
+
file: FILE,
|
200
|
+
campaign_key: campaign_key,
|
201
|
+
user_id: user_id,
|
202
|
+
group_name: group_name
|
203
|
+
)
|
204
|
+
)
|
205
|
+
return nil
|
206
|
+
end
|
207
|
+
|
208
|
+
eligible_campaigns = get_eligible_campaigns(user_id, group_campaigns, campaign, custom_variables)
|
209
|
+
non_eligible_campaigns_key = get_non_eligible_campaigns_key(eligible_campaigns, group_campaigns)
|
210
|
+
|
211
|
+
@logger.log(
|
212
|
+
LogLevelEnum::DEBUG,
|
213
|
+
format(
|
214
|
+
LogMessageEnum::DebugMessages::GOT_ELIGIBLE_CAMPAIGNS,
|
215
|
+
file: FILE,
|
216
|
+
user_id: user_id,
|
217
|
+
eligible_campaigns_key: get_eligible_campaigns_key(eligible_campaigns).join(","),
|
218
|
+
ineligible_campaigns_log_text: non_eligible_campaigns_key ? ("campaigns:" + non_eligible_campaigns_key.join("'")) : "no campaigns",
|
219
|
+
group_name: group_name
|
220
|
+
)
|
221
|
+
)
|
229
222
|
|
230
|
-
if is_valid_segments
|
231
|
-
unless custom_variables
|
232
223
|
@logger.log(
|
233
224
|
LogLevelEnum::INFO,
|
234
225
|
format(
|
235
|
-
LogMessageEnum::InfoMessages::
|
226
|
+
LogMessageEnum::InfoMessages::GOT_ELIGIBLE_CAMPAIGNS,
|
236
227
|
file: FILE,
|
237
|
-
campaign_key: campaign_key,
|
238
228
|
user_id: user_id,
|
239
|
-
|
229
|
+
no_of_eligible_campaigns: eligible_campaigns.length,
|
230
|
+
no_of_group_campaigns: group_campaigns.length,
|
231
|
+
group_name: group_name
|
240
232
|
)
|
241
233
|
)
|
242
|
-
|
243
|
-
|
244
|
-
unless @segment_evaluator.evaluate(campaign_key, user_id, segments, custom_variables)
|
234
|
+
|
235
|
+
winner_campaign = get_winner_campaign(user_id, eligible_campaigns, group_id)
|
245
236
|
@logger.log(
|
246
237
|
LogLevelEnum::INFO,
|
247
238
|
format(
|
248
|
-
LogMessageEnum::InfoMessages::
|
249
|
-
file:
|
239
|
+
LogMessageEnum::InfoMessages::GOT_WINNER_CAMPAIGN,
|
240
|
+
file: FILE,
|
250
241
|
user_id: user_id,
|
251
|
-
campaign_key:
|
252
|
-
|
242
|
+
campaign_key: winner_campaign["key"],
|
243
|
+
group_name: group_name
|
253
244
|
)
|
254
245
|
)
|
255
|
-
|
246
|
+
|
247
|
+
if winner_campaign && winner_campaign["id"] == campaign["id"]
|
248
|
+
variation = get_variation_allotted(user_id, campaign, true)
|
249
|
+
if variation && variation['name']
|
250
|
+
save_user_storage(user_id, campaign_key, campaign['type'], variation['name'], goal_identifier, true) if variation['name']
|
251
|
+
else
|
252
|
+
return nil
|
253
|
+
end
|
254
|
+
else
|
255
|
+
@logger.log(
|
256
|
+
LogLevelEnum::INFO,
|
257
|
+
format(
|
258
|
+
LogMessageEnum::InfoMessages::CALLED_CAMPAIGN_NOT_WINNER,
|
259
|
+
file: FILE,
|
260
|
+
campaign_key: campaign_key,
|
261
|
+
user_id: user_id,
|
262
|
+
group_name: group_name
|
263
|
+
)
|
264
|
+
)
|
265
|
+
return nil
|
266
|
+
end
|
256
267
|
end
|
257
|
-
@logger.log(
|
258
|
-
LogLevelEnum::INFO,
|
259
|
-
format(
|
260
|
-
LogMessageEnum::InfoMessages::USER_PASSED_SEGMENTATION,
|
261
|
-
file: FileNameEnum::SegmentEvaluator,
|
262
|
-
user_id: user_id,
|
263
|
-
campaign_key: campaign_key,
|
264
|
-
custom_variables: custom_variables
|
265
|
-
)
|
266
|
-
)
|
267
|
-
else
|
268
|
-
@logger.log(
|
269
|
-
LogLevelEnum::INFO,
|
270
|
-
format(
|
271
|
-
LogMessageEnum::InfoMessages::SKIPPING_SEGMENTATION,
|
272
|
-
file: FILE,
|
273
|
-
campaign_key: campaign_key,
|
274
|
-
user_id: user_id,
|
275
|
-
api_name: api_name,
|
276
|
-
variation: ''
|
277
|
-
)
|
278
|
-
)
|
279
268
|
end
|
280
269
|
|
281
|
-
variation
|
270
|
+
if variation.nil?
|
271
|
+
variation = get_variation_allotted(user_id, campaign)
|
282
272
|
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
LogMessageEnum::InfoMessages::VARIATION_ALLOCATED,
|
290
|
-
file: FILE,
|
291
|
-
campaign_key: campaign_key,
|
292
|
-
user_id: user_id,
|
293
|
-
variation_name: variation['name'],
|
294
|
-
campaign_type: campaign['type']
|
273
|
+
if variation && variation['name']
|
274
|
+
save_user_storage(user_id, campaign_key, campaign['type'], variation['name'], goal_identifier) if variation['name']
|
275
|
+
else
|
276
|
+
@logger.log(
|
277
|
+
LogLevelEnum::INFO,
|
278
|
+
format(LogMessageEnum::InfoMessages::NO_VARIATION_ALLOCATED, file: FILE, campaign_key: campaign_key, user_id: user_id)
|
295
279
|
)
|
296
|
-
|
297
|
-
|
298
|
-
@logger.log(
|
299
|
-
LogLevelEnum::INFO,
|
300
|
-
format(LogMessageEnum::InfoMessages::NO_VARIATION_ALLOCATED, file: FILE, campaign_key: campaign_key, user_id: user_id)
|
301
|
-
)
|
280
|
+
end
|
281
|
+
|
302
282
|
end
|
303
283
|
|
304
284
|
if variation
|
@@ -321,7 +301,7 @@ class VWO
|
|
321
301
|
#
|
322
302
|
# @return[Hash]
|
323
303
|
|
324
|
-
def get_variation_allotted(user_id, campaign)
|
304
|
+
def get_variation_allotted(user_id, campaign, disable_logs = false)
|
325
305
|
unless valid_value?(user_id)
|
326
306
|
@logger.log(
|
327
307
|
LogLevelEnum::ERROR,
|
@@ -341,7 +321,8 @@ class VWO
|
|
341
321
|
user_id: user_id,
|
342
322
|
campaign_key: campaign['key'],
|
343
323
|
method: 'get_variation_allotted'
|
344
|
-
)
|
324
|
+
),
|
325
|
+
disable_logs
|
345
326
|
)
|
346
327
|
variation
|
347
328
|
else
|
@@ -354,7 +335,8 @@ class VWO
|
|
354
335
|
user_id: user_id,
|
355
336
|
campaign_key: nil,
|
356
337
|
method: 'get_variation_allotted'
|
357
|
-
)
|
338
|
+
),
|
339
|
+
disable_logs
|
358
340
|
)
|
359
341
|
nil
|
360
342
|
end
|
@@ -413,13 +395,15 @@ class VWO
|
|
413
395
|
# @param[String] :campaign_key Unique campaign identifier
|
414
396
|
# @param[String] :variation_name Variation identifier
|
415
397
|
# @param[String] :goal_identifier The unique campaign's goal identifier
|
398
|
+
# @param[Boolean] :disable_logs optional: disable logs if True
|
416
399
|
# @return[Boolean] true if found otherwise false
|
417
400
|
|
418
|
-
def save_user_storage(user_id, campaign_key, variation_name, goal_identifier)
|
401
|
+
def save_user_storage(user_id, campaign_key, campaign_type, variation_name, goal_identifier, disable_logs = false)
|
419
402
|
unless @user_storage_service
|
420
403
|
@logger.log(
|
421
404
|
LogLevelEnum::DEBUG,
|
422
|
-
format(LogMessageEnum::DebugMessages::NO_USER_STORAGE_SERVICE_SAVE, file: FILE)
|
405
|
+
format(LogMessageEnum::DebugMessages::NO_USER_STORAGE_SERVICE_SAVE, file: FILE),
|
406
|
+
disable_logs
|
423
407
|
)
|
424
408
|
return false
|
425
409
|
end
|
@@ -435,13 +419,28 @@ class VWO
|
|
435
419
|
|
436
420
|
@logger.log(
|
437
421
|
LogLevelEnum::INFO,
|
438
|
-
format(LogMessageEnum::InfoMessages::SAVING_DATA_USER_STORAGE_SERVICE, file: FILE, user_id: user_id)
|
422
|
+
format(LogMessageEnum::InfoMessages::SAVING_DATA_USER_STORAGE_SERVICE, file: FILE, user_id: user_id),
|
423
|
+
disable_logs
|
424
|
+
)
|
425
|
+
|
426
|
+
@logger.log(
|
427
|
+
LogLevelEnum::INFO,
|
428
|
+
format(
|
429
|
+
LogMessageEnum::InfoMessages::VARIATION_ALLOCATED,
|
430
|
+
file: FILE,
|
431
|
+
campaign_key: campaign_key,
|
432
|
+
user_id: user_id,
|
433
|
+
variation_name: variation_name,
|
434
|
+
campaign_type: campaign_type
|
435
|
+
),
|
436
|
+
disable_logs
|
439
437
|
)
|
440
438
|
true
|
441
439
|
rescue StandardError
|
442
440
|
@logger.log(
|
443
441
|
LogLevelEnum::ERROR,
|
444
|
-
format(LogMessageEnum::ErrorMessages::SAVE_USER_STORAGE_SERVICE_FAILED, file: FILE, user_id: user_id)
|
442
|
+
format(LogMessageEnum::ErrorMessages::SAVE_USER_STORAGE_SERVICE_FAILED, file: FILE, user_id: user_id),
|
443
|
+
disable_logs
|
445
444
|
)
|
446
445
|
false
|
447
446
|
end
|
@@ -455,14 +454,15 @@ class VWO
|
|
455
454
|
# @param[String] :api_name The key Passed to identify the calling API
|
456
455
|
# @param[String] :campaign_key Unique campaign key
|
457
456
|
# @param[Hash] :variation_targeting_variables Key/value pair of Whitelisting Custom Attributes
|
457
|
+
# @param[Boolean] :disable_logs optional: disable logs if True
|
458
458
|
#
|
459
459
|
# @return[Hash]
|
460
460
|
|
461
|
-
def evaluate_whitelisting(user_id, campaign, api_name, campaign_key, variation_targeting_variables = {})
|
461
|
+
def evaluate_whitelisting(user_id, campaign, api_name, campaign_key, variation_targeting_variables = {}, disable_logs = false)
|
462
462
|
if variation_targeting_variables.nil?
|
463
|
-
variation_targeting_variables = {
|
463
|
+
variation_targeting_variables = { _vwo_user_id: user_id }
|
464
464
|
else
|
465
|
-
variation_targeting_variables[
|
465
|
+
variation_targeting_variables[:_vwo_user_id] = user_id
|
466
466
|
end
|
467
467
|
targeted_variations = []
|
468
468
|
|
@@ -470,7 +470,7 @@ class VWO
|
|
470
470
|
segments = get_segments(variation)
|
471
471
|
is_valid_segments = valid_value?(segments)
|
472
472
|
if is_valid_segments
|
473
|
-
if @segment_evaluator.evaluate(campaign_key, user_id, segments, variation_targeting_variables)
|
473
|
+
if @segment_evaluator.evaluate(campaign_key, user_id, segments, variation_targeting_variables, disable_logs)
|
474
474
|
targeted_variations.push(variation)
|
475
475
|
status = StatusEnum::PASSED
|
476
476
|
else
|
@@ -485,10 +485,11 @@ class VWO
|
|
485
485
|
user_id: user_id,
|
486
486
|
status: status,
|
487
487
|
custom_variables: variation_targeting_variables,
|
488
|
-
variation_name: variation['name'],
|
488
|
+
variation_name: status == StatusEnum::PASSED ? (campaign['type'] == CampaignTypes::FEATURE_ROLLOUT ? 'and hence becomes part of the rollout' : "for " + variation['name']) : '',
|
489
489
|
segmentation_type: SegmentationTypeEnum::WHITELISTING,
|
490
490
|
api_name: api_name
|
491
|
-
)
|
491
|
+
),
|
492
|
+
disable_logs
|
492
493
|
)
|
493
494
|
else
|
494
495
|
@logger.log(
|
@@ -500,7 +501,8 @@ class VWO
|
|
500
501
|
user_id: user_id,
|
501
502
|
api_name: api_name,
|
502
503
|
variation: variation['name']
|
503
|
-
)
|
504
|
+
),
|
505
|
+
disable_logs
|
504
506
|
)
|
505
507
|
end
|
506
508
|
end
|
@@ -525,7 +527,8 @@ class VWO
|
|
525
527
|
whitelisted_variation = @bucketer.get_variation(
|
526
528
|
targeted_variations_deep_clone,
|
527
529
|
@bucketer.get_bucket_value_for_user(
|
528
|
-
user_id
|
530
|
+
user_id,
|
531
|
+
campaign
|
529
532
|
)
|
530
533
|
)
|
531
534
|
else
|
@@ -553,18 +556,26 @@ class VWO
|
|
553
556
|
end
|
554
557
|
end
|
555
558
|
|
559
|
+
def scale_campaigns_weight(campaigns)
|
560
|
+
normalize_weight = 100/campaigns.length
|
561
|
+
campaigns.each do |campaign|
|
562
|
+
campaign['weight'] = normalize_weight
|
563
|
+
end
|
564
|
+
end
|
556
565
|
# Get the UserStorageData after looking up into get method
|
557
566
|
# Being provided via UserStorageService
|
558
567
|
#
|
559
568
|
# @param[String]: Unique user identifier
|
560
569
|
# @param[String]: Unique campaign key
|
570
|
+
# @param[Boolean] :disable_logs if True
|
561
571
|
# @return[Hash|Boolean]: user_storage data
|
562
572
|
|
563
|
-
def get_user_storage(user_id, campaign_key)
|
573
|
+
def get_user_storage(user_id, campaign_key, disable_logs = false)
|
564
574
|
unless @user_storage_service
|
565
575
|
@logger.log(
|
566
576
|
LogLevelEnum::DEBUG,
|
567
|
-
format(LogMessageEnum::DebugMessages::NO_USER_STORAGE_SERVICE_LOOKUP, file: FILE)
|
577
|
+
format(LogMessageEnum::DebugMessages::NO_USER_STORAGE_SERVICE_LOOKUP, file: FILE),
|
578
|
+
disable_logs
|
568
579
|
)
|
569
580
|
return false
|
570
581
|
end
|
@@ -577,13 +588,15 @@ class VWO
|
|
577
588
|
file: FILE,
|
578
589
|
user_id: user_id,
|
579
590
|
status: data.nil? ? 'Not Found' : 'Found'
|
580
|
-
)
|
591
|
+
),
|
592
|
+
disable_logs
|
581
593
|
)
|
582
594
|
data
|
583
595
|
rescue StandardError
|
584
596
|
@logger.log(
|
585
597
|
LogLevelEnum::ERROR,
|
586
|
-
format(LogMessageEnum::ErrorMessages::LOOK_UP_USER_STORAGE_SERVICE_FAILED, file: FILE, user_id: user_id)
|
598
|
+
format(LogMessageEnum::ErrorMessages::LOOK_UP_USER_STORAGE_SERVICE_FAILED, file: FILE, user_id: user_id),
|
599
|
+
disable_logs
|
587
600
|
)
|
588
601
|
false
|
589
602
|
end
|
@@ -593,10 +606,11 @@ class VWO
|
|
593
606
|
# @param[String] :user_id
|
594
607
|
# @param[String] :campaign_key campaign identified
|
595
608
|
# @param[Hash] :user_campaign_map BucketMap consisting of stored user variation
|
609
|
+
# @param[Boolean] :disable_logs if True
|
596
610
|
#
|
597
611
|
# @return[Object, nil] if found then variation settings object otherwise None
|
598
612
|
|
599
|
-
def get_stored_variation(user_id, campaign_key, user_campaign_map)
|
613
|
+
def get_stored_variation(user_id, campaign_key, user_campaign_map, disable_logs = false)
|
600
614
|
return unless user_campaign_map['campaign_key'] == campaign_key
|
601
615
|
|
602
616
|
variation_name = user_campaign_map['variation_name']
|
@@ -608,7 +622,8 @@ class VWO
|
|
608
622
|
campaign_key: campaign_key,
|
609
623
|
user_id: user_id,
|
610
624
|
variation_name: variation_name
|
611
|
-
)
|
625
|
+
),
|
626
|
+
disable_logs
|
612
627
|
)
|
613
628
|
|
614
629
|
get_campaign_variation(
|
@@ -617,6 +632,276 @@ class VWO
|
|
617
632
|
variation_name
|
618
633
|
)
|
619
634
|
end
|
635
|
+
|
636
|
+
# this function check whether pre-segmentation is passed or not
|
637
|
+
#
|
638
|
+
# @param[String] :user_id The unique key assigned to User
|
639
|
+
# @param[Hash] :campaign Campaign hash for Unique campaign key
|
640
|
+
# @param[Hash] :custom_variables Key/value pair for segmentation
|
641
|
+
# @param[String] :api_name The key Passed to identify the calling API
|
642
|
+
# @param[Boolean] :disable_logs optional: disable logs if True
|
643
|
+
#
|
644
|
+
# @return[Boolean]
|
645
|
+
def check_presegmentation(campaign, user_id, custom_variables, api_name, disable_logs = false)
|
646
|
+
campaign_key = campaign['key']
|
647
|
+
segments = get_segments(campaign)
|
648
|
+
is_valid_segments = valid_value?(segments)
|
649
|
+
|
650
|
+
if is_valid_segments
|
651
|
+
unless custom_variables
|
652
|
+
@logger.log(
|
653
|
+
LogLevelEnum::INFO,
|
654
|
+
format(
|
655
|
+
LogMessageEnum::InfoMessages::NO_CUSTOM_VARIABLES,
|
656
|
+
file: FILE,
|
657
|
+
campaign_key: campaign_key,
|
658
|
+
user_id: user_id,
|
659
|
+
api_name: api_name
|
660
|
+
),
|
661
|
+
disable_logs
|
662
|
+
)
|
663
|
+
custom_variables = {}
|
664
|
+
end
|
665
|
+
unless @segment_evaluator.evaluate(campaign_key, user_id, segments, custom_variables, disable_logs)
|
666
|
+
@logger.log(
|
667
|
+
LogLevelEnum::INFO,
|
668
|
+
format(
|
669
|
+
LogMessageEnum::InfoMessages::USER_FAILED_SEGMENTATION,
|
670
|
+
file: FileNameEnum::SegmentEvaluator,
|
671
|
+
user_id: user_id,
|
672
|
+
campaign_key: campaign_key,
|
673
|
+
custom_variables: custom_variables
|
674
|
+
),
|
675
|
+
disable_logs
|
676
|
+
)
|
677
|
+
return false
|
678
|
+
end
|
679
|
+
@logger.log(
|
680
|
+
LogLevelEnum::INFO,
|
681
|
+
format(
|
682
|
+
LogMessageEnum::InfoMessages::USER_PASSED_SEGMENTATION,
|
683
|
+
file: FileNameEnum::SegmentEvaluator,
|
684
|
+
user_id: user_id,
|
685
|
+
campaign_key: campaign_key,
|
686
|
+
custom_variables: custom_variables
|
687
|
+
),
|
688
|
+
disable_logs
|
689
|
+
)
|
690
|
+
else
|
691
|
+
@logger.log(
|
692
|
+
LogLevelEnum::INFO,
|
693
|
+
format(
|
694
|
+
LogMessageEnum::InfoMessages::SKIPPING_SEGMENTATION,
|
695
|
+
file: FILE,
|
696
|
+
campaign_key: campaign_key,
|
697
|
+
user_id: user_id,
|
698
|
+
api_name: api_name,
|
699
|
+
variation: ''
|
700
|
+
),
|
701
|
+
disable_logs
|
702
|
+
)
|
703
|
+
end
|
704
|
+
true
|
705
|
+
end
|
706
|
+
|
707
|
+
# Finds and returns eligible campaigns from group_campaigns.
|
708
|
+
#
|
709
|
+
# @param[String] :user_id The unique key assigned to User
|
710
|
+
# @param[Hash] :called_campaign campaign for which api is called
|
711
|
+
# @param[Array] :group_campaigns campaigns part of group
|
712
|
+
# @param[String] :custom_variables Key/value pair for segmentation
|
713
|
+
#
|
714
|
+
# @return[Array]
|
715
|
+
def get_eligible_campaigns(user_id, group_campaigns, called_campaign, custom_variables)
|
716
|
+
eligible_campaigns = []
|
717
|
+
|
718
|
+
group_campaigns.each do |campaign|
|
719
|
+
if called_campaign["id"] == campaign["id"] || check_presegmentation(campaign, user_id, custom_variables, '', true) && @bucketer.user_part_of_campaign?(user_id, campaign)
|
720
|
+
eligible_campaigns.push(campaign)
|
721
|
+
end
|
722
|
+
end
|
723
|
+
return eligible_campaigns
|
724
|
+
end
|
725
|
+
|
726
|
+
# Finds and returns the winner campaign from eligible_campaigns list.
|
727
|
+
#
|
728
|
+
# @param[String] :user_id The unique key assigned to User
|
729
|
+
# @param[Array] :eligible_campaigns campaigns part of group which were eligible to be winner
|
730
|
+
#
|
731
|
+
# @return[Hash]
|
732
|
+
def get_winner_campaign(user_id, eligible_campaigns, group_id)
|
733
|
+
if eligible_campaigns.length == 1
|
734
|
+
return eligible_campaigns[0]
|
735
|
+
end
|
736
|
+
|
737
|
+
eligible_campaigns = scale_campaigns_weight(eligible_campaigns)
|
738
|
+
eligible_campaigns = set_campaign_allocation(eligible_campaigns)
|
739
|
+
bucket_value = @bucketer.get_bucket_value_for_user(user_id, {}, group_id, true)
|
740
|
+
return @bucketer.get_campaign_using_range(bucket_value, eligible_campaigns)
|
741
|
+
end
|
742
|
+
|
743
|
+
# Get campaign keys of all eligible Campaigns.
|
744
|
+
#
|
745
|
+
# @param[Array] :eligible_campaigns campaigns part of group which were eligible to be winner
|
746
|
+
#
|
747
|
+
# @return[Array]
|
748
|
+
def get_eligible_campaigns_key(eligible_campaigns)
|
749
|
+
eligible_campaigns_key = []
|
750
|
+
eligible_campaigns.each do |campaign|
|
751
|
+
eligible_campaigns_key.push(campaign["key"])
|
752
|
+
end
|
753
|
+
eligible_campaigns_key
|
754
|
+
end
|
755
|
+
|
756
|
+
# Get campaign keys of all non eligible Campaigns.
|
757
|
+
#
|
758
|
+
# @param[Array] :eligible_campaigns campaigns part of group which were eligible to be winner
|
759
|
+
# @param[Array] :group_campaigns campaigns part of group
|
760
|
+
#
|
761
|
+
# @return[Array]
|
762
|
+
def get_non_eligible_campaigns_key(eligible_campaigns, group_campaigns)
|
763
|
+
non_eligible_campaigns_key = []
|
764
|
+
group_campaigns.each do |campaign|
|
765
|
+
unless eligible_campaigns.include? campaign
|
766
|
+
non_eligible_campaigns_key.push(campaign["key"])
|
767
|
+
end
|
768
|
+
end
|
769
|
+
non_eligible_campaigns_key
|
770
|
+
end
|
771
|
+
|
772
|
+
# Checks if any other campaign in groupCampaigns satisfies whitelisting or is in user storage.
|
773
|
+
#
|
774
|
+
# @param[String] :user_id the unique ID assigned to User
|
775
|
+
# @param[Hash] :called_campaign campaign for which api is called
|
776
|
+
# @param[Array] :group_campaigns campaigns part of group
|
777
|
+
# @param[String] :group_name group name
|
778
|
+
# @param[Hash] :variation_targeting_variables Key/value pair of Whitelisting Custom Attributes
|
779
|
+
# @param[Boolean] :disable_logs optional: disable logs if True
|
780
|
+
# @return[Boolean]
|
781
|
+
|
782
|
+
def check_whitelisting_or_storage_for_grouped_campaigns(user_id, called_campaign, group_campaigns, group_name, variation_targeting_variables, disable_logs = false)
|
783
|
+
group_campaigns.each do |campaign|
|
784
|
+
if called_campaign["id"] != campaign["id"]
|
785
|
+
targeted_variation = evaluate_whitelisting(
|
786
|
+
user_id,
|
787
|
+
campaign,
|
788
|
+
'',
|
789
|
+
campaign["key"],
|
790
|
+
variation_targeting_variables,
|
791
|
+
true
|
792
|
+
)
|
793
|
+
if targeted_variation
|
794
|
+
@logger.log(
|
795
|
+
LogLevelEnum::INFO,
|
796
|
+
format(
|
797
|
+
LogMessageEnum::InfoMessages::OTHER_CAMPAIGN_SATISFIES_WHITELISTING_OR_STORAGE,
|
798
|
+
file: FILE,
|
799
|
+
campaign_key: campaign["key"],
|
800
|
+
user_id: user_id,
|
801
|
+
group_name: group_name,
|
802
|
+
type: "whitelisting"
|
803
|
+
),
|
804
|
+
disable_logs
|
805
|
+
)
|
806
|
+
return true
|
807
|
+
end
|
808
|
+
end
|
809
|
+
end
|
810
|
+
|
811
|
+
group_campaigns.each do |campaign|
|
812
|
+
if called_campaign["id"] != campaign["id"]
|
813
|
+
user_storage_data = get_user_storage(user_id, campaign["key"], true)
|
814
|
+
if user_storage_data
|
815
|
+
@logger.log(
|
816
|
+
LogLevelEnum::INFO,
|
817
|
+
format(
|
818
|
+
LogMessageEnum::InfoMessages::OTHER_CAMPAIGN_SATISFIES_WHITELISTING_OR_STORAGE,
|
819
|
+
file: FILE,
|
820
|
+
campaign_key: campaign["key"],
|
821
|
+
user_id: user_id,
|
822
|
+
group_name: group_name,
|
823
|
+
type: "user storage"
|
824
|
+
),
|
825
|
+
disable_logs
|
826
|
+
)
|
827
|
+
return true
|
828
|
+
end
|
829
|
+
end
|
830
|
+
end
|
831
|
+
false
|
832
|
+
end
|
833
|
+
|
834
|
+
# Get variation if whitelisting passes
|
835
|
+
#
|
836
|
+
# @param[String] :user_id the unique ID assigned to User
|
837
|
+
# @param[Hash] :campaign campaign for which checking whitelisting
|
838
|
+
# @param[Hash] :variation_targeting_variables Key/value pair of Whitelisting Custom Attributes
|
839
|
+
# @param[String] :api_name The key Passed to identify the calling API
|
840
|
+
# @param[Hash] :decision data containing campaign info passed to hooks manager
|
841
|
+
# @param[Boolean] :disable_logs optional: disable logs if True
|
842
|
+
# @return[Hash]
|
843
|
+
def get_variation_if_whitelisting_passed(user_id, campaign, variation_targeting_variables, api_name, decision, disable_logs = false)
|
844
|
+
campaign_key = campaign['key']
|
845
|
+
if campaign['isForcedVariationEnabled']
|
846
|
+
variation = evaluate_whitelisting(
|
847
|
+
user_id,
|
848
|
+
campaign,
|
849
|
+
api_name,
|
850
|
+
campaign_key,
|
851
|
+
variation_targeting_variables,
|
852
|
+
disable_logs
|
853
|
+
)
|
854
|
+
status = if variation
|
855
|
+
StatusEnum::PASSED
|
856
|
+
else
|
857
|
+
StatusEnum::FAILED
|
858
|
+
end
|
859
|
+
|
860
|
+
@logger.log(
|
861
|
+
LogLevelEnum::INFO,
|
862
|
+
format(
|
863
|
+
LogMessageEnum::InfoMessages::SEGMENTATION_STATUS,
|
864
|
+
file: FILE,
|
865
|
+
campaign_key: campaign_key,
|
866
|
+
user_id: user_id,
|
867
|
+
status: status,
|
868
|
+
custom_variables: variation_targeting_variables ? variation_targeting_variables : {},
|
869
|
+
variation_name: (status == StatusEnum::PASSED && campaign['type'] != CampaignTypes::FEATURE_ROLLOUT) ? "and #{variation['name']} is Assigned" : ' ',
|
870
|
+
segmentation_type: SegmentationTypeEnum::WHITELISTING,
|
871
|
+
api_name: api_name
|
872
|
+
),
|
873
|
+
disable_logs
|
874
|
+
)
|
875
|
+
|
876
|
+
if variation
|
877
|
+
if campaign['type'] == CampaignTypes::VISUAL_AB || campaign['type'] == CampaignTypes::FEATURE_TEST
|
878
|
+
decision[:variation_name] = variation['name']
|
879
|
+
decision[:variation_id] = variation['id']
|
880
|
+
if campaign['type'] == CampaignTypes::FEATURE_TEST
|
881
|
+
decision[:is_feature_enabled] = variation['isFeatureEnabled']
|
882
|
+
end
|
883
|
+
end
|
884
|
+
decision[:is_user_whitelisted] = true
|
885
|
+
@hooks_manager.execute(decision)
|
886
|
+
end
|
887
|
+
|
888
|
+
return variation if variation && variation['name']
|
889
|
+
else
|
890
|
+
@logger.log(
|
891
|
+
LogLevelEnum::INFO,
|
892
|
+
format(
|
893
|
+
LogMessageEnum::InfoMessages::WHITELISTING_SKIPPED,
|
894
|
+
file: FILE,
|
895
|
+
campaign_key: campaign_key,
|
896
|
+
user_id: user_id,
|
897
|
+
api_name: api_name
|
898
|
+
),
|
899
|
+
disable_logs
|
900
|
+
)
|
901
|
+
end
|
902
|
+
nil
|
903
|
+
end
|
904
|
+
|
620
905
|
end
|
621
906
|
end
|
622
907
|
end
|