prefab-cloud-ruby 0.0.14 → 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 70b7e6905adede604544ce942c02d4b77c8e368b
4
- data.tar.gz: 9b5091d9df705f1c8dd01ab7bc218ac0bcdada04
3
+ metadata.gz: b73b4ea9cec303d84c4e8cd05458a8373cfcb0b7
4
+ data.tar.gz: 243c8d3dda441efd9b3f5741c6b52355a2256665
5
5
  SHA512:
6
- metadata.gz: 75fb25229c3523976b4048c4bbc220705486062620c8f51951ff41cb80c0b575cb4bbab1cf792366c108c553b94a00a0f89b594e328d725eeb7a58bce8990865
7
- data.tar.gz: a8cc43a7a3e102bd4bfe131f93e3ff0eb0a389cc3e8ba10357d426aefd5608ebcee9269cc6ca228ae059ee0b8ec590e09fa7a68cb5f383c176254563df4e0817
6
+ metadata.gz: a2375b7451fcd3623a14dd74cdaf568521baa5e554b15f67d1675570a89783f5212938d6f5e2dc44afa4544709cda070d4b59c72dd7124a3f881f3d8ef34f02e
7
+ data.tar.gz: b1032ec6c8953b2c0896367bd1276315271ba75c68b3f57134b082d35f8b2b972bf36e76546cf34bad48286eadba4cff4d32b2d774403cc550f6d26841a3ef6a
data/Gemfile CHANGED
@@ -1,10 +1,10 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gem 'grpc', '~> 1.8.3'
3
+ gem 'grpc', '~> 1.10.0'
4
4
  gem 'concurrent-ruby', '~> 1.0', '>= 1.0.5'
5
5
 
6
6
  group :development do
7
- gem 'grpc-tools', '~> 1.8.3'
7
+ gem 'grpc-tools', '~> 1.10.0'
8
8
  gem "shoulda", ">= 0"
9
9
  gem "rdoc", "~> 3.12"
10
10
  gem "bundler", "~> 1.0"
data/Gemfile.lock CHANGED
@@ -22,7 +22,7 @@ GEM
22
22
  faraday (~> 0.8)
23
23
  hashie (~> 3.5, >= 3.5.2)
24
24
  oauth2 (~> 1.0)
25
- google-protobuf (3.5.1)
25
+ google-protobuf (3.5.1.2)
26
26
  googleapis-common-protos-types (1.0.1)
27
27
  google-protobuf (~> 3.0)
28
28
  googleauth (0.6.2)
@@ -33,11 +33,11 @@ GEM
33
33
  multi_json (~> 1.11)
34
34
  os (~> 0.9)
35
35
  signet (~> 0.7)
36
- grpc (1.8.3)
36
+ grpc (1.10.0)
37
37
  google-protobuf (~> 3.1)
38
38
  googleapis-common-protos-types (~> 1.0.0)
39
39
  googleauth (>= 0.5.1, < 0.7)
40
- grpc-tools (1.8.3)
40
+ grpc-tools (1.10.0)
41
41
  hashie (3.5.6)
42
42
  highline (1.7.10)
43
43
  i18n (0.9.1)
@@ -105,8 +105,8 @@ PLATFORMS
105
105
  DEPENDENCIES
106
106
  bundler (~> 1.0)
107
107
  concurrent-ruby (~> 1.0, >= 1.0.5)
108
- grpc (~> 1.8.3)
109
- grpc-tools (~> 1.8.3)
108
+ grpc (~> 1.10.0)
109
+ grpc-tools (~> 1.10.0)
110
110
  juwelier (~> 2.1.0)
111
111
  rdoc (~> 3.12)
112
112
  shoulda
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.14
1
+ 0.0.15
data/lib/prefab/client.rb CHANGED
@@ -36,14 +36,8 @@ module Prefab
36
36
  GRPC::Core::Channel.new('api.prefab.cloud:8443', nil, @creds)
37
37
  end
38
38
 
39
- def reset_channel!
40
- @_channel = nil
41
- end
42
-
43
39
  def config_client(timeout: 5.0)
44
40
  @config_client ||= Prefab::ConfigClient.new(self, timeout)
45
- @config_client.init
46
- @config_client
47
41
  end
48
42
 
