prefab-cloud-ruby 1.1.1 → 1.1.2
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/CHANGELOG.md +6 -0
- data/VERSION +1 -1
- data/lib/prefab/client.rb +1 -1
- data/lib/prefab/config_client.rb +48 -1
- data/lib/prefab/config_client_presenter.rb +2 -2
- data/lib/prefab/criteria_evaluator.rb +3 -1
- data/lib/prefab/logger_client.rb +9 -2
- data/lib/prefab/options.rb +16 -1
- data/prefab-cloud-ruby.gemspec +3 -4
- data/test/support/mock_base_client.rb +1 -1
- data/test/test_config_client.rb +34 -1
- data/test/test_criteria_evaluator.rb +2 -0
- data/test/test_helper.rb +1 -1
- metadata +2 -3
- data/.envrc +0 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0d3348f914c10f7f7d45814ff1be70a067e227cbef499b6f44736f10aa5cc30c
|
4
|
+
data.tar.gz: 52699e5fee8f4f6ea26a89d3e3381cc6220d25d4720dcb69d7aee8de8f79e1c9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c960267ea9f3e09664e48965fb470c1a3093061b1e6906f8f73b4c80a396ab80e0b383b3e42209e6cc95d5fab778c6221a2b9292a2015603139a874586eddf22
|
7
|
+
data.tar.gz: 98cc728c27f1b1f6267c4b01b754d07f23fa60f8dfad95edd9e9288de666f6fc92539bf7124e85337023bf772946422c8919c75ebf487e9999a60251734a4d61
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.1.2 - 2023-10-13
|
4
|
+
|
5
|
+
- Add `cloud.prefab.client.criteria_evaluator` `debug` logging of evaluations (#150)
|
6
|
+
- Add `x_use_local_cache` for local caching (#148)
|
7
|
+
- Tests run in RubyMine (#147)
|
8
|
+
|
3
9
|
## 1.1.1 - 2023-10-11
|
4
10
|
|
5
11
|
- Migrate happy-path client-initialization logging to `DEBUG` level rather than `INFO` (#144)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.1.
|
1
|
+
1.1.2
|
data/lib/prefab/client.rb
CHANGED
data/lib/prefab/config_client.rb
CHANGED
@@ -5,6 +5,7 @@ module Prefab
|
|
5
5
|
RECONNECT_WAIT = 5
|
6
6
|
DEFAULT_CHECKPOINT_FREQ_SEC = 60
|
7
7
|
SSE_READ_TIMEOUT = 300
|
8
|
+
STALE_CACHE_WARN_HOURS = 5
|
8
9
|
AUTH_USER = 'authuser'
|
9
10
|
LOGGING_KEY_PREFIX = "#{Prefab::LoggerClient::BASE_KEY}#{Prefab::LoggerClient::SEP}".freeze
|
10
11
|
|
@@ -112,6 +113,10 @@ module Prefab
|
|
112
113
|
|
113
114
|
return if success
|
114
115
|
|
116
|
+
success = load_cache
|
117
|
+
|
118
|
+
return if success
|
119
|
+
|
115
120
|
@base_client.log_internal ::Logger::WARN, 'No success loading checkpoints'
|
116
121
|
end
|
117
122
|
|
@@ -130,6 +135,7 @@ module Prefab
|
|
130
135
|
if resp.status == 200
|
131
136
|
configs = PrefabProto::Configs.decode(resp.body)
|
132
137
|
load_configs(configs, source)
|
138
|
+
cache_configs(configs)
|
133
139
|
true
|
134
140
|
else
|
135
141
|
@base_client.log_internal ::Logger::INFO, "Checkpoint #{source} failed to load. Response #{resp.status}"
|
@@ -171,6 +177,47 @@ module Prefab
|
|
171
177
|
finish_init!(source, project_id)
|
172
178
|
end
|
173
179
|
|
180
|
+
def cache_path
|
181
|
+
return @cache_path unless @cache_path.nil?
|
182
|
+
@cache_path ||= calc_cache_path
|
183
|
+
FileUtils.mkdir_p(File.dirname(@cache_path))
|
184
|
+
@cache_path
|
185
|
+
end
|
186
|
+
|
187
|
+
def calc_cache_path
|
188
|
+
file_name = "prefab.cache.#{@base_client.options.api_key_id}.json"
|
189
|
+
dir = ENV.fetch('XDG_CACHE_HOME', File.join(Dir.home, '.cache'))
|
190
|
+
File.join(dir, file_name)
|
191
|
+
end
|
192
|
+
|
193
|
+
def cache_configs(configs)
|
194
|
+
return unless @options.use_local_cache && !@options.is_fork
|
195
|
+
File.open(cache_path, "w") do |f|
|
196
|
+
f.flock(File::LOCK_EX)
|
197
|
+
f.write(PrefabProto::Configs.encode_json(configs))
|
198
|
+
end
|
199
|
+
@base_client.log_internal ::Logger::DEBUG, "Cached configs to #{cache_path}"
|
200
|
+
rescue => e
|
201
|
+
@base_client.log_internal ::Logger::DEBUG, "Failed to cache configs to #{cache_path} #{e}"
|
202
|
+
end
|
203
|
+
|
204
|
+
def load_cache
|
205
|
+
return false unless @options.use_local_cache
|
206
|
+
File.open(cache_path) do |f|
|
207
|
+
f.flock(File::LOCK_SH)
|
208
|
+
configs = PrefabProto::Configs.decode_json(f.read)
|
209
|
+
load_configs(configs, :cache)
|
210
|
+
|
211
|
+
hours_old = ((Time.now - File.mtime(f)) / 60 / 60).round(2)
|
212
|
+
if hours_old > STALE_CACHE_WARN_HOURS
|
213
|
+
@base_client.log_internal ::Logger::INFO, "Stale Cache Load: #{hours_old} hours old"
|
214
|
+
end
|
215
|
+
end
|
216
|
+
rescue => e
|
217
|
+
@base_client.log_internal ::Logger::DEBUG, "Failed to read cached configs at #{cache_path}. #{e}"
|
218
|
+
false
|
219
|
+
end
|
220
|
+
|
174
221
|
# A thread that checks for a checkpoint
|
175
222
|
def start_checkpointing_thread
|
176
223
|
Thread.new do
|
@@ -197,7 +244,7 @@ module Prefab
|
|
197
244
|
source: source,
|
198
245
|
project_id: project_id,
|
199
246
|
project_env_id: @config_resolver.project_env_id,
|
200
|
-
|
247
|
+
api_key_id: @base_client.options.api_key_id
|
201
248
|
)
|
202
249
|
@base_client.log_internal ::Logger::INFO, presenter.to_s
|
203
250
|
@base_client.log_internal ::Logger::DEBUG, to_s
|
@@ -2,12 +2,12 @@
|
|
2
2
|
|
3
3
|
module Prefab
|
4
4
|
class ConfigClientPresenter
|
5
|
-
def initialize(size:, source:, project_id:, project_env_id:,
|
5
|
+
def initialize(size:, source:, project_id:, project_env_id:, api_key_id:)
|
6
6
|
@size = size
|
7
7
|
@source = source
|
8
8
|
@project_id = project_id
|
9
9
|
@project_env_id = project_env_id
|
10
|
-
@api_key_id =
|
10
|
+
@api_key_id = api_key_id
|
11
11
|
end
|
12
12
|
|
13
13
|
def to_s
|
@@ -19,8 +19,10 @@ module Prefab
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def evaluate(properties)
|
22
|
-
evaluate_for_env(@project_env_id, properties) ||
|
22
|
+
rtn = evaluate_for_env(@project_env_id, properties) ||
|
23
23
|
evaluate_for_env(0, properties)
|
24
|
+
@base_client.log_internal ::Logger::DEBUG, "Eval Key #{@config.key} Result #{rtn&.value} with #{properties.to_h}", :criteria_evaluator unless @config.config_type == :LOG_LEVEL
|
25
|
+
rtn
|
24
26
|
end
|
25
27
|
|
26
28
|
def all_criteria_match?(conditional_value, props)
|
data/lib/prefab/logger_client.rb
CHANGED
@@ -22,6 +22,7 @@ module Prefab
|
|
22
22
|
self.formatter = formatter
|
23
23
|
@config_client = BootstrappingConfigClient.new
|
24
24
|
@silences = Concurrent::Map.new(initial_capacity: 2)
|
25
|
+
@recurse_check = Concurrent::Map.new(initial_capacity: 2)
|
25
26
|
@prefix = "#{prefix}#{prefix && '.'}"
|
26
27
|
|
27
28
|
@log_path_aggregator = log_path_aggregator
|
@@ -37,13 +38,19 @@ module Prefab
|
|
37
38
|
end
|
38
39
|
|
39
40
|
def log_internal(message, path, progname, severity, log_context={}, &block)
|
41
|
+
return if @recurse_check[local_log_id]
|
42
|
+
@recurse_check[local_log_id] = true
|
43
|
+
|
40
44
|
path = if path
|
41
45
|
"#{INTERNAL_PREFIX}.#{path}"
|
42
46
|
else
|
43
47
|
INTERNAL_PREFIX
|
44
48
|
end
|
45
|
-
|
46
|
-
|
49
|
+
begin
|
50
|
+
log(message, path, progname, severity, log_context, &block)
|
51
|
+
ensure
|
52
|
+
@recurse_check[local_log_id] = false
|
53
|
+
end
|
47
54
|
end
|
48
55
|
|
49
56
|
def log(message, path, progname, severity, log_context={})
|
data/lib/prefab/options.rb
CHANGED
@@ -16,6 +16,8 @@ module Prefab
|
|
16
16
|
attr_reader :prefab_config_classpath_dir
|
17
17
|
attr_reader :prefab_envs
|
18
18
|
attr_reader :collect_sync_interval
|
19
|
+
attr_reader :use_local_cache
|
20
|
+
attr_accessor :is_fork
|
19
21
|
|
20
22
|
DEFAULT_LOG_FORMATTER = proc { |data|
|
21
23
|
severity = data[:severity]
|
@@ -77,7 +79,8 @@ module Prefab
|
|
77
79
|
context_max_size: DEFAULT_MAX_EVAL_SUMMARIES,
|
78
80
|
collect_evaluation_summaries: true,
|
79
81
|
collect_max_evaluation_summaries: DEFAULT_MAX_EVAL_SUMMARIES,
|
80
|
-
allow_telemetry_in_local_mode: false
|
82
|
+
allow_telemetry_in_local_mode: false,
|
83
|
+
x_use_local_cache: false
|
81
84
|
)
|
82
85
|
@api_key = api_key
|
83
86
|
@logdev = logdev
|
@@ -98,6 +101,8 @@ module Prefab
|
|
98
101
|
@collect_evaluation_summaries = collect_evaluation_summaries
|
99
102
|
@collect_max_evaluation_summaries = collect_max_evaluation_summaries
|
100
103
|
@allow_telemetry_in_local_mode = allow_telemetry_in_local_mode
|
104
|
+
@use_local_cache = x_use_local_cache
|
105
|
+
@is_fork = false
|
101
106
|
|
102
107
|
# defaults that may be overridden by context_upload_mode
|
103
108
|
@collect_shapes = false
|
@@ -156,6 +161,16 @@ module Prefab
|
|
156
161
|
ENV['PREFAB_CDN_URL'] || "#{@prefab_api_url.gsub(/\./, '-')}.global.ssl.fastly.net"
|
157
162
|
end
|
158
163
|
|
164
|
+
def api_key_id
|
165
|
+
@api_key&.split("-")&.first
|
166
|
+
end
|
167
|
+
|
168
|
+
def for_fork
|
169
|
+
clone = self.clone
|
170
|
+
clone.is_fork = true
|
171
|
+
clone
|
172
|
+
end
|
173
|
+
|
159
174
|
private
|
160
175
|
|
161
176
|
def telemetry_allowed?(option)
|
data/prefab-cloud-ruby.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: prefab-cloud-ruby 1.1.
|
5
|
+
# stub: prefab-cloud-ruby 1.1.2 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "prefab-cloud-ruby".freeze
|
9
|
-
s.version = "1.1.
|
9
|
+
s.version = "1.1.2"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib".freeze]
|
13
13
|
s.authors = ["Jeff Dwyer".freeze]
|
14
|
-
s.date = "2023-10-
|
14
|
+
s.date = "2023-10-13"
|
15
15
|
s.description = "Feature Flags, Live Config, and Dynamic Log Levels as a service".freeze
|
16
16
|
s.email = "jdwyer@prefab.cloud".freeze
|
17
17
|
s.executables = ["console".freeze]
|
@@ -21,7 +21,6 @@ Gem::Specification.new do |s|
|
|
21
21
|
"README.md"
|
22
22
|
]
|
23
23
|
s.files = [
|
24
|
-
".envrc",
|
25
24
|
".envrc.sample",
|
26
25
|
".github/workflows/ruby.yml",
|
27
26
|
".gitmodules",
|
data/test/test_config_client.rb
CHANGED
@@ -9,7 +9,8 @@ class TestConfigClient < Minitest::Test
|
|
9
9
|
prefab_config_override_dir: 'none',
|
10
10
|
prefab_config_classpath_dir: 'test',
|
11
11
|
prefab_envs: 'unit_tests',
|
12
|
-
prefab_datasources: Prefab::Options::DATASOURCES::LOCAL_ONLY
|
12
|
+
prefab_datasources: Prefab::Options::DATASOURCES::LOCAL_ONLY,
|
13
|
+
x_use_local_cache: true,
|
13
14
|
)
|
14
15
|
|
15
16
|
@config_client = Prefab::ConfigClient.new(MockBaseClient.new(options), 10)
|
@@ -73,4 +74,36 @@ class TestConfigClient < Minitest::Test
|
|
73
74
|
|
74
75
|
assert_match(/format is invalid/, err.message)
|
75
76
|
end
|
77
|
+
|
78
|
+
def test_caching
|
79
|
+
@config_client.send(:cache_configs,
|
80
|
+
PrefabProto::Configs.new(configs:
|
81
|
+
[PrefabProto::Config.new(key: 'test', id: 1,
|
82
|
+
rows: [PrefabProto::ConfigRow.new(
|
83
|
+
values: [
|
84
|
+
PrefabProto::ConditionalValue.new(
|
85
|
+
value: PrefabProto::ConfigValue.new(string: "test value")
|
86
|
+
)
|
87
|
+
]
|
88
|
+
)])],
|
89
|
+
config_service_pointer: PrefabProto::ConfigServicePointer.new(project_id: 3, project_env_id: 5)))
|
90
|
+
@config_client.send(:load_cache)
|
91
|
+
assert_equal "test value", @config_client.get("test")
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_cache_path_respects_xdg
|
95
|
+
options = Prefab::Options.new(
|
96
|
+
prefab_datasources: Prefab::Options::DATASOURCES::LOCAL_ONLY,
|
97
|
+
x_use_local_cache: true,
|
98
|
+
api_key: "123-ENV-KEY-SDK",)
|
99
|
+
|
100
|
+
config_client = Prefab::ConfigClient.new(MockBaseClient.new(options), 10)
|
101
|
+
assert_equal "#{Dir.home}/.cache/prefab.cache.123.json", config_client.send(:cache_path)
|
102
|
+
|
103
|
+
with_env('XDG_CACHE_HOME', '/tmp') do
|
104
|
+
config_client = Prefab::ConfigClient.new(MockBaseClient.new(options), 10)
|
105
|
+
assert_equal "/tmp/prefab.cache.123.json", config_client.send(:cache_path)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
76
109
|
end
|
@@ -724,6 +724,8 @@ class TestCriteriaEvaluator < Minitest::Test
|
|
724
724
|
FakeLogger.new
|
725
725
|
end
|
726
726
|
|
727
|
+
def log_internal(level, msg, path = nil, **tags); end
|
728
|
+
|
727
729
|
def evaluation_summary_aggregator
|
728
730
|
@evaluation_summary_aggregator ||= Prefab::EvaluationSummaryAggregator.new(client: self, max_keys: 9999, sync_interval: 9999)
|
729
731
|
end
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prefab-cloud-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeff Dwyer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-10-
|
11
|
+
date: 2023-10-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -180,7 +180,6 @@ extra_rdoc_files:
|
|
180
180
|
- LICENSE.txt
|
181
181
|
- README.md
|
182
182
|
files:
|
183
|
-
- ".envrc"
|
184
183
|
- ".envrc.sample"
|
185
184
|
- ".github/workflows/ruby.yml"
|
186
185
|
- ".gitmodules"
|
data/.envrc
DELETED