rox-rollout 4.7.3 → 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.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +34 -13
  3. data/.editorconfig +12 -0
  4. data/.github/workflows/ruby.yml +20 -0
  5. data/.rubocop.yml +17 -0
  6. data/Gemfile +2 -2
  7. data/README.md +32 -0
  8. data/Rakefile +12 -9
  9. data/bin/console +3 -4
  10. data/e2e-server/run_server.sh +12 -0
  11. data/e2e-server/server.rb +158 -0
  12. data/e2e/container.rb +11 -14
  13. data/e2e/custom_props.rb +9 -9
  14. data/e2e/rox_e2e_test.rb +17 -19
  15. data/e2e/test_vars.rb +3 -6
  16. data/example/local.rb +40 -0
  17. data/lib/rox/core/analytics.rb +18 -0
  18. data/lib/rox/core/client/buid.rb +8 -8
  19. data/lib/rox/core/client/device_properties.rb +7 -1
  20. data/lib/rox/core/client/dynamic_api.rb +53 -15
  21. data/lib/rox/core/client/internal_flags.rb +14 -2
  22. data/lib/rox/core/client/sdk_settings.rb +1 -1
  23. data/lib/rox/core/configuration/configuration.rb +1 -1
  24. data/lib/rox/core/configuration/configuration_fetched_args.rb +2 -2
  25. data/lib/rox/core/configuration/configuration_fetched_invoker.rb +8 -3
  26. data/lib/rox/core/configuration/configuration_parser.rb +38 -37
  27. data/lib/rox/core/configuration/fetcher_error.rb +1 -1
  28. data/lib/rox/core/configuration/fetcher_status.rb +1 -1
  29. data/lib/rox/core/configuration/models/experiment_model.rb +1 -1
  30. data/lib/rox/core/configuration/models/target_group_model.rb +1 -1
  31. data/lib/rox/core/consts/build.rb +2 -2
  32. data/lib/rox/core/consts/environment.rb +10 -8
  33. data/lib/rox/core/consts/property_type.rb +16 -17
  34. data/lib/rox/core/context/merged_context.rb +2 -1
  35. data/lib/rox/core/core.rb +88 -38
  36. data/lib/rox/core/entities/default_flag_values.rb +10 -0
  37. data/lib/rox/core/entities/flag.rb +22 -7
  38. data/lib/rox/core/entities/flag_setter.rb +6 -6
  39. data/lib/rox/core/entities/rox_double.rb +11 -0
  40. data/lib/rox/core/entities/rox_int.rb +11 -0
  41. data/lib/rox/core/entities/{variant.rb → rox_string.rb} +20 -13
  42. data/lib/rox/core/error_handling/exception_trigger.rb +10 -0
  43. data/lib/rox/core/error_handling/userspace_handler_exception.rb +12 -0
  44. data/lib/rox/core/error_handling/userspace_unhandled_error_invoker.rb +41 -0
  45. data/lib/rox/core/impression/impression_args.rb +2 -2
  46. data/lib/rox/core/impression/impression_invoker.rb +41 -7
  47. data/lib/rox/core/impression/models/experiment.rb +1 -1
  48. data/lib/rox/core/impression/models/reporting_value.rb +10 -2
  49. data/lib/rox/core/logging/logging.rb +3 -3
  50. data/lib/rox/core/logging/no_op_logger.rb +1 -1
  51. data/lib/rox/core/network/configuration_fetcher.rb +2 -2
  52. data/lib/rox/core/network/configuration_fetcher_roxy.rb +2 -2
  53. data/lib/rox/core/network/configuration_fetcher_self_managed.rb +30 -0
  54. data/lib/rox/core/network/configuration_source.rb +1 -1
  55. data/lib/rox/core/network/request.rb +1 -1
  56. data/lib/rox/core/network/request_configuration_builder.rb +5 -5
  57. data/lib/rox/core/network/request_data.rb +1 -1
  58. data/lib/rox/core/network/response.rb +6 -8
  59. data/lib/rox/core/network/state_sender.rb +61 -18
  60. data/lib/rox/core/notifications/notification_listener.rb +4 -4
  61. data/lib/rox/core/properties/custom_property.rb +1 -1
  62. data/lib/rox/core/properties/custom_property_type.rb +1 -1
  63. data/lib/rox/core/properties/device_property.rb +2 -2
  64. data/lib/rox/core/properties/property_factory.rb +132 -0
  65. data/lib/rox/core/register/registerer.rb +13 -12
  66. data/lib/rox/core/reporting/error_reporter.rb +14 -13
  67. data/lib/rox/core/repositories/experiment_repository.rb +2 -4
  68. data/lib/rox/core/repositories/flag_repository.rb +7 -7
  69. data/lib/rox/core/repositories/roxx/experiments_extensions.rb +8 -8
  70. data/lib/rox/core/repositories/roxx/properties_extensions.rb +32 -7
  71. data/lib/rox/core/repositories/target_group_repository.rb +2 -4
  72. data/lib/rox/core/roxx/evaluation_result.rb +2 -0
  73. data/lib/rox/core/roxx/node.rb +1 -1
  74. data/lib/rox/core/roxx/parser.rb +35 -21
  75. data/lib/rox/core/roxx/regular_expression_extensions.rb +6 -3
  76. data/lib/rox/core/roxx/string_tokenizer.rb +3 -1
  77. data/lib/rox/core/roxx/symbols.rb +1 -1
  78. data/lib/rox/core/roxx/token_type.rb +1 -1
  79. data/lib/rox/core/roxx/tokenized_expression.rb +16 -12
  80. data/lib/rox/core/roxx/value_compare_extensions.rb +49 -29
  81. data/lib/rox/core/security/signature_verifier.rb +3 -3
  82. data/lib/rox/core/security/signature_verifier_mock.rb +12 -0
  83. data/lib/rox/core/utils/type_utils.rb +1 -1
  84. data/lib/rox/server/client/server_properties.rb +1 -1
  85. data/lib/rox/server/flags/normalize_flag_type.rb +25 -0
  86. data/lib/rox/server/flags/rox_double.rb +8 -0
  87. data/lib/rox/server/flags/rox_flag.rb +1 -1
  88. data/lib/rox/server/flags/rox_int.rb +8 -0
  89. data/lib/rox/server/flags/rox_string.rb +8 -0
  90. data/lib/rox/server/flags/server_entities_provider.rb +14 -4
  91. data/lib/rox/server/logging/server_logger.rb +2 -2
  92. data/lib/rox/server/rox_options.rb +39 -8
  93. data/lib/rox/server/rox_server.rb +80 -59
  94. data/lib/rox/version.rb +1 -1
  95. data/rox.gemspec +11 -9
  96. metadata +66 -37
  97. data/CODEOWNERS +0 -1
  98. data/README_DEVELOP.md +0 -25
  99. data/_archive/.document +0 -5
  100. data/_archive/.rspec +0 -1
  101. data/_archive/Gemfile +0 -15
  102. data/_archive/README.md +0 -32
  103. data/_archive/README.rdoc +0 -19
  104. data/_archive/Rakefile +0 -50
  105. data/_archive/lib/expr_function_definition.rb +0 -52
  106. data/_archive/lib/function_definition.rb +0 -48
  107. data/_archive/lib/function_token.rb +0 -12
  108. data/_archive/lib/object_extends.rb +0 -12
  109. data/_archive/lib/ruby_interpreter.rb +0 -292
  110. data/_archive/lib/stack.rb +0 -48
  111. data/_archive/lib/string_extends.rb +0 -14
  112. data/_archive/spec/ruby_interpreter_spec.rb +0 -203
  113. data/_archive/spec/spec_helper.rb +0 -30
  114. data/_archive/spec/stack_spec.rb +0 -77
  115. data/lib/rox/server/flags/rox_variant.rb +0 -8
