rox-rollout 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +45 -0
  3. data/.gitignore +8 -0
  4. data/Gemfile +6 -0
  5. data/LICENSE +50 -0
  6. data/README_DEVELOP.md +19 -0
  7. data/Rakefile +16 -0
  8. data/_archive/.document +5 -0
  9. data/_archive/.rspec +1 -0
  10. data/_archive/Gemfile +15 -0
  11. data/_archive/Gemfile.lock +87 -0
  12. data/_archive/README.md +32 -0
  13. data/_archive/README.rdoc +19 -0
  14. data/_archive/Rakefile +50 -0
  15. data/_archive/lib/expr_function_definition.rb +52 -0
  16. data/_archive/lib/function_definition.rb +48 -0
  17. data/_archive/lib/function_token.rb +12 -0
  18. data/_archive/lib/object_extends.rb +12 -0
  19. data/_archive/lib/ruby_interpreter.rb +292 -0
  20. data/_archive/lib/stack.rb +48 -0
  21. data/_archive/lib/string_extends.rb +14 -0
  22. data/_archive/spec/ruby_interpreter_spec.rb +203 -0
  23. data/_archive/spec/spec_helper.rb +30 -0
  24. data/_archive/spec/stack_spec.rb +77 -0
  25. data/bin/console +14 -0
  26. data/bin/setup +8 -0
  27. data/e2e/container.rb +38 -0
  28. data/e2e/custom_props.rb +55 -0
  29. data/e2e/rox_e2e_test.rb +159 -0
  30. data/e2e/test_vars.rb +24 -0
  31. data/lib/rox.rb +5 -0
  32. data/lib/rox/core/client/buid.rb +82 -0
  33. data/lib/rox/core/client/device_properties.rb +45 -0
  34. data/lib/rox/core/client/internal_flags.rb +20 -0
  35. data/lib/rox/core/client/sdk_settings.rb +5 -0
  36. data/lib/rox/core/configuration/configuration.rb +5 -0
  37. data/lib/rox/core/configuration/configuration_fetched_args.rb +23 -0
  38. data/lib/rox/core/configuration/configuration_fetched_invoker.rb +37 -0
  39. data/lib/rox/core/configuration/configuration_parser.rb +85 -0
  40. data/lib/rox/core/configuration/fetcher_error.rb +13 -0
  41. data/lib/rox/core/configuration/fetcher_status.rb +10 -0
  42. data/lib/rox/core/configuration/models/experiment_model.rb +5 -0
  43. data/lib/rox/core/configuration/models/target_group_model.rb +5 -0
  44. data/lib/rox/core/consts/build.rb +8 -0
  45. data/lib/rox/core/consts/environment.rb +42 -0
  46. data/lib/rox/core/consts/property_type.rb +29 -0
  47. data/lib/rox/core/context/merged_context.rb +16 -0
  48. data/lib/rox/core/core.rb +131 -0
  49. data/lib/rox/core/entities/flag.rb +26 -0
  50. data/lib/rox/core/entities/flag_setter.rb +39 -0
  51. data/lib/rox/core/entities/variant.rb +56 -0
  52. data/lib/rox/core/impression/impression_args.rb +5 -0
  53. data/lib/rox/core/impression/impression_invoker.rb +41 -0
  54. data/lib/rox/core/impression/models/experiment.rb +14 -0
  55. data/lib/rox/core/impression/models/reporting_value.rb +5 -0
  56. data/lib/rox/core/logging/logging.rb +17 -0
  57. data/lib/rox/core/logging/no_op_logger.rb +11 -0
  58. data/lib/rox/core/network/configuration_fetch_result.rb +5 -0
  59. data/lib/rox/core/network/configuration_fetcher.rb +38 -0
  60. data/lib/rox/core/network/configuration_fetcher_base.rb +25 -0
  61. data/lib/rox/core/network/configuration_fetcher_roxy.rb +29 -0
  62. data/lib/rox/core/network/configuration_source.rb +9 -0
  63. data/lib/rox/core/network/request.rb +46 -0
  64. data/lib/rox/core/network/request_configuration_builder.rb +48 -0
  65. data/lib/rox/core/network/request_data.rb +5 -0
  66. data/lib/rox/core/network/response.rb +16 -0
  67. data/lib/rox/core/properties/custom_property.rb +18 -0
  68. data/lib/rox/core/properties/custom_property_type.rb +18 -0
  69. data/lib/rox/core/properties/device_property.rb +11 -0
  70. data/lib/rox/core/register/registerer.rb +35 -0
  71. data/lib/rox/core/reporting/error_reporter.rb +152 -0
  72. data/lib/rox/core/repositories/custom_property_repository.rb +61 -0
  73. data/lib/rox/core/repositories/experiment_repository.rb +21 -0
  74. data/lib/rox/core/repositories/flag_repository.rb +49 -0
  75. data/lib/rox/core/repositories/roxx/experiments_extensions.rb +82 -0
  76. data/lib/rox/core/repositories/roxx/properties_extensions.rb +26 -0
  77. data/lib/rox/core/repositories/target_group_repository.rb +17 -0
  78. data/lib/rox/core/roxx/core_stack.rb +22 -0
  79. data/lib/rox/core/roxx/evaluation_result.rb +28 -0
  80. data/lib/rox/core/roxx/node.rb +11 -0
  81. data/lib/rox/core/roxx/parser.rb +143 -0
  82. data/lib/rox/core/roxx/regular_expression_extensions.rb +33 -0
  83. data/lib/rox/core/roxx/string_tokenizer.rb +68 -0
  84. data/lib/rox/core/roxx/symbols.rb +14 -0
  85. data/lib/rox/core/roxx/token_type.rb +30 -0
  86. data/lib/rox/core/roxx/tokenized_expression.rb +119 -0
  87. data/lib/rox/core/roxx/value_compare_extensions.rb +137 -0
  88. data/lib/rox/core/security/signature_verifier.rb +18 -0
  89. data/lib/rox/core/utils/periodic_task.rb +12 -0
  90. data/lib/rox/core/utils/type_utils.rb +9 -0
  91. data/lib/rox/server/client/sdk_settings.rb +5 -0
  92. data/lib/rox/server/client/server_properties.rb +20 -0
  93. data/lib/rox/server/flags/rox_flag.rb +19 -0
  94. data/lib/rox/server/flags/rox_variant.rb +8 -0
  95. data/lib/rox/server/logging/server_logger.rb +35 -0
  96. data/lib/rox/server/rox_options.rb +27 -0
  97. data/lib/rox/server/rox_server.rb +83 -0
  98. data/lib/rox/version.rb +3 -0
  99. data/rox.gemspec +29 -0
  100. metadata +184 -0