49
43
  def ratelimit_client(timeout: 5.0)
@@ -55,7 +49,7 @@ module Prefab
55
49
  end
56
50
 
57
51
  def log(base_logger = @logger)
58
- @logger_client || Prefab::LoggerClient.new(self, base_logger)
52
+ @logger_client ||= Prefab::LoggerClient.new(base_logger)
59
53
  end
60
54
 
61
55
  def log_internal(level, msg)
@@ -70,7 +64,7 @@ module Prefab
70
64
 
71
65
  begin
72
66
  attempts += 1
73
- return stub_for(service).send(method, *params)
67
+ return stub_for(service, opts[:timeout]).send(method, *params)
74
68
  rescue => exception
75
69
 
76
70
  log_internal :warn, exception
@@ -95,11 +89,12 @@ module Prefab
95
89
  reset_channel!
96
90
  end
97
91
 
98
- def stub_for(service)
99
- @stubs[service] ||= service::Stub.new(nil,
100
- nil,
101
- channel_override: channel,
102
- interceptors: [@interceptor])
92
+ def stub_for(service, timeout)
93
+ @stubs["#{service}_#{timeout}"] ||= service::Stub.new(nil,
94
+ nil,
95
+ timeout: timeout,
96
+ channel_override: channel,
97
+ interceptors: [@interceptor])
103
98
  end
104
99
 
105
100
  def ssl_certs
@@ -1,29 +1,31 @@
1
1
  module Prefab
2
2
  class ConfigClient
3
3
  RECONNECT_WAIT = 5
4
- CHECKPOINT_FREQ_SEC = 10
5
- SUSPENDERS_FREQ_SEC = 60
4
+ CHECKPOINT_LOCK = 20
5
+ DEFAULT_CHECKPOINT_FREQ_SEC = 10
6
+ DEFAULT_MAX_CHECKPOINT_AGE_SEC = 60
6
7
 
7
8
  def initialize(base_client, timeout)
8
9
  @base_client = base_client
9
10
  @timeout = timeout
10
- @initialized = false
11
- end
12
-
13
- def init
14
- if !@initialized
15
- @initialized = true
16
- @config_loader = Prefab::ConfigLoader.new(@base_client)
17
- @config_resolver = Prefab::ConfigResolver.new(@base_client, @config_loader)
18
- start_at_id = load_checkpoint
19
- start_api_connection_thread(start_at_id)
20
- start_checkpointing_thread
21
- start_suspenders_thread
22
- end
11
+ @initialization_lock = Concurrent::ReadWriteLock.new
12
+
13
+ @checkpoint_max_age_secs = (ENV["PREFAB_CHECKPOINT_MAX_AGE_SEC"] || DEFAULT_MAX_CHECKPOINT_AGE_SEC)
14
+ @checkpoint_max_age = @checkpoint_max_age_secs * 1000 * 10000
15
+ @checkpoint_freq_secs = (ENV["PREFAB_DEFAULT_CHECKPOINT_FREQ_SEC"] || DEFAULT_CHECKPOINT_FREQ_SEC)
16
+
17
+ @config_loader = Prefab::ConfigLoader.new(@base_client)
18
+ @config_resolver = Prefab::ConfigResolver.new(@base_client, @config_loader)
19
+
20
+ @initialization_lock.acquire_write_lock
21
+
22
+ start_checkpointing_thread
23
23
  end
24
24
 
25
25
  def get(prop)
26
- @config_resolver.get(prop) if @config_resolver
26
+ @initialization_lock.with_read_lock do
27
+ @config_resolver.get(prop)
28
+ end
27
29
  end
28
30
 
29
31
  def upsert(key, config_value, namespace = nil, previous_key = nil)
@@ -33,7 +35,7 @@ module Prefab
33
35
  upsert_req = Prefab::UpsertRequest.new(config_delta: config_delta)
34
36
  upsert_req.previous_key = previous_key if previous_key&.present?
35
37
 
36
- @base_client.request Prefab::ConfigService, :upsert, req_options: {timeout: @timeout}, params: upsert_req
38
+ @base_client.request Prefab::ConfigService, :upsert, req_options: { timeout: @timeout }, params: upsert_req
37
39
 
38
40
  @config_loader.set(config_delta)
