configcat 6.0.0 → 7.0.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/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
|