configcat 3.1.0 → 4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b842d2ff2f62e6a6c3dbe2ddab53c561e4b1db93f3928ce805044127cd2d7819
4
- data.tar.gz: 6d64d084c4a732d26d54879d914f4e9ce1722b9e73fee2aa4161cc5503e152d7
3
+ metadata.gz: 118a3db79c8d7d9a0795897380a4dfaf14fecda8a636024abfd9d2433b3af924
4
+ data.tar.gz: 4c85c82b81fe08fcf9b6eed0a40bea06369939301aa09bc12e82b33a3b2176eb
5
5
  SHA512:
6
- metadata.gz: 83a7d19dc642e492bb5443a1fc42f0f35db8f5278f02582848e8677133f4450faa41a1a30b158ccdca58bc5396cad109b914fa4851e4db74dcf03df1f5129d00
7
- data.tar.gz: 2e79ed9965f3c9da2f8afd9fed4636b6d349b0bda09fdfb0d8398b6e4334a458713114d23083fc5f611878ea02801c5e8ea1e73fad54f6e580ef1c098e8f9d7c
6
+ metadata.gz: afe03eda0affc92755ae0eb91196a15bfe61f68a12244270bb5d19b3870bc023fe9ccf3231d8f11f414c4439b49fd2f9481e9a64295c3ab87697511ebcf57b25
7
+ data.tar.gz: 5ac8e3beef89cbc84ef89f2eb5b071fcf5cb348db1c302755ba4fc619c759f9919f80785b2b08a4a583725d35ea6b9ef038d869706956485eec3b4a9d4cadbaa
@@ -10,13 +10,17 @@ module ConfigCat
10
10
  attr_accessor :logger
11
11
  end
12
12
 
13
- def ConfigCat.create_client(sdk_key)
13
+ def ConfigCat.create_client(sdk_key, data_governance: DataGovernance::GLOBAL)
14
14
  #
15
15
  # Create an instance of ConfigCatClient and setup Auto Poll mode with default options
16
16
  #
17
17
  # :param sdk_key: ConfigCat SDK Key to access your configuration.
18
+ # :param data_governance:
19
+ # Default: Global. Set this parameter to be in sync with the Data Governance preference on the Dashboard:
20
+ # https://app.configcat.com/organization/data-governance
21
+ # (Only Organization Admins have access)
18
22
  #
19
- return create_client_with_auto_poll(sdk_key)
23
+ return create_client_with_auto_poll(sdk_key, data_governance: data_governance)
20
24
  end
21
25
 
22
26
  def ConfigCat.create_client_with_auto_poll(sdk_key,
@@ -25,10 +29,11 @@ module ConfigCat
25
29
  on_configuration_changed_callback: nil,
26
30
  config_cache_class: nil,
27
31
  base_url: nil,
28
- proxy_address:nil,
29
- proxy_port:nil,
30
- proxy_user:nil,
31
- proxy_pass:nil)
32
+ proxy_address: nil,
33
+ proxy_port: nil,
34
+ proxy_user: nil,
35
+ proxy_pass: nil,
36
+ data_governance: DataGovernance::GLOBAL)
32
37
  #
33
38
  # Create an instance of ConfigCatClient and setup Auto Poll mode with custom options
34
39
  #
@@ -43,6 +48,10 @@ module ConfigCat
43
48
  # :param proxy_port: Proxy port
44
49
  # :param proxy_user: username for proxy authentication
45
50
  # :param proxy_pass: password for proxy authentication
51
+ # :param data_governance:
52
+ # Default: Global. Set this parameter to be in sync with the Data Governance preference on the Dashboard:
53
+ # https://app.configcat.com/organization/data-governance
54
+ # (Only Organization Admins have access)
46
55
  #
47
56
  if sdk_key === nil
48
57
  raise ConfigCatClientException, "SDK Key is required."
@@ -63,17 +72,19 @@ module ConfigCat
63
72
  proxy_address: proxy_address,
64
73
  proxy_port: proxy_port,
65
74
  proxy_user: proxy_user,
66
- proxy_pass: proxy_pass)
75
+ proxy_pass: proxy_pass,
76
+ data_governance: data_governance)
67
77
  end
68
78
 