@@ -10,4 +10,4 @@ module Rox
10
10
  NO_ERROR = 'NoError'.freeze
11
11
  end
12
12
  end
13
- end
13
+ end
@@ -7,4 +7,4 @@ module Rox
7
7
  ERROR_FETCHED_FAILED = 'ErrorFetchedFailed'.freeze
8
8
  end
9
9
  end
10
- end
10
+ end
@@ -2,4 +2,4 @@ module Rox
2
2
  module Core
3
3
  ExperimentModel = Struct.new(:id, :name, :condition, :is_archived, :flags, :labels)
4
4
  end
5
- end
5
+ end
@@ -2,4 +2,4 @@ module Rox
2
2
  module Core
3
3
  TargetGroupModel = Struct.new(:id, :condition)
4
4
  end
5
- end
5
+ end
@@ -1,8 +1,8 @@
1
1
  module Rox
2
2
  module Core
3
3
  module Build
4
- PLATFORM = 'Ruby'
5
- API_VERSION = '1.8.0'
4
+ PLATFORM = 'Ruby'.freeze
5
+ API_VERSION = '1.9.0'.freeze
6
6
  end
7
7
  end
8
8
  end
@@ -16,14 +16,15 @@ module Rox
16
16
  end
17
17
  end
18
18
 