39
41
  @config_loader.rm(previous_key) if previous_key&.present?
@@ -41,7 +43,7 @@ module Prefab
41
43
  end
42
44
 
43
45
  def reset
44
- @base_client.reset_channel!
46
+ @base_client.reset!
45
47
  @_stub = nil
46
48
  end
47
49
 
@@ -63,30 +65,35 @@ module Prefab
63
65
  interceptors: [@base_client.interceptor])
64
66
  end
65
67
 
66
- def cache_key
67
- "prefab:config:checkpoint"
68
- end
69
-
70
68
  # Bootstrap out of the cache
71
69
  # returns the high-watermark of what was in the cache
72
70
  def load_checkpoint
73
- checkpoint = @base_client.shared_cache.read(cache_key)
74
- start_at_id = 0
71
+ checkpoint = @base_client.shared_cache.read(checkpoint_cache_key)
75
72
 
76
73
  if checkpoint
77
74
  deltas = Prefab::ConfigDeltas.decode(checkpoint)
78
75
  deltas.deltas.each do |delta|
79
- @base_client.log_internal :debug, "checkpoint set #{delta.key} #{delta.value.int} #{delta.value.string} #{delta.id} "
80
76
  @config_loader.set(delta)
81
- start_at_id = [delta.id, start_at_id].max
82
77
  end
83
- @base_client.log_internal :info, "Found checkpoint with highwater id #{start_at_id}"
78
+ @base_client.log_internal :info, "Found checkpoint with highwater id #{@config_loader.highwater_mark}"
84
79
  @config_resolver.update
80
+ finish_init!
85
81
  else
86
82
  @base_client.log_internal :info, "No checkpoint"
87
83
  end
84
+ end
88
85
 
89
- start_at_id
86
+ # Save off the config to a local cache as a backup
87
+ #
88
+ def save_checkpoint
89
+ begin
90
+ deltas = @config_resolver.export_api_deltas
91
+ @base_client.log_internal :debug, "Save Checkpoint #{@config_loader.highwater_mark} Thread #{Thread.current.object_id}"
92
+ @base_client.shared_cache.write(checkpoint_cache_key, Prefab::ConfigDeltas.encode(deltas))
93
+ @base_client.shared_cache.write(checkpoint_highwater_cache_key, @config_loader.highwater_mark)
94
+ rescue StandardError => exn
95
+ @base_client.log_internal :info, "Issue Saving Checkpoint #{exn.message}"
96
+ end
90
97
  end
91
98
 
92
99
  # A thread that saves current state to the cache, "checkpointing" it
@@ -94,14 +101,13 @@ module Prefab
94
101
  Thread.new do
95
102
  loop do
96
103
  begin
104
+ checkpoint_if_needed
105
+
97
106
  started_at = Time.now
98
- delta = CHECKPOINT_FREQ_SEC - (Time.now - started_at)
107
+ delta = @checkpoint_freq_secs - (Time.now - started_at)
99
108
  if delta > 0
100
109
  sleep(delta)
101
110
  end
102
- deltas = @config_resolver.export_api_deltas
103
- @base_client.log_internal :debug, "Save Checkpoint #{deltas.deltas.map {|d| d.id}.max} Thread #{Thread.current.object_id}"
104
- @base_client.shared_cache.write(cache_key, Prefab::ConfigDeltas.encode(deltas))
105
111
  rescue StandardError => exn
106
112
  @base_client.log_internal :info, "Issue Checkpointing #{exn.message}"
107
113
  end
@@ -109,12 +115,74 @@ module Prefab
109
115
  end
110
116
  end
111
117
 
