rox-rollout 4.0.0 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 83830a53d34aa5c51ae4d620b3e21789f5eb2cbd
4
- data.tar.gz: 419c4a400b030dc5e539003bee949b3776a31bbe
3
+ metadata.gz: f4ad60820f71ef8569f15f07fcb1ced8b05e99be
4
+ data.tar.gz: 327115ab21d5889e4783fcef71d33e1cbc72e7ab
5
5
  SHA512:
6
- metadata.gz: a1e076439bc9fb0ffccc6d8f9b3a096b9bc4baa3d22994a9b24c762922ee018105ce4ee3a4f096e111e2bc4a535b661f71559fa7dbe192669c9d7b2f4fb77ecf
7
- data.tar.gz: 4f65eb77eed230bab5fe58fe6f14fb56e9c319650d60d892596a845461bea00dbedfd3bb3a36114edb15488325e3e24589a110d70c26dbae93de980a7134f64f
6
+ metadata.gz: '0368035eb4d7f508749be64e32e89001af56475e57a9018d45654e854c3ac9e9bae322f800525b70ea606240efc35cb1b7c9d140537114e145d92390416b706b'
7
+ data.tar.gz: 75afe906a4eb22195d5020fdb546952bea785a80f49df4eb6cb85bd8cdd9cec7c47e25f702d013525a8e4474b4ef8bd24f4e6acfb33553fde4a48a859dbcd6da
data/e2e/rox_e2e_test.rb CHANGED
@@ -12,7 +12,7 @@ module E2E
12
12
  end
13
13
 
14
14
  def error(message, ex = nil)
15
- puts 'Before Rox.Setup', message
15
+ puts 'Before Rox.Setup', message, ex
16
16
  end
17
17
 
18
18
  def warn(message, ex = nil)
@@ -0,0 +1,36 @@
1
+ require 'rox/core/entities/flag'
2
+
3
+ module Rox
4
+ module Core
5
+ class DynamicApi
6
+ def initialize(flag_repository, entities_provider)
7
+ @flag_repository = flag_repository
8
+ @entities_provider = entities_provider
9
+ end
10
+
11
+ def enabled?(name, default_value, context = nil)
12
+ variant = @flag_repository.flag(name)
13
+ if variant.nil?
14
+ variant = @entities_provider.create_flag(default_value)
15
+ @flag_repository.add_flag(variant, name)
16
+ end
17
+
18
+ return default_value unless variant.is_a?(Flag)
19
+
20
+ is_enabled = variant.internal_enabled?(context, nil_instead_of_default: true)
21
+ is_enabled.nil? ? default_value : is_enabled
22
+ end
23
+
24
+ def value(name, default_value, context = nil, options = [])
25
+ variant = @flag_repository.flag(name)
26
+ if variant.nil?
27
+ variant = @entities_provider.create_variant(default_value, options)
28
+ @flag_repository.add_flag(variant, name)
29
+ end
30
+
31
+ value = variant.internal_value(context, nil_instead_of_default: true)
32
+ value.nil? ? default_value : value
33
+ end
34
+ end
35
+ end
36
+ end
@@ -37,6 +37,17 @@ module Rox
37
37
  'https://analytic.rollout.io'
38
38
  end
39
39
  end
40
+
41
+ def self.notifications_path
42
+ case ENV['ROLLOUT_MODE']
43
+ when 'QA'
44
+ 'https://qax-push.rollout.io/sse'
45
+ when 'LOCAL'
46
+ 'http://127.0.0.1:8887/sse'
47
+ else
48
+ 'https://push.rollout.io/sse'
49
+ end
50
+ end
40
51
  end
41
52
  end
42
53
  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/notifications/notification_listener'
14
15
  require 'rox/core/register/registerer'
15
16
  require 'rox/core/client/internal_flags'
16
17
  require 'rox/core/client/buid'
@@ -19,6 +20,7 @@ require 'rox/core/impression/impression_invoker'
19
20
  require 'rox/core/reporting/error_reporter'
20
21
  require 'rox/core/security/signature_verifier'
21
22
  require 'rox/core/utils/periodic_task'
23
+ require 'rox/core/client/dynamic_api'
22
24
 
23
25
  module Rox
24
26
  module Core
@@ -44,6 +46,8 @@ module Rox
44
46
  @error_reporter = nil