19
- def self.api_path
19
+ def self.api_path(api_url = nil)
20
20
  case ENV['ROLLOUT_MODE']
21
21
  when 'QA'
22
- 'https://qax.rollout.io/device/get_configuration'
22
+ 'https://qa-api.rollout.io/device/get_configuration'
23
23
  when 'LOCAL'
24
24
  'http://127.0.0.1:8557/device/get_configuration'
25
25
  else
26
- 'https://x-api.rollout.io/device/get_configuration'
26
+ api_url ||= 'https://x-api.rollout.io'
27
+ "#{api_url}/device/get_configuration"
27
28
  end
28
29
  end
29
30
 
@@ -38,25 +39,26 @@ module Rox
38
39
  end
39
40
  end
40
41
 
41
- def self.state_api_path
42
+ def self.state_api_path(api_url = nil)
42
43
  case ENV['ROLLOUT_MODE']
43
44
  when 'QA'
44
- 'https://qax.rollout.io/device/update_state_store'
45
+ 'https://qa-api.rollout.io/device/update_state_store'
45
46
  when 'LOCAL'
46
47
  'http://127.0.0.1:8557/device/update_state_store'
47
48
  else
48
- 'https://x-api.rollout.io/device/update_state_store'
49
+ api_url ||= 'https://x-api.rollout.io'
50
+ "#{api_url}/device/update_state_store"
49
51
  end
50
52
  end
51
53
 
52
- def self.analytics_path
54
+ def self.analytics_path(analytics_url = 'https://analytic.rollout.io')
53
55
  case ENV['ROLLOUT_MODE']
54
56
  when 'QA'
55
57
  'https://qaanalytic.rollout.io'
56
58
  when 'LOCAL'
57
59
  'http://127.0.0.1:8787'
58
60
  else
59
- 'https://analytic.rollout.io'
61
+ analytics_url
60
62
  end
61
63
  end
62
64
 
@@ -9,23 +9,22 @@ module Rox
9
9
  end
10
10
 
11
11
  CACHE_MISS_RELATIVE_URL = PropertyType.new(1, 'cache_miss_relative_url')