118
+ # check what our shared highwater mark is
119
+ # if it is higher than our own highwater mark, we must have missed something, so load the checkpoint
120
+ # if it is lower than our own highwater mark, save a checkpoint
121
+ # if everything is up to date, but the shared highwater mark is old, coordinate amongst other processes to have
122
+ # one process "double check" by restarting the API thread
123
+ def checkpoint_if_needed
124
+ shared_highwater_mark = get_shared_highwater_mark
125
+ @base_client.log_internal :debug, "Checkpoint_if_needed apx ahead/behind #{(@config_loader.highwater_mark - shared_highwater_mark) / (1000 * 10000)}"
126
+
127
+ if shared_highwater_mark > @config_loader.highwater_mark
128
+ @base_client.log_internal :debug, "We were behind, loading checkpoint"
129
+ load_checkpoint
130
+ elsif shared_highwater_mark < @config_loader.highwater_mark
131
+ @base_client.log_internal :debug, "Saving off checkpoint"
132
+ save_checkpoint
133
+ elsif shared_highwater_is_old?
134
+ if get_shared_lock?
135
+ @base_client.log_internal :debug, "Shared highwater mark > PREFAB_CHECKPOINT_MAX_AGE #{@checkpoint_max_age_secs}. We have been chosen to run suspenders"
136
+ reset_api_connection
137
+ else
138
+ @base_client.log_internal :debug, "Shared highwater mark > PREFAB_CHECKPOINT_MAX_AGE #{@checkpoint_max_age_secs}. Other process is running suspenders"
139
+ end
140
+ end
141
+ end
142
+
143
+ def current_time_as_id
144
+ Time.now.to_f * 1000 * 10000
145
+ end
146
+
147
+ def shared_highwater_is_old?
148
+ age = current_time_as_id - get_shared_highwater_mark
149
+ @base_client.log_internal :debug, "shared_highwater_is_old? apx #{age / (1000 * 10000)}" if age > @checkpoint_max_age
150
+ age > @checkpoint_max_age_secs
151
+ end
152
+
153
+ def get_shared_highwater_mark
154
+ (@base_client.shared_cache.read(checkpoint_highwater_cache_key) || 0).to_i
155
+ end
156
+
157
+ def get_shared_lock?
158
+ in_progess = @base_client.shared_cache.read(checkpoint_update_in_progress_cache_key)
159
+ if in_progess.nil?
160
+ @base_client.shared_cache.write(checkpoint_update_in_progress_cache_key, "true", { expires_in: CHECKPOINT_LOCK })
161
+ true
162
+ else
163
+ false
164
+ end
165
+ end
166
+
167
+ def reset_api_connection
168
+ @api_connection_thread&.exit
169
+ start_api_connection_thread(@config_loader.highwater_mark)
170
+ end
171
+
172
+ def finish_init!
173
+ if @initialization_lock.write_locked?
174
+ @initialization_lock.release_write_lock
175
+ @base_client.log.set_config_client(self)
176
+ end
177
+ end
178
+
112
179
  # Setup a streaming connection to the API
113
180
  # Save new config values into the loader
114
181
  def start_api_connection_thread(start_at_id)
115
182
  config_req = Prefab::ConfigServicePointer.new(account_id: @base_client.account_id,
116
183
  start_at_id: start_at_id)
117
- Thread.new do
184
+ @base_client.log_internal :debug, "start api connection thread #{start_at_id}"
185
+ @api_connection_thread = Thread.new do
118
186
  while true do
119
187
  begin
120
188
  resp = stub.get_config(config_req)
@@ -123,6 +191,7 @@ module Prefab
123
191
  @config_loader.set(delta)
124
192
  end
125
193
  @config_resolver.update
194
+ finish_init!
126
195
  end
127
196
  rescue => e
128
197
  @base_client.log_internal :info, ("config client encountered #{e.message} pausing #{RECONNECT_WAIT}")
@@ -133,38 +202,16 @@ module Prefab
133
202
  end
134
203
  end
135
204
 
136
- # Streaming connections don't guarantee all items have been seen
137
- #
138
- def start_suspenders_thread
139
- start_at_suspenders = 0
140
-
141
- Thread.new do
142
- loop do
143
- begin
144
- started_at = Time.now
145
- config_req = Prefab::ConfigServicePointer.new(account_id: @base_client.account_id,
146
- start_at_id: start_at_suspenders)
147
-
148
- resp = @base_client.request Prefab::ConfigService, :get_config, req_options: {timeout: @timeout}, params: config_req
205
+ def checkpoint_cache_key
206
+ "prefab:config:checkpoint"
207
+ end
149
208
 
150
- resp.each do |r|
151
- r.deltas.each do |delta|
152
- @config_loader.set(delta)
153
- start_at_suspenders = [start_at_suspenders, delta.id].max
154
- end
155
- end
156
- rescue GRPC::DeadlineExceeded
157
- # Ignore. This is a streaming endpoint, but we only need a single response
158
- rescue => e
159
- @base_client.log_internal :info, "Suspenders encountered an issue #{e.message}"
160
- end
209
+ def checkpoint_update_in_progress_cache_key
210
+ "prefab:config:checkpoint:updating"
211
+ end
161
212
 
