configcat 1.0.1 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/configcat.rb +53 -7
- data/lib/configcat/autopollingcachepolicy.rb +25 -17
- data/lib/configcat/configcatclient.rb +8 -4
- data/lib/configcat/configfetcher.rb +3 -3
- data/lib/configcat/lazyloadingcachepolicy.rb +1 -0
- data/lib/configcat/manualpollingcachepolicy.rb +1 -0
- data/lib/configcat/rolloutevaluator.rb +130 -29
- data/lib/configcat/version.rb +1 -1
- metadata +30 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dada53197ffe2d00bf8f4349bd643312f65d72b970e4de9bb774a490bf2f12c4
|
4
|
+
data.tar.gz: 0e656c1c42d3def92aa47013f8c22a555f0268b2dff5b8df37b79a0ac3952425
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ace75c4e4f36cfb62447beca19786287026fa8be4409506fa54b58a693f4b996a9526acad14b9552012377a6c5e75b5fcd0073118e7cd2af403b1585eecc6e07
|
7
|
+
data.tar.gz: bd98ab5c116d6a4daf2d1f07a214e585bcc630d9f81b268febe9b0fead8f4fdc1cb86e7af4042f5d568c46e8692d8599db2f4e9b83a74fbec80312612c091c46
|
data/lib/configcat.rb
CHANGED
@@ -5,7 +5,7 @@ require 'logger'
|
|
5
5
|
|
6
6
|
module ConfigCat
|
7
7
|
|
8
|
-
@logger = Logger.new(STDOUT, level: Logger::
|
8
|
+
@logger = Logger.new(STDOUT, level: Logger::WARN)
|
9
9
|
class << self
|
10
10
|
attr_accessor :logger
|
11
11
|
end
|
@@ -19,7 +19,16 @@ module ConfigCat
|
|
19
19
|
return create_client_with_auto_poll(api_key)
|
20
20
|
end
|
21
21
|
|
22
|
-
def ConfigCat.create_client_with_auto_poll(api_key,
|
22
|
+
def ConfigCat.create_client_with_auto_poll(api_key,
|
23
|
+
poll_interval_seconds: 60,
|
24
|
+
max_init_wait_time_seconds: 5,
|
25
|
+
on_configuration_changed_callback: nil,
|
26
|
+
config_cache_class: nil,
|
27
|
+
base_url: nil,
|
28
|
+
proxy_address:nil,
|
29
|
+
proxy_port:nil,
|
30
|
+
proxy_user:nil,
|
31
|
+
proxy_pass:nil)
|
23
32
|
#
|
24
33
|
# Create an instance of ConfigCatClient and setup Auto Poll mode with custom options
|
25
34
|
#
|
@@ -30,6 +39,10 @@ module ConfigCat
|
|
30
39
|
# :param config_cache_class: If you want to use custom caching instead of the client's default InMemoryConfigCache,
|
31
40
|
# You can provide an implementation of ConfigCache.
|
32
41
|
# :param base_url: You can set a base_url if you want to use a proxy server between your application and ConfigCat
|
42
|
+
# :param proxy_address: Proxy address
|
43
|
+
# :param proxy_port: Proxy port
|
44
|
+
# :param proxy_user: username for proxy authentication
|
45
|
+
# :param proxy_pass: password for proxy authentication
|
33
46
|
#
|
34
47
|
if api_key === nil
|
35
48
|
raise ConfigCatClientException, "API Key is required."
|
@@ -46,10 +59,21 @@ module ConfigCat
|
|
46
59
|
on_configuration_changed_callback: on_configuration_changed_callback,
|
47
60
|
cache_time_to_live_seconds: 0,
|
48
61
|
config_cache_class: config_cache_class,
|
49
|
-
base_url: base_url
|
62
|
+
base_url: base_url,
|
63
|
+
proxy_address: proxy_address,
|
64
|
+
proxy_port: proxy_port,
|
65
|
+
proxy_user: proxy_user,
|
66
|
+
proxy_pass: proxy_pass)
|
50
67
|
end
|
51
68
|
|
52
|
-
def ConfigCat.create_client_with_lazy_load(api_key,
|
69
|
+
def ConfigCat.create_client_with_lazy_load(api_key,
|
70
|
+
cache_time_to_live_seconds: 60,
|
71
|
+
config_cache_class: nil,
|
72
|
+
base_url: nil,
|
73
|
+
proxy_address:nil,
|
74
|
+
proxy_port:nil,
|
75
|
+
proxy_user:nil,
|
76
|
+
proxy_pass:nil)
|
53
77
|
#
|
54
78
|
# Create an instance of ConfigCatClient and setup Lazy Load mode with custom options
|
55
79
|
#
|
@@ -58,6 +82,10 @@ module ConfigCat
|
|
58
82
|
# :param config_cache_class: If you want to use custom caching instead of the client's default InMemoryConfigCache,
|
59
83
|
# You can provide an implementation of ConfigCache.
|
60
84
|
# :param base_url: You can set a base_url if you want to use a proxy server between your application and ConfigCat
|
85
|
+
# :param proxy_address: Proxy address
|
86
|
+
# :param proxy_port: Proxy port
|
87
|
+
# :param proxy_user: username for proxy authentication
|
88
|
+
# :param proxy_pass: password for proxy authentication
|
61
89
|
#
|
62
90
|
if api_key === nil
|
63
91
|
raise ConfigCatClientException, "API Key is required."
|
@@ -71,10 +99,20 @@ module ConfigCat
|
|
71
99
|
on_configuration_changed_callback: nil,
|
72
100
|
cache_time_to_live_seconds: cache_time_to_live_seconds,
|
73
101
|
config_cache_class: config_cache_class,
|
74
|
-
base_url: base_url
|
102
|
+
base_url: base_url,
|
103
|
+
proxy_address: proxy_address,
|
104
|
+
proxy_port: proxy_port,
|
105
|
+
proxy_user: proxy_user,
|
106
|
+
proxy_pass: proxy_pass)
|
75
107
|
end
|
76
108
|
|
77
|
-
def ConfigCat.create_client_with_manual_poll(api_key,
|
109
|
+
def ConfigCat.create_client_with_manual_poll(api_key,
|
110
|
+
config_cache_class: nil,
|
111
|
+
base_url: nil,
|
112
|
+
proxy_address:nil,
|
113
|
+
proxy_port:nil,
|
114
|
+
proxy_user:nil,
|
115
|
+
proxy_pass:nil)
|
78
116
|
#
|
79
117
|
# Create an instance of ConfigCatClient and setup Manual Poll mode with custom options
|
80
118
|
#
|
@@ -82,6 +120,10 @@ module ConfigCat
|
|
82
120
|
# :param config_cache_class: If you want to use custom caching instead of the client's default InMemoryConfigCache,
|
83
121
|
# You can provide an implementation of ConfigCache.
|
84
122
|
# :param base_url: You can set a base_url if you want to use a proxy server between your application and ConfigCat
|
123
|
+
# :param proxy_address: Proxy address
|
124
|
+
# :param proxy_port: Proxy port
|
125
|
+
# :param proxy_user: username for proxy authentication
|
126
|
+
# :param proxy_pass: password for proxy authentication
|
85
127
|
#
|
86
128
|
if api_key === nil
|
87
129
|
raise ConfigCatClientException, "API Key is required."
|
@@ -92,7 +134,11 @@ module ConfigCat
|
|
92
134
|
on_configuration_changed_callback: nil,
|
93
135
|
cache_time_to_live_seconds: 0,
|
94
136
|
config_cache_class: config_cache_class,
|
95
|
-
base_url: base_url
|
137
|
+
base_url: base_url,
|
138
|
+
proxy_address: proxy_address,
|
139
|
+
proxy_port: proxy_port,
|
140
|
+
proxy_user: proxy_user,
|
141
|
+
proxy_pass: proxy_pass)
|
96
142
|
end
|
97
143
|
|
98
144
|
end
|
@@ -47,30 +47,38 @@ module ConfigCat
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def force_refresh()
|
50
|
-
begin
|
51
|
-
@_lock.acquire_read_lock()
|
52
|
-
old_configuration = @_config_cache.get()
|
53
|
-
ensure
|
54
|
-
@_lock.release_read_lock()
|
55
|
-
end
|
56
50
|
begin
|
57
51
|
configuration = @_config_fetcher.get_configuration_json()
|
52
|
+
|
58
53
|
begin
|
59
|
-
@_lock.
|
60
|
-
@_config_cache.
|
61
|
-
@_initialized = true
|
54
|
+
@_lock.acquire_read_lock()
|
55
|
+
old_configuration = @_config_cache.get()
|
62
56
|
ensure
|
63
|
-
@_lock.
|
57
|
+
@_lock.release_read_lock()
|
64
58
|
end
|
65
|
-
|
66
|
-
|
67
|
-
|
59
|
+
|
60
|
+
if configuration != old_configuration
|
61
|
+
begin
|
62
|
+
@_lock.acquire_write_lock()
|
63
|
+
@_config_cache.set(configuration)
|
64
|
+
@_initialized = true
|
65
|
+
ensure
|
66
|
+
@_lock.release_write_lock()
|
67
|
+
end
|
68
|
+
begin
|
69
|
+
if !@_on_configuration_changed_callback.equal?(nil)
|
70
|
+
@_on_configuration_changed_callback.()
|
71
|
+
end
|
72
|
+
rescue Exception => e
|
73
|
+
ConfigCat.logger.error("Exception in on_configuration_changed_callback: #{e.class}:'#{e}'")
|
68
74
|
end
|
69
|
-
rescue Exception => e
|
70
|
-
ConfigCat.logger.error "threw exception #{e.class}:'#{e}'"
|
71
|
-
ConfigCat.logger.error "stacktrace: #{e.backtrace}"
|
72
75
|
end
|
73
|
-
|
76
|
+
|
77
|
+
if !@_initialized && !old_configuration.equal?(nil)
|
78
|
+
@_initialized = true
|
79
|
+
end
|
80
|
+
rescue Exception => e
|
81
|
+
ConfigCat.logger.error("Double-check your API KEY at https://app.configcat.com/apikey.")
|
74
82
|
ConfigCat.logger.error "threw exception #{e.class}:'#{e}'"
|
75
83
|
ConfigCat.logger.error "stacktrace: #{e.backtrace}"
|
76
84
|
end
|
@@ -14,7 +14,11 @@ module ConfigCat
|
|
14
14
|
on_configuration_changed_callback:nil,
|
15
15
|
cache_time_to_live_seconds:60,
|
16
16
|
config_cache_class:nil,
|
17
|
-
base_url:nil
|
17
|
+
base_url:nil,
|
18
|
+
proxy_address:nil,
|
19
|
+
proxy_port:nil,
|
20
|
+
proxy_user:nil,
|
21
|
+
proxy_pass:nil)
|
18
22
|
if api_key === nil
|
19
23
|
raise ConfigCatClientException, "API Key is required."
|
20
24
|
end
|
@@ -27,14 +31,14 @@ module ConfigCat
|
|
27
31
|
end
|
28
32
|
|
29
33
|
if poll_interval_seconds > 0
|
30
|
-
@_config_fetcher = CacheControlConfigFetcher.new(api_key, "p", base_url)
|
34
|
+
@_config_fetcher = CacheControlConfigFetcher.new(api_key, "p", base_url, proxy_address, proxy_port, proxy_user, proxy_pass)
|
31
35
|
@_cache_policy = AutoPollingCachePolicy.new(@_config_fetcher, @_config_cache, poll_interval_seconds, max_init_wait_time_seconds, on_configuration_changed_callback)
|
32
36
|
else
|
33
37
|
if cache_time_to_live_seconds > 0
|
34
|
-
@_config_fetcher = CacheControlConfigFetcher.new(api_key, "l", base_url)
|
38
|
+
@_config_fetcher = CacheControlConfigFetcher.new(api_key, "l", base_url, proxy_address, proxy_port, proxy_user, proxy_pass)
|
35
39
|
@_cache_policy = LazyLoadingCachePolicy.new(@_config_fetcher, @_config_cache, cache_time_to_live_seconds)
|
36
40
|
else
|
37
|
-
@_config_fetcher = CacheControlConfigFetcher.new(api_key, "m", base_url)
|
41
|
+
@_config_fetcher = CacheControlConfigFetcher.new(api_key, "m", base_url, proxy_address, proxy_port, proxy_user, proxy_pass)
|
38
42
|
@_cache_policy = ManualPollingCachePolicy.new(@_config_fetcher, @_config_cache)
|
39
43
|
end
|
40
44
|
end
|
@@ -7,10 +7,10 @@ require 'json'
|
|
7
7
|
module ConfigCat
|
8
8
|
BASE_URL = "https://cdn.configcat.com"
|
9
9
|
BASE_PATH = "configuration-files/"
|
10
|
-
BASE_EXTENSION = "/
|
10
|
+
BASE_EXTENSION = "/config_v3.json"
|
11
11
|
|
12
12
|
class CacheControlConfigFetcher < ConfigFetcher
|
13
|
-
def initialize(api_key, mode, base_url=nil)
|
13
|
+
def initialize(api_key, mode, base_url=nil, proxy_address=nil, proxy_port=nil, proxy_user=nil, proxy_pass=nil)
|
14
14
|
@_api_key = api_key
|
15
15
|
@_etag = nil
|
16
16
|
@_headers = {"User-Agent" => ((("ConfigCat-Ruby/") + mode) + ("-")) + VERSION, "X-ConfigCat-UserAgent" => ((("ConfigCat-Ruby/") + mode) + ("-")) + VERSION, "Content-Type" => "application/json"}
|
@@ -20,7 +20,7 @@ module ConfigCat
|
|
20
20
|
@_base_url = BASE_URL
|
21
21
|
end
|
22
22
|
uri = URI.parse(@_base_url)
|
23
|
-
@_http = Net::HTTP.new(uri.host, uri.port)
|
23
|
+
@_http = Net::HTTP.new(uri.host, uri.port, proxy_address, proxy_port, proxy_user, proxy_pass)
|
24
24
|
@_http.use_ssl = true if uri.scheme == 'https'
|
25
25
|
@_http.open_timeout = 10 # in seconds
|
26
26
|
@_http.read_timeout = 30 # in seconds
|
@@ -49,6 +49,7 @@ module ConfigCat
|
|
49
49
|
@_lock.release_write_lock()
|
50
50
|
end
|
51
51
|
rescue StandardError => e
|
52
|
+
ConfigCat.logger.error("Double-check your API KEY at https://app.configcat.com/apikey.")
|
52
53
|
ConfigCat.logger.error "threw exception #{e.class}:'#{e}'"
|
53
54
|
ConfigCat.logger.error "stacktrace: #{e.backtrace}"
|
54
55
|
end
|
@@ -29,6 +29,7 @@ module ConfigCat
|
|
29
29
|
@_lock.release_write_lock()
|
30
30
|
end
|
31
31
|
rescue StandardError => e
|
32
|
+
ConfigCat.logger.error("Double-check your API KEY at https://app.configcat.com/apikey.")
|
32
33
|
ConfigCat.logger.error "threw exception #{e.class}:'#{e}'"
|
33
34
|
ConfigCat.logger.error "stacktrace: #{e.backtrace}"
|
34
35
|
end
|
@@ -1,71 +1,172 @@
|
|
1
1
|
require 'configcat/user'
|
2
2
|
require 'digest'
|
3
|
+
require 'semantic'
|
3
4
|
|
4
5
|
module ConfigCat
|
5
6
|
class RolloutEvaluator
|
7
|
+
COMPARATOR_TEXTS = ["IS ONE OF", "IS NOT ONE OF", "CONTAINS", "DOES NOT CONTAIN", "IS ONE OF (SemVer)", "IS NOT ONE OF (SemVer)", "< (SemVer)", "<= (SemVer)", "> (SemVer)", ">= (SemVer)", "= (Number)", "<> (Number)", "< (Number)", "<= (Number)", "> (Number)", ">= (Number)"]
|
8
|
+
|
9
|
+
VALUE = "v"
|
10
|
+
COMPARATOR = "t"
|
11
|
+
COMPARISON_ATTRIBUTE = "a"
|
12
|
+
COMPARISON_VALUE = "c"
|
13
|
+
ROLLOUT_PERCENTAGE_ITEMS = "p"
|
14
|
+
PERCENTAGE = "p"
|
15
|
+
ROLLOUT_RULES = "r"
|
6
16
|
|
7
17
|
def self.evaluate(key, user, default_value, config)
|
8
|
-
|
9
|
-
|
10
|
-
user = nil
|
11
|
-
end
|
18
|
+
ConfigCat.logger.info("Evaluating get_value('%s')." % key)
|
19
|
+
|
12
20
|
setting_descriptor = config.fetch(key, nil)
|
13
21
|
if setting_descriptor === nil
|
14
|
-
ConfigCat.logger.
|
22
|
+
ConfigCat.logger.error("Evaluating get_value('%s') failed. Value not found for key '%s' Returning default_value: [%s]. Here are the available keys: %s" % [key, key, default_value.to_s, config.to_a.join(", ")])
|
15
23
|
return default_value
|
16
24
|
end
|
25
|
+
|
26
|
+
rollout_rules = setting_descriptor.fetch(ROLLOUT_RULES, [])
|
27
|
+
rollout_percentage_items = setting_descriptor.fetch(ROLLOUT_PERCENTAGE_ITEMS, [])
|
28
|
+
|
29
|
+
if !user.equal?(nil) && !user.class.equal?(User)
|
30
|
+
ConfigCat.logger.warn("Evaluating get_value('%s'). User Object is not an instance of User type." % key)
|
31
|
+
user = nil
|
32
|
+
end
|
17
33
|
if user === nil
|
18
|
-
|
34
|
+
if rollout_rules.size > 0 || rollout_percentage_items.size > 0
|
35
|
+
ConfigCat.logger.warn("Evaluating get_value('%s'). UserObject missing! You should pass a UserObject to get_value(), in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/" % key)
|
36
|
+
end
|
37
|
+
return_value = setting_descriptor.fetch(VALUE, default_value)
|
38
|
+
ConfigCat.logger.info("Returning [%s]" % return_value.to_s)
|
39
|
+
return return_value
|
19
40
|
end
|
20
|
-
|
41
|
+
|
42
|
+
ConfigCat.logger.info("User object:\n%s" % user.to_s)
|
43
|
+
|
44
|
+
# Evaluate targeting rules
|
21
45
|
for rollout_rule in rollout_rules
|
22
|
-
comparison_attribute = rollout_rule.fetch(
|
46
|
+
comparison_attribute = rollout_rule.fetch(COMPARISON_ATTRIBUTE)
|
47
|
+
comparison_value = rollout_rule.fetch(COMPARISON_VALUE, nil)
|
48
|
+
comparator = rollout_rule.fetch(COMPARATOR, nil)
|
49
|
+
|
23
50
|
user_value = user.get_attribute(comparison_attribute)
|
24
51
|
if user_value === nil || !user_value
|
52
|
+
ConfigCat.logger.info(format_no_match_rule(comparison_attribute, comparator, comparison_value))
|
25
53
|
next
|
26
54
|
end
|
27
|
-
|
28
|
-
|
29
|
-
|
55
|
+
|
56
|
+
value = rollout_rule.fetch(VALUE, nil)
|
57
|
+
|
58
|
+
# IS ONE OF
|
30
59
|
if comparator == 0
|
31
60
|
if comparison_value.to_s.split(",").map { |x| x.strip() }.include?(user_value.to_s)
|
61
|
+
ConfigCat.logger.info(format_match_rule(comparison_attribute, comparator, comparison_value, value))
|
62
|
+
return value
|
63
|
+
end
|
64
|
+
# IS NOT ONE OF
|
65
|
+
elsif comparator == 1
|
66
|
+
if !comparison_value.to_s.split(",").map { |x| x.strip() }.include?(user_value.to_s)
|
67
|
+
ConfigCat.logger.info(format_match_rule(comparison_attribute, comparator, comparison_value, value))
|
32
68
|
return value
|
33
69
|
end
|
34
|
-
|
35
|
-
|
36
|
-
|
70
|
+
# CONTAINS
|
71
|
+
elsif comparator == 2
|
72
|
+
if user_value.to_s.include?(comparison_value.to_s)
|
73
|
+
ConfigCat.logger.info(format_match_rule(comparison_attribute, comparator, comparison_value, value))
|
74
|
+
return value
|
75
|
+
end
|
76
|
+
# DOES NOT CONTAIN
|
77
|
+
elsif comparator == 3
|
78
|
+
if !user_value.to_s.include?(comparison_value.to_s)
|
79
|
+
ConfigCat.logger.info(format_match_rule(comparison_attribute, comparator, comparison_value, value))
|
80
|
+
return value
|
81
|
+
end
|
82
|
+
# IS ONE OF, IS NOT ONE OF (Semantic version)
|
83
|
+
elsif (4 <= comparator) && (comparator <= 5)
|
84
|
+
begin
|
85
|
+
match = false
|
86
|
+
user_value_version = Semantic::Version.new(user_value.to_s.strip())
|
87
|
+
((comparison_value.to_s.split(",").map { |x| x.strip() }).reject { |c| c.empty? }).each { |x|
|
88
|
+
version = Semantic::Version.new(x)
|
89
|
+
match = (user_value_version == version) || match
|
90
|
+
}
|
91
|
+
if match && comparator == 4 || !match && comparator == 5
|
92
|
+
ConfigCat.logger.info(format_match_rule(comparison_attribute, comparator, comparison_value, value))
|
37
93
|
return value
|
38
94
|
end
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
95
|
+
rescue ArgumentError => e
|
96
|
+
ConfigCat.logger.warn(format_validation_error_rule(comparison_attribute, comparator, comparison_value, e.to_s))
|
97
|
+
next
|
98
|
+
end
|
99
|
+
# LESS THAN, LESS THAN OR EQUALS TO, GREATER THAN, GREATER THAN OR EQUALS TO (Semantic version)
|
100
|
+
elsif (6 <= comparator) && (comparator <= 9)
|
101
|
+
begin
|
102
|
+
user_value_version = Semantic::Version.new(user_value.to_s.strip())
|
103
|
+
comparison_value_version = Semantic::Version.new(comparison_value.to_s.strip())
|
104
|
+
if (comparator == 6 && user_value_version < comparison_value_version) ||
|
105
|
+
(comparator == 7 && user_value_version <= comparison_value_version) ||
|
106
|
+
(comparator == 8 && user_value_version > comparison_value_version) ||
|
107
|
+
(comparator == 9 && user_value_version >= comparison_value_version)
|
108
|
+
ConfigCat.logger.info(format_match_rule(comparison_attribute, comparator, comparison_value, value))
|
109
|
+
return value
|
50
110
|
end
|
111
|
+
rescue ArgumentError => e
|
112
|
+
ConfigCat.logger.warn(format_validation_error_rule(comparison_attribute, comparator, comparison_value, e.to_s))
|
113
|
+
next
|
114
|
+
end
|
115
|
+
elsif (10 <= comparator) && (comparator <= 15)
|
116
|
+
begin
|
117
|
+
user_value_float = Float(user_value.to_s.gsub(",", "."))
|
118
|
+
comparison_value_float = Float(comparison_value.to_s.gsub(",", "."))
|
119
|
+
if (comparator == 10 && user_value_float == comparison_value_float) ||
|
120
|
+
(comparator == 11 && user_value_float != comparison_value_float) ||
|
121
|
+
(comparator == 12 && user_value_float < comparison_value_float) ||
|
122
|
+
(comparator == 13 && user_value_float <= comparison_value_float) ||
|
123
|
+
(comparator == 14 && user_value_float > comparison_value_float) ||
|
124
|
+
(comparator == 15 && user_value_float >= comparison_value_float)
|
125
|
+
ConfigCat.logger.info(format_match_rule(comparison_attribute, comparator, comparison_value, value))
|
126
|
+
return value
|
127
|
+
end
|
128
|
+
rescue Exception => e
|
129
|
+
ConfigCat.logger.warn(format_validation_error_rule(comparison_attribute, comparator, comparison_value, e.to_s))
|
130
|
+
next
|
51
131
|
end
|
52
132
|
end
|
133
|
+
|
134
|
+
ConfigCat.logger.info(format_no_match_rule(comparison_attribute, comparator, comparison_value))
|
53
135
|
end
|
54
|
-
|
136
|
+
|
55
137
|
if rollout_percentage_items.size > 0
|
56
138
|
user_key = user.get_identifier()
|
57
139
|
hash_candidate = ("%s%s" % [key, user_key]).encode("utf-8")
|
58
140
|
hash_val = Digest::SHA1.hexdigest(hash_candidate)[0...7].to_i(base=16) % 100
|
59
141
|
bucket = 0
|
60
142
|
for rollout_percentage_item in rollout_percentage_items || []
|
61
|
-
bucket += rollout_percentage_item.fetch(
|
143
|
+
bucket += rollout_percentage_item.fetch(PERCENTAGE, 0)
|
62
144
|
if hash_val < bucket
|
63
|
-
|
145
|
+
percentage_value = rollout_percentage_item.fetch(VALUE, nil)
|
146
|
+
ConfigCat.logger.info("Evaluating %% options. Returning %s" % percentage_value)
|
147
|
+
return percentage_value
|
64
148
|
end
|
65
149
|
end
|
66
150
|
end
|
67
|
-
|
151
|
+
def_value = setting_descriptor.fetch(VALUE, default_value)
|
152
|
+
ConfigCat.logger.info("Returning %s" % def_value)
|
153
|
+
return def_value
|
68
154
|
end
|
155
|
+
|
156
|
+
private
|
157
|
+
|
158
|
+
def self.format_match_rule(comparison_attribute, comparator, comparison_value, value)
|
159
|
+
return "Evaluating rule: [%s] [%s] [%s] => match, returning: %s" % [comparison_attribute, COMPARATOR_TEXTS[comparator], comparison_value, value]
|
160
|
+
end
|
161
|
+
|
162
|
+
def self.format_no_match_rule(comparison_attribute, comparator, comparison_value)
|
163
|
+
return "Evaluating rule: [%s] [%s] [%s] => no match" % [comparison_attribute, COMPARATOR_TEXTS[comparator], comparison_value]
|
164
|
+
end
|
165
|
+
|
166
|
+
def self.format_validation_error_rule(comparison_attribute, comparator, comparison_value, error)
|
167
|
+
return "Evaluating rule: [%s] [%s] [%s] => SKIP rule. Validation error: %s" % [comparison_attribute, COMPARATOR_TEXTS[comparator], comparison_value, error]
|
168
|
+
end
|
169
|
+
|
69
170
|
end
|
70
171
|
|
71
172
|
end
|
data/lib/configcat/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: configcat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ConfigCat
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-11-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: semantic
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: rspec
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,6 +66,20 @@ dependencies:
|
|
52
66
|
- - ">="
|
53
67
|
- !ruby/object:Gem::Version
|
54
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: coveralls
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
55
83
|
description: ConfigCat is a configuration as a service that lets you manage your features
|
56
84
|
and configurations without actually deploying new code.
|
57
85
|
email:
|