12
- PACKAGE_NAME = PropertyType.new(2, "package_name")
13
- VERSION_NAME = PropertyType.new(3, "version_name")
14
- LIB_VERSION = PropertyType.new(4, "lib_version")
15
- ROLLOUT_BUILD = PropertyType.new(5, "rollout_build")
16
- API_VERSION = PropertyType.new(6, "api_version")
17
- BUID = PropertyType.new(7, "buid")
18
- BUID_GENERATORS_LIST = PropertyType.new(8, "buid_generators_list")
19
- APP_VERSION = PropertyType.new(9, "app_version")
20
- APP_RELEASE = PropertyType.new(10, "app_release")
21
- DISTINCT_ID = PropertyType.new(11, "distinct_id")
22
- APP_KEY = PropertyType.new(12, "app_key")
23
- FEATURE_FLAGS = PropertyType.new(13, "feature_flags")
24
- REMOTE_VARIABLES = PropertyType.new(14, "remote_variables")
25
- CUSTOM_PROPERTIES = PropertyType.new(15, "custom_properties")
26
- PLATFORM = PropertyType.new(16, "platform")
27
- DEV_MODE_SECRET = PropertyType.new(17, "dev_mode_secret")
28
- STATE_MD5 = PropertyType.new(18, "state_md5")
12
+ PACKAGE_NAME = PropertyType.new(2, 'package_name')
13
+ VERSION_NAME = PropertyType.new(3, 'version_name')
14
+ LIB_VERSION = PropertyType.new(4, 'lib_version')
15
+ ROLLOUT_BUILD = PropertyType.new(5, 'rollout_build')
16
+ API_VERSION = PropertyType.new(6, 'api_version')
17
+ BUID = PropertyType.new(7, 'buid')
18
+ BUID_GENERATORS_LIST = PropertyType.new(8, 'buid_generators_list')
19
+ APP_VERSION = PropertyType.new(9, 'app_version')
20
+ APP_RELEASE = PropertyType.new(10, 'app_release')
21
+ DISTINCT_ID = PropertyType.new(11, 'distinct_id')
22
+ APP_KEY = PropertyType.new(12, 'app_key')
23
+ FEATURE_FLAGS = PropertyType.new(13, 'feature_flags')
24
+ CUSTOM_PROPERTIES = PropertyType.new(14, 'custom_properties')
25
+ PLATFORM = PropertyType.new(15, 'platform')
26
+ DEV_MODE_SECRET = PropertyType.new(16, 'dev_mode_secret')
27
+ STATE_MD5 = PropertyType.new(17, 'state_md5')
29
28
  end
30
29
  end
31
30
  end
@@ -9,8 +9,9 @@ module Rox
9
9
  def [](key)
10
10
  return @local_context[key] unless @local_context.nil? || @local_context[key].nil?
11
11
  return @global_context[key] unless @global_context.nil?
12
+
12
13
  nil
13
14
  end
14
15
  end
15
16
  end
16
- end
17
+ end
data/lib/rox/core/core.rb CHANGED
@@ -11,6 +11,7 @@ require 'rox/core/network/request_configuration_builder'
11
11
  require 'rox/core/network/request'
12
12
  require 'rox/core/network/configuration_fetcher'
13
13
  require 'rox/core/network/configuration_fetcher_roxy'
14
+ require 'rox/core/network/configuration_fetcher_self_managed'
14
15
  require 'rox/core/network/state_sender'
15
16
  require 'rox/core/notifications/notification_listener'
16
17
  require 'rox/core/register/registerer'
@@ -20,8 +21,11 @@ require 'rox/core/entities/flag_setter'
20
21
  require 'rox/core/impression/impression_invoker'
21
22
  require 'rox/core/reporting/error_reporter'
22
23
  require 'rox/core/security/signature_verifier'
24
+ require 'rox/core/security/signature_verifier_mock'
23
25
  require 'rox/core/utils/periodic_task'
24
26
  require 'rox/core/client/dynamic_api'
27
+ require 'rox/core/analytics'
28
+ require 'rox/core/error_handling/userspace_unhandled_error_invoker'
25
29
 
26
30
  module Rox
27
31
  module Core
@@ -31,14 +35,10 @@ module Rox
31
35
  @custom_property_repository = CustomPropertyRepository.new
32
36
  @target_group_repository = TargetGroupRepository.new
33
37
  @experiment_repository = ExperimentRepository.new