69
79
  def ConfigCat.create_client_with_lazy_load(sdk_key,
70
80
  cache_time_to_live_seconds: 60,
71
81
  config_cache_class: nil,
72
82
  base_url: nil,
73
- proxy_address:nil,
74
- proxy_port:nil,
75
- proxy_user:nil,
76
- proxy_pass:nil)
83
+ proxy_address: nil,
84
+ proxy_port: nil,
85
+ proxy_user: nil,
86
+ proxy_pass: nil,
87
+ data_governance: DataGovernance::GLOBAL)
77
88
  #
78
89
  # Create an instance of ConfigCatClient and setup Lazy Load mode with custom options
79
90
  #
@@ -86,6 +97,10 @@ module ConfigCat
86
97
  # :param proxy_port: Proxy port
87
98
  # :param proxy_user: username for proxy authentication
88
99
  # :param proxy_pass: password for proxy authentication
100
+ # :param data_governance:
101
+ # Default: Global. Set this parameter to be in sync with the Data Governance preference on the Dashboard:
102
+ # https://app.configcat.com/organization/data-governance
103
+ # (Only Organization Admins have access)
89
104
  #
90
105
  if sdk_key === nil
91
106
  raise ConfigCatClientException, "SDK Key is required."
@@ -103,7 +118,8 @@ module ConfigCat
103
118
  proxy_address: proxy_address,
104
119
  proxy_port: proxy_port,
105
120
  proxy_user: proxy_user,
106
- proxy_pass: proxy_pass)
121
+ proxy_pass: proxy_pass,
122
+ data_governance: data_governance)
107
123
  end
108
124
 
109
125
  def ConfigCat.create_client_with_manual_poll(sdk_key,
@@ -112,7 +128,8 @@ module ConfigCat
112
128
  proxy_address:nil,
113
129
  proxy_port:nil,
114
130
  proxy_user:nil,
115
- proxy_pass:nil)
131
+ proxy_pass:nil,
132
+ data_governance: DataGovernance::GLOBAL)
116
133
  #
117
134
  # Create an instance of ConfigCatClient and setup Manual Poll mode with custom options
118
135
  #
@@ -124,6 +141,10 @@ module ConfigCat
124
141
  # :param proxy_port: Proxy port
125
142
  # :param proxy_user: username for proxy authentication
126
143
  # :param proxy_pass: password for proxy authentication
144
+ # :param data_governance:
145
+ # Default: Global. Set this parameter to be in sync with the Data Governance preference on the Dashboard:
146
+ # https://app.configcat.com/organization/data-governance
147
+ # (Only Organization Admins have access)
127
148
  #
128
149
  if sdk_key === nil
129
150
  raise ConfigCatClientException, "SDK Key is required."
@@ -138,7 +159,8 @@ module ConfigCat
138
159
  proxy_address: proxy_address,
139
160
  proxy_port: proxy_port,
140
161
  proxy_user: proxy_user,
141
- proxy_pass: proxy_pass)
162
+ proxy_pass: proxy_pass,
163
+ data_governance: data_governance)
142
164
  end
143
165
 
144
166
  end
@@ -1,9 +1,10 @@
1
1
  require 'configcat/interfaces'
2
+ require 'configcat/constants'
2
3
  require 'concurrent'
3
4
 
4
5
  module ConfigCat
5
6
  class AutoPollingCachePolicy < CachePolicy
6
- def initialize(config_fetcher, config_cache, poll_interval_seconds=60, max_init_wait_time_seconds=5, on_configuration_changed_callback=nil)
7
+ def initialize(config_fetcher, config_cache, cache_key, poll_interval_seconds=60, max_init_wait_time_seconds=5, on_configuration_changed_callback=nil)
7
8
  if poll_interval_seconds < 1
8
9
  poll_interval_seconds = 1
9
10
  end
@@ -12,6 +13,7 @@ module ConfigCat
12
13
  end
13
14
  @_config_fetcher = config_fetcher
14
15
  @_config_cache = config_cache
16
+ @_cache_key = cache_key
15
17
  @_poll_interval_seconds = poll_interval_seconds
16
18
  @_max_init_wait_time_seconds = max_init_wait_time_seconds
17
19
  @_on_configuration_changed_callback = on_configuration_changed_callback
@@ -40,7 +42,7 @@ module ConfigCat
40
42
  end
41
43
  begin
42
44
  @_lock.acquire_read_lock()
43
- return @_config_cache.get()
45
+ return @_config_cache.get(@_cache_key)
44
46
  ensure
