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