45
47
  @configuration_fetcher = nil
46
48
  @last_configurations = nil
49
+ @internal_flags = nil
50
+ @push_updates_listener = nil
47
51
  end
48
52
 
49
53
  def setup(sdk_settings, device_properties, rox_options)
@@ -52,10 +56,10 @@ module Rox
52
56
  roxy_path = rox_options.nil? || rox_options.roxy_url.nil? ? nil : rox_options.roxy_url
53
57
 
54
58
  # TODO: Analytics.Analytics.Initialize(deviceProperties.RolloutKey, deviceProperties)
55
- internal_flags = InternalFlags.new(@experiment_repository, @parser)
59
+ @internal_flags = InternalFlags.new(@experiment_repository, @parser)
56
60
 
57
61
  # TODO: impressionInvoker = new ImpressionInvoker(internalFlags, customPropertyRepository, deviceProperties, Analytics.Analytics.Client, roxyPath != null);
58
- @impression_invoker = ImpressionInvoker.new(internal_flags, @custom_property_repository, device_properties, nil, !roxy_path.nil?)
62
+ @impression_invoker = ImpressionInvoker.new(@internal_flags, @custom_property_repository, device_properties, nil, !roxy_path.nil?)
59
63
  @flag_setter = FlagSetter.new(@flag_repository, @parser, @experiment_repository, @impression_invoker)
60
64
  buid = BUID.new(sdk_settings, device_properties, @flag_repository, @custom_property_repository)
61
65
 
@@ -72,10 +76,13 @@ module Rox
72
76
  @configuration_fetcher = ConfigurationFetcherRoxy.new(request_config_builder, client_request, @configuration_fetched_invoker)
73
77
  end
74
78
 
75
- if !rox_options.nil? && !rox_options.configuration_fetched_handler.nil?
76
- @configuration_fetched_invoker.register_fetched_handler(&rox_options.configuration_fetched_handler)
79
+ configuration_fetched_handler = nil
80
+ unless rox_options.nil?
81
+ configuration_fetched_handler = rox_options.configuration_fetched_handler
77
82
  end
78
83
 
84
+ @configuration_fetched_invoker.register_fetched_handler(&wrap_configuration_fetched_handler(&configuration_fetched_handler))
85
+
79
86
  Thread.new do
80
87
  Thread.current.report_on_exception = false if Thread.current.respond_to?(:report_on_exception)
81
88
  fetch
@@ -126,6 +133,34 @@ module Rox
126
133
  def add_custom_property_if_not_exists(property)
127
134
  @custom_property_repository.add_custom_property_if_not_exists(property)
128
135
  end
136
+
137
+ def wrap_configuration_fetched_handler(&handler)
138
+ lambda do |args|
139
+ start_or_stop_push_updated_listener unless args.fetcher_status == FetcherStatus::ERROR_FETCHED_FAILED
140
+ handler.call(args) unless handler.nil?
141
+ end
142
+ end
143
+
144
+ def start_or_stop_push_updated_listener
145
+ if @internal_flags.enabled?('rox.internal.pushUpdates')
146
+ if @push_updates_listener.nil?
147
+ @push_updates_listener = NotificationListener.new(Environment.notifications_path, @sdk_settings.api_key)
148
+ @push_updates_listener.on 'changed' do |data|
149
+ fetch
150
+ end
151
+ @push_updates_listener.start
152
+ end
153
+ else
154
+ unless @push_updates_listener.nil?
155
+ @push_updates_listener.stop
156
+ @push_updates_listener = nil
157
+ end
158
+ end
159
+ end
160
+
161
+ def dynamic_api(entities_provider)
162
+ Rox::Core::DynamicApi.new(@flag_repository, entities_provider)
163
+ end
129
164
  end
130
165
  end
131
166
  end
@@ -14,6 +14,11 @@ module Rox
14
14
  value(context) == Flag::FLAG_TRUE_VALUE
15
15
  end
16
16
 
17
+ def internal_enabled?(context, nil_instead_of_default)
18
+ val = internal_value(context, nil_instead_of_default)
19
+ nil_instead_of_default && val.nil? ? nil : (val == Flag::FLAG_TRUE_VALUE)
20
+ end
21
+
17
22
  def enabled(context)