45
47
  @_lock.release_read_lock()
46
48
  end
@@ -52,7 +54,7 @@ module ConfigCat
52
54
 
53
55
  begin
54
56
  @_lock.acquire_read_lock()
55
- old_configuration = @_config_cache.get()
57
+ old_configuration = @_config_cache.get(@_cache_key)
56
58
  ensure
57
59
  @_lock.release_read_lock()
58
60
  end
@@ -62,7 +64,7 @@ module ConfigCat
62
64
  if configuration != old_configuration
63
65
  begin
64
66
  @_lock.acquire_write_lock()
65
- @_config_cache.set(configuration)
67
+ @_config_cache.set(@_cache_key, configuration)
66
68
  @_initialized = true
67
69
  ensure
68
70
  @_lock.release_write_lock()
@@ -3,15 +3,15 @@ require 'configcat/interfaces'
3
3
  module ConfigCat
4
4
  class InMemoryConfigCache < ConfigCache
5
5
  def initialize()
6
- @_value = nil
6
+ @_value = {}
7
7
  end
8
8
 
9
- def get()
10
- return @_value
9
+ def get(key)
10
+ return @_value.fetch(key, nil)
11
11
  end
12
12
 
13
- def set(value)
14
- @_value = value
13
+ def set(key, value)
14
+ @_value[key] = value
15
15
  end
16
16
  end
17
17
  end
@@ -5,6 +5,7 @@ require 'configcat/autopollingcachepolicy'
5
5
  require 'configcat/manualpollingcachepolicy'
6
6
  require 'configcat/lazyloadingcachepolicy'
7
7
  require 'configcat/rolloutevaluator'
8
+ require 'configcat/datagovernance'
8
9
 
9
10
  module ConfigCat
10
11
  KeyValue = Struct.new(:key, :value)
@@ -19,7 +20,8 @@ module ConfigCat
19
20
  proxy_address:nil,
20
21
  proxy_port:nil,
21
22
  proxy_user:nil,
22
- proxy_pass:nil)
23
+ proxy_pass:nil,
24
+ data_governance: DataGovernance::GLOBAL)
23
25
  if sdk_key === nil
24
26
  raise ConfigCatClientException, "SDK Key is required."
25
27
  end
@@ -32,15 +34,15 @@ module ConfigCat
32
34
  end
33
35
 
34
36
  if poll_interval_seconds > 0
35
- @_config_fetcher = CacheControlConfigFetcher.new(sdk_key, "p", base_url, proxy_address, proxy_port, proxy_user, proxy_pass)
36
- @_cache_policy = AutoPollingCachePolicy.new(@_config_fetcher, @_config_cache, poll_interval_seconds, max_init_wait_time_seconds, on_configuration_changed_callback)
37
+ @_config_fetcher = CacheControlConfigFetcher.new(sdk_key, "p", base_url, proxy_address, proxy_port, proxy_user, proxy_pass, data_governance)
38
+ @_cache_policy = AutoPollingCachePolicy.new(@_config_fetcher, @_config_cache, _get_cache_key(), poll_interval_seconds, max_init_wait_time_seconds, on_configuration_changed_callback)
37
39
  else
38
40
  if cache_time_to_live_seconds > 0
39
- @_config_fetcher = CacheControlConfigFetcher.new(sdk_key, "l", base_url, proxy_address, proxy_port, proxy_user, proxy_pass)
40
- @_cache_policy = LazyLoadingCachePolicy.new(@_config_fetcher, @_config_cache, cache_time_to_live_seconds)
41
+ @_config_fetcher = CacheControlConfigFetcher.new(sdk_key, "l", base_url, proxy_address, proxy_port, proxy_user, proxy_pass, data_governance)
42
+ @_cache_policy = LazyLoadingCachePolicy.new(@_config_fetcher, @_config_cache, _get_cache_key(), cache_time_to_live_seconds)
41
43
  else
42
- @_config_fetcher = CacheControlConfigFetcher.new(sdk_key, "m", base_url, proxy_address, proxy_port, proxy_user, proxy_pass)
43
- @_cache_policy = ManualPollingCachePolicy.new(@_config_fetcher, @_config_cache)
44
+ @_config_fetcher = CacheControlConfigFetcher.new(sdk_key, "m", base_url, proxy_address, proxy_port, proxy_user, proxy_pass, data_governance)
45
+ @_cache_policy = ManualPollingCachePolicy.new(@_config_fetcher, @_config_cache, _get_cache_key())
44
46
  end