162
- delta = SUSPENDERS_FREQ_SEC - (Time.now - started_at)
163
- if delta > 0
164
- sleep(delta)
165
- end
166
- end
167
- end
213
+ def checkpoint_highwater_cache_key
214
+ "prefab:config:checkpoint:highwater"
168
215
  end
169
216
  end
170
217
  end
@@ -1,8 +1,11 @@
1
1
  require 'yaml'
2
2
  module Prefab
3
3
  class ConfigLoader
4
+ attr_reader :highwater_mark
5
+
4
6
  def initialize(base_client)
5
7
  @base_client = base_client
8
+ @highwater_mark = 0
6
9
  @classpath_config = load_classpath_config
7
10
  @local_overrides = load_local_overrides
8
11
  @api_config = Concurrent::Map.new
@@ -23,6 +26,7 @@ module Prefab
23
26
  else
24
27
  @api_config[delta.key] = delta
25
28
  end
29
+ @highwater_mark = [delta.id, @highwater_mark].max
26
30
  end
27
31
 
28
32
  def rm(key)
@@ -62,10 +66,10 @@ module Prefab
62
66
 
63
67
  def load(filename)
64
68
  if File.exist? filename
65
- @base_client.log_internal :warn, "Load #{filename}"
69
+ @base_client.log_internal :info, "Load #{filename}"
66
70
  YAML.load_file(filename)
67
71
  else
68
- @base_client.log_internal :warn, "No file #{filename}"
72
+ @base_client.log_internal :info, "No file #{filename}"
69
73
  {}
70
74
  end
71
75
  end
@@ -6,7 +6,6 @@ module Prefab
6
6
  @local_store = {}
7
7
  @namespace = base_client.namespace
8
8
  @config_loader = config_loader
9
- @logger = base_client.log
10
9
  make_local
11
10
  end
12
11
 
@@ -4,9 +4,9 @@ module Prefab
4
4
  SEP = ".".freeze
5
5
  BASE = "log_level".freeze
6
6
 
7
- def initialize(base_client, base_logger)
8
- @base_client = base_client
7
+ def initialize(base_logger)
9
8
  @base_logger = base_logger
9
+ @config_client = BootstrappingConfigClient.new
10
10
  end
11
11
 
12
12
  def debug msg
@@ -29,6 +29,30 @@ module Prefab
29
29
  pf_log_internal level, msg, "", loc
30
30
  end
31
31
 
32
+ def level= lvl
33
+ #noop
34
+ end
35
+
36
+ def formatter
37
+ @formatter ||= ActiveSupport::Logger::SimpleFormatter.new
38
+ end
39
+
40
+ def level
41
+ :debug
42
+ end
43
+
44
+ def debug?
45
+ true
46
+ end
47
+
48
+ def info?
49
+ true
50
+ end
51
+
52
+ def set_config_client(config_client)
53
+ @config_client = config_client
54
+ end
55
+
32
56
  private
33
57
 
34
58
  def pf_log(level, msg, loc)
@@ -43,10 +67,10 @@ module Prefab
43
67
  path = "#{path.gsub("/", SEP).gsub(".rb", "")}#{SEP}#{base_label}"
44
68
  path.slice! SEP
45
69
 
46
- closest_log_level_match = @base_client.config_client.get(BASE) || :warn
70
+ closest_log_level_match = @config_client.get(BASE) || :warn
47
71
  path.split(SEP).inject([BASE]) do |memo, n|
48
72
  memo << n
49
- val = @base_client.config_client.get memo.join(SEP)
73
+ val = @config_client.get(memo.join(SEP))
50
74
  unless val.nil?
51
75
  closest_log_level_match = val
52
76
  end
@@ -71,5 +95,13 @@ module Prefab
71
95
  end
72
96
  end
73
97
  end
98
+
99
+ # StubConfigClient to be used while config client initializes
100
+ # since it may log
101
+ class BootstrappingConfigClient
102
+ def get(key)
103
+ ENV["PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL"] || :info
104
+ end
105
+ end
74
106
  end
