vwo-fme-ruby-sdk 1.0.0 → 1.1.0
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/api/get_flag.rb +236 -0
- data/lib/vwo/api/set_attribute.rb +57 -0
- data/lib/vwo/api/track_event.rb +77 -0
- data/lib/vwo/constants/constants.rb +54 -0
- data/lib/vwo/decorators/storage_decorator.rb +86 -0
- data/lib/vwo/{utils/logger_helper.rb → enums/api_enum.rb} +5 -10
- data/lib/vwo/enums/campaign_type_enum.rb +19 -0
- data/lib/vwo/enums/decision_types_enum.rb +18 -0
- data/lib/vwo/enums/event_enum.rb +19 -0
- data/lib/vwo/enums/headers_enum.rb +20 -0
- data/lib/vwo/enums/hooks_enum.rb +17 -0
- data/lib/vwo/enums/http_method_enum.rb +18 -0
- data/lib/vwo/enums/log_level_enum.rb +21 -0
- data/lib/vwo/enums/status_enum.rb +19 -0
- data/lib/vwo/enums/storage_enum.rb +22 -0
- data/lib/vwo/enums/url_enum.rb +21 -0
- data/lib/vwo/models/campaign/campaign_model.rb +192 -0
- data/lib/vwo/models/campaign/feature_model.rb +111 -0
- data/lib/vwo/models/campaign/impact_campaign_model.rb +38 -0
- data/lib/vwo/models/campaign/metric_model.rb +44 -0
- data/lib/vwo/models/campaign/rule_model.rb +56 -0
- data/lib/vwo/models/campaign/variable_model.rb +51 -0
- data/lib/vwo/models/campaign/variation_model.rb +137 -0
- data/lib/vwo/models/gateway_service_model.rb +39 -0
- data/lib/vwo/models/schemas/settings_schema_validation.rb +102 -0
- data/lib/vwo/models/settings/settings_model.rb +85 -0
- data/lib/vwo/models/storage/storage_data_model.rb +44 -0
- data/lib/vwo/models/user/context_model.rb +100 -0
- data/lib/vwo/models/user/context_vwo_model.rb +38 -0
- data/lib/vwo/{utils/feature_flag_response.rb → models/user/get_flag_response.rb} +14 -14
- data/lib/vwo/models/vwo_options_model.rb +107 -0
- data/lib/vwo/packages/decision_maker/decision_maker.rb +60 -0
- data/lib/vwo/packages/logger/core/log_manager.rb +90 -0
- data/lib/vwo/packages/logger/core/transport_manager.rb +87 -0
- data/lib/vwo/packages/logger/log_message_builder.rb +70 -0
- data/lib/vwo/packages/logger/logger.rb +38 -0
- data/lib/vwo/packages/logger/transports/console_transport.rb +49 -0
- data/lib/vwo/packages/network_layer/client/network_client.rb +107 -0
- data/lib/vwo/packages/network_layer/handlers/request_handler.rb +37 -0
- data/lib/vwo/packages/network_layer/manager/network_manager.rb +78 -0
- data/lib/vwo/packages/network_layer/models/global_request_model.rb +105 -0
- data/lib/vwo/packages/network_layer/models/request_model.rb +145 -0
- data/lib/vwo/packages/network_layer/models/response_model.rb +45 -0
- data/lib/vwo/packages/segmentation_evaluator/core/segmentation_manager.rb +76 -0
- data/lib/vwo/packages/segmentation_evaluator/enums/segment_operand_regex_enum.rb +29 -0
- data/lib/vwo/packages/segmentation_evaluator/enums/segment_operand_value_enum.rb +26 -0
- data/lib/vwo/packages/segmentation_evaluator/enums/segment_operator_value_enum.rb +30 -0
- data/lib/vwo/packages/segmentation_evaluator/evaluators/segment_evaluator.rb +210 -0
- data/lib/vwo/packages/segmentation_evaluator/evaluators/segment_operand_evaluator.rb +198 -0
- data/lib/vwo/packages/segmentation_evaluator/utils/segment_util.rb +44 -0
- data/lib/vwo/{constants.rb → packages/storage/connector.rb} +12 -10
- data/lib/vwo/packages/storage/storage.rb +45 -0
- data/lib/vwo/services/campaign_decision_service.rb +153 -0
- data/lib/vwo/services/hooks_service.rb +51 -0
- data/lib/vwo/services/logger_service.rb +83 -0
- data/lib/vwo/services/settings_service.rb +120 -0
- data/lib/vwo/services/storage_service.rb +65 -0
- data/lib/vwo/utils/campaign_util.rb +249 -0
- data/lib/vwo/utils/data_type_util.rb +105 -0
- data/lib/vwo/utils/decision_util.rb +253 -0
- data/lib/vwo/utils/function_util.rb +123 -0
- data/lib/vwo/utils/gateway_service_util.rb +101 -0
- data/lib/vwo/utils/impression_util.rb +49 -0
- data/lib/vwo/utils/log_message_util.rb +42 -0
- data/lib/vwo/utils/meg_util.rb +350 -0
- data/lib/vwo/utils/network_util.rb +235 -0
- data/lib/vwo/utils/rule_evaluation_util.rb +57 -0
- data/lib/vwo/utils/settings_util.rb +38 -0
- data/lib/vwo/utils/url_util.rb +46 -0
- data/lib/vwo/utils/uuid_util.rb +55 -0
- data/lib/vwo/vwo_builder.rb +156 -11
- data/lib/vwo/vwo_client.rb +163 -113
- data/lib/vwo.rb +49 -31
- metadata +187 -9
- data/lib/vwo/utils/request.rb +0 -89
@@ -0,0 +1,60 @@
|
|
1
|
+
# Copyright 2025 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 'murmurhash3'
|
16
|
+
|
17
|
+
class DecisionMaker
|
18
|
+
SEED_VALUE = 1 # Seed value for the hash function
|
19
|
+
|
20
|
+
# Generates a bucket value based on the hash value, maximum value, and an optional multiplier.
|
21
|
+
#
|
22
|
+
# @param hash_value [Integer] The hash value used for calculation.
|
23
|
+
# @param max_value [Integer] The maximum value for bucket scaling.
|
24
|
+
# @param multiplier [Integer] Optional multiplier to adjust the value (default: 1).
|
25
|
+
# @return [Integer] The calculated bucket value.
|
26
|
+
def generate_bucket_value(hash_value, max_value, multiplier = 1)
|
27
|
+
ratio = hash_value.to_f / (2**32)
|
28
|
+
multiplied_value = ((max_value * ratio) + 1) * multiplier
|
29
|
+
multiplied_value.floor
|
30
|
+
end
|
31
|
+
|
32
|
+
# Gets the bucket value for a user based on the hash key and maximum value.
|
33
|
+
#
|
34
|
+
# @param hash_key [String] The hash key for the user.
|
35
|
+
# @param max_value [Integer] The maximum value for bucket scaling (default: 100).
|
36
|
+
# @return [Integer] The calculated bucket value for the user.
|
37
|
+
def get_bucket_value_for_user(hash_key, max_value = 100)
|
38
|
+
hash_value = MurmurHash3::V32.str_hash(hash_key, SEED_VALUE)
|
39
|
+
generate_bucket_value(hash_value, max_value)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Calculates the bucket value for a given string with an optional multiplier and maximum value.
|
43
|
+
#
|
44
|
+
# @param str [String] The input string to calculate the bucket value for.
|
45
|
+
# @param multiplier [Integer] Optional multiplier to adjust the value (default: 1).
|
46
|
+
# @param max_value [Integer] The maximum value for bucket scaling (default: 10000).
|
47
|
+
# @return [Integer] The calculated bucket value.
|
48
|
+
def calculate_bucket_value(str, multiplier = 1, max_value = 10000)
|
49
|
+
hash_value = generate_hash_value(str)
|
50
|
+
generate_bucket_value(hash_value, max_value, multiplier)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Generates the hash value for a given hash key using MurmurHash v3.
|
54
|
+
#
|
55
|
+
# @param hash_key [String] The hash key for which the hash value is generated.
|
56
|
+
# @return [Integer] The generated hash value.
|
57
|
+
def generate_hash_value(hash_key)
|
58
|
+
MurmurHash3::V32.str_hash(hash_key, SEED_VALUE)
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# Copyright 2025 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
|
+
# log_manager.rb
|
16
|
+
require 'securerandom'
|
17
|
+
require_relative '../logger'
|
18
|
+
require_relative 'transport_manager'
|
19
|
+
require_relative '../transports/console_transport'
|
20
|
+
|
21
|
+
class LogManager < Logger
|
22
|
+
@instance = nil
|
23
|
+
|
24
|
+
# Use the `instance` method to initialize and get the instance
|
25
|
+
def self.instance(config = {})
|
26
|
+
# If an instance already exists, return it
|
27
|
+
if @instance.nil?
|
28
|
+
@instance = new(config)
|
29
|
+
end
|
30
|
+
@instance
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize(config = {})
|
34
|
+
# Store the config in an instance variable
|
35
|
+
@config = config
|
36
|
+
|
37
|
+
# Initialize default config values inside @config
|
38
|
+
@config[:name] ||= 'VWO Logger'
|
39
|
+
@config[:request_id] ||= SecureRandom.uuid
|
40
|
+
@config[:level] ||= 'ERROR'
|
41
|
+
@config[:prefix] ||= 'VWO-SDK'
|
42
|
+
@config[:date_time_format] ||= lambda { Time.now.iso8601 }
|
43
|
+
|
44
|
+
# Initialize the transport manager with the @config hash
|
45
|
+
@transport_manager = LogTransportManager.new(@config)
|
46
|
+
handle_transports
|
47
|
+
end
|
48
|
+
|
49
|
+
def trace(message)
|
50
|
+
@transport_manager.log('TRACE', message)
|
51
|
+
end
|
52
|
+
|
53
|
+
def debug(message)
|
54
|
+
@transport_manager.log('DEBUG', message)
|
55
|
+
end
|
56
|
+
|
57
|
+
def info(message)
|
58
|
+
@transport_manager.log('INFO', message)
|
59
|
+
end
|
60
|
+
|
61
|
+
def warn(message)
|
62
|
+
@transport_manager.log('WARN', message)
|
63
|
+
end
|
64
|
+
|
65
|
+
def error(message)
|
66
|
+
@transport_manager.log('ERROR', message)
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def handle_transports
|
72
|
+
transports = @config[:transports] || []
|
73
|
+
|
74
|
+
if transports.any?
|
75
|
+
add_transports(transports)
|
76
|
+
elsif @config[:transport]
|
77
|
+
add_transport(@config[:transport])
|
78
|
+
else
|
79
|
+
add_transport(ConsoleTransport.new(level: @config[:level]))
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def add_transport(transport)
|
84
|
+
@transport_manager.add_transport(transport)
|
85
|
+
end
|
86
|
+
|
87
|
+
def add_transports(transports)
|
88
|
+
transports.each { |transport| add_transport(transport) }
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# Copyright 2025 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 '../log_message_builder'
|
16
|
+
|
17
|
+
class LogTransportManager
|
18
|
+
def initialize(config)
|
19
|
+
@transports = []
|
20
|
+
@config = config # This should be the global config passed to LogManager
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_transport(transport)
|
24
|
+
@transports.push(transport)
|
25
|
+
end
|
26
|
+
|
27
|
+
def should_log?(transport_level, config_level)
|
28
|
+
target_level = log_level_to_number(transport_level)
|
29
|
+
desired_level = log_level_to_number(config_level || @config[:level])
|
30
|
+
target_level >= desired_level
|
31
|
+
end
|
32
|
+
|
33
|
+
def trace(message)
|
34
|
+
log('TRACE', message)
|
35
|
+
end
|
36
|
+
|
37
|
+
def debug(message)
|
38
|
+
log('DEBUG', message)
|
39
|
+
end
|
40
|
+
|
41
|
+
def info(message)
|
42
|
+
log('INFO', message)
|
43
|
+
end
|
44
|
+
|
45
|
+
def warn(message)
|
46
|
+
log('WARN', message)
|
47
|
+
end
|
48
|
+
|
49
|
+
def error(message)
|
50
|
+
log('ERROR', message)
|
51
|
+
end
|
52
|
+
|
53
|
+
def log(level, message)
|
54
|
+
@transports.each do |transport|
|
55
|
+
# Pass the global config (from LogManager) to LogMessageBuilder, not the transport
|
56
|
+
log_message_builder = LogMessageBuilder.new(@config, transport)
|
57
|
+
formatted_message = log_message_builder.format_message(level, message)
|
58
|
+
|
59
|
+
if should_log?(level, transport.level)
|
60
|
+
if transport.respond_to?(:log) && transport.method(:log).arity == 2
|
61
|
+
# Use custom log handler if available with correct arity
|
62
|
+
transport.log(level, message)
|
63
|
+
elsif transport.respond_to?(level.downcase.to_sym)
|
64
|
+
# Use level-specific method if available
|
65
|
+
transport.send(level.downcase.to_sym, formatted_message)
|
66
|
+
else
|
67
|
+
# Fallback to console_log
|
68
|
+
transport.console_log(level, formatted_message)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def log_level_to_number(level)
|
77
|
+
{
|
78
|
+
'TRACE' => 0,
|
79
|
+
'DEBUG' => 1,
|
80
|
+
'INFO' => 2,
|
81
|
+
'WARN' => 3,
|
82
|
+
'ERROR' => 4
|
83
|
+
}[level.upcase] || 0
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# Copyright 2025 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
|
+
class LogMessageBuilder
|
16
|
+
ANSI_COLOR_ENUM = {
|
17
|
+
bold: "\x1b[1m",
|
18
|
+
cyan: "\x1b[36m",
|
19
|
+
green: "\x1b[32m",
|
20
|
+
lightblue: "\x1b[94m",
|
21
|
+
red: "\x1b[31m",
|
22
|
+
reset: "\x1b[0m",
|
23
|
+
white: "\x1b[30m",
|
24
|
+
yellow: "\x1b[33m"
|
25
|
+
}
|
26
|
+
|
27
|
+
LOG_LEVEL_COLOR = {
|
28
|
+
'TRACE' => ANSI_COLOR_ENUM[:white],
|
29
|
+
'DEBUG' => ANSI_COLOR_ENUM[:lightblue],
|
30
|
+
'INFO' => ANSI_COLOR_ENUM[:cyan],
|
31
|
+
'WARN' => ANSI_COLOR_ENUM[:yellow],
|
32
|
+
'ERROR' => ANSI_COLOR_ENUM[:red]
|
33
|
+
}
|
34
|
+
|
35
|
+
def initialize(logger_config, transport_config)
|
36
|
+
@logger_config = logger_config
|
37
|
+
@transport_config = transport_config
|
38
|
+
|
39
|
+
# Access the values directly from transport_config if available.
|
40
|
+
@prefix = transport_config.instance_variable_get(:@prefix) || logger_config[:prefix] || ''
|
41
|
+
@date_time_format = transport_config.respond_to?(:date_time_format) ? transport_config.date_time_format : logger_config[:date_time_format] || lambda { Time.now.iso8601 }
|
42
|
+
end
|
43
|
+
|
44
|
+
def format_message(level, message)
|
45
|
+
"[#{get_formatted_level(level)}]: #{get_formatted_prefix(@prefix)} #{get_formatted_date_time} #{message}"
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def get_formatted_prefix(prefix)
|
51
|
+
if @logger_config[:is_ansi_color_enabled]
|
52
|
+
"#{ANSI_COLOR_ENUM[:bold]}#{ANSI_COLOR_ENUM[:green]}#{prefix}#{ANSI_COLOR_ENUM[:reset]}"
|
53
|
+
else
|
54
|
+
prefix
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def get_formatted_level(level)
|
59
|
+
color = LOG_LEVEL_COLOR[level.upcase] || ''
|
60
|
+
level_string = level.upcase
|
61
|
+
return "#{color}#{level_string}#{ANSI_COLOR_ENUM[:reset]}" if @logger_config[:is_ansi_color_enabled]
|
62
|
+
|
63
|
+
level_string
|
64
|
+
end
|
65
|
+
|
66
|
+
def get_formatted_date_time
|
67
|
+
@date_time_format.call
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Copyright 2025 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
|
+
# logger.rb
|
16
|
+
class Logger
|
17
|
+
# Abstract method definitions for logging at different levels
|
18
|
+
def trace(message)
|
19
|
+
raise NotImplementedError, "You must implement the trace method"
|
20
|
+
end
|
21
|
+
|
22
|
+
def debug(message)
|
23
|
+
raise NotImplementedError, "You must implement the debug method"
|
24
|
+
end
|
25
|
+
|
26
|
+
def info(message)
|
27
|
+
raise NotImplementedError, "You must implement the info method"
|
28
|
+
end
|
29
|
+
|
30
|
+
def warn(message)
|
31
|
+
raise NotImplementedError, "You must implement the warn method"
|
32
|
+
end
|
33
|
+
|
34
|
+
def error(message)
|
35
|
+
raise NotImplementedError, "You must implement the error method"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# Copyright 2025 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
|
+
class ConsoleTransport
|
16
|
+
attr_reader :level, :prefix
|
17
|
+
|
18
|
+
def initialize(config = {})
|
19
|
+
@config = config
|
20
|
+
@level = @config[:level] || 'ERROR'
|
21
|
+
@prefix = @config[:prefix] || 'VWO-SDK' # Ensure `@prefix` is set here
|
22
|
+
end
|
23
|
+
|
24
|
+
# Define the logging methods
|
25
|
+
def trace(message)
|
26
|
+
console_log('TRACE', message)
|
27
|
+
end
|
28
|
+
|
29
|
+
def debug(message)
|
30
|
+
console_log('DEBUG', message)
|
31
|
+
end
|
32
|
+
|
33
|
+
def info(message)
|
34
|
+
console_log('INFO', message)
|
35
|
+
end
|
36
|
+
|
37
|
+
def warn(message)
|
38
|
+
console_log('WARN', message)
|
39
|
+
end
|
40
|
+
|
41
|
+
def error(message)
|
42
|
+
console_log('ERROR', message)
|
43
|
+
end
|
44
|
+
|
45
|
+
def console_log(level, message)
|
46
|
+
puts "#{message}" # Output the log to console
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# Copyright 2025 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 'json'
|
16
|
+
require 'uri'
|
17
|
+
require_relative '../models/request_model'
|
18
|
+
require_relative '../models/response_model'
|
19
|
+
require_relative '../../../utils/network_util'
|
20
|
+
require 'net/http'
|
21
|
+
require 'concurrent-ruby'
|
22
|
+
require_relative '../../../constants/constants'
|
23
|
+
|
24
|
+
class NetworkClient
|
25
|
+
HTTPS_SCHEME = 'https'
|
26
|
+
|
27
|
+
def initialize(options = {})
|
28
|
+
# options for threading
|
29
|
+
@should_use_threading = options.key?(:enabled) ? options[:enabled] : Constants::SHOULD_USE_THREADING
|
30
|
+
@thread_pool = Concurrent::FixedThreadPool.new(options.key?(:max_pool_size) ? options[:max_pool_size] : Constants::MAX_POOL_SIZE)
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_thread_pool
|
34
|
+
@thread_pool
|
35
|
+
end
|
36
|
+
|
37
|
+
def get(request_model)
|
38
|
+
# Build the URL and headers
|
39
|
+
url = request_model.get_url + request_model.get_path
|
40
|
+
uri = URI(url)
|
41
|
+
|
42
|
+
# Create the HTTP GET request
|
43
|
+
request = Net::HTTP::Get.new(uri)
|
44
|
+
# Add headers to the request
|
45
|
+
request_model.get_headers.each { |k, v| request[k] = v }
|
46
|
+
|
47
|
+
# Send the GET request and get the response
|
48
|
+
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
49
|
+
http.request(request)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Process the response
|
53
|
+
response_model = ResponseModel.new
|
54
|
+
response_model.set_status_code(response.code.to_i) # Convert status code to integer
|
55
|
+
|
56
|
+
begin
|
57
|
+
# Parse the response body as JSON
|
58
|
+
parsed_data = JSON.parse(response.body)
|
59
|
+
response_model.set_data(parsed_data)
|
60
|
+
rescue StandardError => e
|
61
|
+
# Handle any JSON parsing errors
|
62
|
+
response_model.set_error(e.message)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Return the response model
|
66
|
+
response_model
|
67
|
+
end
|
68
|
+
|
69
|
+
def post(request_model)
|
70
|
+
def execute_post(request_model)
|
71
|
+
url = request_model.get_url + request_model.get_path
|
72
|
+
uri = URI(url)
|
73
|
+
headers = request_model.get_headers # Directly use the hash from the request model
|
74
|
+
body = JSON.dump(request_model.get_body)
|
75
|
+
|
76
|
+
request = Net::HTTP::Post.new(uri, headers) # Pass the hash of headers directly
|
77
|
+
request.body = body
|
78
|
+
|
79
|
+
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') { |http| http.request(request) }
|
80
|
+
|
81
|
+
response_model = ResponseModel.new
|
82
|
+
response_model.set_status_code(response.code.to_i)
|
83
|
+
|
84
|
+
# Check if the response body is empty or invalid before parsing
|
85
|
+
if response.is_a?(Net::HTTPSuccess) && !response.body.strip.empty?
|
86
|
+
begin
|
87
|
+
parsed_data = JSON.parse(response.body)
|
88
|
+
response_model.set_data(parsed_data)
|
89
|
+
rescue JSON::ParserError => e
|
90
|
+
# Handle invalid JSON response
|
91
|
+
response_model.set_error("Invalid JSON response: #{e.message}")
|
92
|
+
end
|
93
|
+
else
|
94
|
+
end
|
95
|
+
rescue StandardError => e
|
96
|
+
LoggerService.log(LogLevelEnum::ERROR, "POST request failed: #{e.message}", nil)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Check if threading is enabled in options
|
100
|
+
if @should_use_threading
|
101
|
+
@thread_pool.post { execute_post(request_model) }
|
102
|
+
else
|
103
|
+
execute_post(request_model)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# Copyright 2025 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 '../models/global_request_model'
|
16
|
+
require_relative '../models/request_model'
|
17
|
+
|
18
|
+
class RequestHandler
|
19
|
+
def create_request(request, config)
|
20
|
+
return nil if config.get_base_url.nil? && request.get_url.nil?
|
21
|
+
|
22
|
+
request.set_url(request.get_url || config.get_base_url)
|
23
|
+
request.set_timeout(request.get_timeout || config.get_timeout)
|
24
|
+
request.set_body(request.get_body || config.get_body)
|
25
|
+
request.set_headers(request.get_headers || config.get_headers)
|
26
|
+
|
27
|
+
request_query_params = request.get_query || {}
|
28
|
+
config_query_params = config.get_query || {}
|
29
|
+
|
30
|
+
config_query_params.each do |key, value|
|
31
|
+
request_query_params[key] ||= value
|
32
|
+
end
|
33
|
+
|
34
|
+
request.set_query(request_query_params)
|
35
|
+
request
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# Copyright 2025 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 '../client/network_client'
|
16
|
+
require_relative '../handlers/request_handler'
|
17
|
+
require_relative '../models/global_request_model'
|
18
|
+
require_relative '../../../services/logger_service'
|
19
|
+
require_relative '../../../enums/log_level_enum'
|
20
|
+
require_relative '../../../constants/constants'
|
21
|
+
class NetworkManager
|
22
|
+
@instance = nil
|
23
|
+
|
24
|
+
def initialize(options = {})
|
25
|
+
@client = NetworkClient.new(options)
|
26
|
+
@config = GlobalRequestModel.new(nil, {}, {}, {})
|
27
|
+
@should_use_threading = options.key?(:enabled) ? options[:enabled] : Constants::SHOULD_USE_THREADING
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.instance(options = {})
|
31
|
+
@instance ||= new(options)
|
32
|
+
end
|
33
|
+
|
34
|
+
def attach_client(client = nil)
|
35
|
+
@client = client || NetworkClient.new(@should_use_threading)
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_client
|
39
|
+
@client
|
40
|
+
end
|
41
|
+
|
42
|
+
def set_config(config)
|
43
|
+
@config = config
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_config
|
47
|
+
@config
|
48
|
+
end
|
49
|
+
|
50
|
+
def create_request(request)
|
51
|
+
RequestHandler.new.create_request(request, @config)
|
52
|
+
end
|
53
|
+
|
54
|
+
def get(request)
|
55
|
+
begin
|
56
|
+
network_options = create_request(request)
|
57
|
+
raise 'No URL found' if network_options.get_url.nil?
|
58
|
+
|
59
|
+
response = @client.get(network_options)
|
60
|
+
response
|
61
|
+
rescue => e
|
62
|
+
LoggerService.log(LogLevelEnum::ERROR, "Error getting: #{e.message}", nil)
|
63
|
+
raise e
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def post(request)
|
69
|
+
begin
|
70
|
+
network_options = create_request(request)
|
71
|
+
raise 'No URL found' if network_options.get_url.nil?
|
72
|
+
|
73
|
+
@client.post(network_options)
|
74
|
+
rescue => e
|
75
|
+
LoggerService.log(LogLevelEnum::ERROR, "Error posting: #{e.message}", nil)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|