configcat 4.0.0 → 5.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: 118a3db79c8d7d9a0795897380a4dfaf14fecda8a636024abfd9d2433b3af924
4
- data.tar.gz: 4c85c82b81fe08fcf9b6eed0a40bea06369939301aa09bc12e82b33a3b2176eb
3
+ metadata.gz: 84a383f0a76b49e3daf0072676592b23836937e54430b16fc3183c8f517c0dac
4
+ data.tar.gz: 8d56fcce1d537ce84360a4f9cdc36ac795102ed37015c6efc9e872b8d44cb765
5
5
  SHA512:
6
- metadata.gz: afe03eda0affc92755ae0eb91196a15bfe61f68a12244270bb5d19b3870bc023fe9ccf3231d8f11f414c4439b49fd2f9481e9a64295c3ab87697511ebcf57b25
7
- data.tar.gz: 5ac8e3beef89cbc84ef89f2eb5b071fcf5cb348db1c302755ba4fc619c759f9919f80785b2b08a4a583725d35ea6b9ef038d869706956485eec3b4a9d4cadbaa
6
+ metadata.gz: 4bf91c58c110054015a41062f23dfd8d48b4998b892a255bc8872eab5c7a87209f244a99a1f0dd4face989d1da8cd73c64e3de0efa6154f01bf48f8a1e635f81
7
+ data.tar.gz: 52669ab34441b4abae836c0b474358a78ebbb1c0c1d56447d823eb51a1cfa2c32e999c27f2d5e904aba53a6dc925bf77e227f5e1897d087b585a7655cb07dc6c
@@ -82,6 +82,9 @@ module ConfigCat
82
82
  if !@_initialized && !old_configuration.equal?(nil)
83
83
  @_initialized = true
84
84
  end
85
+ rescue Timeout::Error => e
86
+ ConfigCat.logger.error("Request timed out. Timeout values: [open: %ss, read: %ss]" %
87
+ [@_config_fetcher.get_open_timeout(), @_config_fetcher.get_read_timeout()])
85
88
  rescue Exception => e
86
89
  ConfigCat.logger.error("Double-check your SDK Key at https://app.configcat.com/sdkkey.")
87
90
  ConfigCat.logger.error "threw exception #{e.class}:'#{e}'"
@@ -7,25 +7,41 @@ require 'configcat/lazyloadingcachepolicy'
7
7
  require 'configcat/rolloutevaluator'
8
8
  require 'configcat/datagovernance'
9
9
 
10
+
10
11
  module ConfigCat
11
12
  KeyValue = Struct.new(:key, :value)
12
13
  class ConfigCatClient
14
+ @@sdk_keys = []
15
+
13
16
  def initialize(sdk_key,
14
- poll_interval_seconds:60,
15
- max_init_wait_time_seconds:5,
16
- on_configuration_changed_callback:nil,
17
- cache_time_to_live_seconds:60,
18
- config_cache_class:nil,
19
- base_url:nil,
20
- proxy_address:nil,
21
- proxy_port:nil,
22
- proxy_user:nil,
23
- proxy_pass:nil,
17
+ poll_interval_seconds: 60,
18
+ max_init_wait_time_seconds: 5,
19
+ on_configuration_changed_callback: nil,
20
+ cache_time_to_live_seconds: 60,
21
+ config_cache_class: nil,
22
+ base_url: nil,
23
+ proxy_address: nil,
24
+ proxy_port: nil,
25
+ proxy_user: nil,
26
+ proxy_pass: nil,
27
+ open_timeout: 10,
28
+ read_timeout: 30,
29
+ flag_overrides: nil,
24
30
  data_governance: DataGovernance::GLOBAL)
25
31
  if sdk_key === nil
26
32
  raise ConfigCatClientException, "SDK Key is required."
27
33
  end
34
+
35
+ if @@sdk_keys.include?(sdk_key)
36
+ ConfigCat.logger.warn("A ConfigCat Client is already initialized with sdk_key %s. "\
37
+ "We strongly recommend you to use the ConfigCat Client as "\
38
+ "a Singleton object in your application." % sdk_key)
39
+ else
40
+ @@sdk_keys.push(sdk_key)
41
+ end
42
+
28
43
  @_sdk_key = sdk_key
44
+ @_override_data_source = flag_overrides
29
45
 
30
46
  if config_cache_class
31
47
  @_config_cache = config_cache_class.new()
@@ -33,23 +49,35 @@ module ConfigCat
33
49
  @_config_cache = InMemoryConfigCache.new()
34
50
  end
35
51
 
