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.
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