45
47
  end
46
48
  end
@@ -59,7 +61,11 @@ module ConfigCat
59
61
  if config === nil
60
62
  return []
61
63
  end
62
- return config.keys
64
+ feature_flags = config.fetch(FEATURE_FLAGS, nil)
65
+ if feature_flags === nil
66
+ return []
67
+ end
68
+ return feature_flags.keys
63
69
  end
64
70
 
65
71
  def get_variation_id(key, default_variation_id, user=nil)
@@ -92,22 +98,29 @@ module ConfigCat
92
98
  ConfigCat.logger.warn("Evaluating get_variation_id('%s') failed. Cache is empty. Returning nil." % variation_id)
93
99
  return nil
94
100
  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])
101
+
102
+ feature_flags = config.fetch(FEATURE_FLAGS, nil)
103
+ if feature_flags === nil
104
+ ConfigCat.logger.warn("Evaluating get_key_and_value('%s') failed. Cache is empty. Returning None." % variation_id)
105
+ return nil
106
+ end
107
+
108
+ for key, value in feature_flags
109
+ if variation_id == value.fetch(VARIATION_ID, nil)
110
+ return KeyValue.new(key, value[VALUE])
98
111
  end
99
112
 
100
- rollout_rules = value.fetch(RolloutEvaluator::ROLLOUT_RULES, [])
113
+ rollout_rules = value.fetch(ROLLOUT_RULES, [])
101
114
  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])
115
+ if variation_id == rollout_rule.fetch(VARIATION_ID, nil)
116
+ return KeyValue.new(key, rollout_rule[VALUE])
104
117
  end
105
118
  end
106
119
 
107
- rollout_percentage_items = value.fetch(RolloutEvaluator::ROLLOUT_PERCENTAGE_ITEMS, [])
120
+ rollout_percentage_items = value.fetch(ROLLOUT_PERCENTAGE_ITEMS, [])
108
121
  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])
122
+ if variation_id == rollout_percentage_item.fetch(VARIATION_ID, nil)
123
+ return KeyValue.new(key, rollout_percentage_item[VALUE])
111
124
  end
112
125
  end
113
126
  end
@@ -122,5 +135,11 @@ module ConfigCat
122
135
  @_config_fetcher.close()
123
136
  end
124
137
 
138
+ private
139
+
140
+ def _get_cache_key()
141
+ return Digest::SHA1.hexdigest("ruby_" + CONFIG_FILE_NAME + "_" + @_sdk_key)
142
+ end
143
+
125
144
  end
126
145
  end
@@ -1,13 +1,22 @@
1
1
  require 'configcat/interfaces'
2
2
  require 'configcat/version'
3
+ require 'configcat/datagovernance'
4
+ require 'configcat/constants'
3
5
  require 'net/http'
4
6
  require 'uri'
5
7
  require 'json'
6
8
 
7
9
  module ConfigCat
8
- BASE_URL = "https://cdn.configcat.com"
10
+ BASE_URL_GLOBAL = "https://cdn-global.configcat.com"
11
+ BASE_URL_EU_ONLY = "https://cdn-eu.configcat.com"
9
12
  BASE_PATH = "configuration-files/"
10
- BASE_EXTENSION = "/config_v4.json"
13
+ BASE_EXTENSION = "/" + CONFIG_FILE_NAME + ".json"
14
+
15
+ class RedirectMode
16
+ NO_REDIRECT = 0
17
+ SHOULD_REDIRECT = 1
18
+ FORCE_REDIRECT = 2
19
+ end
11
20
 
12
21
  class FetchResponse
13
22
  def initialize(response)
@@ -32,34 +41,89 @@ module ConfigCat
32
41
  end
33
42
 
34
43
  class CacheControlConfigFetcher < ConfigFetcher
35
- def initialize(sdk_key, mode, base_url=nil, proxy_address=nil, proxy_port=nil, proxy_user=nil, proxy_pass=nil)
44
+ def initialize(sdk_key, mode, base_url=nil, proxy_address=nil, proxy_port=nil, proxy_user=nil, proxy_pass=nil,
45
+ data_governance=DataGovernance::GLOBAL)
36
46
  @_sdk_key = sdk_key