36
- if poll_interval_seconds > 0
37
- @_config_fetcher = CacheControlConfigFetcher.new(sdk_key, "p", base_url, proxy_address, proxy_port, proxy_user, proxy_pass, data_governance)
52
+ if !@_override_data_source.equal?(nil) && @_override_data_source.get_behaviour() == OverrideBehaviour::LOCAL_ONLY
53
+ @_config_fetcher = nil
54
+ @_cache_policy = nil
55
+ elsif poll_interval_seconds > 0
56
+ @_config_fetcher = CacheControlConfigFetcher.new(sdk_key, "p", base_url: base_url,
57
+ proxy_address: proxy_address, proxy_port: proxy_port, proxy_user: proxy_user, proxy_pass: proxy_pass,
58
+ open_timeout: open_timeout, read_timeout: read_timeout,
59
+ data_governance: data_governance)
38
60
  @_cache_policy = AutoPollingCachePolicy.new(@_config_fetcher, @_config_cache, _get_cache_key(), poll_interval_seconds, max_init_wait_time_seconds, on_configuration_changed_callback)
61
+ elsif cache_time_to_live_seconds > 0
62
+ @_config_fetcher = CacheControlConfigFetcher.new(sdk_key, "l", base_url: base_url,
63
+ proxy_address: proxy_address, proxy_port: proxy_port, proxy_user: proxy_user, proxy_pass: proxy_pass,
64
+ open_timeout: open_timeout, read_timeout: read_timeout,
65
+ data_governance: data_governance)
66
+ @_cache_policy = LazyLoadingCachePolicy.new(@_config_fetcher, @_config_cache, _get_cache_key(), cache_time_to_live_seconds)
39
67
  else
40
- if cache_time_to_live_seconds > 0
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)
43
- else
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())
46
- end
68
+ @_config_fetcher = CacheControlConfigFetcher.new(sdk_key, "m", base_url: base_url,
69
+ proxy_address: proxy_address, proxy_port: proxy_port, proxy_user: proxy_user, proxy_pass: proxy_pass,
70
+ open_timeout: open_timeout, read_timeout: read_timeout,
71
+ data_governance: data_governance)
72
+ @_cache_policy = ManualPollingCachePolicy.new(@_config_fetcher, @_config_cache, _get_cache_key())
47
73
  end
48
74
  end
49
75
 
50
76
  def get_value(key, default_value, user=nil)
51
- config = @_cache_policy.get()
77
+ config = _get_settings()
52
78
  if config === nil
79
+ ConfigCat.logger.warn("Evaluating get_value('%s') failed. Cache is empty. "\
80
+ "Returning default_value in your get_value call: [%s]." % [key, default_value.to_s])
53
81
  return default_value
54
82
  end
55
83
  value, variation_id = RolloutEvaluator.evaluate(key, user, default_value, nil, config)
@@ -57,7 +85,7 @@ module ConfigCat
57
85
  end
58
86
 
59
87
  def get_all_keys()
60
- config = @_cache_policy.get()
88
+ config = _get_settings()
61
89
  if config === nil
62
90
  return []
63
91
  end
@@ -69,7 +97,7 @@ module ConfigCat
69
97
  end
70
98
 
71
99
  def get_variation_id(key, default_variation_id, user=nil)
72
- config = @_cache_policy.get()
100
+ config = _get_settings()
73
101
  if config === nil
