rox-rollout 4.1.0 → 5.0.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 +5 -5
- data/.circleci/config.yml +51 -23
- data/.editorconfig +12 -0
- data/.github/workflows/ruby.yml +20 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +17 -0
- data/Gemfile +2 -2
- data/README.md +32 -0
- data/Rakefile +12 -9
- data/bin/console +3 -4
- data/e2e-server/run_server.sh +12 -0
- data/e2e-server/server.rb +158 -0
- data/e2e/container.rb +11 -14
- data/e2e/custom_props.rb +9 -9
- data/e2e/rox_e2e_test.rb +18 -20
- data/e2e/test_vars.rb +3 -6
- data/example/local.rb +40 -0
- data/lib/rox/core/analytics.rb +18 -0
- data/lib/rox/core/client/buid.rb +9 -44
- data/lib/rox/core/client/device_properties.rb +8 -2
- data/lib/rox/core/client/dynamic_api.rb +53 -15
- data/lib/rox/core/client/internal_flags.rb +14 -2
- data/lib/rox/core/client/sdk_settings.rb +1 -1
- data/lib/rox/core/configuration/configuration.rb +1 -1
- data/lib/rox/core/configuration/configuration_fetched_args.rb +2 -2
- data/lib/rox/core/configuration/configuration_fetched_invoker.rb +8 -3
- data/lib/rox/core/configuration/configuration_parser.rb +39 -38
- data/lib/rox/core/configuration/fetcher_error.rb +1 -1
- data/lib/rox/core/configuration/fetcher_status.rb +1 -1
- data/lib/rox/core/configuration/models/experiment_model.rb +1 -1
- data/lib/rox/core/configuration/models/target_group_model.rb +1 -1
- data/lib/rox/core/consts/build.rb +3 -3
- data/lib/rox/core/consts/environment.rb +34 -10
- data/lib/rox/core/consts/property_type.rb +18 -17
- data/lib/rox/core/context/merged_context.rb +2 -1
- data/lib/rox/core/core.rb +101 -33
- data/lib/rox/core/entities/default_flag_values.rb +10 -0
- data/lib/rox/core/entities/flag.rb +22 -7
- data/lib/rox/core/entities/flag_setter.rb +6 -6
- data/lib/rox/core/entities/rox_double.rb +11 -0
- data/lib/rox/core/entities/rox_int.rb +11 -0
- data/lib/rox/core/entities/{variant.rb → rox_string.rb} +20 -13
- data/lib/rox/core/error_handling/exception_trigger.rb +10 -0
- data/lib/rox/core/error_handling/userspace_handler_exception.rb +12 -0
- data/lib/rox/core/error_handling/userspace_unhandled_error_invoker.rb +41 -0
- data/lib/rox/core/impression/impression_args.rb +2 -2
- data/lib/rox/core/impression/impression_invoker.rb +41 -7
- data/lib/rox/core/impression/models/experiment.rb +1 -1
- data/lib/rox/core/impression/models/reporting_value.rb +10 -2
- data/lib/rox/core/logging/logging.rb +3 -3
- data/lib/rox/core/logging/no_op_logger.rb +1 -1
- data/lib/rox/core/network/configuration_fetch_result.rb +1 -1
- data/lib/rox/core/network/configuration_fetcher.rb +9 -8
- data/lib/rox/core/network/configuration_fetcher_base.rb +1 -1
- data/lib/rox/core/network/configuration_fetcher_roxy.rb +4 -4
- data/lib/rox/core/network/configuration_fetcher_self_managed.rb +30 -0
- data/lib/rox/core/network/configuration_source.rb +1 -1
- data/lib/rox/core/network/request.rb +3 -3
- data/lib/rox/core/network/request_configuration_builder.rb +12 -9
- data/lib/rox/core/network/request_data.rb +1 -1
- data/lib/rox/core/network/response.rb +20 -4
- data/lib/rox/core/network/state_sender.rb +146 -0
- data/lib/rox/core/notifications/notification_listener.rb +4 -4
- data/lib/rox/core/properties/custom_property.rb +1 -1
- data/lib/rox/core/properties/custom_property_type.rb +1 -1
- data/lib/rox/core/properties/device_property.rb +2 -2
- data/lib/rox/core/properties/property_factory.rb +132 -0
- data/lib/rox/core/register/registerer.rb +13 -12
- data/lib/rox/core/reporting/error_reporter.rb +14 -13
- data/lib/rox/core/repositories/custom_property_repository.rb +1 -1
- data/lib/rox/core/repositories/experiment_repository.rb +2 -4
- data/lib/rox/core/repositories/flag_repository.rb +8 -8
- data/lib/rox/core/repositories/roxx/experiments_extensions.rb +8 -8
- data/lib/rox/core/repositories/roxx/properties_extensions.rb +32 -7
- data/lib/rox/core/repositories/target_group_repository.rb +2 -4
- data/lib/rox/core/roxx/evaluation_result.rb +2 -0
- data/lib/rox/core/roxx/node.rb +1 -1
- data/lib/rox/core/roxx/parser.rb +46 -20
- data/lib/rox/core/roxx/regular_expression_extensions.rb +6 -3
- data/lib/rox/core/roxx/string_tokenizer.rb +3 -1
- data/lib/rox/core/roxx/symbols.rb +1 -1
- data/lib/rox/core/roxx/token_type.rb +1 -1
- data/lib/rox/core/roxx/tokenized_expression.rb +16 -12
- data/lib/rox/core/roxx/value_compare_extensions.rb +49 -29
- data/lib/rox/core/security/signature_verifier.rb +3 -3
- data/lib/rox/core/security/signature_verifier_mock.rb +12 -0
- data/lib/rox/core/utils/debouncer.rb +18 -0
- data/lib/rox/core/utils/type_utils.rb +1 -1
- data/lib/rox/server/client/sdk_settings.rb +1 -1
- data/lib/rox/server/client/server_properties.rb +1 -1
- data/lib/rox/server/flags/normalize_flag_type.rb +25 -0
- data/lib/rox/server/flags/rox_double.rb +8 -0
- data/lib/rox/server/flags/rox_flag.rb +1 -1
- data/lib/rox/server/flags/rox_int.rb +8 -0
- data/lib/rox/server/flags/rox_string.rb +8 -0
- data/lib/rox/server/flags/server_entities_provider.rb +14 -4
- data/lib/rox/server/logging/server_logger.rb +2 -2
- data/lib/rox/server/rox_options.rb +39 -8
- data/lib/rox/server/rox_server.rb +81 -60
- data/lib/rox/version.rb +1 -1
- data/rox.gemspec +13 -9
- metadata +95 -36
- data/README_DEVELOP.md +0 -19
- data/_archive/.document +0 -5
- data/_archive/.rspec +0 -1
- data/_archive/Gemfile +0 -15
- data/_archive/Gemfile.lock +0 -87
- data/_archive/README.md +0 -32
- data/_archive/README.rdoc +0 -19
- data/_archive/Rakefile +0 -50
- data/_archive/lib/expr_function_definition.rb +0 -52
- data/_archive/lib/function_definition.rb +0 -48
- data/_archive/lib/function_token.rb +0 -12
- data/_archive/lib/object_extends.rb +0 -12
- data/_archive/lib/ruby_interpreter.rb +0 -292
- data/_archive/lib/stack.rb +0 -48
- data/_archive/lib/string_extends.rb +0 -14
- data/_archive/spec/ruby_interpreter_spec.rb +0 -203
- data/_archive/spec/spec_helper.rb +0 -30
- data/_archive/spec/stack_spec.rb +0 -77
- data/lib/rox/server/flags/rox_variant.rb +0 -8
@@ -1,20 +1,35 @@
|
|
1
|
-
require 'rox/core/entities/
|
1
|
+
require 'rox/core/entities/rox_string'
|
2
|
+
require 'rox/core/entities/default_flag_values'
|
2
3
|
|
3
4
|
module Rox
|
4
5
|
module Core
|
5
|
-
class Flag <
|
6
|
+
class Flag < RoxString
|
6
7
|
FLAG_TRUE_VALUE = 'true'.freeze
|
7
8
|
FLAG_FALSE_VALUE = 'false'.freeze
|
8
9
|
|
9
|
-
def initialize(default_value =
|
10
|
-
super(default_value ? Flag::FLAG_TRUE_VALUE : Flag::FLAG_FALSE_VALUE, [Flag::FLAG_FALSE_VALUE,
|
10
|
+
def initialize(default_value = DefaultFlagValues::BOOLEAN)
|
11
|
+
super(default_value ? Flag::FLAG_TRUE_VALUE : Flag::FLAG_FALSE_VALUE, [Flag::FLAG_FALSE_VALUE,
|
12
|
+
Flag::FLAG_TRUE_VALUE])
|
11
13
|
end
|
12
14
|
|
13
15
|
def enabled?(context)
|
14
|
-
|
16
|
+
merged_context = MergedContext.new(@parser&.global_context, context)
|
17
|
+
value = internal_enabled?(merged_context)
|
18
|
+
if [true, false].include? value
|
19
|
+
send_impressions(value, merged_context)
|
20
|
+
return value
|
21
|
+
end
|
22
|
+
|
23
|
+
send_impressions(DefaultFlagValues::BOOLEAN, merged_context)
|
24
|
+
DefaultFlagValues.BOOLEAN
|
25
|
+
end
|
26
|
+
|
27
|
+
def value(context = nil)
|
28
|
+
merged_context = MergedContext.new(@parser&.global_context, context)
|
29
|
+
internal_value(merged_context, false)
|
15
30
|
end
|
16
31
|
|
17
|
-
def internal_enabled?(context, nil_instead_of_default)
|
32
|
+
def internal_enabled?(context, nil_instead_of_default = false)
|
18
33
|
val = internal_value(context, nil_instead_of_default)
|
19
34
|
nil_instead_of_default && val.nil? ? nil : (val == Flag::FLAG_TRUE_VALUE)
|
20
35
|
end
|
@@ -28,4 +43,4 @@ module Rox
|
|
28
43
|
end
|
29
44
|
end
|
30
45
|
end
|
31
|
-
end
|
46
|
+
end
|
@@ -7,9 +7,9 @@ module Rox
|
|
7
7
|
@experiment_repository = experiment_repository
|
8
8
|
@impression_invoker = impression_invoker
|
9
9
|
|
10
|
-
@flag_repository.register_flag_added_handler do |
|
11
|
-
exp = @experiment_repository.experiment_by_flag(
|
12
|
-
set_flag_data(
|
10
|
+
@flag_repository.register_flag_added_handler do |string|
|
11
|
+
exp = @experiment_repository.experiment_by_flag(string.name)
|
12
|
+
set_flag_data(string, exp)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
@@ -31,9 +31,9 @@ module Rox
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
def set_flag_data(
|
35
|
-
|
34
|
+
def set_flag_data(string, experiment = nil)
|
35
|
+
string.set_for_evaluation(@parser, experiment, @impression_invoker)
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
39
|
-
end
|
39
|
+
end
|
@@ -4,22 +4,31 @@ require 'rox/core/impression/models/reporting_value'
|
|
4
4
|
|
5
5
|
module Rox
|
6
6
|
module Core
|
7
|
-
class
|
8
|
-
attr_accessor :default_value, :options, :name, :
|
7
|
+
class RoxString
|
8
|
+
attr_accessor :default_value, :options, :name, :condition, :parser, :impression_invoker,
|
9
|
+
:client_experiment
|
9
10
|
|
10
11
|
def initialize(default_value, options = [])
|
11
12
|
@default_value = default_value
|
12
13
|
@options = options.clone
|
14
|
+
raise ArgumentError, 'options should be an array' unless options.is_a?(Array)
|
15
|
+
if options.length > 0 && options.any? { |x| x.class != default_value.class }
|
16
|
+
raise ArgumentError, 'options should be the same type as default value'
|
17
|
+
end
|
13
18
|
@options << default_value unless options.include?(default_value)
|
14
19
|
|
15
20
|
@condition = nil
|
16
21
|
@parser = nil
|
17
|
-
@context = nil
|
18
22
|
@impression_invoker = nil
|
19
23
|
@client_experiment = nil
|
20
24
|
@name = nil
|
21
25
|
end
|
22
26
|
|
27
|
+
def send_impressions(return_value, merged_context)
|
28
|
+
reporting_value = ReportingValue.new(@name, return_value, @client_experiment)
|
29
|
+
@impression_invoker&.invoke(reporting_value, @client_experiment, merged_context)
|
30
|
+
end
|
31
|
+
|
23
32
|
def set_for_evaluation(parser, experiment, impression_invoker)
|
24
33
|
if experiment.nil?
|
25
34
|
@client_experiment = nil
|
@@ -37,24 +46,22 @@ module Rox
|
|
37
46
|
internal_value(context, false)
|
38
47
|
end
|
39
48
|
|
40
|
-
def internal_value(context, nil_instead_of_default)
|
49
|
+
def internal_value(context, nil_instead_of_default, evaluated_type = String)
|
41
50
|
return_value = nil_instead_of_default ? nil : @default_value
|
42
|
-
merged_context = MergedContext.new(@
|
51
|
+
merged_context = MergedContext.new(@parser&.global_context, context)
|
43
52
|
|
44
|
-
|
53
|
+
unless @parser.nil? || @condition.nil? || @condition.empty?
|
45
54
|
evaluation_result = @parser.evaluate_expression(@condition, merged_context)
|
46
55
|
unless evaluation_result.nil?
|
47
|
-
value = evaluation_result.string_value
|
48
|
-
|
49
|
-
|
50
|
-
end
|
56
|
+
value = evaluated_type == String ? evaluation_result.string_value : evaluation_result.value
|
57
|
+
is_empty = value.is_a?(String) && value.empty?
|
58
|
+
return_value = value if !value.nil? && !is_empty
|
51
59
|
end
|
52
60
|
end
|
53
61
|
|
54
|
-
|
55
|
-
|
62
|
+
send_impressions(return_value, merged_context)
|
56
63
|
return_value
|
57
64
|
end
|
58
65
|
end
|
59
66
|
end
|
60
|
-
end
|
67
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Rox
|
2
|
+
module Core
|
3
|
+
class UserspaceHandlerException < StandardError
|
4
|
+
def initialize(exception_source, exception_trigger, exception)
|
5
|
+
@exception_source = exception_source
|
6
|
+
@exception_trigger = exception_trigger
|
7
|
+
@exception = exception
|
8
|
+
super('user unhandled exception in roxx expression')
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'rox/core/logging/logging'
|
2
|
+
|
3
|
+
module Rox
|
4
|
+
module Core
|
5
|
+
class UserspaceUnhandledErrorInvoker
|
6
|
+
def initialize(user_unhandler_error_handler = nil)
|
7
|
+
@user_unhandler_error_handler = user_unhandler_error_handler
|
8
|
+
end
|
9
|
+
|
10
|
+
def invoke(exception_source, exception_trigger, exception)
|
11
|
+
unless @user_unhandler_error_handler
|
12
|
+
Logging.logger.error("User Unhandled Error Occurred, no fallback handler was set, exception ignored: #{exception}")
|
13
|
+
return
|
14
|
+
end
|
15
|
+
|
16
|
+
begin
|
17
|
+
userspace_unhandled_error_args = UserspaceUnhandledErrorArgs.new(exception_source, exception_trigger, exception)
|
18
|
+
@user_unhandler_error_handler.call(userspace_unhandled_error_args)
|
19
|
+
rescue StandardError => e
|
20
|
+
Logging.logger.error("User Unhandled Error Handler itself threw an exception. original exception: #{e}")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def handler=(handler)
|
25
|
+
@user_unhandler_error_handler = handler
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class UserspaceUnhandledErrorArgs
|
30
|
+
def initialize(exception_source = nil, exception_trigger = nil, exception = nil)
|
31
|
+
@exception_source = exception_source
|
32
|
+
@exception_trigger = exception_trigger
|
33
|
+
@exception = exception
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_s
|
37
|
+
"UserspaceUnhandledErrorArgs(#{@exception_source}, #{@exception_trigger}, #{@exception})"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -1,23 +1,54 @@
|
|
1
1
|
require 'rox/core/impression/impression_args'
|
2
|
+
require 'rox/core/logging/logging'
|
3
|
+
require 'rox/core/error_handling/exception_trigger'
|
4
|
+
require 'rox/core/consts/property_type'
|
2
5
|
|
3
6
|
module Rox
|
4
7
|
module Core
|
5
8
|
class ImpressionInvoker
|
6
|
-
def initialize(internal_flags, custom_property_repository, device_properties, analytics_client, is_roxy)
|
9
|
+
def initialize(internal_flags, custom_property_repository, device_properties, analytics_client, is_roxy, user_unhandled_error_invoker)
|
7
10
|
@internal_flags = internal_flags
|
8
11
|
@custom_property_repository = custom_property_repository
|
9
12
|
@device_properties = device_properties
|
10
13
|
@analytics_client = analytics_client
|
11
14
|
@is_roxy = is_roxy
|
15
|
+
@user_unhandled_error_invoker = user_unhandled_error_invoker
|
12
16
|
|
13
17
|
@impression_handlers = []
|
14
18
|
@mutex = Mutex.new
|
15
19
|
end
|
16
20
|
|
17
|
-
def invoke(reporting_value,
|
18
|
-
|
21
|
+
def invoke(reporting_value, stickiness_property, context)
|
22
|
+
begin
|
23
|
+
analytics_enabled = @internal_flags.enabled?('rox.internal.analytics')
|
24
|
+
if analytics_enabled && !@is_roxy
|
25
|
+
prop = @custom_property_repository.custom_property(stickiness_property) || @custom_property_repository.custom_property("rox.#{Rox::Core::PropertyType::DISTINCT_ID.name}")
|
26
|
+
distinct_id = '(null_distinct_id'
|
27
|
+
unless prop.nil?
|
28
|
+
prop_value = prop.value(context)
|
29
|
+
distinct_id = prop_value if prop_value.instance_of?(String)
|
30
|
+
end
|
19
31
|
|
20
|
-
|
32
|
+
event_time = (Time.now.to_f * 1000.0).to_i
|
33
|
+
begin
|
34
|
+
event_time = ENV['rox.analytics.ms'].to_i
|
35
|
+
rescue StandardError
|
36
|
+
end
|
37
|
+
|
38
|
+
@analytics_client.track({
|
39
|
+
flag: reporting_value.name,
|
40
|
+
value: reporting_value.value,
|
41
|
+
distinctId: distinct_id,
|
42
|
+
experimentVersion: '0',
|
43
|
+
type: 'IMPRESSION',
|
44
|
+
time: event_time
|
45
|
+
})
|
46
|
+
end
|
47
|
+
rescue StandardError => ex
|
48
|
+
Logging.logger.error('Failed to send analytics', ex)
|
49
|
+
end
|
50
|
+
|
51
|
+
raise_impression_event(ImpressionArgs.new(reporting_value, context))
|
21
52
|
end
|
22
53
|
|
23
54
|
def register_impression_handler(&block)
|
@@ -32,10 +63,13 @@ module Rox
|
|
32
63
|
handlers = @impression_handlers.clone
|
33
64
|
end
|
34
65
|
|
35
|
-
|
36
|
-
handler.call(args)
|
66
|
+
begin
|
67
|
+
handlers.each { |handler| handler.call(args) }
|
68
|
+
rescue StandardError => e
|
69
|
+
user_unhandled_error_invoker.invoke(handler, ExceptionTrigger::IMPRESSION_HANDLER, e)
|
70
|
+
Logging.logger.error('Impresssion handler exception', ex)
|
37
71
|
end
|
38
72
|
end
|
39
73
|
end
|
40
74
|
end
|
41
|
-
end
|
75
|
+
end
|
@@ -1,5 +1,13 @@
|
|
1
1
|
module Rox
|
2
2
|
module Core
|
3
|
-
ReportingValue
|
3
|
+
class ReportingValue
|
4
|
+
attr_reader :name, :value, :targeting
|
5
|
+
|
6
|
+
def initialize(name, value, experiment = nil)
|
7
|
+
@name = name
|
8
|
+
@value = value
|
9
|
+
@targeting = !experiment.nil?
|
10
|
+
end
|
11
|
+
end
|
4
12
|
end
|
5
|
-
end
|
13
|
+
end
|
@@ -9,18 +9,18 @@ module Rox
|
|
9
9
|
source = ConfigurationSource::CDN
|
10
10
|
begin
|
11
11
|
fetch_result = fetch_from_cdn
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
if fetch_result.success?
|
13
|
+
return ConfigurationFetchResult.new(fetch_result.text, source)
|
14
|
+
else
|
15
15
|
write_fetch_error_to_log_and_invoke_fetch_handler(source, fetch_result, false, ConfigurationSource::API)
|
16
16
|
source = ConfigurationSource::API
|
17
17
|
fetch_result = fetch_from_api
|
18
|
-
return ConfigurationFetchResult.new(fetch_result.text, source) if fetch_result.
|
18
|
+
return ConfigurationFetchResult.new(fetch_result.text, source) if fetch_result.success?
|
19
19
|
end
|
20
20
|
|
21
21
|
write_fetch_error_to_log_and_invoke_fetch_handler(source, fetch_result)
|
22
|
-
rescue StandardError =>
|
23
|
-
write_fetch_exception_to_log_and_invoke_fetch_handler(source,
|
22
|
+
rescue StandardError => e
|
23
|
+
write_fetch_exception_to_log_and_invoke_fetch_handler(source, e)
|
24
24
|
end
|
25
25
|
|
26
26
|
nil
|
@@ -31,8 +31,9 @@ module Rox
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def fetch_from_api
|
34
|
-
@
|
34
|
+
api_request = @request_configuration_builder.build_for_api
|
35
|
+
@request.send_post(api_request.url, api_request.query_params)
|
35
36
|
end
|
36
37
|
end
|
37
38
|
end
|
38
|
-
end
|
39
|
+
end
|
@@ -9,13 +9,13 @@ module Rox
|
|
9
9
|
source = ConfigurationSource::ROXY
|
10
10
|
begin
|
11
11
|
fetch_roxy = fetch_from_roxy
|
12
|
-
if fetch_roxy.
|
12
|
+
if fetch_roxy.success?
|
13
13
|
return ConfigurationFetchResult.new(fetch_roxy.text, source)
|
14
14
|
else
|
15
15
|
write_fetch_error_to_log_and_invoke_fetch_handler(source, fetch_roxy)
|
16
16
|
end
|
17
|
-
rescue StandardError =>
|
18
|
-
write_fetch_exception_to_log_and_invoke_fetch_handler(source,
|
17
|
+
rescue StandardError => e
|
18
|
+
write_fetch_exception_to_log_and_invoke_fetch_handler(source, e)
|
19
19
|
end
|
20
20
|
|
21
21
|
nil
|
@@ -26,4 +26,4 @@ module Rox
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
29
|
-
end
|
29
|
+
end
|