47
+ @_proxy_address = proxy_address
48
+ @_proxy_port = proxy_port
49
+ @_proxy_user = proxy_user
50
+ @_proxy_pass = proxy_pass
37
51
  @_etag = ""
38
52
  @_headers = {"User-Agent" => ((("ConfigCat-Ruby/") + mode) + ("-")) + VERSION, "X-ConfigCat-UserAgent" => ((("ConfigCat-Ruby/") + mode) + ("-")) + VERSION, "Content-Type" => "application/json"}
39
53
  if !base_url.equal?(nil)
54
+ @_base_url_overridden = true
40
55
  @_base_url = base_url.chomp("/")
41
56
  else
42
- @_base_url = BASE_URL
57
+ @_base_url_overridden = false
58
+ if data_governance == DataGovernance::EU_ONLY
59
+ @_base_url = BASE_URL_EU_ONLY
60
+ else
61
+ @_base_url = BASE_URL_GLOBAL
62
+ end
43
63
  end
44
- uri = URI.parse(@_base_url)
45
- @_http = Net::HTTP.new(uri.host, uri.port, proxy_address, proxy_port, proxy_user, proxy_pass)
46
- @_http.use_ssl = true if uri.scheme == 'https'
47
- @_http.open_timeout = 10 # in seconds
48
- @_http.read_timeout = 30 # in seconds
49
64
  end
50
65
 
51
66
  # Returns the FetchResponse object contains configuration json Dictionary
52
- def get_configuration_json()
67
+ def get_configuration_json(retries=0)
53
68
  ConfigCat.logger.debug "Fetching configuration from ConfigCat"
54
69
  uri = URI.parse((((@_base_url + ("/")) + BASE_PATH) + @_sdk_key) + BASE_EXTENSION)
55
70
  headers = @_headers
56
71
  headers["If-None-Match"] = @_etag unless @_etag.empty?
72
+ _create_http()
57
73
  request = Net::HTTP::Get.new(uri.request_uri, headers)
58
74
  response = @_http.request(request)
59
75
  etag = response["ETag"]
60
76
  @_etag = etag unless etag.nil? || etag.empty?
61
77
  ConfigCat.logger.debug "ConfigCat configuration json fetch response code:#{response.code} Cached:#{response['ETag']}"
62
- return FetchResponse.new(response)
78
+ fetch_response = FetchResponse.new(response)
79
+
80
+ # If there wasn't a config change, we return the response.
81
+ if !fetch_response.is_fetched()
82
+ return fetch_response
83
+ end
84
+
85
+ preferences = fetch_response.json().fetch(PREFERENCES, nil)
86
+ if preferences === nil
87
+ return fetch_response
88
+ end
89
+
90
+ base_url = preferences.fetch(BASE_URL, nil)
91
+
92
+ # If the base_url is the same as the last called one, just return the response.
93
+ if base_url.equal?(nil) || @_base_url == base_url
94
+ return fetch_response
95
+ end
96
+
97
+ redirect = preferences.fetch(REDIRECT, nil)
98
+ # If the base_url is overridden, and the redirect parameter is not 2 (force),
99
+ # the SDK should not redirect the calls and it just have to return the response.
100
+ if @_base_url_overridden && redirect != RedirectMode::FORCE_REDIRECT
101
+ return fetch_response
102
+ end
103
+
104
+ # The next call should use the base_url provided in the config json
105
+ @_base_url = base_url
106
+
107
+ # If the redirect property == 0 (redirect not needed), return the response
108
+ if redirect == RedirectMode::NO_REDIRECT
109
+ # Return the response
110
+ return fetch_response
111
+ end
112
+
113
+ # Try to download again with the new url
114
+
115
+ if redirect == RedirectMode::SHOULD_REDIRECT
116
+ ConfigCat.logger.warn("Your data_governance parameter at ConfigCatClient initialization is not in sync with your preferences on the ConfigCat Dashboard: https://app.configcat.com/organization/data-governance. Only Organization Admins can set this preference.")
117
+ end
118
+
119
+ # To prevent loops we check if we retried at least 3 times with the new base_url
120
+ if retries >= 2
121
+ ConfigCat.logger.error("Redirect loop during config.json fetch. Please contact support@configcat.com.")
122
+ return fetch_response
123
+ end
124
+
125
+ # Retry the config download with the new base_url
126
+ return get_configuration_json(retries + 1)
63
127
  end
64
128
 