34
- @parser = Parser.new
38
+ @user_unhandled_error_invoker = Rox::Core::UserspaceUnhandledErrorInvoker.new
39
+ @parser = Parser.new(@user_unhandled_error_invoker)
35
40
 
36
- experiments_extensions = ExperimentsExtensions.new(@parser, @target_group_repository, @flag_repository, @experiment_repository)
37
- properties_extensions = PropertiesExtensions.new(@parser, @custom_property_repository)
38
- experiments_extensions.extend
39
- properties_extensions.extend
40
-
41
- @configuration_fetched_invoker = ConfigurationFetchedInvoker.new
41
+ @configuration_fetched_invoker = ConfigurationFetchedInvoker.new(@user_unhandled_error_invoker)
42
42
  @registerer = Registerer.new(@flag_repository)
43
43
 
44
44
  @sdk_settings = nil
@@ -51,65 +51,106 @@ module Rox
51
51
  @push_updates_listener = nil
52
52
  end
53
53
 
54
- def setup(sdk_settings, device_properties, rox_options)
54
+ def userspace_unhandled_error_handler=(handler)
55
+ @user_unhandled_error_invoker.handler = handler
56
+ end
57
+
58
+ def setup(sdk_settings, device_properties)
55
59
  @sdk_settings = sdk_settings
60
+ @rox_options = device_properties.rox_options
61
+
62
+ experiments_extensions = ExperimentsExtensions.new(@parser, @target_group_repository, @flag_repository,
63
+ @experiment_repository)
64
+ properties_extensions = PropertiesExtensions.new(@parser, @custom_property_repository, @rox_options.dynamic_property_rule_handler)
65
+ experiments_extensions.extend
66
+ properties_extensions.extend
56
67
 
57
- roxy_path = rox_options.nil? || rox_options.roxy_url.nil? ? nil : rox_options.roxy_url
68
+ roxy_path = @rox_options.nil? || @rox_options.roxy_url.nil? ? nil : @rox_options.roxy_url
58
69
 
59
- if roxy_path.nil?
60
- validate_api_key(sdk_settings&.api_key)
61
- end
70
+ validate_api_key(sdk_settings&.api_key) if roxy_path.nil?
62
71
 
63
72
  # TODO: Analytics.Analytics.Initialize(deviceProperties.RolloutKey, deviceProperties)
64
- @internal_flags = InternalFlags.new(@experiment_repository, @parser)
73
+ @internal_flags = InternalFlags.new(@experiment_repository, @parser, @rox_options)
65
74
 
75
+ @analytics_client = Analytics.new(sdk_settings.api_key).client
66
76
  # TODO: impressionInvoker = new ImpressionInvoker(internalFlags, customPropertyRepository, deviceProperties, Analytics.Analytics.Client, roxyPath != null);
67
- @impression_invoker = ImpressionInvoker.new(@internal_flags, @custom_property_repository, device_properties, nil, !roxy_path.nil?)
77
+ @impression_invoker = ImpressionInvoker.new(@internal_flags, @custom_property_repository, device_properties,
78
+ @analytics_client, !roxy_path.nil?, @user_unhandled_error_invoker)
68
79
  @flag_setter = FlagSetter.new(@flag_repository, @parser, @experiment_repository, @impression_invoker)
69
80
  buid = BUID.new(sdk_settings, device_properties, @flag_repository, @custom_property_repository)
70
81
 
71
- request_config_builder = RequestConfigurationBuilder.new(sdk_settings, buid, device_properties, roxy_path)
82
+ request_config_builder = RequestConfigurationBuilder.new(sdk_settings, buid, device_properties)
72
83
 
73
84
  client_request = Request.new
74
85
  err_reporter_request = Request.new
75
86
 
76
87
  @error_reporter = ErrorReporter.new(err_reporter_request, device_properties, buid)
77
88
 
