prefab-cloud-ruby 0.0.18 → 0.0.19
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/VERSION +1 -1
- data/lib/prefab/client.rb +5 -1
- data/lib/prefab/config_client.rb +55 -28
- data/lib/prefab/config_loader.rb +5 -0
- data/lib/prefab/noop_stats.rb +1 -1
- data/lib/prefab/ratelimit_client.rb +5 -1
- data/prefab-cloud-ruby.gemspec +3 -3
- data/test/test_config_loader.rb +17 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2d4da69f7090effaacca738be0a70baec8e2c8d0
|
4
|
+
data.tar.gz: 42b6de32dbefaa8f23ef024a4b7b8250d78d2c48
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 70ef17720139c952bdfdfa3938578c69365554155f20687bee068e5d3715b811394932e548b31673529448321b76f6c8892eec21dcaacd41fc4031ab63f9fb66
|
7
|
+
data.tar.gz: 85fddf3468abde394bada8b5404935e213bd52f193f0cc6e0abb04d34c5c6ad8b55c4fb83ab83d3234663f649354158aca1fb4c14a897dfb1477ad43e2926204
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.19
|
data/lib/prefab/client.rb
CHANGED
data/lib/prefab/config_client.rb
CHANGED
@@ -1,17 +1,16 @@
|
|
1
1
|
module Prefab
|
2
2
|
class ConfigClient
|
3
3
|
RECONNECT_WAIT = 5
|
4
|
-
|
4
|
+
SUSPENDERS_RESET_LOCK_SEC = 20
|
5
5
|
DEFAULT_CHECKPOINT_FREQ_SEC = 10
|
6
|
-
|
6
|
+
DEFAULT_MAX_SUSPENDERS_AGE_SEC = 60
|
7
7
|
|
8
8
|
def initialize(base_client, timeout)
|
9
9
|
@base_client = base_client
|
10
10
|
@timeout = timeout
|
11
11
|
@initialization_lock = Concurrent::ReadWriteLock.new
|
12
12
|
|
13
|
-
@
|
14
|
-
@checkpoint_max_age = @checkpoint_max_age_secs * 1000 * 10000
|
13
|
+
@suspenders_max_age_secs = (ENV["PREFAB_SUSPENDERS_MAX_AGE_SEC"] || DEFAULT_MAX_SUSPENDERS_AGE_SEC)
|
15
14
|
@checkpoint_freq_secs = (ENV["PREFAB_DEFAULT_CHECKPOINT_FREQ_SEC"] || DEFAULT_CHECKPOINT_FREQ_SEC)
|
16
15
|
|
17
16
|
@config_loader = Prefab::ConfigLoader.new(@base_client)
|
@@ -19,7 +18,9 @@ module Prefab
|
|
19
18
|
|
20
19
|
@initialization_lock.acquire_write_lock
|
21
20
|
|
22
|
-
|
21
|
+
load_or_save_checkpoint
|
22
|
+
ensure_api_connection_started
|
23
|
+
start_checkpointing_thread if has_real_cache?
|
23
24
|
end
|
24
25
|
|
25
26
|
def get(prop)
|
@@ -29,14 +30,14 @@ module Prefab
|
|
29
30
|
end
|
30
31
|
|
31
32
|
def upsert(key, config_value, namespace = nil, previous_key = nil)
|
32
|
-
raise "
|
33
|
-
raise "
|
33
|
+
raise "Key must not contain ':' set namespaces separately" if key.include? ":"
|
34
|
+
raise "Namespace must not contain ':'" if namespace&.include?(":")
|
34
35
|
config_delta = Prefab::ConfigClient.value_to_delta(key, config_value, namespace)
|
35
36
|
upsert_req = Prefab::UpsertRequest.new(config_delta: config_delta)
|
36
37
|
upsert_req.previous_key = previous_key if previous_key&.present?
|
37
38
|
|
38
39
|
@base_client.request Prefab::ConfigService, :upsert, req_options: { timeout: @timeout }, params: upsert_req
|
39
|
-
|
40
|
+
@base_client.stats.increment("prefab.config.upsert")
|
40
41
|
@config_loader.set(config_delta)
|
41
42
|
@config_loader.rm(previous_key) if previous_key&.present?
|
42
43
|
@config_resolver.update
|
@@ -76,6 +77,7 @@ module Prefab
|
|
76
77
|
@config_loader.set(delta)
|
77
78
|
end
|
78
79
|
@base_client.log_internal Logger::INFO, "Found checkpoint with highwater id #{@config_loader.highwater_mark}"
|
80
|
+
@base_client.stats.increment("prefab.config.checkpoint.load")
|
79
81
|
@config_resolver.update
|
80
82
|
finish_init!
|
81
83
|
else
|
@@ -91,6 +93,7 @@ module Prefab
|
|
91
93
|
@base_client.log_internal Logger::DEBUG, "Save Checkpoint #{@config_loader.highwater_mark} Thread #{Thread.current.object_id}"
|
92
94
|
@base_client.shared_cache.write(checkpoint_cache_key, Prefab::ConfigDeltas.encode(deltas))
|
93
95
|
@base_client.shared_cache.write(checkpoint_highwater_cache_key, @config_loader.highwater_mark)
|
96
|
+
@base_client.stats.increment("prefab.config.checkpoint.save")
|
94
97
|
rescue StandardError => exn
|
95
98
|
@base_client.log_internal Logger::INFO, "Issue Saving Checkpoint #{exn.message}"
|
96
99
|
end
|
@@ -101,7 +104,9 @@ module Prefab
|
|
101
104
|
Thread.new do
|
102
105
|
loop do
|
103
106
|
begin
|
104
|
-
|
107
|
+
load_or_save_checkpoint
|
108
|
+
|
109
|
+
suspenders_if_needed
|
105
110
|
|
106
111
|
started_at = Time.now
|
107
112
|
delta = @checkpoint_freq_secs - (Time.now - started_at)
|
@@ -120,9 +125,9 @@ module Prefab
|
|
120
125
|
# if it is lower than our own highwater mark, save a checkpoint
|
121
126
|
# if everything is up to date, but the shared highwater mark is old, coordinate amongst other processes to have
|
122
127
|
# one process "double check" by restarting the API thread
|
123
|
-
def
|
128
|
+
def load_or_save_checkpoint
|
124
129
|
shared_highwater_mark = get_shared_highwater_mark
|
125
|
-
@base_client.log_internal Logger::DEBUG, "Checkpoint_if_needed apx ahead/behind #{(@config_loader.highwater_mark - shared_highwater_mark) / (1000 * 10000)}"
|
130
|
+
@base_client.log_internal Logger::DEBUG, "Checkpoint_if_needed highwater apx ahead/behind #{(@config_loader.highwater_mark - shared_highwater_mark) / (1000 * 10000)}"
|
126
131
|
|
127
132
|
if shared_highwater_mark > @config_loader.highwater_mark
|
128
133
|
@base_client.log_internal Logger::DEBUG, "We were behind, loading checkpoint"
|
@@ -130,40 +135,52 @@ module Prefab
|
|
130
135
|
elsif shared_highwater_mark < @config_loader.highwater_mark
|
131
136
|
@base_client.log_internal Logger::DEBUG, "Saving off checkpoint"
|
132
137
|
save_checkpoint
|
133
|
-
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def suspenders_if_needed
|
142
|
+
if suspenders_age_is_old?
|
134
143
|
if get_shared_lock?
|
135
|
-
@base_client.log_internal Logger::DEBUG, "
|
144
|
+
@base_client.log_internal Logger::DEBUG, "Suspenders > PREFAB_SUSPENDERS_MAX_AGE_SEC #{@suspenders_max_age_secs}. We have been chosen to run suspenders"
|
136
145
|
reset_api_connection
|
137
146
|
else
|
138
|
-
@base_client.log_internal Logger::DEBUG, "
|
147
|
+
@base_client.log_internal Logger::DEBUG, "Suspenders > PREFAB_SUSPENDERS_MAX_AGE_SEC #{@suspenders_max_age_secs}. Other process is running suspenders"
|
139
148
|
end
|
140
149
|
end
|
141
150
|
end
|
142
151
|
|
143
|
-
def
|
144
|
-
Time.now.
|
145
|
-
|
146
|
-
|
147
|
-
def shared_highwater_is_old?
|
148
|
-
age = current_time_as_id - get_shared_highwater_mark
|
149
|
-
@base_client.log_internal Logger::DEBUG, "shared_highwater_is_old? apx #{age / (1000 * 10000)}" if age > @checkpoint_max_age
|
150
|
-
age > @checkpoint_max_age_secs
|
152
|
+
def suspenders_age_is_old?
|
153
|
+
age = Time.now.to_i - get_checkpoint_suspenders
|
154
|
+
@base_client.log_internal Logger::DEBUG, "checkpoint_suspenders_is_old? apx #{age}" if age > @suspenders_max_age_secs
|
155
|
+
age > @suspenders_max_age_secs
|
151
156
|
end
|
152
157
|
|
153
158
|
def get_shared_highwater_mark
|
154
159
|
(@base_client.shared_cache.read(checkpoint_highwater_cache_key) || 0).to_i
|
155
160
|
end
|
156
161
|
|
162
|
+
def get_checkpoint_suspenders
|
163
|
+
(@base_client.shared_cache.read(suspenders_last_run_cache_key) || 0).to_i
|
164
|
+
end
|
165
|
+
|
166
|
+
def set_suspenders
|
167
|
+
@base_client.shared_cache.write(suspenders_last_run_cache_key, Time.now.to_i)
|
168
|
+
end
|
169
|
+
|
157
170
|
def get_shared_lock?
|
158
|
-
in_progess = @base_client.shared_cache.read(
|
171
|
+
in_progess = @base_client.shared_cache.read(suspenders_reset_in_progress_cache_key)
|
159
172
|
if in_progess.nil?
|
160
|
-
@base_client.shared_cache.write(
|
173
|
+
@base_client.shared_cache.write(suspenders_reset_in_progress_cache_key, "true", { expires_in: SUSPENDERS_RESET_LOCK_SEC })
|
161
174
|
true
|
162
175
|
else
|
163
176
|
false
|
164
177
|
end
|
165
178
|
end
|
166
179
|
|
180
|
+
def ensure_api_connection_started
|
181
|
+
reset_api_connection if @api_connection_thread.nil?
|
182
|
+
end
|
183
|
+
|
167
184
|
def reset_api_connection
|
168
185
|
@api_connection_thread&.exit
|
169
186
|
start_api_connection_thread(@config_loader.highwater_mark)
|
@@ -182,6 +199,8 @@ module Prefab
|
|
182
199
|
config_req = Prefab::ConfigServicePointer.new(account_id: @base_client.account_id,
|
183
200
|
start_at_id: start_at_id)
|
184
201
|
@base_client.log_internal Logger::DEBUG, "start api connection thread #{start_at_id}"
|
202
|
+
@base_client.stats.increment("prefab.config.api.start")
|
203
|
+
set_suspenders
|
185
204
|
@api_connection_thread = Thread.new do
|
186
205
|
while true do
|
187
206
|
begin
|
@@ -202,16 +221,24 @@ module Prefab
|
|
202
221
|
end
|
203
222
|
end
|
204
223
|
|
224
|
+
def has_real_cache?
|
225
|
+
@base_client.shared_cache.class != NoopCache
|
226
|
+
end
|
227
|
+
|
205
228
|
def checkpoint_cache_key
|
206
|
-
"
|
229
|
+
@base_client.cache_key "config:checkpoint"
|
207
230
|
end
|
208
231
|
|
209
|
-
def
|
210
|
-
"
|
232
|
+
def suspenders_reset_in_progress_cache_key
|
233
|
+
@base_client.cache_key "config:checkpoint:updating"
|
211
234
|
end
|
212
235
|
|
213
236
|
def checkpoint_highwater_cache_key
|
214
|
-
"
|
237
|
+
@base_client.cache_key "config:checkpoint:highwater"
|
238
|
+
end
|
239
|
+
|
240
|
+
def suspenders_last_run_cache_key
|
241
|
+
@base_client.cache_key "config:checkpoint:suspenders"
|
215
242
|
end
|
216
243
|
end
|
217
244
|
end
|
data/lib/prefab/config_loader.rb
CHANGED
data/lib/prefab/noop_stats.rb
CHANGED
@@ -39,7 +39,7 @@ module Prefab
|
|
39
39
|
handle_error(e, on_error, groups)
|
40
40
|
end
|
41
41
|
|
42
|
-
def upsert(group, policy_name, limit, burst: nil)
|
42
|
+
def upsert(group, policy_name, limit, burst: nil, safety_level: nil)
|
43
43
|
burst = limit if burst.nil?
|
44
44
|
limit_defintion = Prefab::LimitDefinition.new(
|
45
45
|
account_id: @base_client.account_id,
|
@@ -48,6 +48,10 @@ module Prefab
|
|
48
48
|
limit: limit,
|
49
49
|
burst: burst
|
50
50
|
)
|
51
|
+
unless safety_level.nil?
|
52
|
+
limit_defintion.safety_level = safety_level
|
53
|
+
end
|
54
|
+
|
51
55
|
@base_client.request Prefab::RateLimitService, :upsert_limit_definition, params: limit_defintion
|
52
56
|
end
|
53
57
|
|
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 0.0.
|
5
|
+
# stub: prefab-cloud-ruby 0.0.19 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "prefab-cloud-ruby".freeze
|
9
|
-
s.version = "0.0.
|
9
|
+
s.version = "0.0.19"
|
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 = "2018-
|
14
|
+
s.date = "2018-04-09"
|
15
15
|
s.description = "RateLimits & Config as a service".freeze
|
16
16
|
s.email = "jdwyer@prefab.cloud".freeze
|
17
17
|
s.extra_rdoc_files = [
|
data/test/test_config_loader.rb
CHANGED
@@ -25,6 +25,23 @@ class TestConfigLoader < Minitest::Test
|
|
25
25
|
assert_equal 5, @loader.highwater_mark
|
26
26
|
end
|
27
27
|
|
28
|
+
|
29
|
+
|
30
|
+
def test_keeps_most_recent
|
31
|
+
assert_equal 0, @loader.highwater_mark
|
32
|
+
@loader.set(Prefab::ConfigDelta.new(id: 1, key: "sample_int", value: Prefab::ConfigValue.new(int: 1)))
|
33
|
+
assert_equal 1, @loader.highwater_mark
|
34
|
+
should_be :int, 1, "sample_int"
|
35
|
+
|
36
|
+
@loader.set(Prefab::ConfigDelta.new(id: 4, key: "sample_int", value: Prefab::ConfigValue.new(int: 4)))
|
37
|
+
assert_equal 4, @loader.highwater_mark
|
38
|
+
should_be :int, 4, "sample_int"
|
39
|
+
|
40
|
+
@loader.set(Prefab::ConfigDelta.new(id: 2, key: "sample_int", value: Prefab::ConfigValue.new(int: 2)))
|
41
|
+
assert_equal 4, @loader.highwater_mark
|
42
|
+
should_be :int, 4, "sample_int"
|
43
|
+
end
|
44
|
+
|
28
45
|
def test_api_precedence
|
29
46
|
should_be :int, 123, "sample_int"
|
30
47
|
|
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: 0.0.
|
4
|
+
version: 0.0.19
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeff Dwyer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-04-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: grpc
|