74
102
  ConfigCat.logger.warn("Evaluating get_variation_id('%s') failed. Cache is empty. "\
75
103
  "Returning default_variation_id in your get_variation_id call: [%s]." %
@@ -93,7 +121,7 @@ module ConfigCat
93
121
  end
94
122
 
95
123
  def get_key_and_value(variation_id)
96
- config = @_cache_policy.get()
124
+ config = _get_settings()
97
125
  if config === nil
98
126
  ConfigCat.logger.warn("Evaluating get_variation_id('%s') failed. Cache is empty. Returning nil." % variation_id)
99
127
  return nil
@@ -126,17 +154,56 @@ module ConfigCat
126
154
  end
127
155
  end
128
156
 
157
+ def get_all_values(user: nil)
158
+ keys = get_all_keys()
159
+ all_values = {}
160
+ for key in keys
161
+ value = get_value(key, nil, user)
162
+ if !value.equal?(nil)
163
+ all_values[key] = value
164
+ end
165
+ end
166
+ return all_values
167
+ end
168
+
129
169
  def force_refresh()
130
170
  @_cache_policy.force_refresh()
131
171
  end
132
172
 
133
173
  def stop()
134
- @_cache_policy.stop()
135
- @_config_fetcher.close()
174
+ @_cache_policy.stop() if @_cache_policy
175
+ @_config_fetcher.close() if @_config_fetcher
176
+ @@sdk_keys.delete(@_sdk_key)
136
177
  end
137
178
 
138
179
  private
139
180
 
181
+ def _get_settings()
182
+ if !@_override_data_source.nil?
183
+ behaviour = @_override_data_source.get_behaviour()
184
+ if behaviour == OverrideBehaviour::LOCAL_ONLY
185
+ return @_override_data_source.get_overrides()
186
+ elsif behaviour == OverrideBehaviour::REMOTE_OVER_LOCAL
187
+ remote_settings = @_cache_policy.get()
188
+ local_settings = @_override_data_source.get_overrides()
189
+ result = local_settings.clone()
190
+ if remote_settings.key?(FEATURE_FLAGS) && local_settings.key?(FEATURE_FLAGS)
191
+ result[FEATURE_FLAGS] = result[FEATURE_FLAGS].merge(remote_settings[FEATURE_FLAGS])
192
+ end
193
+ return result
194
+ elsif behaviour == OverrideBehaviour::LOCAL_OVER_REMOTE
195
+ remote_settings = @_cache_policy.get()
196
+ local_settings = @_override_data_source.get_overrides()
197
+ result = remote_settings.clone()
198
+ if remote_settings.key?(FEATURE_FLAGS) && local_settings.key?(FEATURE_FLAGS)
199
+ result[FEATURE_FLAGS] = result[FEATURE_FLAGS].merge(local_settings[FEATURE_FLAGS])
200
+ end
201
+ return result
202
+ end
203
+ end
204
+ return @_cache_policy.get()
205
+ end
206
+
140
207
  def _get_cache_key()
141
208
  return Digest::SHA1.hexdigest("ruby_" + CONFIG_FILE_NAME + "_" + @_sdk_key)
142
209
  end
@@ -41,13 +41,16 @@ module ConfigCat
41
41
  end
42
42
 
43
43
  class CacheControlConfigFetcher < ConfigFetcher
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)
44
+ def initialize(sdk_key, mode, base_url:nil, proxy_address:nil, proxy_port:nil, proxy_user:nil, proxy_pass:nil,
45
+ open_timeout:10, read_timeout:30,
46
+ data_governance:DataGovernance::GLOBAL)
46
47
  @_sdk_key = sdk_key
47
48
  @_proxy_address = proxy_address
48
49
  @_proxy_port = proxy_port
49
50
  @_proxy_user = proxy_user
50
51
  @_proxy_pass = proxy_pass
52
+ @_open_timeout = open_timeout
53
+ @_read_timeout = read_timeout
51
54
  @_etag = ""
52
55
  @_headers = {"User-Agent" => ((("ConfigCat-Ruby/") + mode) + ("-")) + VERSION, "X-ConfigCat-UserAgent" => ((("ConfigCat-Ruby/") + mode) + ("-")) + VERSION, "Content-Type" => "application/json"}
53
56
  if !base_url.equal?(nil)
@@ -63,6 +66,14 @@ module ConfigCat
63
66
  end
64
67
  end
65
68
 
69
+ def get_open_timeout()
70
+ return @_open_timeout
71
+ end
72
+
73
+ def get_read_timeout()
74
+ return @_read_timeout
75
+ end
76
+
66
77
  # Returns the FetchResponse object contains configuration json Dictionary
67
78
  def get_configuration_json(retries=0)
68
79
  ConfigCat.logger.debug "Fetching configuration from ConfigCat"
@@ -141,8 +152,8 @@ module ConfigCat
141
152
  close()
142
153
  @_http = Net::HTTP.new(uri.host, uri.port, @_proxy_address, @_proxy_port, @_proxy_user, @_proxy_pass)
143
154
  @_http.use_ssl = use_ssl
144
- @_http.open_timeout = 10 # in seconds
145
- @_http.read_timeout = 30 # in seconds
155
+ @_http.open_timeout = @_open_timeout
156
+ @_http.read_timeout = @_read_timeout
146
157
  end
147
158
  end
148
159
  end
