rox-rollout 4.7.3 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
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