@@ -0,0 +1,45 @@
1
+ require 'rox/core/consts/property_type'
2
+ require 'rox/core/consts/build'
3
+
4
+ module Rox
5
+ module Core
6
+ class DeviceProperties
7
+ def initialize(sdk_settings, rox_options)
8
+ @sdk_settings = sdk_settings
9
+ @rox_options = rox_options
10
+ end
11
+
12
+ def all_properties
13
+ {
14
+ PropertyType::PACKAGE_NAME.name => @rox_options.version,
15
+ PropertyType::VERSION_NAME.name => @rox_options.version,
16
+ PropertyType::LIB_VERSION.name => lib_version,
17
+ PropertyType::ROLLOUT_BUILD.name => '50',
18
+ PropertyType::API_VERSION.name => Build::API_VERSION,
19
+ PropertyType::APP_VERSION.name => @rox_options.version,
20
+ PropertyType::APP_RELEASE.name => @rox_options.version,
21
+ PropertyType::DISTINCT_ID.name => distinct_id,
22
+ PropertyType::APP_KEY.name => @sdk_settings.api_key,
23
+ PropertyType::PLATFORM.name => Build::PLATFORM,
24
+ }
25
+ end
26
+
27
+ def rollout_environment
28
+ env = ENV['ROLLOUT_MODE']
29
+ %w[QA LOCAL].include?(env) ? env : 'PRODUCTION'
30
+ end
31
+
32
+ def lib_version
33
+ '1.0.0'
34
+ end
35
+
36
+ def rollout_key
37
+ all_properties[PropertyType::APP_KEY.name]
38
+ end
39
+
40
+ def distinct_id
41
+ 'stam'
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,20 @@
1
+ require 'rox/core/entities/flag'
2
+
3
+ module Rox
4
+ module Core
5
+ class InternalFlags
6
+ def initialize(experiment_repository, parser)
7
+ @experiment_repository = experiment_repository
8
+ @parser = parser
9
+ end
10
+
11
+ def enabled?(flag_name)
12
+ internal_experiment = @experiment_repository.experiment_by_flag(flag_name)
13
+ return false if internal_experiment.nil?
14
+
15
+ value = @parser.evaluate_expression(internal_experiment.condition, nil).string_value
16
+ value == Flag::FLAG_TRUE_VALUE
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,5 @@
1
+ module Rox
2
+ module Core
3
+ SdkSettings = Struct.new(:api_key, :dev_mode_secret)
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Rox
2
+ module Core
3
+ Configuration = Struct.new(:experiments, :target_groups, :signature_date)
4
+ end
5
+ end
@@ -0,0 +1,23 @@
1
+ require 'rox/core/configuration/fetcher_error'
2
+ require 'rox/core/configuration/fetcher_status'
3
+
4
+ module Rox
5
+ module Core
6
+ class ConfigurationFetchedArgs
7
+ attr_accessor :fetcher_status, :creation_date, :has_changes, :error_details
8
+
9
+ def initialize(fetcher_status, creation_date, has_changes)
10
+ @fetcher_status = fetcher_status
11
+ @creation_date = creation_date
12
+ @has_changes = has_changes
13
+ @error_details = FetcherError::NO_ERROR
14
+ end
15
+
16
+ def self.error(error_details)
17
+ args = ConfigurationFetchedArgs.new(FetcherStatus::ERROR_FETCHED_FAILED, nil, false )
18
+ args.error_details = error_details
19
+ args
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,37 @@
1
+ require 'rox/core/configuration/configuration_fetched_args'
2
+
3
+ module Rox
4
+ module Core
5
+ class ConfigurationFetchedInvoker
6
+ def initialize
7
+ @fetched_handlers = []
8
+ @mutex = Mutex.new
9
+ end
10
+
11
+ def invoke(fetcher_status, creation_date, has_changes)
12
+ raise_fetched_event(Rox::Core::ConfigurationFetchedArgs.new(fetcher_status, creation_date, has_changes))
13
+ end
14
+
15
+ def invoke_error(error_details)
16
+ raise_fetched_event(Rox::Core::ConfigurationFetchedArgs.error(error_details))
17
+ end
18
+
19
+ def register_fetched_handler(&block)
20
+ @mutex.synchronize do
21
+ @fetched_handlers << block
22
+ end
23
+ end
24
+
25
+ def raise_fetched_event(args)
26
+ handlers = []
27
+ @mutex.synchronize do
28
+ handlers = @fetched_handlers.clone
29
+ end
30
+
31
+ handlers.each do |handler|
32
+ handler.call(args)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,85 @@
1
+ require 'date'
2
+ require 'json'
3
+ require 'rox/core/configuration/configuration'
4
+ require 'rox/core/configuration/fetcher_error'
5
+ require 'rox/core/configuration/models/experiment_model'
6
+ require 'rox/core/configuration/models/target_group_model'
7
+ require 'rox/core/network/configuration_source'
8
+ require 'rox/core/logging/logging'
9
+
10
+ module Rox
11
+ module Core
12
+ class ConfigurationParser
13
+ def initialize(signature_verifier, error_reporter, configuration_fetched_invoker)
14
+ @signature_verifier = signature_verifier
15
+ @error_reporter = error_reporter
16
+ @configuration_fetched_invoker = configuration_fetched_invoker
17
+ end
18
+
19
+ def parse(fetch_result, sdk_settings)
20
+ begin
21
+ if fetch_result.nil? || fetch_result.data.nil? || fetch_result.data.empty?
22
+ @configuration_fetched_invoker.invoke_error(FetcherError::EMPTY_JSON)
23
+ @error_reporter.report('Failed to parse JSON configuration - Null Or Empty', ArgumentError.new('data'))
24
+ return nil
25
+ end
26
+
27
+ begin
28
+ json_obj = JSON.parse(fetch_result.data)
29
+ rescue StandardError => ex
30
+ @configuration_fetched_invoker.invoke_error(FetcherError::CORRUPTED_JSON)
31
+ @error_reporter.report('Failed to parse JSON configuration', ex)
32
+ return nil
33
+ end
34
+
35
+ if fetch_result.source != ConfigurationSource::ROXY && !@signature_verifier.verify(json_obj['data'], json_obj['signature_v0'])
36
+ @configuration_fetched_invoker.invoke_error(FetcherError::SIGNATURE_VERIFICATION_ERROR)
37
+ @error_reporter.report('Failed to validate signature', StandardError.new("Data : #{json_obj['data']} Signature : #{json_obj['signature_v0']}"))
38
+ return nil
39
+ end
40
+
41
+ signature_date = DateTime.rfc3339(json_obj['signed_date']).to_time
42
+ internal_data_string = json_obj['data']
43
+ internal_data_object = JSON.parse(internal_data_string)
44
+
45
+ if fetch_result.source != ConfigurationSource::ROXY && internal_data_object['application'] != sdk_settings.api_key
46
+ @configuration_fetched_invoker.invoke_error(FetcherError::MISMATCH_APP_KEY)
47
+ @error_reporter.report('Failed to parse JSON configuration - ', StandardError.new("Internal Data: #{internal_data_object['application']} SdkSettings: #{sdk_settings.api_key}"))
48
+ return nil
49
+ end
50
+
51
+ experiments = parse_experiments(internal_data_object)
52
+ target_groups = parse_target_groups(internal_data_object)
53
+
54
+ Configuration.new(experiments, target_groups, signature_date)
55
+ rescue StandardError => ex
56
+ Logging.logger.error('Failed to parse configurations', ex)
57
+ @configuration_fetched_invoker.invoke_error(FetcherError::UNKNOWN)
58
+ return nil
59
+ end
60
+ end
61
+
62
+ def parse_experiments(data)
63
+ data['experiments'].map { |e| parse_experiment(e)}
64
+ end
65
+
66
+ def parse_experiment(data)
67
+ condition = data['deploymentConfiguration']['condition']
68
+ is_archived = data['archived']
69
+ name = data['name']
70
+ id = data['_id']
71
+ labels = data['labels'] || []
72
+ flags = data['featureFlags'].map {|f| f['name']}
73
+ ExperimentModel.new(id, name, condition, is_archived, flags, labels)
74
+ end
75
+
76
+ def parse_target_groups(data)
77
+ data['targetGroups'].map { |g| parse_target_group(g)}
78
+ end
79
+
80
+ def parse_target_group(data)
81
+ TargetGroupModel.new(data['_id'], data['condition'])
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,13 @@
1
+ module Rox
2
+ module Core
3
+ module FetcherError
4
+ CORRUPTED_JSON = 'CorruptedJson'.freeze
5
+ EMPTY_JSON = 'EmptyJson'.freeze
6
+ SIGNATURE_VERIFICATION_ERROR = 'SignatureVerificationError'.freeze
7
+ NETWORK_ERROR = 'NetworkError'.freeze
8
+ MISMATCH_APP_KEY = 'MismatchAppKey'.freeze
9
+ UNKNOWN = 'Unknown'.freeze
10
+ NO_ERROR = 'NoError'.freeze
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ module Rox
2
+ module Core
3
+ class FetcherStatus
4
+ APPLIED_FROM_EMBEDDED = 'AppliedFromEmbedded'.freeze
5
+ APPLIED_FROM_LOCAL_STORAGE = 'AppliedFromLocalStorage'.freeze
6
+ APPLIED_FROM_NETWORK = 'AppliedFromNetwork'.freeze
7
+ ERROR_FETCHED_FAILED = 'ErrorFetchedFailed'.freeze
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ module Rox
2
+ module Core
3
+ ExperimentModel = Struct.new(:id, :name, :condition, :is_archived, :flags, :labels)
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Rox
2
+ module Core
3
+ TargetGroupModel = Struct.new(:id, :condition)
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ module Rox
2
+ module Core
3
+ module Build
4
+ PLATFORM = 'Ruby'
5
+ API_VERSION = '1.7.0'
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,42 @@
1
+ module Rox
2
+ module Core
3
+ module Environment
4
+ def self.roxy_internal_path
5
+ 'device/request_configuration'
6
+ end
7
+
8
+ def self.cdn_path
9
+ case ENV['ROLLOUT_MODE']
10
+ when 'QA'
11
+ 'https://s3.amazonaws.com/qa-rox-conf.rollout.io/v1/qa'
12
+ when 'LOCAL'
13
+ 'https://s3.amazonaws.com/qa-rox-conf.rollout.io/v1/development'
14
+ else
15
+ 'https://s3.amazonaws.com/rox-conf.rollout.io/v1/production'
16
+ end
17
+ end
18
+
19
+ def self.api_path
20
+ case ENV['ROLLOUT_MODE']
21
+ when 'QA'
22
+ 'https://qax.rollout.io/device/request_configuration'
23
+ when 'LOCAL'
24
+ 'http://127.0.0.1:8557/device/request_configuration'
25
+ else
26
+ 'https://x-api.rollout.io/device/request_configuration'
27
+ end
28
+ end
29
+
30
+ def self.analytics_path
31
+ case ENV['ROLLOUT_MODE']
32
+ when 'QA'
33
+ 'https://qaanalytic.rollout.io'
34
+ when 'LOCAL'
35
+ 'http://127.0.0.1:8787'
36
+ else
37
+ 'https://analytic.rollout.io'
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,29 @@
1
+ module Rox
2
+ module Core
3
+ class PropertyType
4
+ attr_accessor :value, :name
5
+
6
+ def initialize(value, name)
7
+ @value = value
8
+ @name = name
9
+ end
10
+
11
+ CACHE_MISS_URL = PropertyType.new(1, 'cache_miss_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
+ end
28
+ end
29
+ end
@@ -0,0 +1,16 @@
1
+ module Rox
2
+ module Core
3
+ class MergedContext
4
+ def initialize(global_context, local_context)
5
+ @global_context = global_context
6
+ @local_context = local_context
7
+ end
8
+
9
+ def [](key)
10
+ return @local_context[key] unless @local_context.nil? || @local_context[key].nil?
11
+ return @global_context[key] unless @global_context.nil?
12
+ nil
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,131 @@
1
+ require 'rox/core/repositories/flag_repository'
2
+ require 'rox/core/repositories/custom_property_repository'
3
+ require 'rox/core/repositories/target_group_repository'
4
+ require 'rox/core/repositories/experiment_repository'
5
+ require 'rox/core/roxx/parser'
6
+ require 'rox/core/repositories/roxx/experiments_extensions'
7
+ require 'rox/core/repositories/roxx/properties_extensions'
8
+ require 'rox/core/configuration/configuration_fetched_invoker'
9
+ require 'rox/core/configuration/configuration_parser'
10
+ require 'rox/core/network/request_configuration_builder'
11
+ require 'rox/core/network/request'
12
+ require 'rox/core/network/configuration_fetcher'
13
+ require 'rox/core/network/configuration_fetcher_roxy'
14
+ require 'rox/core/register/registerer'
15
+ require 'rox/core/client/internal_flags'
16
+ require 'rox/core/client/buid'
17
+ require 'rox/core/entities/flag_setter'
18
+ require 'rox/core/impression/impression_invoker'
19
+ require 'rox/core/reporting/error_reporter'
20
+ require 'rox/core/security/signature_verifier'
21
+ require 'rox/core/utils/periodic_task'
22
+
23
+ module Rox
24
+ module Core
25
+ class Core
26
+ def initialize
27
+ @flag_repository = FlagRepository.new
28
+ @custom_property_repository = CustomPropertyRepository.new
29
+ @target_group_repository = TargetGroupRepository.new
30
+ @experiment_repository = ExperimentRepository.new
31
+ @parser = Parser.new
32
+
33
+ experiments_extensions = ExperimentsExtensions.new(@parser, @target_group_repository, @flag_repository, @experiment_repository)
34
+ properties_extensions = PropertiesExtensions.new(@parser, @custom_property_repository)
35
+ experiments_extensions.extend
36
+ properties_extensions.extend
37
+
38
+ @configuration_fetched_invoker = ConfigurationFetchedInvoker.new
39
+ @registerer = Registerer.new(@flag_repository)
40
+
41
+ @sdk_settings = nil
42
+ @impression_invoker = nil
43
+ @flag_setter = nil
44
+ @error_reporter = nil
45
+ @configuration_fetcher = nil
46
+ @last_configurations = nil
47
+ end
48
+
49
+ def setup(sdk_settings, device_properties, rox_options)
50
+ @sdk_settings = sdk_settings
51
+
52
+ roxy_path = rox_options.nil? || rox_options.roxy_url.nil? ? nil : rox_options.roxy_url
53
+
54
+ # TODO: Analytics.Analytics.Initialize(deviceProperties.RolloutKey, deviceProperties)
55
+ internal_flags = InternalFlags.new(@experiment_repository, @parser)
56
+
57
+ # 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?)
59
+ @flag_setter = FlagSetter.new(@flag_repository, @parser, @experiment_repository, @impression_invoker)
60
+ buid = BUID.new(sdk_settings, device_properties, @flag_repository, @custom_property_repository)
61
+
62
+ request_config_builder = RequestConfigurationBuilder.new(sdk_settings, buid, device_properties, roxy_path)
63
+
64
+ client_request = Request.new
65
+ err_reporter_request = Request.new
66
+
67
+ @error_reporter = ErrorReporter.new(err_reporter_request, device_properties, buid)
68
+
69
+ if roxy_path.nil?
70
+ @configuration_fetcher = ConfigurationFetcher.new(request_config_builder, client_request, @configuration_fetched_invoker)
71
+ else
72
+ @configuration_fetcher = ConfigurationFetcherRoxy.new(request_config_builder, client_request, @configuration_fetched_invoker)
73
+ end
74
+
75
+ if !rox_options.nil? && !rox_options.configuration_fetched_handler.nil?
76
+ @configuration_fetched_invoker.register_fetched_handler(&rox_options.configuration_fetched_handler)
77
+ end
78
+
79
+ Thread.new do
80
+ Thread.current.report_on_exception = false if Thread.current.respond_to?(:report_on_exception)
81
+ fetch
82
+
83
+ if !rox_options.nil? && !rox_options.impression_handler.nil?
84
+ @impression_invoker.register_impression_handler(&rox_options.impression_handler)
85
+ end
86
+
87
+ if !rox_options.nil? && !rox_options.fetch_interval.nil?
88
+ PeriodicTask.run(rox_options.fetch_interval) { fetch }
89
+ end
90
+ end
91
+ end
92
+
93
+ def fetch
94
+ return if @configuration_fetcher.nil?
95
+
96
+ configuration_parser = ConfigurationParser.new(SignatureVerifier.new, @error_reporter, @configuration_fetched_invoker)
97
+ result = @configuration_fetcher.fetch
98
+ return if result.nil?
99
+
100
+ configuration = configuration_parser.parse(result, @sdk_settings)
101
+ return if configuration.nil?
102
+
103
+ @experiment_repository.experiments = configuration.experiments
104
+ @target_group_repository.target_groups = configuration.target_groups
105
+ @flag_setter.set_experiments
106
+
107
+ has_changes = @last_configurations.nil? || @last_configurations.data != result.data
108
+ @last_configurations = result
109
+ @configuration_fetched_invoker.invoke(FetcherStatus::APPLIED_FROM_NETWORK, configuration.signature_date, has_changes)
110
+ end
111
+
112
+ def register(ns, rox_container)
113
+ @registerer.register_instance(rox_container, ns)
114
+ end
115
+
116
+ def context=(context)
117
+ @flag_repository.all_flags.each do |flag|
118
+ flag.context = context
119
+ end
120
+ end
121
+
122
+ def add_custom_property(property)
123
+ @custom_property_repository.add_custom_property(property)
124
+ end
125
+
126
+ def add_custom_property_if_not_exists(property)
127
+ @custom_property_repository.add_custom_property_if_not_exists(property)
128
+ end
129
+ end
130
+ end
131
+ end