78
- if roxy_path.nil?
79
- @configuration_fetcher = ConfigurationFetcher.new(request_config_builder, client_request, @configuration_fetched_invoker)
80
- @state_sender = StateSender.new(@sdk_settings, device_properties, @flag_repository, @custom_property_repository)
89
+ if @rox_options.self_managed?
90
+ @configuration_fetcher = ConfigurationFetcherSelfManaged.new(request_config_builder, client_request,
91
+ @configuration_fetched_invoker)
92
+ @state_sender = StateSender.new(@sdk_settings, device_properties, @flag_repository,
93
+ @custom_property_repository)
94
+ @flag_repository.register_flag_added_handler { @state_sender.delayed_send }
95
+ @custom_property_repository.register_property_added_handler { @state_sender.delayed_send }
96
+ elsif roxy_path.nil?
97
+ @configuration_fetcher = ConfigurationFetcher.new(request_config_builder, client_request,
98
+ @configuration_fetched_invoker)
99
+ @state_sender = StateSender.new(@sdk_settings, device_properties, @flag_repository,
100
+ @custom_property_repository)
81
101
  @flag_repository.register_flag_added_handler { @state_sender.delayed_send }
82
102
  @custom_property_repository.register_property_added_handler { @state_sender.delayed_send }
83
103
  else
84
- @configuration_fetcher = ConfigurationFetcherRoxy.new(request_config_builder, client_request, @configuration_fetched_invoker)
104
+ @configuration_fetcher = ConfigurationFetcherRoxy.new(request_config_builder, client_request,
105
+ @configuration_fetched_invoker)
85
106
  end
86
107
 
87
108
  configuration_fetched_handler = nil
88
- unless rox_options.nil?
89
- configuration_fetched_handler = rox_options.configuration_fetched_handler
90
- end
109
+ configuration_fetched_handler = @rox_options.configuration_fetched_handler unless @rox_options.nil?
91
110
 
92
111
  @configuration_fetched_invoker.register_fetched_handler(&wrap_configuration_fetched_handler(&configuration_fetched_handler))
93
112
 
94
- Thread.new do
113
+ @thread = Thread.new do
95
114
  Thread.current.report_on_exception = false if Thread.current.respond_to?(:report_on_exception)
96
115
  fetch
97
116
  @state_sender&.send
98
117
 
99
- if !rox_options.nil? && !rox_options.impression_handler.nil?
100
- @impression_invoker.register_impression_handler(&rox_options.impression_handler)
118
+ if !@rox_options.nil? && !@rox_options.impression_handler.nil?
119
+ @impression_invoker.register_impression_handler(&@rox_options.impression_handler)
101
120
  end
102
121
 
103
- if !rox_options.nil? && !rox_options.fetch_interval.nil?
104
- PeriodicTask.run(rox_options.fetch_interval) { fetch }
122
+ if !@rox_options.nil? && !@rox_options.fetch_interval.nil?
123
+ PeriodicTask.run(@rox_options.fetch_interval) { fetch }
105
124
  end
106
125
  end
107
126
  end
108
127
 
128
+ def shutdown
129
+ return if @thread.nil?
130
+
131
+ Thread.kill(@thread)
132
+ @thread = nil
133
+
134
+ unless @push_updates_listener.nil?
135
+ @push_updates_listener.stop
136
+ @push_updates_listener = nil
137
+ end
138
+
139
+ return if @analytics_client.nil?
140
+
141
+ @analytics_client.flush
142
+ end
143
+
109
144
  def fetch
110
145
  return if @configuration_fetcher.nil?
111
146
 
112
- configuration_parser = ConfigurationParser.new(SignatureVerifier.new, @error_reporter, @configuration_fetched_invoker)
147
+ signature_verifier = if @rox_options.self_managed?
148
+ SignatureVerifierMock.new
149
+ else
150
+ SignatureVerifier.new
151
+ end
152
+ configuration_parser = ConfigurationParser.new(signature_verifier, @error_reporter,
153
+ @configuration_fetched_invoker)
113
154
  result = @configuration_fetcher.fetch
114
155
  return if result.nil?
