configcat 6.0.0 → 7.0.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/configcatclient.rb +26 -65
- data/lib/configcat/configcatlogger.rb +7 -7
- data/lib/configcat/configentry.rb +34 -21
- data/lib/configcat/configfetcher.rb +12 -11
- data/lib/configcat/configservice.rb +24 -14
- data/lib/configcat/constants.rb +1 -0
- data/lib/configcat/localfiledatasource.rb +3 -3
- data/lib/configcat/rolloutevaluator.rb +16 -11
- data/lib/configcat/version.rb +1 -1
- data/lib/configcat.rb +0 -160
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e0dc6578b7a148dda7c630d560098fb295eb139f237362db056b235d0feaa7e
|
4
|
+
data.tar.gz: e9f97b6d5f0af6fa72288bfeac3b13c6354bb1726af129349653b9365a10e665
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a895b147c9238dbeb7e2f02d5021002032b47e023214842fb4528bdfabdf5c6c729bc746ff630f1f5cfb325442ba70ae71e7e3ee2257b3d81cfc8cf60ad06dee
|
7
|
+
data.tar.gz: 95d70831f41b93bcfa3306e9af41de05eb27ce80df4b734c0f1a6f7f98f83da468ed8abacbd4b252c105cd807bd21859b2cd4f19699b5a426c689bf6b15eedd7
|
@@ -28,8 +28,9 @@ module ConfigCat
|
|
28
28
|
client = @@instances[sdk_key]
|
29
29
|
if client
|
30
30
|
if options
|
31
|
-
client.log.warn("
|
32
|
-
|
31
|
+
client.log.warn(3000, "There is an existing client instance for the specified SDK Key. " \
|
32
|
+
"No new client instance will be created and the specified options are ignored. " \
|
33
|
+
"Returning the existing client instance. SDK Key: '#{sdk_key}'.")
|
33
34
|
end
|
34
35
|
return client
|
35
36
|
end
|
@@ -105,9 +106,8 @@ module ConfigCat
|
|
105
106
|
def get_value(key, default_value, user = nil)
|
106
107
|
settings, fetch_time = _get_settings()
|
107
108
|
if settings.nil?
|
108
|
-
message = "
|
109
|
-
|
110
|
-
@log.error(message)
|
109
|
+
message = "Config JSON is not present when evaluating setting '#{key}'. Returning the `default_value` parameter that you specified in your application: '#{default_value}'."
|
110
|
+
@log.error(1000, message)
|
111
111
|
@hooks.invoke_on_flag_evaluated(EvaluationDetails.from_error(key, default_value, error: message))
|
112
112
|
return default_value
|
113
113
|
end
|
@@ -124,11 +124,11 @@ module ConfigCat
|
|
124
124
|
def get_value_details(key, default_value, user = nil)
|
125
125
|
settings, fetch_time = _get_settings()
|
126
126
|
if settings.nil?
|
127
|
-
message = "
|
128
|
-
|
129
|
-
|
130
|
-
@hooks.invoke_on_flag_evaluated(
|
131
|
-
return
|
127
|
+
message = "Config JSON is not present when evaluating setting '#{key}'. Returning the `default_value` parameter that you specified in your application: '#{default_value}'."
|
128
|
+
@log.error(1000, message)
|
129
|
+
details = EvaluationDetails.from_error(key, default_value, error: message)
|
130
|
+
@hooks.invoke_on_flag_evaluated(details)
|
131
|
+
return details
|
132
132
|
end
|
133
133
|
details = _evaluate(key, user, default_value, nil, settings, fetch_time)
|
134
134
|
return details
|
@@ -140,54 +140,12 @@ module ConfigCat
|
|
140
140
|
def get_all_keys
|
141
141
|
settings, _ = _get_settings()
|
142
142
|
if settings === nil
|
143
|
+
@log.error(1000, "Config JSON is not present. Returning empty list.")
|
143
144
|
return []
|
144
145
|
end
|
145
146
|
return settings.keys
|
146
147
|
end
|
147
148
|
|
148
|
-
# Gets the Variation ID (analytics) of a feature flag or setting based on it's key.
|
149
|
-
#
|
150
|
-
# :param key [String] the identifier of the feature flag or setting.
|
151
|
-
# :param default_variation_id in case of any failure, this value will be returned.
|
152
|
-
# :param user [User] the user object to identify the caller.
|
153
|
-
# :return the variation ID.
|
154
|
-
def get_variation_id(key, default_variation_id, user = nil)
|
155
|
-
@log.warn("get_variation_id is deprecated and will be removed in a future major version. "\
|
156
|
-
"Please use [get_value_details] instead.")
|
157
|
-
|
158
|
-
settings, fetch_time = _get_settings()
|
159
|
-
if settings === nil
|
160
|
-
message = "Evaluating get_variation_id('%s') failed. Cache is empty. "\
|
161
|
-
"Returning default_variation_id in your get_variation_id call: [%s]." %
|
162
|
-
[key, default_variation_id.to_s]
|
163
|
-
@log.error(message)
|
164
|
-
@hooks.invoke_on_flag_evaluated(EvaluationDetails.from_error(key, nil, error: message,
|
165
|
-
variation_id: default_variation_id))
|
166
|
-
return default_variation_id
|
167
|
-
end
|
168
|
-
details = _evaluate(key, user, nil, default_variation_id, settings, fetch_time)
|
169
|
-
return details.variation_id
|
170
|
-
end
|
171
|
-
|
172
|
-
# Gets the Variation IDs (analytics) of all feature flags or settings.
|
173
|
-
#
|
174
|
-
# :param user [User] the user object to identify the caller.
|
175
|
-
# :return list of variation IDs
|
176
|
-
def get_all_variation_ids(user = nil)
|
177
|
-
@log.warn("get_all_variation_ids is deprecated and will be removed in a future major version. "\
|
178
|
-
"Please use [get_value_details] instead.")
|
179
|
-
|
180
|
-
keys = get_all_keys()
|
181
|
-
variation_ids = []
|
182
|
-
for key in keys
|
183
|
-
variation_id = get_variation_id(key, nil, user)
|
184
|
-
if !variation_id.equal?(nil)
|
185
|
-
variation_ids.push(variation_id)
|
186
|
-
end
|
187
|
-
end
|
188
|
-
return variation_ids
|
189
|
-
end
|
190
|
-
|
191
149
|
# Gets the key of a setting, and it's value identified by the given Variation ID (analytics)
|
192
150
|
#
|
193
151
|
# :param variation_id [String] variation ID
|
@@ -195,7 +153,7 @@ module ConfigCat
|
|
195
153
|
def get_key_and_value(variation_id)
|
196
154
|
settings, _ = _get_settings()
|
197
155
|
if settings === nil
|
198
|
-
@log.
|
156
|
+
@log.error(1000, "Config JSON is not present. Returning nil.")
|
199
157
|
return nil
|
200
158
|
end
|
201
159
|
|
@@ -219,7 +177,7 @@ module ConfigCat
|
|
219
177
|
end
|
220
178
|
end
|
221
179
|
|
222
|
-
@log.error("Could not find the setting for the
|
180
|
+
@log.error(2011, "Could not find the setting for the specified variation ID: '#{variation_id}'.")
|
223
181
|
end
|
224
182
|
|
225
183
|
# Evaluates and returns the values of all feature flags and settings.
|
@@ -227,9 +185,14 @@ module ConfigCat
|
|
227
185
|
# :param user [User] the user object to identify the caller.
|
228
186
|
# :return dictionary of values
|
229
187
|
def get_all_values(user = nil)
|
230
|
-
|
188
|
+
settings, _ = _get_settings()
|
189
|
+
if settings === nil
|
190
|
+
@log.error(1000, "Config JSON is not present. Returning empty dictionary.")
|
191
|
+
return {}
|
192
|
+
end
|
193
|
+
|
231
194
|
all_values = {}
|
232
|
-
for key in keys
|
195
|
+
for key in settings.keys
|
233
196
|
value = get_value(key, nil, user)
|
234
197
|
if !value.equal?(nil)
|
235
198
|
all_values[key] = value
|
@@ -245,7 +208,7 @@ module ConfigCat
|
|
245
208
|
def get_all_value_details(user = nil)
|
246
209
|
settings, fetch_time = _get_settings()
|
247
210
|
if settings.nil?
|
248
|
-
@log.error("
|
211
|
+
@log.error(1000, "Config JSON is not present. Returning empty list.")
|
249
212
|
return []
|
250
213
|
end
|
251
214
|
|
@@ -282,14 +245,16 @@ module ConfigCat
|
|
282
245
|
|
283
246
|
# Configures the SDK to allow HTTP requests.
|
284
247
|
def set_online
|
285
|
-
|
286
|
-
|
248
|
+
if @_config_service
|
249
|
+
@_config_service.set_online
|
250
|
+
else
|
251
|
+
@log.warn(3202, "Client is configured to use the `LOCAL_ONLY` override behavior, thus `set_online()` has no effect.")
|
252
|
+
end
|
287
253
|
end
|
288
254
|
|
289
255
|
# Configures the SDK to not initiate HTTP requests and work only from its cache.
|
290
256
|
def set_offline
|
291
257
|
@_config_service.set_offline if @_config_service
|
292
|
-
@log.debug('Switched to OFFLINE mode.')
|
293
258
|
end
|
294
259
|
|
295
260
|
# Returns true when the SDK is configured not to initiate HTTP requests, otherwise false.
|
@@ -339,10 +304,6 @@ module ConfigCat
|
|
339
304
|
return @_config_service.get_settings()
|
340
305
|
end
|
341
306
|
|
342
|
-
def _get_cache_key
|
343
|
-
return Digest::SHA1.hexdigest("ruby_" + CONFIG_FILE_NAME + "_" + @_sdk_key)
|
344
|
-
end
|
345
|
-
|
346
307
|
def _evaluate(key, user, default_value, default_variation_id, settings, fetch_time)
|
347
308
|
user = user || @_default_user
|
348
309
|
value, variation_id, rule, percentage_rule, error = @_rollout_evaluator.evaluate(
|
@@ -5,20 +5,20 @@ module ConfigCat
|
|
5
5
|
end
|
6
6
|
|
7
7
|
def debug(message)
|
8
|
-
ConfigCat.logger.debug(message)
|
8
|
+
ConfigCat.logger.debug("[0] " + message)
|
9
9
|
end
|
10
10
|
|
11
|
-
def info(message)
|
12
|
-
ConfigCat.logger.info(message)
|
11
|
+
def info(event_id, message)
|
12
|
+
ConfigCat.logger.info("[" + event_id.to_s + "] " + message)
|
13
13
|
end
|
14
14
|
|
15
|
-
def warn(message)
|
16
|
-
ConfigCat.logger.warn(message)
|
15
|
+
def warn(event_id, message)
|
16
|
+
ConfigCat.logger.warn("[" + event_id.to_s + "] " + message)
|
17
17
|
end
|
18
18
|
|
19
|
-
def error(message)
|
19
|
+
def error(event_id, message)
|
20
20
|
@hooks.invoke_on_error(message)
|
21
|
-
ConfigCat.logger.error(message)
|
21
|
+
ConfigCat.logger.error("[" + event_id.to_s + "] " + message)
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
@@ -2,37 +2,50 @@ require 'configcat/utils'
|
|
2
2
|
|
3
3
|
module ConfigCat
|
4
4
|
class ConfigEntry
|
5
|
-
|
6
|
-
ETAG = 'etag'
|
7
|
-
FETCH_TIME = 'fetch_time'
|
5
|
+
attr_accessor :config, :etag, :config_json_string, :fetch_time
|
8
6
|
|
9
|
-
|
10
|
-
|
11
|
-
def initialize(config = {}, etag = '', fetch_time = Utils::DISTANT_PAST)
|
7
|
+
def initialize(config = {}, etag = '', config_json_string = '{}', fetch_time = Utils::DISTANT_PAST)
|
12
8
|
@config = config
|
13
9
|
@etag = etag
|
10
|
+
@config_json_string = config_json_string
|
14
11
|
@fetch_time = fetch_time
|
15
12
|
end
|
16
13
|
|
17
|
-
def self.create_from_json(json)
|
18
|
-
return ConfigEntry::EMPTY if json.nil?
|
19
|
-
return ConfigEntry.new(
|
20
|
-
config = json.fetch(CONFIG, {}),
|
21
|
-
etag = json.fetch(ETAG, ''),
|
22
|
-
fetch_time = json.fetch(FETCH_TIME, Utils::DISTANT_PAST)
|
23
|
-
)
|
24
|
-
end
|
25
|
-
|
26
14
|
def empty?
|
27
15
|
self == ConfigEntry::EMPTY
|
28
16
|
end
|
29
17
|
|
30
|
-
def
|
31
|
-
{
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
18
|
+
def serialize
|
19
|
+
"#{(fetch_time * 1000).floor}\n#{etag}\n#{config_json_string}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.create_from_string(string)
|
23
|
+
return ConfigEntry.empty if string.nil? || string.empty?
|
24
|
+
|
25
|
+
fetch_time_index = string.index("\n")
|
26
|
+
etag_index = string.index("\n", fetch_time_index + 1)
|
27
|
+
if fetch_time_index.nil? || etag_index.nil?
|
28
|
+
raise 'Number of values is fewer than expected.'
|
29
|
+
end
|
30
|
+
|
31
|
+
begin
|
32
|
+
fetch_time = Float(string[0...fetch_time_index])
|
33
|
+
rescue ArgumentError
|
34
|
+
raise "Invalid fetch time: #{string[0...fetch_time_index]}"
|
35
|
+
end
|
36
|
+
|
37
|
+
etag = string[fetch_time_index + 1...etag_index]
|
38
|
+
if etag.nil? || etag.empty?
|
39
|
+
raise 'Empty eTag value'
|
40
|
+
end
|
41
|
+
begin
|
42
|
+
config_json = string[etag_index + 1..-1]
|
43
|
+
config = JSON.parse(config_json)
|
44
|
+
rescue => e
|
45
|
+
raise "Invalid config JSON: #{config_json}. #{e.message}"
|
46
|
+
end
|
47
|
+
|
48
|
+
ConfigEntry.new(config, etag, config_json, fetch_time / 1000.0)
|
36
49
|
end
|
37
50
|
|
38
51
|
EMPTY = ConfigEntry.new(etag: 'empty')
|
@@ -140,12 +140,13 @@ module ConfigCat
|
|
140
140
|
# Try to download again with the new url
|
141
141
|
|
142
142
|
if redirect == RedirectMode::SHOULD_REDIRECT
|
143
|
-
@log.warn("
|
143
|
+
@log.warn(3002, "The `dataGovernance` parameter specified at the client initialization is not in sync with the preferences on the ConfigCat Dashboard. " \
|
144
|
+
"Read more: https://configcat.com/docs/advanced/data-governance/")
|
144
145
|
end
|
145
146
|
|
146
147
|
# To prevent loops we check if we retried at least 3 times with the new base_url
|
147
148
|
if retries >= 2
|
148
|
-
@log.error("
|
149
|
+
@log.error(1104, "Redirection loop encountered while trying to fetch config JSON. Please contact us at https://configcat.com/support/")
|
149
150
|
return fetch_response
|
150
151
|
end
|
151
152
|
|
@@ -178,27 +179,27 @@ module ConfigCat
|
|
178
179
|
response_etag = ""
|
179
180
|
end
|
180
181
|
config = JSON.parse(response.body)
|
181
|
-
return FetchResponse.success(ConfigEntry.new(config, response_etag, Utils.get_utc_now_seconds_since_epoch))
|
182
|
+
return FetchResponse.success(ConfigEntry.new(config, response_etag, response.body, Utils.get_utc_now_seconds_since_epoch))
|
182
183
|
when Net::HTTPNotModified
|
183
184
|
return FetchResponse.not_modified
|
184
185
|
when Net::HTTPNotFound, Net::HTTPForbidden
|
185
|
-
error = "
|
186
|
-
@log.error(error)
|
186
|
+
error = "Your SDK Key seems to be wrong. You can find the valid SDK Key at https://app.configcat.com/sdkkey. Received unexpected response: #{response}"
|
187
|
+
@log.error(1100, error)
|
187
188
|
return FetchResponse.failure(error, false)
|
188
189
|
else
|
189
190
|
raise Net::HTTPError.new("", response)
|
190
191
|
end
|
191
192
|
rescue Net::HTTPError => e
|
192
|
-
error = "Unexpected HTTP response was received: #{e}"
|
193
|
-
@log.error(error)
|
193
|
+
error = "Unexpected HTTP response was received while trying to fetch config JSON: #{e}"
|
194
|
+
@log.error(1101, error)
|
194
195
|
return FetchResponse.failure(error, true)
|
195
196
|
rescue Timeout::Error => e
|
196
|
-
error = "Request timed out. Timeout values: [connect: #{get_open_timeout()}s, read: #{get_read_timeout()}s]"
|
197
|
-
@log.error(error)
|
197
|
+
error = "Request timed out while trying to fetch config JSON. Timeout values: [connect: #{get_open_timeout()}s, read: #{get_read_timeout()}s]"
|
198
|
+
@log.error(1102, error)
|
198
199
|
return FetchResponse.failure(error, true)
|
199
200
|
rescue Exception => e
|
200
|
-
error = "
|
201
|
-
@log.error(error)
|
201
|
+
error = "Unexpected error occurred while trying to fetch config JSON: #{e}"
|
202
|
+
@log.error(1103, error)
|
202
203
|
return FetchResponse.failure(error, true)
|
203
204
|
end
|
204
205
|
end
|
@@ -7,14 +7,13 @@ require 'configcat/refreshresult'
|
|
7
7
|
module ConfigCat
|
8
8
|
class ConfigService
|
9
9
|
def initialize(sdk_key, polling_mode, hooks, config_fetcher, log, config_cache, is_offline)
|
10
|
-
@sdk_key = sdk_key
|
11
10
|
@cached_entry = ConfigEntry::EMPTY
|
12
11
|
@cached_entry_string = ''
|
13
12
|
@polling_mode = polling_mode
|
14
13
|
@log = log
|
15
14
|
@config_cache = config_cache
|
16
15
|
@hooks = hooks
|
17
|
-
@cache_key =
|
16
|
+
@cache_key = ConfigService.get_cache_key(sdk_key)
|
18
17
|
@config_fetcher = config_fetcher
|
19
18
|
@is_offline = is_offline
|
20
19
|
@response_future = nil
|
@@ -24,7 +23,7 @@ module ConfigCat
|
|
24
23
|
@fetch_finished = Concurrent::Event.new
|
25
24
|
@start_time = Utils.get_utc_now_seconds_since_epoch
|
26
25
|
|
27
|
-
if @polling_mode.is_a?(AutoPollingMode)
|
26
|
+
if @polling_mode.is_a?(AutoPollingMode) && !@is_offline
|
28
27
|
start_poll
|
29
28
|
else
|
30
29
|
set_initialized
|
@@ -34,7 +33,10 @@ module ConfigCat
|
|
34
33
|
def get_settings
|
35
34
|
if @polling_mode.is_a?(LazyLoadingMode)
|
36
35
|
entry, _ = fetch_if_older(Utils.get_utc_now_seconds_since_epoch - @polling_mode.cache_refresh_interval_seconds)
|
37
|
-
return entry.
|
36
|
+
return !entry.empty? ?
|
37
|
+
[entry.config.fetch(FEATURE_FLAGS, {}), entry.fetch_time] :
|
38
|
+
[nil, Utils::DISTANT_PAST]
|
39
|
+
|
38
40
|
elsif @polling_mode.is_a?(AutoPollingMode) && !@initialized.set?
|
39
41
|
elapsed_time = Utils.get_utc_now_seconds_since_epoch - @start_time # Elapsed time in seconds
|
40
42
|
if elapsed_time < @polling_mode.max_init_wait_time_seconds
|
@@ -43,13 +45,17 @@ module ConfigCat
|
|
43
45
|
# Max wait time expired without result, notify subscribers with the cached config.
|
44
46
|
if !@initialized.set?
|
45
47
|
set_initialized
|
46
|
-
return
|
48
|
+
return !@cached_entry.empty? ?
|
49
|
+
[@cached_entry.config.fetch(FEATURE_FLAGS, {}), @cached_entry.fetch_time] :
|
50
|
+
[nil, Utils::DISTANT_PAST]
|
47
51
|
end
|
48
52
|
end
|
49
53
|
end
|
50
54
|
|
51
55
|
entry, _ = fetch_if_older(Utils::DISTANT_PAST, prefer_cache: true)
|
52
|
-
return entry.
|
56
|
+
return !entry.empty? ?
|
57
|
+
[entry.config.fetch(FEATURE_FLAGS, {}), entry.fetch_time] :
|
58
|
+
[nil, Utils::DISTANT_PAST]
|
53
59
|
end
|
54
60
|
|
55
61
|
# :return [RefreshResult]
|
@@ -68,7 +74,7 @@ module ConfigCat
|
|
68
74
|
if @polling_mode.is_a?(AutoPollingMode)
|
69
75
|
start_poll
|
70
76
|
end
|
71
|
-
@log.
|
77
|
+
@log.info(5200, 'Switched to ONLINE mode.')
|
72
78
|
end
|
73
79
|
end
|
74
80
|
|
@@ -84,7 +90,7 @@ module ConfigCat
|
|
84
90
|
@thread.join
|
85
91
|
end
|
86
92
|
|
87
|
-
@log.
|
93
|
+
@log.info(5200, 'Switched to OFFLINE mode.')
|
88
94
|
end
|
89
95
|
end
|
90
96
|
|
@@ -100,6 +106,10 @@ module ConfigCat
|
|
100
106
|
|
101
107
|
private
|
102
108
|
|
109
|
+
def self.get_cache_key(sdk_key)
|
110
|
+
Digest::SHA1.hexdigest("#{sdk_key}_#{CONFIG_FILE_NAME}.json_#{SERIALIZATION_FORMAT_VERSION}")
|
111
|
+
end
|
112
|
+
|
103
113
|
# :return [ConfigEntry, String] Returns the ConfigEntry object and error message in case of any error.
|
104
114
|
def fetch_if_older(time, prefer_cache: false)
|
105
115
|
# Sync up with the cache and use it when it's not expired.
|
@@ -127,8 +137,8 @@ module ConfigCat
|
|
127
137
|
|
128
138
|
# If we are in offline mode we are not allowed to initiate fetch.
|
129
139
|
if @is_offline
|
130
|
-
offline_warning =
|
131
|
-
@log.warn(offline_warning)
|
140
|
+
offline_warning = "Client is in offline mode, it cannot initiate HTTP calls."
|
141
|
+
@log.warn(3200, offline_warning)
|
132
142
|
return @cached_entry, offline_warning
|
133
143
|
end
|
134
144
|
end
|
@@ -194,18 +204,18 @@ module ConfigCat
|
|
194
204
|
end
|
195
205
|
|
196
206
|
@cached_entry_string = json_string
|
197
|
-
return ConfigEntry.
|
207
|
+
return ConfigEntry.create_from_string(json_string)
|
198
208
|
rescue Exception => e
|
199
|
-
@log.error("
|
209
|
+
@log.error(2200, "Error occurred while reading the cache. #{e}")
|
200
210
|
return ConfigEntry::EMPTY
|
201
211
|
end
|
202
212
|
end
|
203
213
|
|
204
214
|
def write_cache(config_entry)
|
205
215
|
begin
|
206
|
-
@config_cache.set(@cache_key, config_entry.
|
216
|
+
@config_cache.set(@cache_key, config_entry.serialize)
|
207
217
|
rescue Exception => e
|
208
|
-
@log.error("
|
218
|
+
@log.error(2201, "Error occurred while writing the cache. #{e}")
|
209
219
|
end
|
210
220
|
end
|
211
221
|
end
|
data/lib/configcat/constants.rb
CHANGED
@@ -19,7 +19,7 @@ module ConfigCat
|
|
19
19
|
super(override_behaviour)
|
20
20
|
@log = log
|
21
21
|
if !File.exists?(file_path)
|
22
|
-
@log.error("
|
22
|
+
@log.error(1300, "Cannot find the local config file '#{file_path}'. This is a path that your application provided to the ConfigCat SDK by passing it to the `LocalFileFlagOverrides.new()` method. Read more: https://configcat.com/docs/sdk-reference/ruby/#json-file")
|
23
23
|
end
|
24
24
|
@_file_path = file_path
|
25
25
|
@_settings = nil
|
@@ -51,9 +51,9 @@ module ConfigCat
|
|
51
51
|
end
|
52
52
|
end
|
53
53
|
rescue JSON::ParserError => e
|
54
|
-
@log.error("
|
54
|
+
@log.error(2302, "Failed to decode JSON from the local config file '#{@_file_path}'. #{e}")
|
55
55
|
rescue Exception => e
|
56
|
-
@log.error("
|
56
|
+
@log.error(1302, "Failed to read the local config file '#{@_file_path}'. #{e}")
|
57
57
|
end
|
58
58
|
end
|
59
59
|
end
|
@@ -15,25 +15,30 @@ module ConfigCat
|
|
15
15
|
def evaluate(key:, user:, default_value:, default_variation_id:, settings:)
|
16
16
|
setting_descriptor = settings[key]
|
17
17
|
if setting_descriptor === nil
|
18
|
-
error = "
|
19
|
-
|
18
|
+
error = "Failed to evaluate setting '#{key}' (the key was not found in config JSON). " \
|
19
|
+
"Returning the `default_value` parameter that you specified in your application: '#{default_value}'. " \
|
20
|
+
"Available keys: [#{settings.keys.map { |s| "'#{s}'" }.join(", ")}]."
|
21
|
+
@log.error(1001, error)
|
20
22
|
return default_value, default_variation_id, nil, nil, error
|
21
23
|
end
|
22
24
|
|
23
25
|
rollout_rules = setting_descriptor.fetch(ROLLOUT_RULES, [])
|
24
26
|
rollout_percentage_items = setting_descriptor.fetch(ROLLOUT_PERCENTAGE_ITEMS, [])
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
+
user_has_invalid_type = !user.equal?(nil) && !user.class.equal?(User)
|
29
|
+
if user_has_invalid_type
|
30
|
+
@log.warn(4001, "Cannot evaluate targeting rules and % options for setting '#{key}' (User Object is not an instance of User type).")
|
28
31
|
user = nil
|
29
32
|
end
|
30
33
|
if user === nil
|
31
|
-
if rollout_rules.size > 0 || rollout_percentage_items.size > 0
|
32
|
-
@log.warn("
|
34
|
+
if !user_has_invalid_type && (rollout_rules.size > 0 || rollout_percentage_items.size > 0)
|
35
|
+
@log.warn(3001, "Cannot evaluate targeting rules and % options for setting '#{key}' (User Object is missing). " \
|
36
|
+
"You should pass a User Object to the evaluation methods like `get_value()` in order to make targeting work properly. " \
|
37
|
+
"Read more: https://configcat.com/docs/advanced/user-object/")
|
33
38
|
end
|
34
39
|
return_value = setting_descriptor.fetch(VALUE, default_value)
|
35
40
|
return_variation_id = setting_descriptor.fetch(VARIATION_ID, default_variation_id)
|
36
|
-
@log.info("Returning [
|
41
|
+
@log.info(5000, "Returning [#{return_value}]")
|
37
42
|
return return_value, return_variation_id, nil, nil, nil
|
38
43
|
end
|
39
44
|
|
@@ -94,7 +99,7 @@ module ConfigCat
|
|
94
99
|
end
|
95
100
|
rescue ArgumentError => e
|
96
101
|
message = format_validation_error_rule(comparison_attribute, user_value, comparator, comparison_value, e.to_s)
|
97
|
-
@log.warn(message)
|
102
|
+
@log.warn(0, message)
|
98
103
|
log_entries.push(message)
|
99
104
|
next
|
100
105
|
end
|
@@ -112,7 +117,7 @@ module ConfigCat
|
|
112
117
|
end
|
113
118
|
rescue ArgumentError => e
|
114
119
|
message = format_validation_error_rule(comparison_attribute, user_value, comparator, comparison_value, e.to_s)
|
115
|
-
@log.warn(message)
|
120
|
+
@log.warn(0, message)
|
116
121
|
log_entries.push(message)
|
117
122
|
next
|
118
123
|
end
|
@@ -131,7 +136,7 @@ module ConfigCat
|
|
131
136
|
end
|
132
137
|
rescue Exception => e
|
133
138
|
message = format_validation_error_rule(comparison_attribute, user_value, comparator, comparison_value, e.to_s)
|
134
|
-
@log.warn(message)
|
139
|
+
@log.warn(0, message)
|
135
140
|
log_entries.push(message)
|
136
141
|
next
|
137
142
|
end
|
@@ -171,7 +176,7 @@ module ConfigCat
|
|
171
176
|
log_entries.push("Returning %s" % return_value)
|
172
177
|
return return_value, return_variation_id, nil, nil, nil
|
173
178
|
ensure
|
174
|
-
@log.info(log_entries.join("\n"))
|
179
|
+
@log.info(5000, log_entries.join("\n"))
|
175
180
|
end
|
176
181
|
end
|
177
182
|
|
data/lib/configcat/version.rb
CHANGED
data/lib/configcat.rb
CHANGED
@@ -24,164 +24,4 @@ module ConfigCat
|
|
24
24
|
def ConfigCat.close_all
|
25
25
|
ConfigCatClient.close_all
|
26
26
|
end
|
27
|
-
|
28
|
-
def ConfigCat.create_client(sdk_key, data_governance: DataGovernance::GLOBAL)
|
29
|
-
#
|
30
|
-
# Create an instance of ConfigCatClient and setup Auto Poll mode with default options
|
31
|
-
#
|
32
|
-
# :param sdk_key: ConfigCat SDK Key to access your configuration.
|
33
|
-
# :param data_governance:
|
34
|
-
# Default: Global. Set this parameter to be in sync with the Data Governance preference on the Dashboard:
|
35
|
-
# https://app.configcat.com/organization/data-governance
|
36
|
-
# (Only Organization Admins have access)
|
37
|
-
#
|
38
|
-
return create_client_with_auto_poll(sdk_key, data_governance: data_governance)
|
39
|
-
end
|
40
|
-
|
41
|
-
# Create an instance of ConfigCatClient and setup Auto Poll mode with custom options
|
42
|
-
#
|
43
|
-
# :param sdk_key: ConfigCat SDK Key to access your configuration.
|
44
|
-
# :param poll_interval_seconds: The client's poll interval in seconds. Default: 60 seconds.
|
45
|
-
# :param on_configuration_changed_callback: You can subscribe to configuration changes with this callback
|
46
|
-
# :param max_init_wait_time_seconds: maximum waiting time for first configuration fetch in polling mode.
|
47
|
-
# :param config_cache: If you want to use custom caching instead of the client's default,
|
48
|
-
# You can provide an implementation of ConfigCache.
|
49
|
-
# :param base_url: You can set a base_url if you want to use a proxy server between your application and ConfigCat
|
50
|
-
# :param proxy_address: Proxy address
|
51
|
-
# :param proxy_port: Proxy port
|
52
|
-
# :param proxy_user: username for proxy authentication
|
53
|
-
# :param proxy_pass: password for proxy authentication
|
54
|
-
# :param open_timeout_seconds: The number of seconds to wait for the server to make the initial connection. Default: 10 seconds.
|
55
|
-
# :param read_timeout_seconds: The number of seconds to wait for the server to respond before giving up. Default: 30 seconds.
|
56
|
-
# :param flag_overrides: A FlagOverrides implementation used to override feature flags & settings.
|
57
|
-
# :param data_governance:
|
58
|
-
# Default: Global. Set this parameter to be in sync with the Data Governance preference on the Dashboard:
|
59
|
-
# https://app.configcat.com/organization/data-governance
|
60
|
-
# (Only Organization Admins have access)
|
61
|
-
def ConfigCat.create_client_with_auto_poll(sdk_key,
|
62
|
-
poll_interval_seconds: 60,
|
63
|
-
max_init_wait_time_seconds: 5,
|
64
|
-
on_configuration_changed_callback: nil,
|
65
|
-
config_cache: nil,
|
66
|
-
base_url: nil,
|
67
|
-
proxy_address: nil,
|
68
|
-
proxy_port: nil,
|
69
|
-
proxy_user: nil,
|
70
|
-
proxy_pass: nil,
|
71
|
-
open_timeout_seconds: 10,
|
72
|
-
read_timeout_seconds: 30,
|
73
|
-
flag_overrides: nil,
|
74
|
-
data_governance: DataGovernance::GLOBAL)
|
75
|
-
options = ConfigCatOptions.new(
|
76
|
-
base_url: base_url,
|
77
|
-
polling_mode: PollingMode.auto_poll(poll_interval_seconds: poll_interval_seconds, max_init_wait_time_seconds: max_init_wait_time_seconds),
|
78
|
-
config_cache: config_cache,
|
79
|
-
proxy_address: proxy_address,
|
80
|
-
proxy_port: proxy_port,
|
81
|
-
proxy_user: proxy_user,
|
82
|
-
proxy_pass: proxy_pass,
|
83
|
-
open_timeout_seconds: open_timeout_seconds,
|
84
|
-
read_timeout_seconds: read_timeout_seconds,
|
85
|
-
flag_overrides: flag_overrides,
|
86
|
-
data_governance: data_governance
|
87
|
-
)
|
88
|
-
client = ConfigCatClient.get(sdk_key, options)
|
89
|
-
client.hooks.add_on_config_changed(on_configuration_changed_callback) if on_configuration_changed_callback
|
90
|
-
client.log.warn('create_client_with_auto_poll is deprecated. Create the ConfigCat Client as a Singleton object with `configcatclient.get()` instead')
|
91
|
-
return client
|
92
|
-
end
|
93
|
-
|
94
|
-
# Create an instance of ConfigCatClient and setup Lazy Load mode with custom options
|
95
|
-
#
|
96
|
-
# :param sdk_key: ConfigCat SDK Key to access your configuration.
|
97
|
-
# :param cache_time_to_live_seconds: The cache TTL.
|
98
|
-
# :param config_cache: If you want to use custom caching instead of the client's default,
|
99
|
-
# You can provide an implementation of ConfigCache.
|
100
|
-
# :param base_url: You can set a base_url if you want to use a proxy server between your application and ConfigCat
|
101
|
-
# :param proxy_address: Proxy address
|
102
|
-
# :param proxy_port: Proxy port
|
103
|
-
# :param proxy_user: username for proxy authentication
|
104
|
-
# :param proxy_pass: password for proxy authentication
|
105
|
-
# :param open_timeout_seconds: The number of seconds to wait for the server to make the initial connection. Default: 10 seconds.
|
106
|
-
# :param read_timeout_seconds: The number of seconds to wait for the server to respond before giving up. Default: 30 seconds.
|
107
|
-
# :param flag_overrides: A FlagOverrides implementation used to override feature flags & settings.
|
108
|
-
# :param data_governance:
|
109
|
-
# Default: Global. Set this parameter to be in sync with the Data Governance preference on the Dashboard:
|
110
|
-
# https://app.configcat.com/organization/data-governance
|
111
|
-
# (Only Organization Admins have access)
|
112
|
-
def ConfigCat.create_client_with_lazy_load(sdk_key,
|
113
|
-
cache_time_to_live_seconds: 60,
|
114
|
-
config_cache: nil,
|
115
|
-
base_url: nil,
|
116
|
-
proxy_address: nil,
|
117
|
-
proxy_port: nil,
|
118
|
-
proxy_user: nil,
|
119
|
-
proxy_pass: nil,
|
120
|
-
open_timeout_seconds: 10,
|
121
|
-
read_timeout_seconds: 30,
|
122
|
-
flag_overrides: nil,
|
123
|
-
data_governance: DataGovernance::GLOBAL)
|
124
|
-
options = ConfigCatOptions.new(
|
125
|
-
base_url: base_url,
|
126
|
-
polling_mode: PollingMode.lazy_load(cache_refresh_interval_seconds: cache_time_to_live_seconds),
|
127
|
-
config_cache: config_cache,
|
128
|
-
proxy_address: proxy_address,
|
129
|
-
proxy_port: proxy_port,
|
130
|
-
proxy_user: proxy_user,
|
131
|
-
proxy_pass: proxy_pass,
|
132
|
-
open_timeout_seconds: open_timeout_seconds,
|
133
|
-
read_timeout_seconds: read_timeout_seconds,
|
134
|
-
flag_overrides: flag_overrides,
|
135
|
-
data_governance: data_governance
|
136
|
-
)
|
137
|
-
client = ConfigCatClient.get(sdk_key, options)
|
138
|
-
client.log.warn('create_client_with_lazy_load is deprecated. Create the ConfigCat Client as a Singleton object with `configcatclient.get()` instead')
|
139
|
-
return client
|
140
|
-
end
|
141
|
-
|
142
|
-
# Create an instance of ConfigCatClient and setup Manual Poll mode with custom options
|
143
|
-
#
|
144
|
-
# :param sdk_key: ConfigCat SDK Key to access your configuration.
|
145
|
-
# :param config_cache: If you want to use custom caching instead of the client's default,
|
146
|
-
# You can provide an implementation of ConfigCache.
|
147
|
-
# :param base_url: You can set a base_url if you want to use a proxy server between your application and ConfigCat
|
148
|
-
# :param proxy_address: Proxy address
|
149
|
-
# :param proxy_port: Proxy port
|
150
|
-
# :param proxy_user: username for proxy authentication
|
151
|
-
# :param proxy_pass: password for proxy authentication
|
152
|
-
# :param open_timeout_seconds: The number of seconds to wait for the server to make the initial connection. Default: 10 seconds.
|
153
|
-
# :param read_timeout_seconds: The number of seconds to wait for the server to respond before giving up. Default: 30 seconds.
|
154
|
-
# :param flag_overrides: A FlagOverrides implementation used to override feature flags & settings.
|
155
|
-
# :param data_governance:
|
156
|
-
# Default: Global. Set this parameter to be in sync with the Data Governance preference on the Dashboard:
|
157
|
-
# https://app.configcat.com/organization/data-governance
|
158
|
-
# (Only Organization Admins have access)
|
159
|
-
def ConfigCat.create_client_with_manual_poll(sdk_key,
|
160
|
-
config_cache: nil,
|
161
|
-
base_url: nil,
|
162
|
-
proxy_address: nil,
|
163
|
-
proxy_port: nil,
|
164
|
-
proxy_user: nil,
|
165
|
-
proxy_pass: nil,
|
166
|
-
open_timeout_seconds: 10,
|
167
|
-
read_timeout_seconds: 30,
|
168
|
-
flag_overrides: nil,
|
169
|
-
data_governance: DataGovernance::GLOBAL)
|
170
|
-
options = ConfigCatOptions.new(
|
171
|
-
base_url: base_url,
|
172
|
-
polling_mode: PollingMode.manual_poll(),
|
173
|
-
config_cache: config_cache,
|
174
|
-
proxy_address: proxy_address,
|
175
|
-
proxy_port: proxy_port,
|
176
|
-
proxy_user: proxy_user,
|
177
|
-
proxy_pass: proxy_pass,
|
178
|
-
open_timeout_seconds: open_timeout_seconds,
|
179
|
-
read_timeout_seconds: read_timeout_seconds,
|
180
|
-
flag_overrides: flag_overrides,
|
181
|
-
data_governance: data_governance
|
182
|
-
)
|
183
|
-
client = ConfigCatClient.get(sdk_key, options)
|
184
|
-
client.log.warn('create_client_with_manual_poll is deprecated. Create the ConfigCat Client as a Singleton object with `configcatclient.get()` instead')
|
185
|
-
return client
|
186
|
-
end
|
187
27
|
end
|
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:
|
4
|
+
version: 7.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ConfigCat
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-07-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|