18
23
  yield if enabled?(context)
19
24
  end
@@ -7,7 +7,7 @@ module Rox
7
7
  class Variant
8
8
  attr_accessor :default_value, :options, :name, :context, :condition, :parser, :impression_invoker, :client_experiment
9
9
 
10
- def initialize(default_value, options)
10
+ def initialize(default_value, options = [])
11
11
  @default_value = default_value
12
12
  @options = options.clone
13
13
  @options << default_value unless options.include?(default_value)
@@ -34,7 +34,11 @@ module Rox
34
34
  end
35
35
 
36
36
  def value(context = nil)
37
- return_value = @default_value
37
+ internal_value(context, false)
38
+ end
39
+
40
+ def internal_value(context, nil_instead_of_default)
41
+ return_value = nil_instead_of_default ? nil : @default_value
38
42
  merged_context = MergedContext.new(@context, context)
39
43
 
40
44
  if !@parser.nil? && !@condition.nil? && !@condition.empty?
@@ -42,7 +46,7 @@ module Rox
42
46
  unless evaluation_result.nil?
43
47
  value = evaluation_result.string_value
44
48
  if !value.nil? && !value.empty?
45
- return_value = value if @options.include?(value)
49
+ return_value = value
46
50
  end
47
51
  end
48
52
  end
@@ -0,0 +1,45 @@
1
+ require "em-eventsource"
2
+
3
+ module Rox
4
+ module Core
5
+ class NotificationListener
6
+ def initialize(listen_url, app_key)
7
+ @listen_url = listen_url
8
+ @app_key = app_key
9
+ @handlers = {}
10
+ end
11
+
12
+ def on(event_name, &handler)
13
+ @handlers[event_name] ||= []
14
+ @handlers[event_name] << handler
15
+ end
16
+
17
+ def start
18
+ sse_url = @listen_url.chomp('/') + '/' + @app_key
19
+ @thread = Thread.new do
20
+ EM.run do
21
+ source = EventMachine::EventSource.new(sse_url)
22
+ @handlers.each do |event_name, event_handlers|
23
+ event_handlers.each do |handler|
24
+ source.on event_name do |data|
25
+ # Start new thread to allow the handler to stop the Listener (terminate the current thread)
26
+ # and continue handler code execution without interruption
27
+ handler_thread = Thread.new do
28
+ handler.call(data)
29
+ end
30
+ handler_thread.join
31
+ end
32
+ end
33
+ end
34
+ source.start
35
+ end
36
+ end
37
+ end
38
+
39
+ def stop
40
+ @thread.terminate unless @thread.nil?
41
+ @thread = nil
42
+ end
43
+ end
44
+ end
45
+ end
@@ -16,14 +16,16 @@ module Rox
16
16
 
17
17
  @namespaces << ns
18
18
 
19
- container.methods.each do |method_name|
20
- method = container.method(method_name)
21
- next unless method.arity.zero?
22
-
19
+ container.instance_variables().each do |attribute_name|
23
20
  begin
24
- value = method.call
25
- if value.is_a?(Variant)
26
- @flag_repository.add_flag(value, ns == '' ? method_name.to_s : "#{ns}.#{method_name}")
21
+ value = container.instance_variable_get(attribute_name)
22
+ if value != nil && value.is_a?(Variant)
23
+ var_name = attribute_name.to_s();
24
+ # removing the attribute starting @ (if [always] exists)
25
+ if (var_name[0] == '@')
26
+ var_name[0] = '';
27
+ end
28
+ @flag_repository.add_flag(value, ns == '' ? var_name : "#{ns}.#{var_name}")
27
29
  end
28
30
  rescue StandardError
29
31
  next
@@ -32,4 +34,4 @@ module Rox
32
34
  end
33
35
  end
34
36
  end
35
- end
37
+ end
@@ -127,15 +127,21 @@ module Rox
127
127
 
128
128
  add_operator('md5') do |parser, stack, context|
129
129
  op1 = stack.pop
130
- raise ArgumentError, 'should be string' unless op1.is_a?(String)
131
- stack.push(Digest::MD5.hexdigest(op1))
130
+ if op1.is_a?(String)
131
+ stack.push(Digest::MD5.hexdigest(op1))
132
+ else
133
+ stack.push(TokenType::UNDEFINED)
134
+ end
132
135
  end