65
129
  def close()
@@ -67,5 +131,19 @@ module ConfigCat
67
131
  @_http = nil
68
132
  end
69
133
  end
134
+
135
+ private
136
+
137
+ def _create_http()
138
+ uri = URI.parse(@_base_url)
139
+ use_ssl = true if uri.scheme == 'https'
140
+ if @_http.equal?(nil) || @_http.address != uri.host || @_http.port != uri.port || @_http.use_ssl? != use_ssl
141
+ close()
142
+ @_http = Net::HTTP.new(uri.host, uri.port, @_proxy_address, @_proxy_port, @_proxy_user, @_proxy_pass)
143
+ @_http.use_ssl = use_ssl
144
+ @_http.open_timeout = 10 # in seconds
145
+ @_http.read_timeout = 30 # in seconds
146
+ end
147
+ end
70
148
  end
71
149
  end
@@ -0,0 +1,17 @@
1
+ module ConfigCat
2
+ CONFIG_FILE_NAME = "config_v5"
3
+
4
+ PREFERENCES = "p"
5
+ BASE_URL = "u"
6
+ REDIRECT = "r"
7
+
8
+ FEATURE_FLAGS = "f"
9
+ VALUE = "v"
10
+ COMPARATOR = "t"
11
+ COMPARISON_ATTRIBUTE = "a"
12
+ COMPARISON_VALUE = "c"
13
+ ROLLOUT_PERCENTAGE_ITEMS = "p"
14
+ PERCENTAGE = "p"
15
+ ROLLOUT_RULES = "r"
16
+ VARIATION_ID = "i"
17
+ end
@@ -0,0 +1,10 @@
1
+ module ConfigCat
2
+ class DataGovernance
3
+ # Control the location of the config.json files containing your feature flags
4
+ # and settings within the ConfigCat CDN.
5
+ # Global: Select this if your feature flags are published to all global CDN nodes.
6
+ # EuOnly: Select this if your feature flags are published to CDN nodes only in the EU.
7
+ GLOBAL = 0
8
+ EU_ONLY = 1
9
+ end
10
+ end
@@ -23,13 +23,13 @@ module ConfigCat
23
23
  # Config cache interface
24
24
  #
25
25
 
26
- def get()
26
+ def get(key)
27
27
  #
28
28
  # :returns the config json object from the cache
29
29
  #
30
30
  end
31
31
 
32
- def set(value)
32
+ def set(key, value)
33
33
  #
34
34
  # Sets the config json cache.
35
35
  #
@@ -1,15 +1,18 @@
1
1
  require 'configcat/interfaces'
2
+ require 'configcat/constants'
2
3
  require 'concurrent'
3
4
 
5
+
4
6
  module ConfigCat
5
7
  class LazyLoadingCachePolicy < CachePolicy
6
8
 
7
- def initialize(config_fetcher, config_cache, cache_time_to_live_seconds=60)
9
+ def initialize(config_fetcher, config_cache, cache_key, cache_time_to_live_seconds=60)
8
10
  if cache_time_to_live_seconds < 1
9
11
  cache_time_to_live_seconds = 1
10
12
  end
11
13
  @_config_fetcher = config_fetcher
12
14
  @_config_cache = config_cache
15
+ @_cache_key = cache_key
13
16
  @_cache_time_to_live = cache_time_to_live_seconds
14
17
  @_lock = Concurrent::ReadWriteLock.new()
15
18
  @_last_updated = nil
@@ -20,7 +23,7 @@ module ConfigCat
20
23
  @_lock.acquire_read_lock()
21
24
  utc_now = Time.now.utc
22
25
  if !@_last_updated.equal?(nil) && (@_last_updated + @_cache_time_to_live > utc_now)
23
- config = @_config_cache.get()
26
+ config = @_config_cache.get(@_cache_key)
24
27
  if !config.equal?(nil)
25
28
  return config
26
29
  end
@@ -31,7 +34,7 @@ module ConfigCat
31
34
  force_refresh()
32
35
  begin
33
36
  @_lock.acquire_read_lock()
34
- config = @_config_cache.get()
37
+ config = @_config_cache.get(@_cache_key)
35
38
  return config
36
39
  ensure
37
40
  @_lock.release_read_lock()
@@ -45,7 +48,7 @@ module ConfigCat
45
48
  configuration = configuration_response.json()
46
49
  begin
