optimizely-sdk 3.3.1 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/lib/optimizely.rb +199 -38
- data/lib/optimizely/audience.rb +2 -2
- data/lib/optimizely/config/datafile_project_config.rb +15 -3
- data/lib/optimizely/config/proxy_config.rb +34 -0
- data/lib/optimizely/config_manager/async_scheduler.rb +8 -4
- data/lib/optimizely/config_manager/http_project_config_manager.rb +50 -28
- data/lib/optimizely/config_manager/static_project_config_manager.rb +6 -2
- data/lib/optimizely/event/batch_event_processor.rb +67 -58
- data/lib/optimizely/event_dispatcher.rb +35 -17
- data/lib/optimizely/exceptions.rb +8 -9
- data/lib/optimizely/helpers/constants.rb +6 -3
- data/lib/optimizely/helpers/http_utils.rb +64 -0
- data/lib/optimizely/helpers/variable_type.rb +8 -1
- data/lib/optimizely/notification_center.rb +13 -5
- data/lib/optimizely/optimizely_config.rb +116 -0
- data/lib/optimizely/optimizely_factory.rb +54 -5
- data/lib/optimizely/version.rb +1 -1
- metadata +6 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c89ea6be1aa10ab05c2d47e74ebe054987e6fc0e08b85417a63b579d80f2fac4
|
4
|
+
data.tar.gz: 1f35f5d10017780db25f46e270d64010d0dc5e245bd4b183ae1da8ee1dfb060d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d2fd93c8952496d3feb12ec4dd8fb8ced95f7123a94447b646b14e157cdaf82af65adfc193943a6efc7ff77069d4600d5006728c876f9ff0d06d9116ad2c58a1
|
7
|
+
data.tar.gz: a5ffc4c7db14a01e4bc7741eca6c636b6f41e755a7256fae64703e5241bd6ade20190c8f0b83bdc37d7cb18277439659ce09faa68388c7e74db2d6d3463d470a
|
data/lib/optimizely.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#
|
4
|
-
# Copyright 2016-
|
4
|
+
# Copyright 2016-2020, Optimizely and contributors
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
7
|
# you may not use this file except in compliance with the License.
|
@@ -33,6 +33,7 @@ require_relative 'optimizely/helpers/validator'
|
|
33
33
|
require_relative 'optimizely/helpers/variable_type'
|
34
34
|
require_relative 'optimizely/logger'
|
35
35
|
require_relative 'optimizely/notification_center'
|
36
|
+
require_relative 'optimizely/optimizely_config'
|
36
37
|
|
37
38
|
module Optimizely
|
38
39
|
class Project
|
@@ -70,7 +71,7 @@ module Optimizely
|
|
70
71
|
)
|
71
72
|
@logger = logger || NoOpLogger.new
|
72
73
|
@error_handler = error_handler || NoOpErrorHandler.new
|
73
|
-
@event_dispatcher = event_dispatcher || EventDispatcher.new
|
74
|
+
@event_dispatcher = event_dispatcher || EventDispatcher.new(logger: @logger, error_handler: @error_handler)
|
74
75
|
@user_profile_service = user_profile_service
|
75
76
|
|
76
77
|
begin
|
@@ -429,6 +430,32 @@ module Optimizely
|
|
429
430
|
variable_value
|
430
431
|
end
|
431
432
|
|
433
|
+
# Get the Json value of the specified variable in the feature flag in a Dict.
|
434
|
+
#
|
435
|
+
# @param feature_flag_key - String key of feature flag the variable belongs to
|
436
|
+
# @param variable_key - String key of variable for which we are getting the string value
|
437
|
+
# @param user_id - String user ID
|
438
|
+
# @param attributes - Hash representing visitor attributes and values which need to be recorded.
|
439
|
+
#
|
440
|
+
# @return [Dict] the Dict containing variable value.
|
441
|
+
# @return [nil] if the feature flag or variable are not found.
|
442
|
+
|
443
|
+
def get_feature_variable_json(feature_flag_key, variable_key, user_id, attributes = nil)
|
444
|
+
unless is_valid
|
445
|
+
@logger.log(Logger::ERROR, InvalidProjectConfigError.new('get_feature_variable_json').message)
|
446
|
+
return nil
|
447
|
+
end
|
448
|
+
variable_value = get_feature_variable_for_type(
|
449
|
+
feature_flag_key,
|
450
|
+
variable_key,
|
451
|
+
Optimizely::Helpers::Constants::VARIABLE_TYPES['JSON'],
|
452
|
+
user_id,
|
453
|
+
attributes
|
454
|
+
)
|
455
|
+
|
456
|
+
variable_value
|
457
|
+
end
|
458
|
+
|
432
459
|
# Get the Boolean value of the specified variable in the feature flag.
|
433
460
|
#
|
434
461
|
# @param feature_flag_key - String key of feature flag the variable belongs to
|
@@ -483,6 +510,71 @@ module Optimizely
|
|
483
510
|
variable_value
|
484
511
|
end
|
485
512
|
|
513
|
+
# Get values of all the variables in the feature flag and returns them in a Dict
|
514
|
+
#
|
515
|
+
# @param feature_flag_key - String key of feature flag
|
516
|
+
# @param user_id - String user ID
|
517
|
+
# @param attributes - Hash representing visitor attributes and values which need to be recorded.
|
518
|
+
#
|
519
|
+
# @return [Dict] the Dict containing all the varible values
|
520
|
+
# @return [nil] if the feature flag is not found.
|
521
|
+
|
522
|
+
def get_all_feature_variables(feature_flag_key, user_id, attributes = nil)
|
523
|
+
unless is_valid
|
524
|
+
@logger.log(Logger::ERROR, InvalidProjectConfigError.new('get_all_feature_variables').message)
|
525
|
+
return nil
|
526
|
+
end
|
527
|
+
|
528
|
+
return nil unless Optimizely::Helpers::Validator.inputs_valid?(
|
529
|
+
{
|
530
|
+
feature_flag_key: feature_flag_key,
|
531
|
+
user_id: user_id
|
532
|
+
},
|
533
|
+
@logger, Logger::ERROR
|
534
|
+
)
|
535
|
+
|
536
|
+
return nil unless user_inputs_valid?(attributes)
|
537
|
+
|
538
|
+
config = project_config
|
539
|
+
|
540
|
+
feature_flag = config.get_feature_flag_from_key(feature_flag_key)
|
541
|
+
unless feature_flag
|
542
|
+
@logger.log(Logger::INFO, "No feature flag was found for key '#{feature_flag_key}'.")
|
543
|
+
return nil
|
544
|
+
end
|
545
|
+
|
546
|
+
decision = @decision_service.get_variation_for_feature(config, feature_flag, user_id, attributes)
|
547
|
+
variation = decision ? decision['variation'] : nil
|
548
|
+
feature_enabled = variation ? variation['featureEnabled'] : false
|
549
|
+
all_variables = {}
|
550
|
+
|
551
|
+
feature_flag['variables'].each do |variable|
|
552
|
+
variable_value = get_feature_variable_for_variation(feature_flag_key, feature_enabled, variation, variable, user_id)
|
553
|
+
all_variables[variable['key']] = Helpers::VariableType.cast_value_to_type(variable_value, variable['type'], @logger)
|
554
|
+
end
|
555
|
+
|
556
|
+
source_string = Optimizely::DecisionService::DECISION_SOURCES['ROLLOUT']
|
557
|
+
if decision && decision['source'] == Optimizely::DecisionService::DECISION_SOURCES['FEATURE_TEST']
|
558
|
+
source_info = {
|
559
|
+
experiment_key: decision.experiment['key'],
|
560
|
+
variation_key: variation['key']
|
561
|
+
}
|
562
|
+
source_string = Optimizely::DecisionService::DECISION_SOURCES['FEATURE_TEST']
|
563
|
+
end
|
564
|
+
|
565
|
+
@notification_center.send_notifications(
|
566
|
+
NotificationCenter::NOTIFICATION_TYPES[:DECISION],
|
567
|
+
Helpers::Constants::DECISION_NOTIFICATION_TYPES['ALL_FEATURE_VARIABLES'], user_id, (attributes || {}),
|
568
|
+
feature_key: feature_flag_key,
|
569
|
+
feature_enabled: feature_enabled,
|
570
|
+
source: source_string,
|
571
|
+
variable_values: all_variables,
|
572
|
+
source_info: source_info || {}
|
573
|
+
)
|
574
|
+
|
575
|
+
all_variables
|
576
|
+
end
|
577
|
+
|
486
578
|
# Get the Integer value of the specified variable in the feature flag.
|
487
579
|
#
|
488
580
|
# @param feature_flag_key - String key of feature flag the variable belongs to
|
@@ -523,6 +615,57 @@ module Optimizely
|
|
523
615
|
@event_processor.stop! if @event_processor.respond_to?(:stop!)
|
524
616
|
end
|
525
617
|
|
618
|
+
def get_optimizely_config
|
619
|
+
# Get OptimizelyConfig object containing experiments and features data
|
620
|
+
# Returns Object
|
621
|
+
#
|
622
|
+
# OptimizelyConfig Object Schema
|
623
|
+
# {
|
624
|
+
# 'experimentsMap' => {
|
625
|
+
# 'my-fist-experiment' => {
|
626
|
+
# 'id' => '111111',
|
627
|
+
# 'key' => 'my-fist-experiment'
|
628
|
+
# 'variationsMap' => {
|
629
|
+
# 'variation_1' => {
|
630
|
+
# 'id' => '121212',
|
631
|
+
# 'key' => 'variation_1',
|
632
|
+
# 'variablesMap' => {
|
633
|
+
# 'age' => {
|
634
|
+
# 'id' => '222222',
|
635
|
+
# 'key' => 'age',
|
636
|
+
# 'type' => 'integer',
|
637
|
+
# 'value' => '0',
|
638
|
+
# }
|
639
|
+
# }
|
640
|
+
# }
|
641
|
+
# }
|
642
|
+
# }
|
643
|
+
# },
|
644
|
+
# 'featuresMap' => {
|
645
|
+
# 'awesome-feature' => {
|
646
|
+
# 'id' => '333333',
|
647
|
+
# 'key' => 'awesome-feature',
|
648
|
+
# 'experimentsMap' => Object,
|
649
|
+
# 'variablesMap' => Object,
|
650
|
+
# }
|
651
|
+
# },
|
652
|
+
# 'revision' => '13',
|
653
|
+
# }
|
654
|
+
#
|
655
|
+
unless is_valid
|
656
|
+
@logger.log(Logger::ERROR, InvalidProjectConfigError.new('get_optimizely_config').message)
|
657
|
+
return nil
|
658
|
+
end
|
659
|
+
|
660
|
+
# config_manager might not contain optimizely_config if its supplied by the consumer
|
661
|
+
# Generating a new OptimizelyConfig object in this case as a fallback
|
662
|
+
if @config_manager.respond_to?(:optimizely_config)
|
663
|
+
@config_manager.optimizely_config
|
664
|
+
else
|
665
|
+
OptimizelyConfig.new(project_config).config
|
666
|
+
end
|
667
|
+
end
|
668
|
+
|
526
669
|
private
|
527
670
|
|
528
671
|
def get_variation_with_config(experiment_key, user_id, attributes, config)
|
@@ -597,8 +740,6 @@ module Optimizely
|
|
597
740
|
# Error message logged in DatafileProjectConfig- get_feature_flag_from_key
|
598
741
|
return nil if variable.nil?
|
599
742
|
|
600
|
-
feature_enabled = false
|
601
|
-
|
602
743
|
# If variable_type is nil, set it equal to variable['type']
|
603
744
|
variable_type ||= variable['type']
|
604
745
|
# Returns nil if type differs
|
@@ -606,43 +747,24 @@ module Optimizely
|
|
606
747
|
@logger.log(Logger::WARN,
|
607
748
|
"Requested variable as type '#{variable_type}' but variable '#{variable_key}' is of type '#{variable['type']}'.")
|
608
749
|
return nil
|
609
|
-
else
|
610
|
-
source_string = Optimizely::DecisionService::DECISION_SOURCES['ROLLOUT']
|
611
|
-
decision = @decision_service.get_variation_for_feature(config, feature_flag, user_id, attributes)
|
612
|
-
variable_value = variable['defaultValue']
|
613
|
-
if decision
|
614
|
-
variation = decision['variation']
|
615
|
-
if decision['source'] == Optimizely::DecisionService::DECISION_SOURCES['FEATURE_TEST']
|
616
|
-
source_info = {
|
617
|
-
experiment_key: decision.experiment['key'],
|
618
|
-
variation_key: variation['key']
|
619
|
-
}
|
620
|
-
source_string = Optimizely::DecisionService::DECISION_SOURCES['FEATURE_TEST']
|
621
|
-
end
|
622
|
-
feature_enabled = variation['featureEnabled']
|
623
|
-
if feature_enabled == true
|
624
|
-
variation_variable_usages = config.variation_id_to_variable_usage_map[variation['id']]
|
625
|
-
variable_id = variable['id']
|
626
|
-
if variation_variable_usages&.key?(variable_id)
|
627
|
-
variable_value = variation_variable_usages[variable_id]['value']
|
628
|
-
@logger.log(Logger::INFO,
|
629
|
-
"Got variable value '#{variable_value}' for variable '#{variable_key}' of feature flag '#{feature_flag_key}'.")
|
630
|
-
else
|
631
|
-
@logger.log(Logger::DEBUG,
|
632
|
-
"Variable '#{variable_key}' is not used in variation '#{variation['key']}'. Returning the default variable value '#{variable_value}'.")
|
633
|
-
end
|
634
|
-
else
|
635
|
-
@logger.log(Logger::DEBUG,
|
636
|
-
"Feature '#{feature_flag_key}' for variation '#{variation['key']}' is not enabled. Returning the default variable value '#{variable_value}'.")
|
637
|
-
end
|
638
|
-
else
|
639
|
-
@logger.log(Logger::INFO,
|
640
|
-
"User '#{user_id}' was not bucketed into any variation for feature flag '#{feature_flag_key}'. Returning the default variable value '#{variable_value}'.")
|
641
|
-
end
|
642
750
|
end
|
643
751
|
|
752
|
+
decision = @decision_service.get_variation_for_feature(config, feature_flag, user_id, attributes)
|
753
|
+
variation = decision ? decision['variation'] : nil
|
754
|
+
feature_enabled = variation ? variation['featureEnabled'] : false
|
755
|
+
|
756
|
+
variable_value = get_feature_variable_for_variation(feature_flag_key, feature_enabled, variation, variable, user_id)
|
644
757
|
variable_value = Helpers::VariableType.cast_value_to_type(variable_value, variable_type, @logger)
|
645
758
|
|
759
|
+
source_string = Optimizely::DecisionService::DECISION_SOURCES['ROLLOUT']
|
760
|
+
if decision && decision['source'] == Optimizely::DecisionService::DECISION_SOURCES['FEATURE_TEST']
|
761
|
+
source_info = {
|
762
|
+
experiment_key: decision.experiment['key'],
|
763
|
+
variation_key: variation['key']
|
764
|
+
}
|
765
|
+
source_string = Optimizely::DecisionService::DECISION_SOURCES['FEATURE_TEST']
|
766
|
+
end
|
767
|
+
|
646
768
|
@notification_center.send_notifications(
|
647
769
|
NotificationCenter::NOTIFICATION_TYPES[:DECISION],
|
648
770
|
Helpers::Constants::DECISION_NOTIFICATION_TYPES['FEATURE_VARIABLE'], user_id, (attributes || {}),
|
@@ -658,6 +780,45 @@ module Optimizely
|
|
658
780
|
variable_value
|
659
781
|
end
|
660
782
|
|
783
|
+
def get_feature_variable_for_variation(feature_flag_key, feature_enabled, variation, variable, user_id)
|
784
|
+
# Helper method to get the non type-casted value for a variable attached to a
|
785
|
+
# feature flag. Returns appropriate variable value depending on whether there
|
786
|
+
# was a matching variation, feature was enabled or not or varible was part of the
|
787
|
+
# available variation or not. Also logs the appropriate message explaining how it
|
788
|
+
# evaluated the value of the variable.
|
789
|
+
#
|
790
|
+
# feature_flag_key - String key of feature flag the variable belongs to
|
791
|
+
# feature_enabled - Boolean indicating if feature is enabled or not
|
792
|
+
# variation - varition returned by decision service
|
793
|
+
# user_id - String user ID
|
794
|
+
#
|
795
|
+
# Returns string value of the variable.
|
796
|
+
|
797
|
+
config = project_config
|
798
|
+
variable_value = variable['defaultValue']
|
799
|
+
if variation
|
800
|
+
if feature_enabled == true
|
801
|
+
variation_variable_usages = config.variation_id_to_variable_usage_map[variation['id']]
|
802
|
+
variable_id = variable['id']
|
803
|
+
if variation_variable_usages&.key?(variable_id)
|
804
|
+
variable_value = variation_variable_usages[variable_id]['value']
|
805
|
+
@logger.log(Logger::INFO,
|
806
|
+
"Got variable value '#{variable_value}' for variable '#{variable['key']}' of feature flag '#{feature_flag_key}'.")
|
807
|
+
else
|
808
|
+
@logger.log(Logger::DEBUG,
|
809
|
+
"Variable '#{variable['key']}' is not used in variation '#{variation['key']}'. Returning the default variable value '#{variable_value}'.")
|
810
|
+
end
|
811
|
+
else
|
812
|
+
@logger.log(Logger::DEBUG,
|
813
|
+
"Feature '#{feature_flag_key}' for variation '#{variation['key']}' is not enabled. Returning the default variable value '#{variable_value}'.")
|
814
|
+
end
|
815
|
+
else
|
816
|
+
@logger.log(Logger::INFO,
|
817
|
+
"User '#{user_id}' was not bucketed into any variation for feature flag '#{feature_flag_key}'. Returning the default variable value '#{variable_value}'.")
|
818
|
+
end
|
819
|
+
variable_value
|
820
|
+
end
|
821
|
+
|
661
822
|
def user_inputs_valid?(attributes = nil, event_tags = nil)
|
662
823
|
# Helper method to validate user inputs.
|
663
824
|
#
|
@@ -701,7 +862,7 @@ module Optimizely
|
|
701
862
|
|
702
863
|
return if Helpers::Validator.event_dispatcher_valid?(@event_dispatcher)
|
703
864
|
|
704
|
-
@event_dispatcher = EventDispatcher.new
|
865
|
+
@event_dispatcher = EventDispatcher.new(logger: @logger, error_handler: @error_handler)
|
705
866
|
raise InvalidInputError, 'event_dispatcher'
|
706
867
|
end
|
707
868
|
|
data/lib/optimizely/audience.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#
|
4
|
-
# Copyright 2016-2017, 2019, Optimizely and contributors
|
4
|
+
# Copyright 2016-2017, 2019-2020, Optimizely and contributors
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
7
|
# you may not use this file except in compliance with the License.
|
@@ -84,7 +84,7 @@ module Optimizely
|
|
84
84
|
result = ConditionTreeEvaluator.evaluate(audience_conditions, evaluate_custom_attr)
|
85
85
|
result_str = result.nil? ? 'UNKNOWN' : result.to_s.upcase
|
86
86
|
logger.log(
|
87
|
-
Logger::
|
87
|
+
Logger::DEBUG,
|
88
88
|
format(Helpers::Constants::AUDIENCE_EVALUATION_LOGS['AUDIENCE_EVALUATION_RESULT'], audience_id, result_str)
|
89
89
|
)
|
90
90
|
result
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright 2019, Optimizely and contributors
|
3
|
+
# Copyright 2019-2020, Optimizely and contributors
|
4
4
|
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
@@ -82,6 +82,17 @@ module Optimizely
|
|
82
82
|
@revision = config['revision']
|
83
83
|
@rollouts = config.fetch('rollouts', [])
|
84
84
|
|
85
|
+
# Json type is represented in datafile as a subtype of string for the sake of backwards compatibility.
|
86
|
+
# Converting it to a first-class json type while creating Project Config
|
87
|
+
@feature_flags.each do |feature_flag|
|
88
|
+
feature_flag['variables'].each do |variable|
|
89
|
+
if variable['type'] == 'string' && variable['subType'] == 'json'
|
90
|
+
variable['type'] = 'json'
|
91
|
+
variable.delete('subType')
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
85
96
|
# Utility maps for quick lookup
|
86
97
|
@attribute_key_map = generate_key_map(@attributes, 'key')
|
87
98
|
@event_key_map = generate_key_map(@events, 'key')
|
@@ -159,8 +170,9 @@ module Optimizely
|
|
159
170
|
config = new(datafile, logger, error_handler)
|
160
171
|
rescue StandardError => e
|
161
172
|
default_logger = SimpleLogger.new
|
162
|
-
|
163
|
-
|
173
|
+
error_to_handle = e.class == InvalidDatafileVersionError ? e : InvalidInputError.new('datafile')
|
174
|
+
error_msg = error_to_handle.message
|
175
|
+
|
164
176
|
default_logger.log(Logger::ERROR, error_msg)
|
165
177
|
error_handler.handle_error error_to_handle
|
166
178
|
return nil
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2020, Optimizely and contributors
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
#
|
18
|
+
|
19
|
+
module Optimizely
|
20
|
+
class ProxyConfig
|
21
|
+
attr_reader :host, :port, :username, :password
|
22
|
+
|
23
|
+
def initialize(host, port = nil, username = nil, password = nil)
|
24
|
+
# host - DNS name or IP address of proxy
|
25
|
+
# port - port to use to acess the proxy
|
26
|
+
# username - username if authorization is required
|
27
|
+
# password - password if authorization is required
|
28
|
+
@host = host
|
29
|
+
@port = port
|
30
|
+
@username = username
|
31
|
+
@password = password
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#
|
4
|
-
# Copyright 2019, Optimizely and contributors
|
4
|
+
# Copyright 2019-2020, Optimizely and contributors
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
7
|
# you may not use this file except in compliance with the License.
|
@@ -19,13 +19,14 @@ module Optimizely
|
|
19
19
|
class AsyncScheduler
|
20
20
|
attr_reader :running
|
21
21
|
|
22
|
-
def initialize(callback, interval, auto_update, logger = nil)
|
22
|
+
def initialize(callback, interval, auto_update, logger = nil, error_handler = nil)
|
23
23
|
# Sets up AsyncScheduler to execute a callback periodically.
|
24
24
|
#
|
25
25
|
# callback - Main function to be executed periodically.
|
26
26
|
# interval - How many seconds to wait between executions.
|
27
27
|
# auto_update - boolean indicates to run infinitely or only once.
|
28
28
|
# logger - Optional Provides a logger instance.
|
29
|
+
# error_handler - Optional Provides a handle_error method to handle exceptions.
|
29
30
|
|
30
31
|
@callback = callback
|
31
32
|
@interval = interval
|
@@ -33,6 +34,7 @@ module Optimizely
|
|
33
34
|
@running = false
|
34
35
|
@thread = nil
|
35
36
|
@logger = logger || NoOpLogger.new
|
37
|
+
@error_handler = error_handler || NoOpErrorHandler.new
|
36
38
|
end
|
37
39
|
|
38
40
|
def start!
|
@@ -54,6 +56,7 @@ module Optimizely
|
|
54
56
|
Logger::ERROR,
|
55
57
|
"Couldn't create a new thread for async scheduler. #{e.message}"
|
56
58
|
)
|
59
|
+
@error_handler.handle_error(e)
|
57
60
|
end
|
58
61
|
end
|
59
62
|
|
@@ -75,11 +78,12 @@ module Optimizely
|
|
75
78
|
loop do
|
76
79
|
begin
|
77
80
|
callback.call
|
78
|
-
rescue
|
81
|
+
rescue StandardError => e
|
79
82
|
@logger.log(
|
80
83
|
Logger::ERROR,
|
81
|
-
|
84
|
+
"Something went wrong when executing passed callback. #{e.message}"
|
82
85
|
)
|
86
|
+
@error_handler.handle_error(e)
|
83
87
|
stop!
|
84
88
|
end
|
85
89
|
break unless @auto_update
|