configcat 1.2.3 → 3.1.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 +18 -18
- data/lib/configcat/autopollingcachepolicy.rb +18 -15
- data/lib/configcat/configcatclient.rb +61 -8
- data/lib/configcat/configfetcher.rb +34 -10
- data/lib/configcat/lazyloadingcachepolicy.rb +11 -8
- data/lib/configcat/manualpollingcachepolicy.rb +10 -7
- data/lib/configcat/rolloutevaluator.rb +31 -15
- data/lib/configcat/user.rb +5 -5
- data/lib/configcat/version.rb +1 -1
- metadata +34 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b842d2ff2f62e6a6c3dbe2ddab53c561e4b1db93f3928ce805044127cd2d7819
|
4
|
+
data.tar.gz: 6d64d084c4a732d26d54879d914f4e9ce1722b9e73fee2aa4161cc5503e152d7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 83a7d19dc642e492bb5443a1fc42f0f35db8f5278f02582848e8677133f4450faa41a1a30b158ccdca58bc5396cad109b914fa4851e4db74dcf03df1f5129d00
|
7
|
+
data.tar.gz: 2e79ed9965f3c9da2f8afd9fed4636b6d349b0bda09fdfb0d8398b6e4334a458713114d23083fc5f611878ea02801c5e8ea1e73fad54f6e580ef1c098e8f9d7c
|
data/lib/configcat.rb
CHANGED
@@ -10,16 +10,16 @@ module ConfigCat
|
|
10
10
|
attr_accessor :logger
|
11
11
|
end
|
12
12
|
|
13
|
-
def ConfigCat.create_client(
|
13
|
+
def ConfigCat.create_client(sdk_key)
|
14
14
|
#
|
15
15
|
# Create an instance of ConfigCatClient and setup Auto Poll mode with default options
|
16
16
|
#
|
17
|
-
# :param
|
17
|
+
# :param sdk_key: ConfigCat SDK Key to access your configuration.
|
18
18
|
#
|
19
|
-
return create_client_with_auto_poll(
|
19
|
+
return create_client_with_auto_poll(sdk_key)
|
20
20
|
end
|
21
21
|
|
22
|
-
def ConfigCat.create_client_with_auto_poll(
|
22
|
+
def ConfigCat.create_client_with_auto_poll(sdk_key,
|
23
23
|
poll_interval_seconds: 60,
|
24
24
|
max_init_wait_time_seconds: 5,
|
25
25
|
on_configuration_changed_callback: nil,
|
@@ -32,7 +32,7 @@ module ConfigCat
|
|
32
32
|
#
|
33
33
|
# Create an instance of ConfigCatClient and setup Auto Poll mode with custom options
|
34
34
|
#
|
35
|
-
# :param
|
35
|
+
# :param sdk_key: ConfigCat SDK Key to access your configuration.
|
36
36
|
# :param poll_interval_seconds: The client's poll interval in seconds. Default: 60 seconds.
|
37
37
|
# :param on_configuration_changed_callback: You can subscribe to configuration changes with this callback
|
38
38
|
# :param max_init_wait_time_seconds: maximum waiting time for first configuration fetch in polling mode.
|
@@ -44,8 +44,8 @@ module ConfigCat
|
|
44
44
|
# :param proxy_user: username for proxy authentication
|
45
45
|
# :param proxy_pass: password for proxy authentication
|
46
46
|
#
|
47
|
-
if
|
48
|
-
raise ConfigCatClientException, "
|
47
|
+
if sdk_key === nil
|
48
|
+
raise ConfigCatClientException, "SDK Key is required."
|
49
49
|
end
|
50
50
|
if poll_interval_seconds < 1
|
51
51
|
poll_interval_seconds = 1
|
@@ -53,7 +53,7 @@ module ConfigCat
|
|
53
53
|
if max_init_wait_time_seconds < 0
|
54
54
|
max_init_wait_time_seconds = 0
|
55
55
|
end
|
56
|
-
return ConfigCatClient.new(
|
56
|
+
return ConfigCatClient.new(sdk_key,
|
57
57
|
poll_interval_seconds: poll_interval_seconds,
|
58
58
|
max_init_wait_time_seconds: max_init_wait_time_seconds,
|
59
59
|
on_configuration_changed_callback: on_configuration_changed_callback,
|
@@ -66,7 +66,7 @@ module ConfigCat
|
|
66
66
|
proxy_pass: proxy_pass)
|
67
67
|
end
|
68
68
|
|
69
|
-
def ConfigCat.create_client_with_lazy_load(
|
69
|
+
def ConfigCat.create_client_with_lazy_load(sdk_key,
|
70
70
|
cache_time_to_live_seconds: 60,
|
71
71
|
config_cache_class: nil,
|
72
72
|
base_url: nil,
|
@@ -77,7 +77,7 @@ module ConfigCat
|
|
77
77
|
#
|
78
78
|
# Create an instance of ConfigCatClient and setup Lazy Load mode with custom options
|
79
79
|
#
|
80
|
-
# :param
|
80
|
+
# :param sdk_key: ConfigCat SDK Key to access your configuration.
|
81
81
|
# :param cache_time_to_live_seconds: The cache TTL.
|
82
82
|
# :param config_cache_class: If you want to use custom caching instead of the client's default InMemoryConfigCache,
|
83
83
|
# You can provide an implementation of ConfigCache.
|
@@ -87,13 +87,13 @@ module ConfigCat
|
|
87
87
|
# :param proxy_user: username for proxy authentication
|
88
88
|
# :param proxy_pass: password for proxy authentication
|
89
89
|
#
|
90
|
-
if
|
91
|
-
raise ConfigCatClientException, "
|
90
|
+
if sdk_key === nil
|
91
|
+
raise ConfigCatClientException, "SDK Key is required."
|
92
92
|
end
|
93
93
|
if cache_time_to_live_seconds < 1
|
94
94
|
cache_time_to_live_seconds = 1
|
95
95
|
end
|
96
|
-
return ConfigCatClient.new(
|
96
|
+
return ConfigCatClient.new(sdk_key,
|
97
97
|
poll_interval_seconds: 0,
|
98
98
|
max_init_wait_time_seconds: 0,
|
99
99
|
on_configuration_changed_callback: nil,
|
@@ -106,7 +106,7 @@ module ConfigCat
|
|
106
106
|
proxy_pass: proxy_pass)
|
107
107
|
end
|
108
108
|
|
109
|
-
def ConfigCat.create_client_with_manual_poll(
|
109
|
+
def ConfigCat.create_client_with_manual_poll(sdk_key,
|
110
110
|
config_cache_class: nil,
|
111
111
|
base_url: nil,
|
112
112
|
proxy_address:nil,
|
@@ -116,7 +116,7 @@ module ConfigCat
|
|
116
116
|
#
|
117
117
|
# Create an instance of ConfigCatClient and setup Manual Poll mode with custom options
|
118
118
|
#
|
119
|
-
# :param
|
119
|
+
# :param sdk_key: ConfigCat SDK Key to access your configuration.
|
120
120
|
# :param config_cache_class: If you want to use custom caching instead of the client's default InMemoryConfigCache,
|
121
121
|
# You can provide an implementation of ConfigCache.
|
122
122
|
# :param base_url: You can set a base_url if you want to use a proxy server between your application and ConfigCat
|
@@ -125,10 +125,10 @@ module ConfigCat
|
|
125
125
|
# :param proxy_user: username for proxy authentication
|
126
126
|
# :param proxy_pass: password for proxy authentication
|
127
127
|
#
|
128
|
-
if
|
129
|
-
raise ConfigCatClientException, "
|
128
|
+
if sdk_key === nil
|
129
|
+
raise ConfigCatClientException, "SDK Key is required."
|
130
130
|
end
|
131
|
-
return ConfigCatClient.new(
|
131
|
+
return ConfigCatClient.new(sdk_key,
|
132
132
|
poll_interval_seconds: 0,
|
133
133
|
max_init_wait_time_seconds: 0,
|
134
134
|
on_configuration_changed_callback: nil,
|
@@ -48,7 +48,7 @@ module ConfigCat
|
|
48
48
|
|
49
49
|
def force_refresh()
|
50
50
|
begin
|
51
|
-
|
51
|
+
configuration_response = @_config_fetcher.get_configuration_json()
|
52
52
|
|
53
53
|
begin
|
54
54
|
@_lock.acquire_read_lock()
|
@@ -57,20 +57,23 @@ module ConfigCat
|
|
57
57
|
@_lock.release_read_lock()
|
58
58
|
end
|
59
59
|
|
60
|
-
if
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
60
|
+
if configuration_response.is_fetched()
|
61
|
+
configuration = configuration_response.json()
|
62
|
+
if configuration != old_configuration
|
63
|
+
begin
|
64
|
+
@_lock.acquire_write_lock()
|
65
|
+
@_config_cache.set(configuration)
|
66
|
+
@_initialized = true
|
67
|
+
ensure
|
68
|
+
@_lock.release_write_lock()
|
69
|
+
end
|
70
|
+
begin
|
71
|
+
if !@_on_configuration_changed_callback.equal?(nil)
|
72
|
+
@_on_configuration_changed_callback.()
|
73
|
+
end
|
74
|
+
rescue Exception => e
|
75
|
+
ConfigCat.logger.error("Exception in on_configuration_changed_callback: #{e.class}:'#{e}'")
|
71
76
|
end
|
72
|
-
rescue Exception => e
|
73
|
-
ConfigCat.logger.error("Exception in on_configuration_changed_callback: #{e.class}:'#{e}'")
|
74
77
|
end
|
75
78
|
end
|
76
79
|
|
@@ -78,7 +81,7 @@ module ConfigCat
|
|
78
81
|
@_initialized = true
|
79
82
|
end
|
80
83
|
rescue Exception => e
|
81
|
-
ConfigCat.logger.error("Double-check your
|
84
|
+
ConfigCat.logger.error("Double-check your SDK Key at https://app.configcat.com/sdkkey.")
|
82
85
|
ConfigCat.logger.error "threw exception #{e.class}:'#{e}'"
|
83
86
|
ConfigCat.logger.error "stacktrace: #{e.backtrace}"
|
84
87
|
end
|
@@ -7,8 +7,9 @@ require 'configcat/lazyloadingcachepolicy'
|
|
7
7
|
require 'configcat/rolloutevaluator'
|
8
8
|
|
9
9
|
module ConfigCat
|
10
|
+
KeyValue = Struct.new(:key, :value)
|
10
11
|
class ConfigCatClient
|
11
|
-
def initialize(
|
12
|
+
def initialize(sdk_key,
|
12
13
|
poll_interval_seconds:60,
|
13
14
|
max_init_wait_time_seconds:5,
|
14
15
|
on_configuration_changed_callback:nil,
|
@@ -19,10 +20,10 @@ module ConfigCat
|
|
19
20
|
proxy_port:nil,
|
20
21
|
proxy_user:nil,
|
21
22
|
proxy_pass:nil)
|
22
|
-
if
|
23
|
-
raise ConfigCatClientException, "
|
23
|
+
if sdk_key === nil
|
24
|
+
raise ConfigCatClientException, "SDK Key is required."
|
24
25
|
end
|
25
|
-
@
|
26
|
+
@_sdk_key = sdk_key
|
26
27
|
|
27
28
|
if config_cache_class
|
28
29
|
@_config_cache = config_cache_class.new()
|
@@ -31,14 +32,14 @@ module ConfigCat
|
|
31
32
|
end
|
32
33
|
|
33
34
|
if poll_interval_seconds > 0
|
34
|
-
@_config_fetcher = CacheControlConfigFetcher.new(
|
35
|
+
@_config_fetcher = CacheControlConfigFetcher.new(sdk_key, "p", base_url, proxy_address, proxy_port, proxy_user, proxy_pass)
|
35
36
|
@_cache_policy = AutoPollingCachePolicy.new(@_config_fetcher, @_config_cache, poll_interval_seconds, max_init_wait_time_seconds, on_configuration_changed_callback)
|
36
37
|
else
|
37
38
|
if cache_time_to_live_seconds > 0
|
38
|
-
@_config_fetcher = CacheControlConfigFetcher.new(
|
39
|
+
@_config_fetcher = CacheControlConfigFetcher.new(sdk_key, "l", base_url, proxy_address, proxy_port, proxy_user, proxy_pass)
|
39
40
|
@_cache_policy = LazyLoadingCachePolicy.new(@_config_fetcher, @_config_cache, cache_time_to_live_seconds)
|
40
41
|
else
|
41
|
-
@_config_fetcher = CacheControlConfigFetcher.new(
|
42
|
+
@_config_fetcher = CacheControlConfigFetcher.new(sdk_key, "m", base_url, proxy_address, proxy_port, proxy_user, proxy_pass)
|
42
43
|
@_cache_policy = ManualPollingCachePolicy.new(@_config_fetcher, @_config_cache)
|
43
44
|
end
|
44
45
|
end
|
@@ -49,7 +50,8 @@ module ConfigCat
|
|
49
50
|
if config === nil
|
50
51
|
return default_value
|
51
52
|
end
|
52
|
-
|
53
|
+
value, variation_id = RolloutEvaluator.evaluate(key, user, default_value, nil, config)
|
54
|
+
return value
|
53
55
|
end
|
54
56
|
|
55
57
|
def get_all_keys()
|
@@ -60,6 +62,57 @@ module ConfigCat
|
|
60
62
|
return config.keys
|
61
63
|
end
|
62
64
|
|
65
|
+
def get_variation_id(key, default_variation_id, user=nil)
|
66
|
+
config = @_cache_policy.get()
|
67
|
+
if config === nil
|
68
|
+
ConfigCat.logger.warn("Evaluating get_variation_id('%s') failed. Cache is empty. "\
|
69
|
+
"Returning default_variation_id in your get_variation_id call: [%s]." %
|
70
|
+
[key, default_variation_id.to_s])
|
71
|
+
return default_variation_id
|
72
|
+
end
|
73
|
+
value, variation_id = RolloutEvaluator.evaluate(key, user, nil, default_variation_id, config)
|
74
|
+
return variation_id
|
75
|
+
end
|
76
|
+
|
77
|
+
def get_all_variation_ids(user: nil)
|
78
|
+
keys = get_all_keys()
|
79
|
+
variation_ids = []
|
80
|
+
for key in keys
|
81
|
+
variation_id = get_variation_id(key, nil, user)
|
82
|
+
if !variation_id.equal?(nil)
|
83
|
+
variation_ids.push(variation_id)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
return variation_ids
|
87
|
+
end
|
88
|
+
|
89
|
+
def get_key_and_value(variation_id)
|
90
|
+
config = @_cache_policy.get()
|
91
|
+
if config === nil
|
92
|
+
ConfigCat.logger.warn("Evaluating get_variation_id('%s') failed. Cache is empty. Returning nil." % variation_id)
|
93
|
+
return nil
|
94
|
+
end
|
95
|
+
for key, value in config
|
96
|
+
if variation_id == value.fetch(RolloutEvaluator::VARIATION_ID, nil)
|
97
|
+
return KeyValue.new(key, value[RolloutEvaluator::VALUE])
|
98
|
+
end
|
99
|
+
|
100
|
+
rollout_rules = value.fetch(RolloutEvaluator::ROLLOUT_RULES, [])
|
101
|
+
for rollout_rule in rollout_rules
|
102
|
+
if variation_id == rollout_rule.fetch(RolloutEvaluator::VARIATION_ID, nil)
|
103
|
+
return KeyValue.new(key, rollout_rule[RolloutEvaluator::VALUE])
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
rollout_percentage_items = value.fetch(RolloutEvaluator::ROLLOUT_PERCENTAGE_ITEMS, [])
|
108
|
+
for rollout_percentage_item in rollout_percentage_items
|
109
|
+
if variation_id == rollout_percentage_item.fetch(RolloutEvaluator::VARIATION_ID, nil)
|
110
|
+
return KeyValue.new(key, rollout_percentage_item[RolloutEvaluator::VALUE])
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
63
116
|
def force_refresh()
|
64
117
|
@_cache_policy.force_refresh()
|
65
118
|
end
|
@@ -7,12 +7,34 @@ 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_v4.json"
|
11
|
+
|
12
|
+
class FetchResponse
|
13
|
+
def initialize(response)
|
14
|
+
@_response = response
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns the json-encoded content of a response, if any
|
18
|
+
def json()
|
19
|
+
return JSON.parse(@_response.body)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Gets whether a new configuration value was fetched or not
|
23
|
+
def is_fetched()
|
24
|
+
code = @_response.code.to_i
|
25
|
+
return 200 <= code && code < 300
|
26
|
+
end
|
27
|
+
|
28
|
+
# Gets whether the fetch resulted a '304 Not Modified' or not
|
29
|
+
def is_not_modified()
|
30
|
+
return @_response.code == "304"
|
31
|
+
end
|
32
|
+
end
|
11
33
|
|
12
34
|
class CacheControlConfigFetcher < ConfigFetcher
|
13
|
-
def initialize(
|
14
|
-
@
|
15
|
-
@_etag =
|
35
|
+
def initialize(sdk_key, mode, base_url=nil, proxy_address=nil, proxy_port=nil, proxy_user=nil, proxy_pass=nil)
|
36
|
+
@_sdk_key = sdk_key
|
37
|
+
@_etag = ""
|
16
38
|
@_headers = {"User-Agent" => ((("ConfigCat-Ruby/") + mode) + ("-")) + VERSION, "X-ConfigCat-UserAgent" => ((("ConfigCat-Ruby/") + mode) + ("-")) + VERSION, "Content-Type" => "application/json"}
|
17
39
|
if !base_url.equal?(nil)
|
18
40
|
@_base_url = base_url.chomp("/")
|
@@ -26,16 +48,18 @@ module ConfigCat
|
|
26
48
|
@_http.read_timeout = 30 # in seconds
|
27
49
|
end
|
28
50
|
|
51
|
+
# Returns the FetchResponse object contains configuration json Dictionary
|
29
52
|
def get_configuration_json()
|
30
53
|
ConfigCat.logger.debug "Fetching configuration from ConfigCat"
|
31
|
-
uri = URI.parse((((@_base_url + ("/")) + BASE_PATH) + @
|
32
|
-
|
33
|
-
|
54
|
+
uri = URI.parse((((@_base_url + ("/")) + BASE_PATH) + @_sdk_key) + BASE_EXTENSION)
|
55
|
+
headers = @_headers
|
56
|
+
headers["If-None-Match"] = @_etag unless @_etag.empty?
|
57
|
+
request = Net::HTTP::Get.new(uri.request_uri, headers)
|
34
58
|
response = @_http.request(request)
|
35
|
-
|
36
|
-
@_etag =
|
59
|
+
etag = response["ETag"]
|
60
|
+
@_etag = etag unless etag.nil? || etag.empty?
|
37
61
|
ConfigCat.logger.debug "ConfigCat configuration json fetch response code:#{response.code} Cached:#{response['ETag']}"
|
38
|
-
return
|
62
|
+
return FetchResponse.new(response)
|
39
63
|
end
|
40
64
|
|
41
65
|
def close()
|
@@ -40,16 +40,19 @@ module ConfigCat
|
|
40
40
|
|
41
41
|
def force_refresh()
|
42
42
|
begin
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
43
|
+
configuration_response = @_config_fetcher.get_configuration_json()
|
44
|
+
if configuration_response.is_fetched()
|
45
|
+
configuration = configuration_response.json()
|
46
|
+
begin
|
47
|
+
@_lock.acquire_write_lock()
|
48
|
+
@_config_cache.set(configuration)
|
49
|
+
@_last_updated = Time.now.utc
|
50
|
+
ensure
|
51
|
+
@_lock.release_write_lock()
|
52
|
+
end
|
50
53
|
end
|
51
54
|
rescue StandardError => e
|
52
|
-
ConfigCat.logger.error("Double-check your
|
55
|
+
ConfigCat.logger.error("Double-check your SDK Key at https://app.configcat.com/sdkkey.")
|
53
56
|
ConfigCat.logger.error "threw exception #{e.class}:'#{e}'"
|
54
57
|
ConfigCat.logger.error "stacktrace: #{e.backtrace}"
|
55
58
|
end
|
@@ -21,15 +21,18 @@ module ConfigCat
|
|
21
21
|
|
22
22
|
def force_refresh()
|
23
23
|
begin
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
24
|
+
configuration_response = @_config_fetcher.get_configuration_json()
|
25
|
+
if configuration_response.is_fetched()
|
26
|
+
configuration = configuration_response.json()
|
27
|
+
begin
|
28
|
+
@_lock.acquire_write_lock()
|
29
|
+
@_config_cache.set(configuration)
|
30
|
+
ensure
|
31
|
+
@_lock.release_write_lock()
|
32
|
+
end
|
30
33
|
end
|
31
34
|
rescue StandardError => e
|
32
|
-
ConfigCat.logger.error("Double-check your
|
35
|
+
ConfigCat.logger.error("Double-check your SDK Key at https://app.configcat.com/sdkkey.")
|
33
36
|
ConfigCat.logger.error "threw exception #{e.class}:'#{e}'"
|
34
37
|
ConfigCat.logger.error "stacktrace: #{e.backtrace}"
|
35
38
|
end
|
@@ -13,14 +13,15 @@ module ConfigCat
|
|
13
13
|
ROLLOUT_PERCENTAGE_ITEMS = "p"
|
14
14
|
PERCENTAGE = "p"
|
15
15
|
ROLLOUT_RULES = "r"
|
16
|
+
VARIATION_ID = "i"
|
16
17
|
|
17
|
-
def self.evaluate(key, user, default_value, config)
|
18
|
+
def self.evaluate(key, user, default_value, default_variation_id, config)
|
18
19
|
ConfigCat.logger.info("Evaluating get_value('%s')." % key)
|
19
20
|
|
20
21
|
setting_descriptor = config.fetch(key, nil)
|
21
22
|
if setting_descriptor === nil
|
22
23
|
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.keys.join(", ")])
|
23
|
-
return default_value
|
24
|
+
return default_value, default_variation_id
|
24
25
|
end
|
25
26
|
|
26
27
|
rollout_rules = setting_descriptor.fetch(ROLLOUT_RULES, [])
|
@@ -35,8 +36,9 @@ module ConfigCat
|
|
35
36
|
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
37
|
end
|
37
38
|
return_value = setting_descriptor.fetch(VALUE, default_value)
|
39
|
+
return_variation_id = setting_descriptor.fetch(VARIATION_ID, default_variation_id)
|
38
40
|
ConfigCat.logger.info("Returning [%s]" % return_value.to_s)
|
39
|
-
return return_value
|
41
|
+
return return_value, return_variation_id
|
40
42
|
end
|
41
43
|
|
42
44
|
ConfigCat.logger.info("User object:\n%s" % user.to_s)
|
@@ -54,30 +56,31 @@ module ConfigCat
|
|
54
56
|
end
|
55
57
|
|
56
58
|
value = rollout_rule.fetch(VALUE, nil)
|
59
|
+
variation_id = rollout_rule.fetch(VARIATION_ID, default_variation_id)
|
57
60
|
|
58
61
|
# IS ONE OF
|
59
62
|
if comparator == 0
|
60
63
|
if comparison_value.to_s.split(",").map { |x| x.strip() }.include?(user_value.to_s)
|
61
64
|
ConfigCat.logger.info(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
|
62
|
-
return value
|
65
|
+
return value, variation_id
|
63
66
|
end
|
64
67
|
# IS NOT ONE OF
|
65
68
|
elsif comparator == 1
|
66
69
|
if !comparison_value.to_s.split(",").map { |x| x.strip() }.include?(user_value.to_s)
|
67
70
|
ConfigCat.logger.info(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
|
68
|
-
return value
|
71
|
+
return value, variation_id
|
69
72
|
end
|
70
73
|
# CONTAINS
|
71
74
|
elsif comparator == 2
|
72
75
|
if user_value.to_s.include?(comparison_value.to_s)
|
73
76
|
ConfigCat.logger.info(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
|
74
|
-
return value
|
77
|
+
return value, variation_id
|
75
78
|
end
|
76
79
|
# DOES NOT CONTAIN
|
77
80
|
elsif comparator == 3
|
78
81
|
if !user_value.to_s.include?(comparison_value.to_s)
|
79
82
|
ConfigCat.logger.info(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
|
80
|
-
return value
|
83
|
+
return value, variation_id
|
81
84
|
end
|
82
85
|
# IS ONE OF, IS NOT ONE OF (Semantic version)
|
83
86
|
elsif (4 <= comparator) && (comparator <= 5)
|
@@ -90,7 +93,7 @@ module ConfigCat
|
|
90
93
|
}
|
91
94
|
if match && comparator == 4 || !match && comparator == 5
|
92
95
|
ConfigCat.logger.info(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
|
93
|
-
return value
|
96
|
+
return value, variation_id
|
94
97
|
end
|
95
98
|
rescue ArgumentError => e
|
96
99
|
ConfigCat.logger.warn(format_validation_error_rule(comparison_attribute, user_value, comparator, comparison_value, e.to_s))
|
@@ -106,7 +109,7 @@ module ConfigCat
|
|
106
109
|
(comparator == 8 && user_value_version > comparison_value_version) ||
|
107
110
|
(comparator == 9 && user_value_version >= comparison_value_version)
|
108
111
|
ConfigCat.logger.info(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
|
109
|
-
return value
|
112
|
+
return value, variation_id
|
110
113
|
end
|
111
114
|
rescue ArgumentError => e
|
112
115
|
ConfigCat.logger.warn(format_validation_error_rule(comparison_attribute, user_value, comparator, comparison_value, e.to_s))
|
@@ -123,14 +126,25 @@ module ConfigCat
|
|
123
126
|
(comparator == 14 && user_value_float > comparison_value_float) ||
|
124
127
|
(comparator == 15 && user_value_float >= comparison_value_float)
|
125
128
|
ConfigCat.logger.info(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
|
126
|
-
return value
|
129
|
+
return value, variation_id
|
127
130
|
end
|
128
131
|
rescue Exception => e
|
129
132
|
ConfigCat.logger.warn(format_validation_error_rule(comparison_attribute, user_value, comparator, comparison_value, e.to_s))
|
130
133
|
next
|
131
134
|
end
|
135
|
+
# IS ONE OF (Sensitive)
|
136
|
+
elsif comparator == 16
|
137
|
+
if comparison_value.to_s.split(",").map { |x| x.strip() }.include?(Digest::SHA1.hexdigest(user_value).to_s)
|
138
|
+
ConfigCat.logger.info(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
|
139
|
+
return value, variation_id
|
140
|
+
end
|
141
|
+
# IS NOT ONE OF (Sensitive)
|
142
|
+
elsif comparator == 17
|
143
|
+
if !comparison_value.to_s.split(",").map { |x| x.strip() }.include?(Digest::SHA1.hexdigest(user_value).to_s)
|
144
|
+
ConfigCat.logger.info(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
|
145
|
+
return value, variation_id
|
146
|
+
end
|
132
147
|
end
|
133
|
-
|
134
148
|
ConfigCat.logger.info(format_no_match_rule(comparison_attribute, user_value, comparator, comparison_value))
|
135
149
|
end
|
136
150
|
|
@@ -143,14 +157,16 @@ module ConfigCat
|
|
143
157
|
bucket += rollout_percentage_item.fetch(PERCENTAGE, 0)
|
144
158
|
if hash_val < bucket
|
145
159
|
percentage_value = rollout_percentage_item.fetch(VALUE, nil)
|
160
|
+
variation_id = rollout_percentage_item.fetch(VARIATION_ID, default_variation_id)
|
146
161
|
ConfigCat.logger.info("Evaluating %% options. Returning %s" % percentage_value)
|
147
|
-
return percentage_value
|
162
|
+
return percentage_value, variation_id
|
148
163
|
end
|
149
164
|
end
|
150
165
|
end
|
151
|
-
|
152
|
-
|
153
|
-
|
166
|
+
return_value = setting_descriptor.fetch(VALUE, default_value)
|
167
|
+
return_variation_id = setting_descriptor.fetch(VARIATION_ID, default_variation_id)
|
168
|
+
ConfigCat.logger.info("Returning %s" % return_value)
|
169
|
+
return return_value, return_variation_id
|
154
170
|
end
|
155
171
|
|
156
172
|
private
|
data/lib/configcat/user.rb
CHANGED
@@ -5,11 +5,11 @@ module ConfigCat
|
|
5
5
|
# The user object for variation evaluation
|
6
6
|
#
|
7
7
|
|
8
|
-
PREDEFINED = ["
|
8
|
+
PREDEFINED = ["Identifier", "Email", "Country"]
|
9
9
|
|
10
10
|
def initialize(identifier, email: nil, country: nil, custom: nil)
|
11
|
-
@__identifier = identifier
|
12
|
-
@__data = {"
|
11
|
+
@__identifier = (!identifier.equal?(nil)) ? identifier : ""
|
12
|
+
@__data = {"Identifier" => identifier, "Email" => email, "Country" => country}
|
13
13
|
@__custom = custom
|
14
14
|
end
|
15
15
|
|
@@ -18,14 +18,14 @@ module ConfigCat
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def get_attribute(attribute)
|
21
|
-
attribute = attribute.to_s
|
21
|
+
attribute = attribute.to_s
|
22
22
|
if PREDEFINED.include?(attribute)
|
23
23
|
return @__data[attribute]
|
24
24
|
end
|
25
25
|
|
26
26
|
if !@__custom.equal?(nil)
|
27
27
|
@__custom.each do |customField, customValue|
|
28
|
-
if customField.to_s
|
28
|
+
if customField.to_s == attribute
|
29
29
|
return customValue
|
30
30
|
end
|
31
31
|
end
|
data/lib/configcat/version.rb
CHANGED
metadata
CHANGED
@@ -1,43 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: configcat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ConfigCat
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-09-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '1.1'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '1.1'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: semantic
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '1.6'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '1.6'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -56,30 +56,44 @@ dependencies:
|
|
56
56
|
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '12.3'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '12.3'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: coveralls
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0.8'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0.8'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: webmock
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
74
88
|
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
89
|
+
version: '3.0'
|
76
90
|
type: :development
|
77
91
|
prerelease: false
|
78
92
|
version_requirements: !ruby/object:Gem::Requirement
|
79
93
|
requirements:
|
80
|
-
- - "
|
94
|
+
- - "~>"
|
81
95
|
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
96
|
+
version: '3.0'
|
83
97
|
description: Feature Flags created by developers for developers with ❤️. ConfigCat
|
84
98
|
lets you manage feature flags across frontend, backend, mobile, and desktop apps
|
85
99
|
without (re)deploying code. % rollouts, user targeting, segmentation. Feature toggle
|
@@ -112,7 +126,7 @@ require_paths:
|
|
112
126
|
- lib
|
113
127
|
required_ruby_version: !ruby/object:Gem::Requirement
|
114
128
|
requirements:
|
115
|
-
- - "
|
129
|
+
- - ">="
|
116
130
|
- !ruby/object:Gem::Version
|
117
131
|
version: '2.2'
|
118
132
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
@@ -121,8 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
121
135
|
- !ruby/object:Gem::Version
|
122
136
|
version: '0'
|
123
137
|
requirements: []
|
124
|
-
|
125
|
-
rubygems_version: 2.7.7
|
138
|
+
rubygems_version: 3.0.8
|
126
139
|
signing_key:
|
127
140
|
specification_version: 4
|
128
141
|
summary: ConfigCat SDK for Ruby.
|