Skip to content

Commit 45e7e2b

Browse files
rashidspmikeproeng37
authored andcommitted
feat(datafile management): Add Polling Manager and Config Update (#179)
1 parent aaca718 commit 45e7e2b

13 files changed

+920
-7
lines changed

.rubocop_todo.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ Lint/LiteralAsCondition:
2020
# Configuration parameters: CountKeywordArgs.
2121
Metrics/ParameterLists:
2222
Max: 6
23+
Exclude:
24+
- 'lib/optimizely/config_manager/http_project_config_manager.rb'
25+
- 'lib/optimizely.rb'
26+
- 'lib/optimizely/optimizely_factory.rb'
27+
28+
Naming/AccessorMethodName:
29+
Exclude:
30+
- 'lib/optimizely/config_manager/http_project_config_manager.rb'
31+
- 'spec/optimizely_factory_spec.rb'
2332

2433
# Offense count: 1
2534
# Configuration parameters: NamePrefix, NamePrefixBlacklist, NameWhitelist, MethodDefinitionMacros.

lib/optimizely.rb

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#
1818
require_relative 'optimizely/audience'
1919
require_relative 'optimizely/config/datafile_project_config'
20+
require_relative 'optimizely/config_manager/http_project_config_manager'
2021
require_relative 'optimizely/config_manager/static_project_config_manager'
2122
require_relative 'optimizely/decision_service'
2223
require_relative 'optimizely/error_handler'
@@ -46,8 +47,22 @@ class Project
4647
# By default all exceptions will be suppressed.
4748
# @param user_profile_service - Optional component which provides methods to store and retreive user profiles.
4849
# @param skip_json_validation - Optional boolean param to skip JSON schema validation of the provided datafile.
49-
50-
def initialize(datafile, event_dispatcher = nil, logger = nil, error_handler = nil, skip_json_validation = false, user_profile_service = nil)
50+
# @params sdk_key - Optional string uniquely identifying the datafile corresponding to project and environment combination.
51+
# Must provide at least one of datafile or sdk_key.
52+
# @param config_manager - Optional Responds to get_config.
53+
# @param notification_center - Optional Instance of NotificationCenter.
54+
55+
def initialize(
56+
datafile = nil,
57+
event_dispatcher = nil,
58+
logger = nil,
59+
error_handler = nil,
60+
skip_json_validation = false,
61+
user_profile_service = nil,
62+
sdk_key = nil,
63+
config_manager = nil,
64+
notification_center = nil
65+
)
5166
@logger = logger || NoOpLogger.new
5267
@error_handler = error_handler || NoOpErrorHandler.new
5368
@event_dispatcher = event_dispatcher || EventDispatcher.new
@@ -60,10 +75,24 @@ def initialize(datafile, event_dispatcher = nil, logger = nil, error_handler = n
6075
@logger.log(Logger::ERROR, e.message)
6176
end
6277

63-
@config_manager = StaticProjectConfigManager.new(datafile, @logger, @error_handler, skip_json_validation)
78+
@notification_center = notification_center.is_a?(Optimizely::NotificationCenter) ? notification_center : NotificationCenter.new(@logger, @error_handler)
79+
80+
@config_manager = if config_manager.respond_to?(:get_config)
81+
config_manager
82+
elsif sdk_key
83+
HTTPProjectConfigManager.new(
84+
sdk_key: sdk_key,
85+
datafile: datafile,
86+
logger: @logger,
87+
error_handler: @error_handler,
88+
skip_json_validation: skip_json_validation,
89+
notification_center: @notification_center
90+
)
91+
else
92+
StaticProjectConfigManager.new(datafile, @logger, @error_handler, skip_json_validation)
93+
end
6494
@decision_service = DecisionService.new(@logger, @user_profile_service)
6595
@event_builder = EventBuilder.new(@logger)
66-
@notification_center = NotificationCenter.new(@logger, @error_handler)
6796
end
6897

6998
# Buckets visitor and sends impression event to Optimizely.

lib/optimizely/config/datafile_project_config.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ def initialize(datafile, logger, error_handler)
140140
end
141141
end
142142

143-
def self.create_project_config_from_datafile(datafile, logger, error_handler, skip_json_validation)
143+
def self.create(datafile, logger, error_handler, skip_json_validation)
144144
# Looks up and sets datafile and config based on response body.
145145
#
146146
# datafile - JSON string representing the Optimizely project.
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# frozen_string_literal: true
2+
3+
#
4+
# Copyright 2019, Optimizely and contributors
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
#
18+
module Optimizely
19+
class AsyncScheduler
20+
attr_reader :running
21+
22+
def initialize(callback, interval, auto_update, logger = nil)
23+
# Sets up AsyncScheduler to execute a callback periodically.
24+
#
25+
# callback - Main function to be executed periodically.
26+
# interval - How many seconds to wait between executions.
27+
# auto_update - boolean indicates to run infinitely or only once.
28+
# logger - Optional Provides a logger instance.
29+
30+
@callback = callback
31+
@interval = interval
32+
@auto_update = auto_update
33+
@running = false
34+
@thread = nil
35+
@logger = logger || NoOpLogger.new
36+
end
37+
38+
def start!
39+
# Starts the async scheduler.
40+
41+
if @running
42+
@logger.log(
43+
Logger::WARN,
44+
'Scheduler is already running. Ignoring .start() call.'
45+
)
46+
return
47+
end
48+
49+
begin
50+
@running = true
51+
@thread = Thread.new { execution_wrapper(@callback) }
52+
rescue StandardError => e
53+
@logger.log(
54+
Logger::ERROR,
55+
"Couldn't create a new thread for async scheduler. #{e.message}"
56+
)
57+
end
58+
end
59+
60+
def stop!
61+
# Stops the async scheduler.
62+
63+
# If the scheduler is not running do nothing.
64+
return unless @running
65+
66+
@running = false
67+
@thread.exit
68+
end
69+
70+
private
71+
72+
def execution_wrapper(callback)
73+
# Executes the given callback periodically
74+
75+
loop do
76+
begin
77+
callback.call
78+
rescue
79+
@logger.log(
80+
Logger::ERROR,
81+
'Something went wrong when running passed function.'
82+
)
83+
stop!
84+
end
85+
break unless @auto_update
86+
87+
sleep @interval
88+
end
89+
end
90+
end
91+
end

0 commit comments

Comments
 (0)