Skip to content

Commit 1c19b8e

Browse files
feat: Optimizely Factory Revised (#204)
* feat: Optimizely Factory Revised * Line Endings * address feedback * use instance_variable_get * revert private method names Co-authored-by: msohailhussain <mirza.sohailhussain@gmail.com>
1 parent 5112d84 commit 1c19b8e

File tree

3 files changed

+130
-63
lines changed

3 files changed

+130
-63
lines changed

.rubocop_todo.yml

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This configuration was generated by
22
# `rubocop --auto-gen-config`
3-
# on 2017-12-06 17:48:00 +0500 using RuboCop version 0.51.0.
3+
# on 2020-04-28 01:01:46 +0500 using RuboCop version 0.60.0.
44
# The point is for the user to remove these configuration records
55
# one by one as the offenses are removed from the code base.
66
# Note that changes in the inspected code, or installation of new
@@ -11,32 +11,18 @@ Lint/HandleExceptions:
1111
Exclude:
1212
- 'Rakefile'
1313

14-
# Offense count: 1
15-
Lint/LiteralAsCondition:
16-
Exclude:
17-
- 'lib/optimizely/config/datafile_project_config.rb'
18-
19-
# Offense count: 1
14+
# Offense count: 8
2015
# Configuration parameters: CountKeywordArgs.
2116
Metrics/ParameterLists:
22-
Max: 6
23-
Exclude:
24-
- 'lib/optimizely.rb'
25-
- 'lib/optimizely/config_manager/http_project_config_manager.rb'
26-
- 'lib/optimizely/event/batch_event_processor.rb'
27-
- 'lib/optimizely/event/entity/conversion_event.rb'
28-
- 'lib/optimizely/event/entity/event_context.rb'
29-
- 'lib/optimizely/event/entity/impression_event.rb'
30-
- 'lib/optimizely/event/entity/snapshot_event.rb'
31-
- 'lib/optimizely/optimizely_factory.rb'
17+
Max: 12
3218

19+
# Offense count: 2
3320
Naming/AccessorMethodName:
3421
Exclude:
35-
- 'lib/optimizely/config_manager/http_project_config_manager.rb'
36-
- 'spec/optimizely_factory_spec.rb'
3722
- 'lib/optimizely.rb'
23+
- 'lib/optimizely/config_manager/http_project_config_manager.rb'
3824

39-
# Offense count: 1
25+
# Offense count: 2
4026
# Configuration parameters: NamePrefix, NamePrefixBlacklist, NameWhitelist, MethodDefinitionMacros.
4127
# NamePrefix: is_, has_, have_
4228
# NamePrefixBlacklist: is_, has_, have_
@@ -46,3 +32,17 @@ Naming/PredicateName:
4632
Exclude:
4733
- 'spec/**/*'
4834
- 'lib/optimizely.rb'
35+
36+
# Offense count: 2
37+
# Cop supports --auto-correct.
38+
# Configuration parameters: ExactNameMatch, AllowPredicates, AllowDSLWriters, IgnoreClassMethods, Whitelist.
39+
# Whitelist: to_ary, to_a, to_c, to_enum, to_h, to_hash, to_i, to_int, to_io, to_open, to_path, to_proc, to_r, to_regexp, to_str, to_s, to_sym
40+
Style/TrivialAccessors:
41+
Exclude:
42+
- 'lib/optimizely/optimizely_factory.rb'
43+
44+
# Offense count: 2465
45+
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
46+
# URISchemes: http, https
47+
Metrics/LineLength:
48+
Max: 215

lib/optimizely/optimizely_factory.rb

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,18 @@
1717
#
1818

1919
require 'optimizely'
20+
require 'optimizely/error_handler'
2021
require 'optimizely/event_dispatcher'
2122
require 'optimizely/event/batch_event_processor'
23+
require 'optimizely/logger'
24+
require 'optimizely/notification_center'
25+
2226
module Optimizely
2327
class OptimizelyFactory
24-
attr_reader :max_event_batch_size, :max_event_flush_interval
25-
2628
# Convenience method for setting the maximum number of events contained within a batch.
2729
# @param batch_size Integer - Sets size of EventQueue.
2830
# @param logger - Optional LoggerInterface Provides a log method to log messages.
29-
def self.max_event_batch_size(batch_size, logger)
31+
def self.max_event_batch_size(batch_size, logger = NoOpLogger.new)
3032
unless batch_size.is_a? Integer
3133
logger.log(
3234
Logger::ERROR,
@@ -48,7 +50,7 @@ def self.max_event_batch_size(batch_size, logger)
4850
# Convenience method for setting the maximum time interval in milliseconds between event dispatches.
4951
# @param flush_interval Numeric - Time interval between event dispatches.
5052
# @param logger - Optional LoggerInterface Provides a log method to log messages.
51-
def self.max_event_flush_interval(flush_interval, logger)
53+
def self.max_event_flush_interval(flush_interval, logger = NoOpLogger.new)
5254
unless flush_interval.is_a? Numeric
5355
logger.log(
5456
Logger::ERROR,
@@ -67,12 +69,42 @@ def self.max_event_flush_interval(flush_interval, logger)
6769
@max_event_flush_interval = flush_interval
6870
end
6971

72+
# Convenience method for setting frequency at which datafile has to be polled and ProjectConfig updated.
73+
#
74+
# @param polling_interval Numeric - Time in seconds after which to update datafile.
75+
def self.polling_interval(polling_interval)
76+
@polling_interval = polling_interval
77+
end
78+
79+
# Convenience method for setting timeout to block the config call until config has been initialized.
80+
#
81+
# @param blocking_timeout Numeric - Time in seconds.
82+
def self.blocking_timeout(blocking_timeout)
83+
@blocking_timeout = blocking_timeout
84+
end
85+
7086
# Returns a new optimizely instance.
7187
#
7288
# @params sdk_key - Required String uniquely identifying the fallback datafile corresponding to project.
7389
# @param fallback datafile - Optional JSON string datafile.
7490
def self.default_instance(sdk_key, datafile = nil)
75-
Optimizely::Project.new(datafile, nil, nil, nil, nil, nil, sdk_key)
91+
error_handler = NoOpErrorHandler.new
92+
logger = NoOpLogger.new
93+
notification_center = NotificationCenter.new(logger, error_handler)
94+
95+
config_manager = Optimizely::HTTPProjectConfigManager.new(
96+
sdk_key: sdk_key,
97+
polling_interval: @polling_interval,
98+
blocking_timeout: @blocking_timeout,
99+
datafile: datafile,
100+
logger: logger,
101+
error_handler: error_handler,
102+
notification_center: notification_center
103+
)
104+
105+
Optimizely::Project.new(
106+
datafile, nil, logger, error_handler, nil, nil, sdk_key, config_manager, notification_center
107+
)
76108
end
77109

78110
# Returns a new optimizely instance.
@@ -108,10 +140,27 @@ def self.custom_instance(
108140
config_manager = nil,
109141
notification_center = nil
110142
)
143+
144+
error_handler ||= NoOpErrorHandler.new
145+
logger ||= NoOpLogger.new
146+
notification_center = notification_center.is_a?(Optimizely::NotificationCenter) ? notification_center : NotificationCenter.new(logger, error_handler)
147+
111148
event_processor = BatchEventProcessor.new(
112149
event_dispatcher: event_dispatcher || EventDispatcher.new,
113150
batch_size: @max_event_batch_size,
114151
flush_interval: @max_event_flush_interval,
152+
logger: logger,
153+
notification_center: notification_center
154+
)
155+
156+
config_manager ||= Optimizely::HTTPProjectConfigManager.new(
157+
sdk_key: sdk_key,
158+
polling_interval: @polling_interval,
159+
blocking_timeout: @blocking_timeout,
160+
datafile: datafile,
161+
logger: logger,
162+
error_handler: error_handler,
163+
skip_json_validation: skip_json_validation,
115164
notification_center: notification_center
116165
)
117166

spec/optimizely_factory_spec.rb

Lines changed: 56 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,38 @@
3030
let(:event_dispatcher) { Optimizely::EventDispatcher.new }
3131
let(:notification_center) { Optimizely::NotificationCenter.new(spy_logger, error_handler) }
3232

33-
describe '.default_instance' do
34-
it 'should take http config manager' do
35-
allow(Optimizely::HTTPProjectConfigManager).to receive(:new)
36-
37-
http_project_config_manager = Optimizely::HTTPProjectConfigManager.new(
38-
sdk_key: 'sdk_key',
39-
datafile: datafile,
40-
logger: spy_logger,
41-
error_handler: error_handler,
42-
skip_json_validation: false,
43-
notification_center: notification_center
33+
before(:example) do
34+
WebMock.allow_net_connect!
35+
stub_request(:get, 'https://cdn.optimizely.com/datafiles/sdk_key.json')
36+
.with(
37+
headers: {
38+
'Content-Type' => 'application/json'
39+
}
4440
)
41+
.to_return(status: 200, body: '', headers: {})
42+
end
43+
44+
describe '.default_instance' do
45+
it 'should create http config manager when sdk_key is given' do
46+
optimizely_instance = Optimizely::OptimizelyFactory.default_instance('sdk_key', datafile)
47+
expect(optimizely_instance.config_manager). to be_instance_of(Optimizely::HTTPProjectConfigManager)
48+
end
4549

50+
it 'should create http config manager when polling interval and blocking timeout are set' do
51+
Optimizely::OptimizelyFactory.polling_interval(40)
52+
Optimizely::OptimizelyFactory.blocking_timeout(5)
4653
optimizely_instance = Optimizely::OptimizelyFactory.default_instance('sdk_key', datafile)
4754

48-
expect(optimizely_instance.config_manager). to eq(http_project_config_manager)
55+
# Verify that values set in OptimizelyFactory are being used inside config manager.
56+
expect(optimizely_instance.config_manager.instance_variable_get(:@polling_interval)). to eq(40)
57+
expect(optimizely_instance.config_manager.instance_variable_get(:@blocking_timeout)). to eq(5)
58+
end
59+
60+
it 'should create http config manager with the same components as the instance' do
61+
optimizely_instance = Optimizely::OptimizelyFactory.default_instance('sdk_key', datafile)
62+
expect(optimizely_instance.error_handler). to be(optimizely_instance.config_manager.instance_variable_get(:@error_handler))
63+
expect(optimizely_instance.logger). to be(optimizely_instance.config_manager.instance_variable_get(:@logger))
64+
expect(optimizely_instance.notification_center). to be(optimizely_instance.config_manager.instance_variable_get(:@notification_center))
4965
end
5066
end
5167

@@ -57,61 +73,63 @@ class CustomConfigManager
5773

5874
custom_config_manager = CustomConfigManager.new
5975
optimizely_instance = Optimizely::OptimizelyFactory.default_instance_with_config_manager(custom_config_manager)
60-
expect(optimizely_instance.config_manager). to eq(custom_config_manager)
76+
expect(optimizely_instance.config_manager). to be(custom_config_manager)
6177
end
6278
end
6379

6480
describe '.custom_instance' do
65-
it 'should take http config manager when sdk key is given' do
66-
allow(Optimizely::HTTPProjectConfigManager).to receive(:new)
67-
http_project_config_manager = Optimizely::HTTPProjectConfigManager.new(
68-
sdk_key: 'sdk_key',
69-
datafile: datafile,
70-
logger: spy_logger,
71-
error_handler: error_handler,
72-
skip_json_validation: false,
73-
notification_center: notification_center
74-
)
75-
81+
it 'should take http config manager when sdk key, polling interval, blocking timeout are given' do
82+
Optimizely::OptimizelyFactory.polling_interval(50)
83+
Optimizely::OptimizelyFactory.blocking_timeout(10)
7684
optimizely_instance = Optimizely::OptimizelyFactory.custom_instance(
7785
'sdk_key',
7886
datafile,
7987
event_dispatcher,
80-
spy_logger,
88+
Optimizely::NoOpLogger.new,
8189
error_handler,
8290
false,
8391
user_profile_service,
8492
nil,
8593
notification_center
8694
)
87-
expect(optimizely_instance.config_manager). to eq(http_project_config_manager)
95+
96+
# Verify that values set in OptimizelyFactory are being used inside config manager.
97+
expect(optimizely_instance.config_manager.instance_variable_get(:@polling_interval)). to eq(50)
98+
expect(optimizely_instance.config_manager.instance_variable_get(:@blocking_timeout)). to eq(10)
8899
end
89100

90101
it 'should take event processor when flush interval and batch size are set' do
91-
Optimizely::OptimizelyFactory.max_event_flush_interval(5, spy_logger)
92-
Optimizely::OptimizelyFactory.max_event_batch_size(100, spy_logger)
93-
94-
event_processor = Optimizely::BatchEventProcessor.new(
95-
event_dispatcher: event_dispatcher,
96-
batch_size: 100,
97-
flush_interval: 5,
98-
notification_center: notification_center
99-
)
102+
Optimizely::OptimizelyFactory.max_event_flush_interval(5)
103+
Optimizely::OptimizelyFactory.max_event_batch_size(100)
100104

105+
optimizely_instance = Optimizely::OptimizelyFactory.custom_instance('sdk_key')
106+
107+
expect(optimizely_instance.event_processor.flush_interval).to eq(5)
108+
expect(optimizely_instance.event_processor.batch_size).to eq(100)
109+
optimizely_instance.close
110+
end
111+
112+
it 'should assign passed components to both the instance and http manager' do
113+
logger = Optimizely::NoOpLogger.new
101114
optimizely_instance = Optimizely::OptimizelyFactory.custom_instance(
102115
'sdk_key',
103116
datafile,
104117
event_dispatcher,
105-
spy_logger,
118+
logger,
106119
error_handler,
107120
false,
108121
user_profile_service,
109122
nil,
110123
notification_center
111124
)
112125

113-
expect(optimizely_instance.event_processor).equal? event_processor
114-
optimizely_instance.close
126+
expect(error_handler). to be(optimizely_instance.config_manager.instance_variable_get(:@error_handler))
127+
expect(logger). to be(optimizely_instance.config_manager.instance_variable_get(:@logger))
128+
expect(notification_center). to be(optimizely_instance.config_manager.instance_variable_get(:@notification_center))
129+
130+
expect(error_handler). to be(optimizely_instance.error_handler)
131+
expect(logger). to be(optimizely_instance.logger)
132+
expect(notification_center). to be(optimizely_instance.notification_center)
115133
end
116134
end
117135

0 commit comments

Comments
 (0)