@@ -0,0 +1,20 @@
1
+ require 'configcat/overridedatasource'
2
+ require 'configcat/constants'
3
+
4
+
5
+ module ConfigCat
6
+ class LocalDictionaryDataSource < OverrideDataSource
7
+ def initialize(source, override_behaviour)
8
+ super(override_behaviour)
9
+ dictionary = {}
10
+ source.each do |key, value|
11
+ dictionary[key] = {VALUE => value}
12
+ end
13
+ @_settings = {FEATURE_FLAGS => dictionary}
14
+ end
15
+
16
+ def get_overrides()
17
+ return @_settings
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,49 @@
1
+ require 'configcat/overridedatasource'
2
+ require 'configcat/constants'
3
+
4
+
5
+ module ConfigCat
6
+ class LocalFileDataSource < OverrideDataSource
7
+ def initialize(file_path, override_behaviour)
8
+ super(override_behaviour)
9
+ if File.exists?(file_path)
10
+ ConfigCat.logger.error("The file '%s' does not exists." % file_path)
11
+ end
12
+ @_file_path = file_path
13
+ @_settings = nil
14
+ @_cached_file_stamp = 0
15
+ end
16
+
17
+ def get_overrides()
18
+ reload_file_content()
19
+ return @_settings
20
+ end
21
+
22
+ private
23
+
24
+ def reload_file_content()
25
+ begin
26
+ stamp = File.mtime(@_file_path)
27
+ if stamp != @_cached_file_stamp
28
+ @_cached_file_stamp = stamp
29
+ file = File.read(@_file_path)
30
+ data = JSON.parse(file)
31
+ if data.key?("flags")
32
+ dictionary = {}
33
+ source = data["flags"]
34
+ source.each do |key, value|
35
+ dictionary[key] = {VALUE => value}
36
+ end
37
+ @_settings = {FEATURE_FLAGS => dictionary}
38
+ else
39
+ @_settings = data
40
+ end
41
+ end
42
+ rescue JSON::ParserError => e
43
+ ConfigCat.logger.error("Could not decode json from file %s. %s" % [@_file_path, e.to_s])
44
+ rescue Exception => e
45
+ ConfigCat.logger.error("Could not read the content of the file %s. %s" % [@_file_path, e.to_s])
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,32 @@
1
+ module ConfigCat
2
+ class OverrideBehaviour
3
+ # When evaluating values, the SDK will not use feature flags & settings from the ConfigCat CDN, but it will use
4
+ # all feature flags & settings that are loaded from local-override sources.
5
+ LOCAL_ONLY = 0
6
+
7
+ # When evaluating values, the SDK will use all feature flags & settings that are downloaded from the ConfigCat CDN,
8
+ # plus all feature flags & settings that are loaded from local-override sources. If a feature flag or a setting is
9
+ # defined both in the fetched and the local-override source then the local-override version will take precedence.
10
+ LOCAL_OVER_REMOTE = 1
11
+
12
+ # When evaluating values, the SDK will use all feature flags & settings that are downloaded from the ConfigCat CDN,
13
+ # plus all feature flags & settings that are loaded from local-override sources. If a feature flag or a setting is
14
+ # defined both in the fetched and the local-override source then the fetched version will take precedence.
15
+ REMOTE_OVER_LOCAL = 2
16
+ end
17
+
18
+ class OverrideDataSource
19
+ def initialize(override_behaviour)
20
+ @_override_behaviour = override_behaviour
21
+ end
22
+
23
+ def get_behaviour()
24
+ return @_override_behaviour
25
+ end
26
+
27
+ def get_overrides()
28
+ # :returns the override dictionary
29
+ return {}
30
+ end
31
+ end
32
+ end
@@ -39,132 +39,142 @@ module ConfigCat
39
39
  return return_value, return_variation_id
40
40
  end
41
41
 
42
- ConfigCat.logger.info("User object:\n%s" % user.to_s)
43
-
44
- # Evaluate targeting rules
45
- for rollout_rule in rollout_rules
46
- comparison_attribute = rollout_rule.fetch(COMPARISON_ATTRIBUTE)
47
- comparison_value = rollout_rule.fetch(COMPARISON_VALUE, nil)
48
- comparator = rollout_rule.fetch(COMPARATOR, nil)
49
-
50
- user_value = user.get_attribute(comparison_attribute)
51
- if user_value === nil || !user_value
52
- ConfigCat.logger.info(format_no_match_rule(comparison_attribute, user_value, comparator, comparison_value))
53
- next
54
- end
42
+ log_entries = ["Evaluating get_value('%s')." % key, "User object:\n%s" % user.to_s]
43
+
44
+ begin
45
+ # Evaluate targeting rules
46
+ for rollout_rule in rollout_rules
47
+ comparison_attribute = rollout_rule.fetch(COMPARISON_ATTRIBUTE)
48
+ comparison_value = rollout_rule.fetch(COMPARISON_VALUE, nil)
49
+ comparator = rollout_rule.fetch(COMPARATOR, nil)
50
+
51
+ user_value = user.get_attribute(comparison_attribute)
52
+ if user_value === nil || !user_value
53
+ log_entries.push(format_no_match_rule(comparison_attribute, user_value, comparator, comparison_value))
54
+ next
55
+ end
55
56
 
56
- value = rollout_rule.fetch(VALUE, nil)
57
- variation_id = rollout_rule.fetch(VARIATION_ID, default_variation_id)
57
+ value = rollout_rule.fetch(VALUE, nil)
58
+ variation_id = rollout_rule.fetch(VARIATION_ID, default_variation_id)
58
59
 
