prefab-cloud-ruby 0.0.14 → 0.0.15

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
  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