configcat 1.0.1 → 1.2.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 +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:
|