59
- # IS ONE OF
60
- if comparator == 0
61
- if comparison_value.to_s.split(",").map { |x| x.strip() }.include?(user_value.to_s)
62
- ConfigCat.logger.info(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
63
- return value, variation_id
64
- end
65
- # IS NOT ONE OF
66
- elsif comparator == 1
67
- if !comparison_value.to_s.split(",").map { |x| x.strip() }.include?(user_value.to_s)
68
- ConfigCat.logger.info(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
69
- return value, variation_id
70
- end
71
- # CONTAINS
72
- elsif comparator == 2
73
- if user_value.to_s.include?(comparison_value.to_s)
74
- ConfigCat.logger.info(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
75
- return value, variation_id
76
- end
77
- # DOES NOT CONTAIN
78
- elsif comparator == 3
79
- if !user_value.to_s.include?(comparison_value.to_s)
80
- ConfigCat.logger.info(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
81
- return value, variation_id
82
- end
83
- # IS ONE OF, IS NOT ONE OF (Semantic version)
84
- elsif (4 <= comparator) && (comparator <= 5)
85
- begin
86
- match = false
87
- user_value_version = Semantic::Version.new(user_value.to_s.strip())
88
- ((comparison_value.to_s.split(",").map { |x| x.strip() }).reject { |c| c.empty? }).each { |x|
89
- version = Semantic::Version.new(x)
90
- match = (user_value_version == version) || match
91
- }
92
- if match && comparator == 4 || !match && comparator == 5
93
- ConfigCat.logger.info(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
60
+ # IS ONE OF
61
+ if comparator == 0
62
+ if comparison_value.to_s.split(",").map { |x| x.strip() }.include?(user_value.to_s)
63
+ log_entries.push(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
94
64
  return value, variation_id
95
65
  end
96
- rescue ArgumentError => e
97
- ConfigCat.logger.warn(format_validation_error_rule(comparison_attribute, user_value, comparator, comparison_value, e.to_s))
98
- next
99
- end
100
- # LESS THAN, LESS THAN OR EQUALS TO, GREATER THAN, GREATER THAN OR EQUALS TO (Semantic version)
101
- elsif (6 <= comparator) && (comparator <= 9)
102
- begin
103
- user_value_version = Semantic::Version.new(user_value.to_s.strip())
104
- comparison_value_version = Semantic::Version.new(comparison_value.to_s.strip())
105
- if (comparator == 6 && user_value_version < comparison_value_version) ||
106
- (comparator == 7 && user_value_version <= comparison_value_version) ||
107
- (comparator == 8 && user_value_version > comparison_value_version) ||
108
- (comparator == 9 && user_value_version >= comparison_value_version)
109
- ConfigCat.logger.info(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
66
+ # IS NOT ONE OF
67
+ elsif comparator == 1
68
+ if !comparison_value.to_s.split(",").map { |x| x.strip() }.include?(user_value.to_s)
69
+ log_entries.push(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
110
70
  return value, variation_id
111
71
  end
112
- rescue ArgumentError => e
113
- ConfigCat.logger.warn(format_validation_error_rule(comparison_attribute, user_value, comparator, comparison_value, e.to_s))
114
- next
115
- end
116
- elsif (10 <= comparator) && (comparator <= 15)
117
- begin
118
- user_value_float = Float(user_value.to_s.gsub(",", "."))
119
- comparison_value_float = Float(comparison_value.to_s.gsub(",", "."))
120
- if (comparator == 10 && user_value_float == comparison_value_float) ||
121
- (comparator == 11 && user_value_float != comparison_value_float) ||
122
- (comparator == 12 && user_value_float < comparison_value_float) ||
123
- (comparator == 13 && user_value_float <= comparison_value_float) ||
124
- (comparator == 14 && user_value_float > comparison_value_float) ||
125
- (comparator == 15 && user_value_float >= comparison_value_float)
126
- ConfigCat.logger.info(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
72
+ # CONTAINS
73
+ elsif comparator == 2
74
+ if user_value.to_s.include?(comparison_value.to_s)
75
+ log_entries.push(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
76
+ return value, variation_id
77
+ end
78
+ # DOES NOT CONTAIN
79
+ elsif comparator == 3
80
+ if !user_value.to_s.include?(comparison_value.to_s)
81
+ log_entries.push(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
82
+ return value, variation_id
83
+ end
84
+ # IS ONE OF, IS NOT ONE OF (Semantic version)
85
+ elsif (4 <= comparator) && (comparator <= 5)
86
+ begin
87
+ match = false
88
+ user_value_version = Semantic::Version.new(user_value.to_s.strip())
89
+ ((comparison_value.to_s.split(",").map { |x| x.strip() }).reject { |c| c.empty? }).each { |x|
90
+ version = Semantic::Version.new(x)
91
+ match = (user_value_version == version) || match
92
+ }
93
+ if match && comparator == 4 || !match && comparator == 5
94
+ log_entries.push(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
95
+ return value, variation_id
96
+ end
97
+ rescue ArgumentError => e
98
+ message = format_validation_error_rule(comparison_attribute, user_value, comparator, comparison_value, e.to_s)
99
+ ConfigCat.logger.warn(message)
100
+ log_entries.push(message)
101
+ next
102
+ end
103
+ # LESS THAN, LESS THAN OR EQUALS TO, GREATER THAN, GREATER THAN OR EQUALS TO (Semantic version)
104
+ elsif (6 <= comparator) && (comparator <= 9)
105
+ begin
106
+ user_value_version = Semantic::Version.new(user_value.to_s.strip())
107
+ comparison_value_version = Semantic::Version.new(comparison_value.to_s.strip())
108
+ if (comparator == 6 && user_value_version < comparison_value_version) ||
109
+ (comparator == 7 && user_value_version <= comparison_value_version) ||
110
+ (comparator == 8 && user_value_version > comparison_value_version) ||
111
+ (comparator == 9 && user_value_version >= comparison_value_version)
112
+ log_entries.push(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
113
+ return value, variation_id
114
+ end
115
+ rescue ArgumentError => e
116
+ message = format_validation_error_rule(comparison_attribute, user_value, comparator, comparison_value, e.to_s)
117
+ ConfigCat.logger.warn(message)
118
+ log_entries.push(message)
119
+ next
120
+ end
121
+ elsif (10 <= comparator) && (comparator <= 15)
122
+ begin
123
+ user_value_float = Float(user_value.to_s.gsub(",", "."))
124
+ comparison_value_float = Float(comparison_value.to_s.gsub(",", "."))
125
+ if (comparator == 10 && user_value_float == comparison_value_float) ||
126
+ (comparator == 11 && user_value_float != comparison_value_float) ||
127
+ (comparator == 12 && user_value_float < comparison_value_float) ||
128
+ (comparator == 13 && user_value_float <= comparison_value_float) ||
129
+ (comparator == 14 && user_value_float > comparison_value_float) ||
130
+ (comparator == 15 && user_value_float >= comparison_value_float)
131
+ log_entries.push(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
132
+ return value, variation_id
133
+ end
134
+ rescue Exception => e
135
+ message = format_validation_error_rule(comparison_attribute, user_value, comparator, comparison_value, e.to_s)
136
+ ConfigCat.logger.warn(message)
137
+ log_entries.push(message)
138
+ next
139
+ end
140
+ # IS ONE OF (Sensitive)
141
+ elsif comparator == 16
142
+ if comparison_value.to_s.split(",").map { |x| x.strip() }.include?(Digest::SHA1.hexdigest(user_value).to_s)
143
+ log_entries.push(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
144
+ return value, variation_id
145
+ end
146
+ # IS NOT ONE OF (Sensitive)
147
+ elsif comparator == 17
148
+ if !comparison_value.to_s.split(",").map { |x| x.strip() }.include?(Digest::SHA1.hexdigest(user_value).to_s)
149
+ log_entries.push(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
127
150
  return value, variation_id
128
151
  end
129
- rescue Exception => e
130
- ConfigCat.logger.warn(format_validation_error_rule(comparison_attribute, user_value, comparator, comparison_value, e.to_s))
131
- next
132
- end
133
- # IS ONE OF (Sensitive)
134
- elsif comparator == 16
135
- if comparison_value.to_s.split(",").map { |x| x.strip() }.include?(Digest::SHA1.hexdigest(user_value).to_s)
136
- ConfigCat.logger.info(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
137
- return value, variation_id
138
- end
139
- # IS NOT ONE OF (Sensitive)
140
- elsif comparator == 17
141
- if !comparison_value.to_s.split(",").map { |x| x.strip() }.include?(Digest::SHA1.hexdigest(user_value).to_s)
142
- ConfigCat.logger.info(format_match_rule(comparison_attribute, user_value, comparator, comparison_value, value))
143
- return value, variation_id
144
152
  end
153
+ log_entries.push(format_no_match_rule(comparison_attribute, user_value, comparator, comparison_value))
145
154
  end
146
- ConfigCat.logger.info(format_no_match_rule(comparison_attribute, user_value, comparator, comparison_value))
147
- end
148
155
 
149
- if rollout_percentage_items.size > 0
150
- user_key = user.get_identifier()
151
- hash_candidate = ("%s%s" % [key, user_key]).encode("utf-8")
152
- hash_val = Digest::SHA1.hexdigest(hash_candidate)[0...7].to_i(base=16) % 100
153
- bucket = 0
154
- for rollout_percentage_item in rollout_percentage_items || []
155
- bucket += rollout_percentage_item.fetch(PERCENTAGE, 0)
156
- if hash_val < bucket
157
- percentage_value = rollout_percentage_item.fetch(VALUE, nil)
158
- variation_id = rollout_percentage_item.fetch(VARIATION_ID, default_variation_id)
159
- ConfigCat.logger.info("Evaluating %% options. Returning %s" % percentage_value)
160
- return percentage_value, variation_id
156
+ if rollout_percentage_items.size > 0
157
+ user_key = user.get_identifier()
158
+ hash_candidate = ("%s%s" % [key, user_key]).encode("utf-8")
159
+ hash_val = Digest::SHA1.hexdigest(hash_candidate)[0...7].to_i(base=16) % 100
160
+ bucket = 0
161
+ for rollout_percentage_item in rollout_percentage_items || []
162
+ bucket += rollout_percentage_item.fetch(PERCENTAGE, 0)
163
+ if hash_val < bucket
164
+ percentage_value = rollout_percentage_item.fetch(VALUE, nil)
165
+ variation_id = rollout_percentage_item.fetch(VARIATION_ID, default_variation_id)
166
+ log_entries.push("Evaluating %% options. Returning %s" % percentage_value)
167
+ return percentage_value, variation_id
168
+ end
161
169
  end
162
170
  end
171
+ return_value = setting_descriptor.fetch(VALUE, default_value)
172
+ return_variation_id = setting_descriptor.fetch(VARIATION_ID, default_variation_id)
173
+ log_entries.push("Returning %s" % return_value)
174
+ return return_value, return_variation_id
175
+ ensure
176
+ ConfigCat.logger.info(log_entries.join("\n"))
163
177
  end
164
- return_value = setting_descriptor.fetch(VALUE, default_value)
165
- return_variation_id = setting_descriptor.fetch(VARIATION_ID, default_variation_id)
166
- ConfigCat.logger.info("Returning %s" % return_value)
167
- return return_value, return_variation_id
168
178
  end
169
179
 
170
180
  private
@@ -32,6 +32,25 @@ module ConfigCat
32
32
  end
33
33
  return nil
34
34
  end
35
+
36
+ def to_s()
37
+ r = %Q({\n "Identifier": "#{@__identifier}")
38
+ if !@__data["Email"].equal?(nil)
39
+ r += %Q(,\n "Email": "#{@__data["Email"]}")
40
+ end
41
+ if !@__data["Country"].equal?(nil)
42
+ r += %Q(,\n "Country": "#{@__data["Country"]}")
43
+ end
44
+ if !@__custom.equal?(nil)
45
+ r += %Q(,\n "Custom": {)
46
+ for customField in @__custom
47
+ r += %Q(\n "#{customField}": "#{@__custom[customField]}",)
48
+ end
49
+ r += "\n }"
50
+ end
51
+ r += "\n}"
52
+ return r
53
+ end
35
54
  end
36
55
 
37
56
  end
@@ -1,3 +1,3 @@
1
1
  module ConfigCat
2
- VERSION = "4.0.0"
2
+ VERSION = "5.0.0"
3
3
  end
data/lib/configcat.rb CHANGED
@@ -33,6 +33,9 @@ module ConfigCat
33
33
  proxy_port: nil,
34
34
  proxy_user: nil,
35
35
  proxy_pass: nil,
36
+ open_timeout: 10,
37
+ read_timeout: 30,
38
+ flag_overrides: nil,
36
39
  data_governance: DataGovernance::GLOBAL)
37
40
  #
38
41
  # Create an instance of ConfigCatClient and setup Auto Poll mode with custom options
@@ -48,6 +51,9 @@ module ConfigCat
48
51
  # :param proxy_port: Proxy port
49
52
  # :param proxy_user: username for proxy authentication
50
53
  # :param proxy_pass: password for proxy authentication
54
+ # :param open_timeout: The number of seconds to wait for the server to make the initial connection. Default: 10 seconds.
55
+ # :param read_timeout: The number of seconds to wait for the server to respond before giving up. Default: 30 seconds.
56
+ # :param flag_overrides: An OverrideDataSource implementation used to override feature flags & settings.
51
57
  # :param data_governance:
52
58
  # Default: Global. Set this parameter to be in sync with the Data Governance preference on the Dashboard:
53
59
  # https://app.configcat.com/organization/data-governance
@@ -73,6 +79,9 @@ module ConfigCat
73
79
  proxy_port: proxy_port,
74
80
  proxy_user: proxy_user,
75
81
  proxy_pass: proxy_pass,
82
+ open_timeout: open_timeout,
83
+ read_timeout: read_timeout,
84
+ flag_overrides: flag_overrides,
76
85
  data_governance: data_governance)
77
86
  end
78
87
 
@@ -84,6 +93,9 @@ module ConfigCat
84
93
  proxy_port: nil,
85
94
  proxy_user: nil,
86
95
  proxy_pass: nil,
96
+ open_timeout: 10,
97
+ read_timeout: 30,
98
+ flag_overrides: nil,
87
99
  data_governance: DataGovernance::GLOBAL)
88
100
  #
89
101
  # Create an instance of ConfigCatClient and setup Lazy Load mode with custom options
@@ -97,6 +109,9 @@ module ConfigCat
97
109
  # :param proxy_port: Proxy port
98
110
  # :param proxy_user: username for proxy authentication
99
111
  # :param proxy_pass: password for proxy authentication
112
+ # :param open_timeout: The number of seconds to wait for the server to make the initial connection. Default: 10 seconds.
113
+ # :param read_timeout: The number of seconds to wait for the server to respond before giving up. Default: 30 seconds.
114
+ # :param flag_overrides: An OverrideDataSource implementation used to override feature flags & settings.
100
115
  # :param data_governance:
101
116
  # Default: Global. Set this parameter to be in sync with the Data Governance preference on the Dashboard:
102
117
  # https://app.configcat.com/organization/data-governance
@@ -119,16 +134,22 @@ module ConfigCat
119
134
  proxy_port: proxy_port,
120
135
  proxy_user: proxy_user,
121
136
  proxy_pass: proxy_pass,
137
+ open_timeout: open_timeout,
138
+ read_timeout: read_timeout,
139
+ flag_overrides: flag_overrides,
122
140
  data_governance: data_governance)
123
141
  end
124
142
 
125
143
  def ConfigCat.create_client_with_manual_poll(sdk_key,
126
144
  config_cache_class: nil,
127
145
  base_url: nil,
128
- proxy_address:nil,
129
- proxy_port:nil,
130
- proxy_user:nil,
131
- proxy_pass:nil,
146
+ proxy_address: nil,
147
+ proxy_port: nil,
148
+ proxy_user: nil,
149
+ proxy_pass: nil,
150
+ open_timeout: 10,
151
+ read_timeout: 30,
152
+ flag_overrides: nil,
132
153
  data_governance: DataGovernance::GLOBAL)
133
154
  #
134
155
  # Create an instance of ConfigCatClient and setup Manual Poll mode with custom options
@@ -141,6 +162,9 @@ module ConfigCat
141
162
  # :param proxy_port: Proxy port
142
163
  # :param proxy_user: username for proxy authentication
143
164
  # :param proxy_pass: password for proxy authentication
165
+ # :param open_timeout: The number of seconds to wait for the server to make the initial connection. Default: 10 seconds.
166
+ # :param read_timeout: The number of seconds to wait for the server to respond before giving up. Default: 30 seconds.
167
+ # :param flag_overrides: An OverrideDataSource implementation used to override feature flags & settings.
144
168
  # :param data_governance:
145
169
  # Default: Global. Set this parameter to be in sync with the Data Governance preference on the Dashboard:
146
170
  # https://app.configcat.com/organization/data-governance
@@ -160,6 +184,9 @@ module ConfigCat
160
184
  proxy_port: proxy_port,
161
185
  proxy_user: proxy_user,
162
186
  proxy_pass: proxy_pass,
187
+ open_timeout: open_timeout,
188
+ read_timeout: read_timeout,
189
+ flag_overrides: flag_overrides,
163
190
  data_governance: data_governance)
164
191
  end
165
192
 
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.0.0
4
+ version: 5.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-10-12 00:00:00.000000000 Z
11
+ date: 2022-04-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -67,19 +67,19 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '12.3'
69
69
  - !ruby/object:Gem::Dependency
70
- name: coveralls
70
+ name: codecov
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '0.8'
75
+ version: '0.5'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '0.8'
82
+ version: '0.5'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: webmock
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -114,7 +114,10 @@ files:
114
114
  - lib/configcat/datagovernance.rb
115
115
  - lib/configcat/interfaces.rb
116
116
  - lib/configcat/lazyloadingcachepolicy.rb
117
+ - lib/configcat/localdictionarydatasource.rb
118
+ - lib/configcat/localfiledatasource.rb
117
119
  - lib/configcat/manualpollingcachepolicy.rb
120
+ - lib/configcat/overridedatasource.rb
118
121
  - lib/configcat/rolloutevaluator.rb
119
122
  - lib/configcat/user.rb
120
123
  - lib/configcat/version.rb
@@ -137,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
137
140
  - !ruby/object:Gem::Version
138
141
  version: '0'
139
142
  requirements: []
140
- rubygems_version: 3.0.8
143
+ rubygems_version: 3.0.3.1
141
144
  signing_key:
142
145
  specification_version: 4
143
146
  summary: ConfigCat SDK for Ruby.