75
107
 
@@ -9,5 +9,8 @@ module Prefab
9
9
 
10
10
  def read(name)
11
11
  end
12
+
13
+ def delete(name)
14
+ end
12
15
  end
13
16
  end
@@ -39,6 +39,18 @@ module Prefab
39
39
  handle_error(e, on_error, groups)
40
40
  end
41
41
 
42
+ def upsert(group, policy_name, limit, burst: nil)
43
+ burst = limit if burst.nil?
44
+ limit_defintion = Prefab::LimitDefinition.new(
45
+ account_id: @base_client.account_id,
46
+ group: group,
47
+ policy_name: Object.const_get("Prefab::LimitResponse::LimitPolicyNames::#{policy_name}"),
48
+ limit: limit,
49
+ burst: burst
50
+ )
51
+ @base_client.request Prefab::RateLimitService, :upsert_limit_definition, params: limit_defintion
52
+ end
53
+
42
54
  private
43
55
 
44
56
  def handle_error(e, on_error, groups)
@@ -47,10 +59,10 @@ module Prefab
47
59
  message = "ratelimit for #{groups} error: #{e.message}"
48
60
  case on_error
49
61
  when :log_and_pass
50
- @base_client.logger.warn(message)
62
+ @base_client.log.warn(message)
51
63
  Prefab::LimitResponse.new(passed: true, amount: 0)
52
64
  when :log_and_hit
53
- @base_client.logger.warn(message)
65
+ @base_client.log.warn(message)
54
66
  Prefab::LimitResponse.new(passed: false, amount: 0)
55
67
  when :throw
56
68
  raise e
data/lib/prefab_pb.rb CHANGED
@@ -109,6 +109,9 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
109
109
  optional :batch_template, :string, 6
110
110
  optional :batch_separator, :string, 7
111
111
  end
112
+ add_message "prefab.BasicResponse" do
113
+ optional :message, :string, 1
114
+ end
112
115
  add_enum "prefab.OnFailure" do
113
116
  value :NOT_SET, 0
114
117
  value :LOG_AND_PASS, 1
@@ -134,5 +137,6 @@ module Prefab
134
137
  FeatureFlags = Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.FeatureFlags").msgclass
135
138
  BufferedRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.BufferedRequest").msgclass
136
139
  BatchRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.BatchRequest").msgclass
140
+ BasicResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.BasicResponse").msgclass
137
141
  OnFailure = Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.OnFailure").enummodule
138
142
  end
@@ -15,6 +15,7 @@ module Prefab
15
15
  self.service_name = 'prefab.RateLimitService'
16
16
 
17
17
  rpc :LimitCheck, LimitRequest, LimitResponse
18
+ rpc :UpsertLimitDefinition, LimitDefinition, BasicResponse
18
19
  end
19
20
 
20
21
  Stub = Service.rpc_stub_class
@@ -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.14 ruby lib
5
+ # stub: prefab-cloud-ruby 0.0.15 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "prefab-cloud-ruby".freeze
9
- s.version = "0.0.14"
9
+ s.version = "0.0.15"
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-02-20"
14
+ s.date = "2018-03-08"
15
15
  s.description = "RateLimits & Config as a service".freeze
16
16
  s.email = "jdwyer@prefab.cloud".freeze
