vwo-sdk 1.3.0 → 1.14.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 +5 -5
- data/lib/vwo.rb +1020 -84
- data/lib/vwo/constants.rb +64 -13
- data/lib/vwo/core/bucketer.rb +10 -14
- data/lib/vwo/core/variation_decider.rb +391 -80
- data/lib/vwo/enums.rb +113 -10
- data/lib/vwo/logger.rb +9 -3
- data/lib/vwo/schemas/settings_file.rb +1 -3
- data/lib/vwo/services/batch_events_dispatcher.rb +110 -0
- data/lib/vwo/services/batch_events_queue.rb +175 -0
- data/lib/vwo/services/event_dispatcher.rb +3 -17
- data/lib/vwo/services/hooks_manager.rb +36 -0
- data/lib/vwo/services/operand_evaluator.rb +122 -0
- data/lib/vwo/services/segment_evaluator.rb +88 -0
- data/lib/vwo/services/settings_file_manager.rb +11 -9
- data/lib/vwo/services/settings_file_processor.rb +6 -3
- data/lib/vwo/services/usage_stats.rb +29 -0
- data/lib/vwo/user_storage.rb +1 -3
- data/lib/vwo/utils/campaign.rb +151 -22
- data/lib/vwo/utils/custom_dimensions.rb +72 -0
- data/lib/vwo/utils/feature.rb +56 -0
- data/lib/vwo/utils/function.rb +6 -3
- data/lib/vwo/utils/impression.rb +76 -7
- data/lib/vwo/utils/request.rb +15 -3
- data/lib/vwo/utils/segment.rb +116 -0
- data/lib/vwo/utils/uuid.rb +3 -5
- data/lib/vwo/utils/validations.rb +96 -4
- metadata +30 -8
data/lib/vwo/enums.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2019 Wingify Software Pvt. Ltd.
|
1
|
+
# Copyright 2019-2021 Wingify Software Pvt. Ltd.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -12,14 +12,54 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
# frozen_string_literal: true
|
16
|
-
|
17
15
|
# rubocop:disable Metrics/LineLength
|
18
16
|
|
19
17
|
require 'logger'
|
20
18
|
|
21
19
|
class VWO
|
22
20
|
module Enums
|
21
|
+
module OperandValueTypesName
|
22
|
+
REGEX = 'regex'
|
23
|
+
WILDCARD = 'wildcard'
|
24
|
+
LOWER = 'lower'
|
25
|
+
EQUALS = 'equals'
|
26
|
+
end
|
27
|
+
|
28
|
+
module OperandValueTypes
|
29
|
+
LOWER = 'lower'
|
30
|
+
CONTAINS = 'contains'
|
31
|
+
STARTS_WITH = 'starts_with'
|
32
|
+
ENDS_WITH = 'ends_with'
|
33
|
+
REGEX = 'regex'
|
34
|
+
EQUALS = 'equals'
|
35
|
+
end
|
36
|
+
|
37
|
+
module OperatorTypes
|
38
|
+
AND = 'and'
|
39
|
+
OR = 'or'
|
40
|
+
NOT = 'not'
|
41
|
+
end
|
42
|
+
|
43
|
+
module OperandTypes
|
44
|
+
CUSTOM_VARIABLE = 'custom_variable'
|
45
|
+
USER = 'user'
|
46
|
+
end
|
47
|
+
|
48
|
+
module OperandValuesBooleanTypes
|
49
|
+
TRUE = 'true'
|
50
|
+
FALSE = 'false'
|
51
|
+
end
|
52
|
+
|
53
|
+
module StatusEnum
|
54
|
+
PASSED = 'passed'
|
55
|
+
FAILED = 'failed'
|
56
|
+
end
|
57
|
+
|
58
|
+
module SegmentationTypeEnum
|
59
|
+
WHITELISTING = 'whitelisting'
|
60
|
+
PRE_SEGMENTATION = 'pre-segmentation'
|
61
|
+
end
|
62
|
+
|
23
63
|
module FileNameEnum
|
24
64
|
VWO_PATH = 'vwo'
|
25
65
|
UTIL_PATH = 'vwo/utils'
|
@@ -28,14 +68,19 @@ class VWO
|
|
28
68
|
Bucketer = VWO_PATH + '/core/bucketer'
|
29
69
|
VariationDecider = VWO_PATH + '/core/variation_decider'
|
30
70
|
EventDispatcher = VWO_PATH + '/services/event_dispatcher'
|
71
|
+
SegmentEvaluator = VWO_PATH + '/services/segment_evaluator'
|
31
72
|
Logger = VWO_PATH + '/logger'
|
32
73
|
SettingsFileProcessor = VWO_PATH + '/services/settings_file_processor'
|
74
|
+
BatchEventsQueue = VWO_PATH + '/services/batch_events_queue'
|
75
|
+
BatchEventsDispatcher = VWO_PATH + '/services/batch_events_dispatcher'
|
33
76
|
|
34
77
|
CampaignUtil = UTIL_PATH + '/campaign'
|
35
78
|
FunctionUtil = UTIL_PATH + '/function'
|
79
|
+
FeatureUtil = UTIL_PATH + '/feature'
|
36
80
|
ImpressionUtil = UTIL_PATH + '/impression'
|
37
81
|
UuidUtil = UTIL_PATH + '/uuid'
|
38
82
|
ValidateUtil = UTIL_PATH + '/validations'
|
83
|
+
CustomDimensionsUtil = UTIL_PATH + '/custom_dimensions_util'
|
39
84
|
end
|
40
85
|
|
41
86
|
# Logging Enums
|
@@ -61,12 +106,19 @@ class VWO
|
|
61
106
|
IMPRESSION_FOR_TRACK_USER = '(%<file>s): Impression built for track-user - %<properties>s'
|
62
107
|
IMPRESSION_FOR_TRACK_GOAL = '(%<file>s): Impression built for track-goal - %<properties>s'
|
63
108
|
GOT_VARIATION_FOR_USER = '(%<file>s): userId:%<user_id>s for campaign:%<campaign_key>s got variationName:%<variation_name>s'
|
109
|
+
SEGMENTATION_STATUS = '(%<file>s): In API: %<api_name>s, for UserId:%<user_id>s of campaign:%<campaign_key>s with variables:%<custom_variables>s %<status>s %<segmentation_type>s for %<variation_name>s'
|
110
|
+
PARAMS_FOR_PUSH_CALL = '(%<file>s): Params for push call - %<properties>s'
|
111
|
+
CAMPAIGN_NOT_ACTIVATED = '(%<file>s): Campaign:%<campaign_key>s for User ID:%<user_id>s is not yet activated for API:%<api_name>s. Use activate API to activate A/B test or isFeatureEnabled API to activate Feature Test.'
|
112
|
+
BATCH_EVENT_LIMIT_EXCEEDED = '(%<file>s): Impression event - %<end_point>s failed due to exceeding payload size. Parameter eventsPerRequest in batchEvents config in launch API has value:%<eventsPerRequest>s for accountId:%<accountId>s. Please read the official documentation for knowing the size limits.'
|
113
|
+
BULK_NOT_PROCESSED = "(%<file>s): Batch events couldn't be received by VWO. Calling Flush Callback with error and data."
|
114
|
+
BEFORE_FLUSHING = '(%<file>s): Flushing events queue %<manually>s having %<length>s events %<timer>s queue summary: %<queue_metadata>s'
|
115
|
+
EVENT_BATCHING_INSUFFICIENT = '(%<file>s): %<key>s not provided, assigning default value'
|
64
116
|
end
|
65
117
|
|
66
118
|
# Info Messages
|
67
119
|
module InfoMessages
|
68
120
|
VARIATION_RANGE_ALLOCATION = '(%<file>s): Campaign:%<campaign_key>s having variations:%<variation_name>s with weight:%<variation_weight>s got range as: ( %<start>s - %<end>s ))'
|
69
|
-
VARIATION_ALLOCATED = '(%<file>s): UserId:%<user_id>s of Campaign:%<campaign_key>s got variation: %<variation_name>s'
|
121
|
+
VARIATION_ALLOCATED = '(%<file>s): UserId:%<user_id>s of Campaign:%<campaign_key>s type: %<campaign_type>s got variation: %<variation_name>s'
|
70
122
|
LOOKING_UP_USER_STORAGE_SERVICE = '(%<file>s): Looked into UserStorageService for userId:%<user_id>s %<status>s'
|
71
123
|
SAVING_DATA_USER_STORAGE_SERVICE = '(%<file>s): Saving into UserStorageService for userId:%<user_id>s successful'
|
72
124
|
GOT_STORED_VARIATION = '(%<file>s): Got stored variation:%<variation_name>s of campaign:%<campaign_key>s for userId:%<user_id>s from UserStorageService'
|
@@ -75,8 +127,34 @@ class VWO
|
|
75
127
|
AUDIENCE_CONDITION_NOT_MET = '(%<file>s): userId:%<user_id>s does not become part of campaign because of not meeting audience conditions'
|
76
128
|
GOT_VARIATION_FOR_USER = '(%<file>s): userId:%<user_id>s for campaign:%<campaign_key>s got variationName:%<variation_name>s'
|
77
129
|
USER_GOT_NO_VARIATION = '(%<file>s): userId:%<user_id>s for campaign:%<campaign_key>s did not allot any variation'
|
78
|
-
IMPRESSION_SUCCESS = '(%<file>s): Impression event - %<end_point>s was successfully received by VWO having main keys:
|
130
|
+
IMPRESSION_SUCCESS = '(%<file>s): Impression event - %<end_point>s was successfully received by VWO having main keys: sdkKey:%<sdk_key>s accountId:%<account_id>s campaignId:%<campaign_id>s and variationId:%<variation_id>s'
|
131
|
+
MAIN_KEYS_FOR_IMPRESSION = '(%<file>s): Having main keys: {sdkKey:%<sdk_key>s accountId:%<account_id>s campaignId:%<campaign_id>s and variationId:%<variation_id>s}'
|
132
|
+
MAIN_KEYS_FOR_PUSH_API = '(%<file>s): Having main keys: {sdkKey:%<sdk_key>s accountId:%<account_id>s u:%<u>s and tags:%<tags>s}'
|
79
133
|
INVALID_VARIATION_KEY = '(%<file>s): Variation was not assigned to userId:%<user_id>s for campaign:%<campaign_key>s'
|
134
|
+
|
135
|
+
USER_IN_FEATURE_ROLLOUT = '(%<file>s): User ID:%<user_id>s is in feature rollout:%<campaign_key>s'
|
136
|
+
USER_NOT_IN_FEATURE_ROLLOUT = '(%<file>s): User ID:%<user_id>s is NOT in feature rollout:%<campaign_key>s'
|
137
|
+
FEATURE_ENABLED_FOR_USER = '(%<file>s): In API: %<api_name>s Feature having feature-key:%<feature_key>s for user ID:%<user_id>s is enabled'
|
138
|
+
FEATURE_NOT_ENABLED_FOR_USER = '(%<file>s): In API: %<api_name>s Feature having feature-key:%<feature_key>s for user ID:%<user_id>s is not enabled'
|
139
|
+
|
140
|
+
VARIABLE_FOUND = '(%<file>s): In API: %<api_name>s Value for variable:%<variable_key>s of campaign:%<campaign_key>s and campaign type: %<campaign_type>s is:%<variable_value>s for user:%<user_id>s'
|
141
|
+
|
142
|
+
USER_PASSED_SEGMENTATION = '(%<file>s): UserId:%<user_id>s of campaign:%<campaign_key>s with custom_variables:%<custom_variables>s passed segmentation'
|
143
|
+
USER_FAILED_SEGMENTATION = '(%<file>s): UserId:%<user_id>s of campaign:%<campaign_key>s with custom_variables:%<custom_variables>s failed segmentation'
|
144
|
+
|
145
|
+
NO_CUSTOM_VARIABLES = '(%<file>s): In API: %<api_name>s, for UserId:%<user_id>s preSegments/customVariables are not passed for campaign:%<campaign_key>s and campaign has pre-segmentation'
|
146
|
+
SKIPPING_SEGMENTATION = '(%<file>s): In API: %<api_name>s, Skipping segmentation:%<variation>s for UserId:%<user_id>s as no valid segments found in campaign:%<campaign_key>s'
|
147
|
+
|
148
|
+
SEGMENTATION_STATUS = '(%<file>s): In API: %<api_name>s, for UserId:%<user_id>s of campaign:%<campaign_key>s with variables:%<custom_variables>s %<status>s %<segmentation_type>s %<variation_name>s'
|
149
|
+
WHITELISTING_SKIPPED = '(%<file>s): In API: %<api_name>s, Skipping whitelisting for UserId:%<user_id>s of campaign:%<campaign_key>s'
|
150
|
+
SETTINGS_NOT_UPDATED = '(%<file>s): Settings-file fetched are same as earlier fetched settings'
|
151
|
+
SETTINGS_FILE_UPDATED = '(%<file>s): %<api_name>s vwo_sdk_instance is updated with the latest settings_file'
|
152
|
+
CAMPAIGN_NOT_ACTIVATED = '(%<file>s): Activate the campaign:%<campaign_key>s for User ID:%<user_id>s to %<reason>s.'
|
153
|
+
GOAL_ALREADY_TRACKED = '(%<file>s): Goal:%<goal_identifier>s of Campaign:%<campaign_key>s for User ID:%<user_id>s has already been tracked earlier. Skipping now'
|
154
|
+
USER_ALREADY_TRACKED = '(%<file>s): User ID:%<user_id>s for Campaign:%<campaign_key>s has already been tracked earlier for "%<api_name>s" API. Skipping now'
|
155
|
+
API_CALLED = '(%<file>s): API: {api_name} called for UserId:%<user_id>s'
|
156
|
+
BULK_IMPRESSION_SUCCESS = '(%<file>s): Impression event - %<end_point>s was successfully received by VWO having accountId:%<a>s'
|
157
|
+
AFTER_FLUSHING = '(%<file>s): Events queue having %<length>s events has been flushed %<manually>s queue summary: %<queue_metadata>s'
|
80
158
|
end
|
81
159
|
|
82
160
|
# Warning Messages
|
@@ -85,22 +163,47 @@ class VWO
|
|
85
163
|
# Error Messages
|
86
164
|
module ErrorMessages
|
87
165
|
SETTINGS_FILE_CORRUPTED = '(%<file>s): Settings file is corrupted. Please contact VWO Support for help.'
|
88
|
-
ACTIVATE_API_MISSING_PARAMS = '(%<file>s):
|
89
|
-
|
90
|
-
|
166
|
+
ACTIVATE_API_MISSING_PARAMS = '(%<file>s): %<api_name>s API got bad parameters. It expects campaignTestKey(String) as first and userId(String) as second argument, customVariables(Hash) can be passed via options for pre-segmentation'
|
167
|
+
API_CONFIG_CORRUPTED = '(%<file>s): %<api_name>s API has corrupted configuration'
|
168
|
+
GET_VARIATION_NAME_API_INVALID_PARAMS = '(%<file>s): %<api_name>s API got bad parameters. It expects campaignTestKey(String) as first and userId(String) as second argument, customVariables(Hash) can be passed via options for pre-segmentation'
|
91
169
|
GET_VARIATION_API_CONFIG_CORRUPTED = '(%<file>s): "getVariation" API has corrupted configuration'
|
92
|
-
|
170
|
+
TRACK_API_INVALID_PARAMS = '(%<file>s): %<api_name>s API got bad parameters. It expects campaignTestKey(Nil/String/Array) as first userId(String) as second and goalIdentifier(String/Number) as third argument. Fourth is revenueValue(Float/Number/String) and is required for revenue goal only. customVariables(Hash) can be passed via options for pre-segmentation'
|
93
171
|
TRACK_API_CONFIG_CORRUPTED = '(%<file>s): "track" API has corrupted configuration'
|
94
172
|
TRACK_API_GOAL_NOT_FOUND = '(%<file>s): Goal:%<goal_identifier>s not found for campaign:%<campaign_key>s and userId:%<user_id>s'
|
95
173
|
TRACK_API_REVENUE_NOT_PASSED_FOR_REVENUE_GOAL = '(%<file>s): Revenue value should be passed for revenue goal:%<goal_identifier>s for campaign:%<campaign_key>s and userId:%<user_id>s'
|
96
174
|
TRACK_API_VARIATION_NOT_FOUND = '(%<file>s): Variation not found for campaign:%<campaign_key>s and userId:%<user_id>s'
|
97
|
-
CAMPAIGN_NOT_RUNNING = '(%<file>s): API used:%<
|
175
|
+
CAMPAIGN_NOT_RUNNING = '(%<file>s): API used:%<api_name>s - Campaign:%<campaign_key>s is not RUNNING. Please verify from VWO App'
|
98
176
|
LOOK_UP_USER_STORAGE_SERVICE_FAILED = '(%<file>s): Looking data from UserStorageService failed for userId:%<user_id>s'
|
99
177
|
SAVE_USER_STORAGE_SERVICE_FAILED = '(%<file>s): Saving data into UserStorageService failed for userId:%<user_id>s'
|
100
178
|
INVALID_CAMPAIGN = '(%<file>s): Invalid campaign passed to %<method>s of this file'
|
101
179
|
INVALID_USER_ID = '(%<file>s): Invalid userId:%<user_id>s passed to %<method>s of this file'
|
102
180
|
IMPRESSION_FAILED = '(%<file>s): Impression event could not be sent to VWO - %<end_point>s'
|
103
181
|
CUSTOM_LOGGER_MISCONFIGURED = '(%<file>s): Custom logger is provided but seems to have mis-configured. %<extra_info>s Please check the API Docs. Using default logger.'
|
182
|
+
INVALID_API = '(%<file>s): %<api_name>s API is not valid for user ID: %<user_id>s in campaign ID: %<campaign_key>s having campaign type: %<campaign_type>s.'
|
183
|
+
IS_FEATURE_ENABLED_API_INVALID_PARAMS = '(%<file>s): %<api_name>s API got bad parameters. It expects campaign_key(String) as first and user_id(String) as second argument, customVariables(dict) can be passed via options for pre-segmentation'
|
184
|
+
GET_FEATURE_VARIABLE_VALUE_API_INVALID_PARAMS = '(%<file>s): "get_feature_variable" API got bad parameters. It expects campaign_key(String) as first, variable_key(string) as second and user_id(String) as third argument, customVariables(dict) can be passed via options for pre-segmentation'
|
185
|
+
|
186
|
+
VARIABLE_NOT_FOUND = '(%<file>s): In API: %<api_name>s Variable %<variable_key>s not found for campaign %<campaign_key>s and type %<campaign_type>s for user ID %<user_id>s'
|
187
|
+
UNABLE_TO_TYPE_CAST = '(%<file>s): Unable to typecast value: %<value>s of type: %<of_type>s to type: %<variable_type>s.'
|
188
|
+
|
189
|
+
USER_NOT_IN_CAMPAIGN = '(%<file>s): userId:%<user_id>s did not become part of campaign:%<campaign_key>s and campaign type:%<campaign_type>s'
|
190
|
+
API_NOT_WORKING = '(%<file>s): API: %<api_name>s not working, exception caught: %<exception>s. Please contact VWO Support for help.'
|
191
|
+
|
192
|
+
SEGMENTATION_ERROR = '(%<file>s): Error while segmenting the UserId:%<user_id>s of campaign:%<campaign_key>s with custom_variables:%<custom_variables>s. Error message: %<error_message>s'
|
193
|
+
|
194
|
+
PUSH_API_INVALID_PARAMS = '(%<file>s): %<api_name>s API got bad parameters. It expects tag_key(String) as first and tag_value(String) as second argument and user_id(String) as third argument'
|
195
|
+
TAG_VALUE_LENGTH_EXCEEDED = '(%<file>s): In API: %<api_name>s, the length of tag_value:%<tag_value>s and userID: %<user_id>s can not be greater than 255'
|
196
|
+
TAG_KEY_LENGTH_EXCEEDED = '(%<file>s): In API: %<api_name>s, the length of tag_key:%<tag_key>s and userID: %<user_id>s can not be greater than 255'
|
197
|
+
TRACK_API_MISSING_PARAMS = '(%<file>s): "track" API got bad parameters. It expects campaignKey(null/String/array) as first, userId(String/Number) as second and goalIdentifier (string) as third argument. options is revenueValue(Float/Number/String) and is required for revenue goal only.'
|
198
|
+
NO_CAMPAIGN_FOUND = '(%<file>s): No campaign found for goal_identifier:%<goal_identifier>s. Please verify from VWO app.'
|
199
|
+
INVALID_TRACK_RETURNING_USER_VALUE = '(%<file>s): should_track_returning_user should be boolean'
|
200
|
+
INVALID_GOAL_TYPE = '(%<file>s): goal_type_to_track should be certain strings'
|
201
|
+
EVENT_BATCHING_NOT_OBJECT = '(%<file>s): Batch events settings are not of type object.'
|
202
|
+
EVENTS_PER_REQUEST_INVALID = '(%<file>s): events_per_request should be an integer'
|
203
|
+
REQUEST_TIME_INTERVAL_INVALID = '(%<file>s): request_time_interval should be a number'
|
204
|
+
EVENTS_PER_REQUEST_OUT_OF_BOUNDS = '(%<file>s): events_per_request should be >= %<min_value>s and <= %<max_value>s'
|
205
|
+
REQUEST_TIME_INTERVAL_OUT_OF_BOUNDS = '(%<file>s): request_time_interval should be >= %<min_value>s'
|
206
|
+
FLUSH_CALLBACK_INVALID = '(%<file>s): flush_callback is not callable'
|
104
207
|
end
|
105
208
|
end
|
106
209
|
|
data/lib/vwo/logger.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2019 Wingify Software Pvt. Ltd.
|
1
|
+
# Copyright 2019-2021 Wingify Software Pvt. Ltd.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -12,8 +12,6 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
# frozen_string_literal: true
|
16
|
-
|
17
15
|
require 'logger'
|
18
16
|
|
19
17
|
class VWO
|
@@ -33,5 +31,13 @@ class VWO
|
|
33
31
|
def log(level, message)
|
34
32
|
@@logger_instance.log(level, message)
|
35
33
|
end
|
34
|
+
|
35
|
+
def instance
|
36
|
+
@@logger_instance
|
37
|
+
end
|
38
|
+
|
39
|
+
def level
|
40
|
+
@@logger_instance.level
|
41
|
+
end
|
36
42
|
end
|
37
43
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2019 Wingify Software Pvt. Ltd.
|
1
|
+
# Copyright 2019-2021 Wingify Software Pvt. Ltd.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -12,8 +12,6 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
# frozen_string_literal: true
|
16
|
-
|
17
15
|
require 'json'
|
18
16
|
|
19
17
|
class VWO
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# Copyright 2019-2021 Wingify Software Pvt. Ltd.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require_relative '../logger'
|
16
|
+
require_relative '../enums'
|
17
|
+
require_relative '../utils/request'
|
18
|
+
class VWO
|
19
|
+
module Services
|
20
|
+
class BatchEventsDispatcher
|
21
|
+
include VWO::Enums
|
22
|
+
# Initialize the BatchEventDispatcher with logger and development mode
|
23
|
+
#
|
24
|
+
# @param [Boolean] : To specify whether the request
|
25
|
+
# to our server should be made or not.
|
26
|
+
#
|
27
|
+
def initialize
|
28
|
+
@logger = VWO::Logger.get_instance
|
29
|
+
@queue = []
|
30
|
+
end
|
31
|
+
|
32
|
+
# Dispatch the impression event having properties object only if dev-mode is OFF
|
33
|
+
#
|
34
|
+
# @param[Hash] :properties hash having impression properties
|
35
|
+
# the request to be dispatched to the VWO server
|
36
|
+
# @return[Boolean]
|
37
|
+
#
|
38
|
+
def dispatch(impression, callback, query_params)
|
39
|
+
url = CONSTANTS::HTTPS_PROTOCOL + CONSTANTS::ENDPOINTS::BASE_URL + CONSTANTS::ENDPOINTS::BATCH_EVENTS
|
40
|
+
account_id = query_params[:a]
|
41
|
+
resp = VWO::Utils::Request.post(url, query_params, impression)
|
42
|
+
if resp.code == '200'
|
43
|
+
@logger.log(
|
44
|
+
LogLevelEnum::INFO,
|
45
|
+
format(
|
46
|
+
LogMessageEnum::InfoMessages::BULK_IMPRESSION_SUCCESS,
|
47
|
+
file: FileNameEnum::BatchEventsDispatcher,
|
48
|
+
end_point: url,
|
49
|
+
a: account_id
|
50
|
+
)
|
51
|
+
)
|
52
|
+
message = nil
|
53
|
+
elsif resp.code == '413'
|
54
|
+
@logger.log(
|
55
|
+
LogLevelEnum::DEBUG,
|
56
|
+
format(
|
57
|
+
LogMessageEnum::DebugMessages::BATCH_EVENT_LIMIT_EXCEEDED,
|
58
|
+
file: FileNameEnum::BatchEventsDispatcher,
|
59
|
+
end_point: url,
|
60
|
+
accountId: impression[:a],
|
61
|
+
eventsPerRequest: impression.length()
|
62
|
+
)
|
63
|
+
)
|
64
|
+
|
65
|
+
@logger.log(
|
66
|
+
LogLevelEnum::ERROR,
|
67
|
+
format(
|
68
|
+
LogMessageEnum::ErrorMessages::IMPRESSION_FAILED,
|
69
|
+
file: FileNameEnum::BatchEventsDispatcher,
|
70
|
+
end_point: url
|
71
|
+
)
|
72
|
+
)
|
73
|
+
message = resp.message
|
74
|
+
else
|
75
|
+
@logger.log(
|
76
|
+
LogLevelEnum::DEBUG,
|
77
|
+
format(
|
78
|
+
LogMessageEnum::DebugMessages::BULK_NOT_PROCESSED,
|
79
|
+
file: FileNameEnum::BatchEventsDispatcher
|
80
|
+
)
|
81
|
+
)
|
82
|
+
|
83
|
+
@logger.log(
|
84
|
+
LogLevelEnum::ERROR,
|
85
|
+
format(LogMessageEnum::ErrorMessages::IMPRESSION_FAILED, file: FileNameEnum::BatchEventsDispatcher, end_point: url)
|
86
|
+
)
|
87
|
+
message = resp.message
|
88
|
+
end
|
89
|
+
if callback
|
90
|
+
callback.call(message, impression)
|
91
|
+
end
|
92
|
+
rescue StandardError => e
|
93
|
+
@logger.log(
|
94
|
+
LogLevelEnum::DEBUG,
|
95
|
+
format(
|
96
|
+
LogMessageEnum::DebugMessages::BULK_NOT_PROCESSED,
|
97
|
+
file: FileNameEnum::BatchEventsDispatcher
|
98
|
+
)
|
99
|
+
)
|
100
|
+
|
101
|
+
@logger.log(
|
102
|
+
LogLevelEnum::ERROR,
|
103
|
+
format(LogMessageEnum::ErrorMessages::IMPRESSION_FAILED, file: FileNameEnum::BatchEventsDispatcher, end_point: url)
|
104
|
+
)
|
105
|
+
false
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
# Copyright 2019-2021 Wingify Software Pvt. Ltd.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require_relative '../logger'
|
16
|
+
require_relative '../enums'
|
17
|
+
require_relative '../utils/request'
|
18
|
+
|
19
|
+
class VWO
|
20
|
+
module Services
|
21
|
+
class BatchEventsQueue
|
22
|
+
include VWO::Enums
|
23
|
+
|
24
|
+
def initialize(batch_config, is_development_mode = false)
|
25
|
+
@is_development_mode = is_development_mode
|
26
|
+
@logger = VWO::Logger.get_instance
|
27
|
+
@queue = []
|
28
|
+
@queue_metadata = {}
|
29
|
+
@batch_config = batch_config
|
30
|
+
|
31
|
+
if batch_config[:request_time_interval]
|
32
|
+
@request_time_interval = batch_config[:request_time_interval]
|
33
|
+
else
|
34
|
+
@request_time_interval = CONSTANTS::DEFAULT_REQUEST_TIME_INTERVAL
|
35
|
+
@logger.log(
|
36
|
+
LogLevelEnum::DEBUG,
|
37
|
+
format(
|
38
|
+
LogMessageEnum::DebugMessages::EVENT_BATCHING_INSUFFICIENT,
|
39
|
+
file: FileNameEnum::BatchEventsQueue,
|
40
|
+
key: 'request_time_interval'
|
41
|
+
)
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
if batch_config[:events_per_request]
|
46
|
+
@events_per_request = batch_config[:events_per_request]
|
47
|
+
else
|
48
|
+
@events_per_request = CONSTANTS::DEFAULT_EVENTS_PER_REQUEST
|
49
|
+
@logger.log(
|
50
|
+
LogLevelEnum::DEBUG,
|
51
|
+
format(
|
52
|
+
LogMessageEnum::DebugMessages::EVENT_BATCHING_INSUFFICIENT,
|
53
|
+
file: FileNameEnum::BatchEventsQueue,
|
54
|
+
key: 'events_per_request'
|
55
|
+
)
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
@flush_callback = nil
|
60
|
+
if batch_config.key?(:flushCallback) && batch_config[:flushCallback].is_a?(Method)
|
61
|
+
@flush_callback = batch_config[:flushCallback]
|
62
|
+
end
|
63
|
+
|
64
|
+
@dispatcher = batch_config[:dispatcher]
|
65
|
+
end
|
66
|
+
|
67
|
+
def create_new_batch_timer
|
68
|
+
@timer = Time.now + @request_time_interval
|
69
|
+
end
|
70
|
+
|
71
|
+
def enqueue(event)
|
72
|
+
return true if @is_development_mode
|
73
|
+
@queue.push(event)
|
74
|
+
update_queue_metadata(event)
|
75
|
+
unless @timer
|
76
|
+
create_new_batch_timer
|
77
|
+
@thread = Thread.new{flush_when_request_times_up}
|
78
|
+
end
|
79
|
+
if @events_per_request === @queue.length()
|
80
|
+
flush
|
81
|
+
kill_old_thread
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def flush_when_request_times_up
|
86
|
+
while @timer > Time.now
|
87
|
+
sleep(1)
|
88
|
+
end
|
89
|
+
flush
|
90
|
+
kill_old_thread
|
91
|
+
end
|
92
|
+
|
93
|
+
def flush(manual = false)
|
94
|
+
if @queue.length() > 0
|
95
|
+
@logger.log(
|
96
|
+
LogLevelEnum::DEBUG,
|
97
|
+
format(
|
98
|
+
LogMessageEnum::DebugMessages::BEFORE_FLUSHING,
|
99
|
+
file: FileNameEnum::BatchEventsQueue,
|
100
|
+
manually: manual ? 'manually' : '',
|
101
|
+
length: @queue.length(),
|
102
|
+
timer: manual ? 'Timer will be cleared and registered again,' : '',
|
103
|
+
queue_metadata: @queue_metadata
|
104
|
+
)
|
105
|
+
)
|
106
|
+
|
107
|
+
@dispatcher.call(@queue, @flush_callback)
|
108
|
+
@logger.log(
|
109
|
+
LogLevelEnum::INFO,
|
110
|
+
format(
|
111
|
+
LogMessageEnum::InfoMessages::AFTER_FLUSHING,
|
112
|
+
file: FILE,
|
113
|
+
manually: manual ? 'manually,' : '',
|
114
|
+
length: @queue.length(),
|
115
|
+
queue_metadata: @queue_metadata
|
116
|
+
)
|
117
|
+
)
|
118
|
+
@queue_metadata = {}
|
119
|
+
@queue = []
|
120
|
+
else
|
121
|
+
@logger.log(
|
122
|
+
LogLevelEnum::INFO,
|
123
|
+
format(
|
124
|
+
'Batch queue is empty. Nothing to flush.',
|
125
|
+
file: FILE
|
126
|
+
)
|
127
|
+
)
|
128
|
+
end
|
129
|
+
|
130
|
+
clear_request_timer
|
131
|
+
unless manual
|
132
|
+
if @thread
|
133
|
+
@old_thread = @thread
|
134
|
+
end
|
135
|
+
end
|
136
|
+
true
|
137
|
+
end
|
138
|
+
|
139
|
+
def clear_request_timer
|
140
|
+
@timer = nil
|
141
|
+
end
|
142
|
+
|
143
|
+
def kill_thread
|
144
|
+
if @thread
|
145
|
+
@thread.kill
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def kill_old_thread
|
150
|
+
if @old_thread
|
151
|
+
@old_thread.kill
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def update_queue_metadata(event)
|
156
|
+
if event[:eT] == 1
|
157
|
+
unless @queue_metadata.key?(VWO::EVENTS::TRACK_USER)
|
158
|
+
@queue_metadata[VWO::EVENTS::TRACK_USER] = 0
|
159
|
+
end
|
160
|
+
@queue_metadata[VWO::EVENTS::TRACK_USER] = @queue_metadata[VWO::EVENTS::TRACK_USER] + 1
|
161
|
+
elsif event[:eT] == 2
|
162
|
+
unless @queue_metadata.key?(VWO::EVENTS::TRACK_GOAL)
|
163
|
+
@queue_metadata[VWO::EVENTS::TRACK_GOAL] = 0
|
164
|
+
end
|
165
|
+
@queue_metadata[VWO::EVENTS::TRACK_GOAL] = @queue_metadata[VWO::EVENTS::TRACK_GOAL] + 1
|
166
|
+
elsif event[:eT] == 3
|
167
|
+
unless @queue_metadata.key?(VWO::EVENTS::PUSH)
|
168
|
+
@queue_metadata[VWO::EVENTS::PUSH] = 0
|
169
|
+
end
|
170
|
+
@queue_metadata[VWO::EVENTS::PUSH] = @queue_metadata[VWO::EVENTS::PUSH] + 1
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|