47
50
  @_lock.acquire_write_lock()
48
- @_config_cache.set(configuration)
51
+ @_config_cache.set(@_cache_key, configuration)
49
52
  @_last_updated = Time.now.utc
50
53
  ensure
51
54
  @_lock.release_write_lock()
@@ -1,18 +1,20 @@
1
1
  require 'configcat/interfaces'
2
+ require 'configcat/constants'
2
3
  require 'concurrent'
3
4
 
4
5
  module ConfigCat
5
6
  class ManualPollingCachePolicy < CachePolicy
6
- def initialize(config_fetcher, config_cache)
7
+ def initialize(config_fetcher, config_cache, cache_key)
7
8
  @_config_fetcher = config_fetcher
8
9
  @_config_cache = config_cache
10
+ @_cache_key = cache_key
9
11
  @_lock = Concurrent::ReadWriteLock.new()
10
12
  end
11
13
 
12
14
  def get()
13
15
  begin
14
16
  @_lock.acquire_read_lock()
15
- config = @_config_cache.get()
17
+ config = @_config_cache.get(@_cache_key)
16
18
  return config
17
19
  ensure
18
20
  @_lock.release_read_lock()
@@ -26,7 +28,7 @@ module ConfigCat
26
28
  configuration = configuration_response.json()
27
29
  begin
28
30
  @_lock.acquire_write_lock()
29
- @_config_cache.set(configuration)
31
+ @_config_cache.set(@_cache_key, configuration)
30
32
  ensure
31
33
  @_lock.release_write_lock()
32
34
  end
@@ -1,4 +1,5 @@
1
1
  require 'configcat/user'
2
+ require 'configcat/constants'
2
3
  require 'digest'
3
4
  require 'semantic'
4
5
 
@@ -6,21 +7,18 @@ module ConfigCat
6
7
  class RolloutEvaluator
7
8
  COMPARATOR_TEXTS = ["IS ONE OF", "IS NOT ONE OF", "CONTAINS", "DOES NOT CONTAIN", "IS ONE OF (SemVer)", "IS NOT ONE OF (SemVer)", "< (SemVer)", "<= (SemVer)", "> (SemVer)", ">= (SemVer)", "= (Number)", "<> (Number)", "< (Number)", "<= (Number)", "> (Number)", ">= (Number)"]
8
9
 
9
- VALUE = "v"
10
- COMPARATOR = "t"
11
- COMPARISON_ATTRIBUTE = "a"
12
- COMPARISON_VALUE = "c"
13
- ROLLOUT_PERCENTAGE_ITEMS = "p"
14
- PERCENTAGE = "p"
15
- ROLLOUT_RULES = "r"
16
- VARIATION_ID = "i"
17
-
18
10
  def self.evaluate(key, user, default_value, default_variation_id, config)
19
11
  ConfigCat.logger.info("Evaluating get_value('%s')." % key)
20
12
 
21
- setting_descriptor = config.fetch(key, nil)
13
+ feature_flags = config.fetch(FEATURE_FLAGS, nil)
14
+ if feature_flags === nil
15
+ ConfigCat.logger.error("Evaluating get_value('%s') failed. Value not found for key '%s' Returning default_value: [%s]." % [key, key, default_value.to_s])
16
+ return default_value, default_variation_id
17
+ end
18
+
19
+ setting_descriptor = feature_flags.fetch(key, nil)
22
20
  if setting_descriptor === nil
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(", ")])
21
+ 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, feature_flags.keys.join(", ")])
24
22
  return default_value, default_variation_id
25
23
  end
26
24
 
@@ -1,3 +1,3 @@
1
1
  module ConfigCat
2
- VERSION = "3.1.0"
2
+ VERSION = "4.0.0"
3
3
  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: 3.1.0
4
+ version: 4.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: 2020-09-14 00:00:00.000000000 Z
11
+ date: 2020-10-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -110,6 +110,8 @@ files:
110
110
  - lib/configcat/configcache.rb
111
111
  - lib/configcat/configcatclient.rb
112
112
  - lib/configcat/configfetcher.rb
113
+ - lib/configcat/constants.rb
114
+ - lib/configcat/datagovernance.rb
113
115
  - lib/configcat/interfaces.rb
114
116
  - lib/configcat/lazyloadingcachepolicy.rb
115
117
  - lib/configcat/manualpollingcachepolicy.rb