133
136
 
134
137
  add_operator('concat') do |parser, stack, context|
135
138
  op1 = stack.pop
136
139
  op2 = stack.pop
137
- raise ArgumentError, 'should be string' unless op1.is_a?(String) && op2.is_a?(String)
138
- stack.push("#{op1}#{op2}")
140
+ if op1.is_a?(String) && op2.is_a?(String)
141
+ stack.push("#{op1}#{op2}")
142
+ else
143
+ stack.push(TokenType::UNDEFINED)
144
+ end
139
145
  end
140
146
  end
141
147
  end
@@ -0,0 +1,16 @@
1
+ require 'rox/server/flags/rox_flag'
2
+ require 'rox/server/flags/rox_variant'
3
+
4
+ module Rox
5
+ module Server
6
+ class ServerEntitiesProvider
7
+ def create_flag(default_value)
8
+ Rox::Server::RoxFlag.new(default_value)
9
+ end
10
+
11
+ def create_variant(default_value, options)
12
+ Rox::Server::RoxVariant.new(default_value, options)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -8,6 +8,8 @@ require 'rox/core/properties/device_property'
8
8
  require 'rox/core/properties/custom_property'
9
9
  require 'rox/core/properties/custom_property_type'
10
10
  require 'rox/core/consts/property_type'
11
+ require 'rox/server/flags/server_entities_provider'
12
+
11
13
 
12
14
  module Rox
13
15
  module Server
@@ -78,6 +80,10 @@ module Rox
78
80
  def self.set_custom_semver_property(name, value = nil, &block)
79
81
  @core.add_custom_property(Rox::Core::CustomProperty.new(name, Rox::Core::CustomPropertyType::SEMVER, value, &block))
80
82
  end
83
+
84
+ def self.dynamic_api
85
+ @core.dynamic_api(Rox::Server::ServerEntitiesProvider.new)
86
+ end
81
87
  end
82
88
  end
83
89
  end
data/lib/rox/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Rox
2
- VERSION = "4.0.0"
2
+ VERSION = "4.1.0"
3
3
  end
data/rox.gemspec CHANGED
@@ -23,6 +23,8 @@ Gem::Specification.new do |spec|
23
23
 
24
24
  spec.required_ruby_version = '>= 2.3'
25
25
 
26
+ spec.add_runtime_dependency 'em-eventsource', '~> 0.3.0'
27
+
26
28
  spec.add_development_dependency 'bundler', '~> 1.16'
27
29
  spec.add_development_dependency 'minitest', '~> 5.0'
28
30
  spec.add_development_dependency 'rake', '~> 12.3'
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rox-rollout
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0
4
+ version: 4.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rollout.io
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-10-07 00:00:00.000000000 Z
11
+ date: 2019-05-14 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: em-eventsource
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.3.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.3.0
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -91,6 +105,7 @@ files:
91
105
  - lib/rox.rb
92
106
  - lib/rox/core/client/buid.rb
93
107
  - lib/rox/core/client/device_properties.rb
108
+ - lib/rox/core/client/dynamic_api.rb
94
109
  - lib/rox/core/client/internal_flags.rb
95
110
  - lib/rox/core/client/sdk_settings.rb
96
111
  - lib/rox/core/configuration/configuration.rb
@@ -124,6 +139,7 @@ files:
124
139
  - lib/rox/core/network/request_configuration_builder.rb
125
140
  - lib/rox/core/network/request_data.rb
126
141
  - lib/rox/core/network/response.rb
142
+ - lib/rox/core/notifications/notification_listener.rb
127
143
  - lib/rox/core/properties/custom_property.rb
128
144
  - lib/rox/core/properties/custom_property_type.rb
129
145
  - lib/rox/core/properties/device_property.rb
@@ -152,6 +168,7 @@ files:
152
168
  - lib/rox/server/client/server_properties.rb
153
169
  - lib/rox/server/flags/rox_flag.rb
154
170
  - lib/rox/server/flags/rox_variant.rb
171
+ - lib/rox/server/flags/server_entities_provider.rb
155
172
  - lib/rox/server/logging/server_logger.rb
156
173
  - lib/rox/server/rox_options.rb
157
174
  - lib/rox/server/rox_server.rb