vwo-sdk 1.3.0 → 1.14.1

Sign up to get free protection for your applications and to get access to all the features.
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: accountId:%<account_id>s userId:%<user_id>s campaignId:%<campaign_id>s and variationId:%<variation_id>s'
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): "activate" API got bad parameters. It expects campaignTestKey(String) as first and userId(String) as second argument'
89
- ACTIVATE_API_CONFIG_CORRUPTED = '(%<file>s): "activate" API has corrupted configuration'
90
- GET_VARIATION_NAME_API_MISSING_PARAMS = '(%<file>s): "getVariation" API got bad parameters. It expects campaignTestKey(String) as first and userId(String) as second argument'
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
- TRACK_API_MISSING_PARAMS = '(%<file>s): "track" API got bad parameters. It expects campaignTestKey(String) 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.'
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:%<api>s - Campaign:%<campaign_key>s is not RUNNING. Please verify from VWO App'
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