17
17
  s.extra_rdoc_files = [
@@ -55,18 +55,18 @@ Gem::Specification.new do |s|
55
55
  s.specification_version = 4
56
56
 
57
57
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
58
- s.add_runtime_dependency(%q<grpc>.freeze, ["~> 1.8.3"])
58
+ s.add_runtime_dependency(%q<grpc>.freeze, ["~> 1.10.0"])
59
59
  s.add_runtime_dependency(%q<concurrent-ruby>.freeze, [">= 1.0.5", "~> 1.0"])
60
- s.add_development_dependency(%q<grpc-tools>.freeze, ["~> 1.8.3"])
60
+ s.add_development_dependency(%q<grpc-tools>.freeze, ["~> 1.10.0"])
61
61
  s.add_development_dependency(%q<shoulda>.freeze, [">= 0"])
62
62
  s.add_development_dependency(%q<rdoc>.freeze, ["~> 3.12"])
63
63
  s.add_development_dependency(%q<bundler>.freeze, ["~> 1.0"])
64
64
  s.add_development_dependency(%q<juwelier>.freeze, ["~> 2.1.0"])
65
65
  s.add_development_dependency(%q<simplecov>.freeze, [">= 0"])
66
66
  else
67
- s.add_dependency(%q<grpc>.freeze, ["~> 1.8.3"])
67
+ s.add_dependency(%q<grpc>.freeze, ["~> 1.10.0"])
68
68
  s.add_dependency(%q<concurrent-ruby>.freeze, [">= 1.0.5", "~> 1.0"])
69
- s.add_dependency(%q<grpc-tools>.freeze, ["~> 1.8.3"])
69
+ s.add_dependency(%q<grpc-tools>.freeze, ["~> 1.10.0"])
70
70
  s.add_dependency(%q<shoulda>.freeze, [">= 0"])
71
71
  s.add_dependency(%q<rdoc>.freeze, ["~> 3.12"])
72
72
  s.add_dependency(%q<bundler>.freeze, ["~> 1.0"])
@@ -74,9 +74,9 @@ Gem::Specification.new do |s|
74
74
  s.add_dependency(%q<simplecov>.freeze, [">= 0"])
75
75
  end
76
76
  else
77
- s.add_dependency(%q<grpc>.freeze, ["~> 1.8.3"])
77
+ s.add_dependency(%q<grpc>.freeze, ["~> 1.10.0"])
78
78
  s.add_dependency(%q<concurrent-ruby>.freeze, [">= 1.0.5", "~> 1.0"])
79
- s.add_dependency(%q<grpc-tools>.freeze, ["~> 1.8.3"])
79
+ s.add_dependency(%q<grpc-tools>.freeze, ["~> 1.10.0"])
80
80
  s.add_dependency(%q<shoulda>.freeze, [">= 0"])
81
81
  s.add_dependency(%q<rdoc>.freeze, ["~> 3.12"])
82
82
  s.add_dependency(%q<bundler>.freeze, ["~> 1.0"])
@@ -14,13 +14,22 @@ class TestConfigLoader < Minitest::Test
14
14
  should_be :double, 12.12, "sample_double"
15
15
  end
16
16
 
17
+ def test_highwater
18
+ assert_equal 0, @loader.highwater_mark
19
+ @loader.set(Prefab::ConfigDelta.new(id: 1, key: "sample_int", value: Prefab::ConfigValue.new(int: 456)))
20
+ assert_equal 1, @loader.highwater_mark
21
+
22
+ @loader.set(Prefab::ConfigDelta.new(id: 5, key: "sample_int", value: Prefab::ConfigValue.new(int: 456)))
23
+ assert_equal 5, @loader.highwater_mark
24
+ @loader.set(Prefab::ConfigDelta.new(id: 2, key: "sample_int", value: Prefab::ConfigValue.new(int: 456)))
25
+ assert_equal 5, @loader.highwater_mark
26
+ end
17
27
 
18
28
  def test_api_precedence
19
29
  should_be :int, 123, "sample_int"
20
30
 
21
31
  @loader.set(Prefab::ConfigDelta.new(key: "sample_int", value: Prefab::ConfigValue.new(int: 456)))
22
32
  should_be :int, 456, "sample_int"
23
-
24
33
  end
25
34
 
26
35
  def test_api_deltas
data/test/test_helper.rb CHANGED
@@ -12,10 +12,12 @@ class MockBaseClient
12
12
  def account_id
13
13
  1
14
14
  end
15
+
16
+ def log_internal level, message
17
+ end
15
18
  end
16
19
 
17
20
  class MockConfigLoader
18
21
  def calc_config
19
-
20
22
  end
21
23
  end
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.14
4
+ version: 0.0.15
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-02-20 00:00:00.000000000 Z
11
+ date: 2018-03-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: grpc
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 1.8.3
19
+ version: 1.10.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 1.8.3
26
+ version: 1.10.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: concurrent-ruby
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -50,14 +50,14 @@ dependencies:
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: 1.8.3
53
+ version: 1.10.0
54
54
  type: :development
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
- version: 1.8.3
60
+ version: 1.10.0
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: shoulda
63
63
  requirement: !ruby/object:Gem::Requirement