115
156
 
@@ -122,17 +163,22 @@ module Rox
122
163
 
123
164
  has_changes = @last_configurations.nil? || @last_configurations.data != result.data
124
165
  @last_configurations = result
125
- @configuration_fetched_invoker.invoke(FetcherStatus::APPLIED_FROM_NETWORK, configuration.signature_date, has_changes)
166
+ @configuration_fetched_invoker.invoke(FetcherStatus::APPLIED_FROM_NETWORK, configuration.signature_date,
167
+ has_changes)
168
+ end
169
+
170
+ def register_with_namespace(namespace, rox_container)
171
+ @registerer.register_instance(rox_container, namespace)
126
172
  end
127
173
 
128
- def register(ns, rox_container)
129
- @registerer.register_instance(rox_container, ns)
174
+ def register(*args)
175
+ rox_container = args.pop
176
+ namespace = args.length == 1 ? args.pop : ''
177
+ @registerer.register_instance(rox_container, namespace)
130
178
  end
131
179
 
132
180
  def context=(context)
133
- @flag_repository.all_flags.each do |flag|
134
- flag.context = context
135
- end
181
+ @parser.global_context = context
136
182
  end
137
183
 
138
184
  def add_custom_property(property)
@@ -146,7 +192,7 @@ module Rox
146
192
  def wrap_configuration_fetched_handler(&handler)
147
193
  lambda do |args|
148
194
  start_or_stop_push_updated_listener unless args.fetcher_status == FetcherStatus::ERROR_FETCHED_FAILED
149
- handler.call(args) unless handler.nil?
195
+ handler&.call(args)
150
196
  end
151
197
  end
152
198
 
@@ -154,7 +200,7 @@ module Rox
154
200
  if @internal_flags.enabled?('rox.internal.pushUpdates')
155
201
  if @push_updates_listener.nil?
156
202
  @push_updates_listener = NotificationListener.new(Environment.notifications_path, @sdk_settings.api_key)
157
- @push_updates_listener.on 'changed' do |data|
203
+ @push_updates_listener.on 'changed' do |_data|
158
204
  fetch
159
205
  end
160
206
  @push_updates_listener.start
@@ -171,12 +217,16 @@ module Rox
171
217
  Rox::Core::DynamicApi.new(@flag_repository, entities_provider)
172
218
  end
173
219
 
220
+ def dump_state
221
+ @state_sender.dump_state
222
+ end
223
+
174
224
  def validate_api_key(api_key)
175
225
  valid_api_key_pattern = /^[a-f\d]{24}$/
176
226
  if api_key&.strip&.empty?
177
- raise ArgumentError.new('Blank Rollout api key - must be specified')
227
+ raise ArgumentError, 'Blank Rollout api key - must be specified'
178
228
  elsif !valid_api_key_pattern.match(api_key)
179
- raise ArgumentError.new('Illegal Rollout api key')
229
+ raise ArgumentError, 'Illegal Rollout api key'
180
230
  end
181
231
  end
182
232
  end
@@ -0,0 +1,10 @@
1
+ module Rox
2
+ module Core
3
+ class DefaultFlagValues
4
+ STRING = ''
5
+ INT = 0
6
+ FLOAT = 0.0
7
+ BOOLEAN = false
8
+ end
9
+ end
10
+ end
@@ -1,20 +1,35 @@
1
- require 'rox/core/entities/variant'
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 < Variant
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 = false)
10
- super(default_value ? Flag::FLAG_TRUE_VALUE : Flag::FLAG_FALSE_VALUE, [Flag::FLAG_FALSE_VALUE, Flag::FLAG_TRUE_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
- value(context) == Flag::FLAG_TRUE_VALUE
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 |variant|
11
- exp = @experiment_repository.experiment_by_flag(variant.name)
12
- set_flag_data(variant, exp)
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(variant, experiment = nil)
35
- variant.set_for_evaluation(@parser, experiment, @impression_invoker)
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