prefab-cloud-ruby 0.0.13 → 0.0.14

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: 4e22f15bdc4f3f3d98d0a397e0685a7b457231cc
4
- data.tar.gz: 3a1b5af166637f72160e1fdea3ed2f0d08aa2ded
3
+ metadata.gz: 70b7e6905adede604544ce942c02d4b77c8e368b
4
+ data.tar.gz: 9b5091d9df705f1c8dd01ab7bc218ac0bcdada04
5
5
  SHA512:
6
- metadata.gz: a94a74cc16025df1c4cf0cdf2a1a8b1aa1f7b501bb9aba66d7643ba643ed96f82b840adabed2f14a3038a5f10aac4641557869777da0cf56d842dfcb1e3d9e06
7
- data.tar.gz: 9c659f681aa37174f81967e8a698fbf796f87c4d12bc647353e5e30b0266b6e6f0a127ace4fe342bb4d55c97fdf83957559ad95ff750c4b81310e6cd3a6957e5
6
+ metadata.gz: 75fb25229c3523976b4048c4bbc220705486062620c8f51951ff41cb80c0b575cb4bbab1cf792366c108c553b94a00a0f89b594e328d725eeb7a58bce8990865
7
+ data.tar.gz: a8cc43a7a3e102bd4bfe131f93e3ff0eb0a389cc3e8ba10357d426aefd5608ebcee9269cc6ca228ae059ee0b8ec590e09fa7a68cb5f383c176254563df4e0817
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.13
1
+ 0.0.14
@@ -13,6 +13,5 @@ require 'prefab/logger_client'
13
13
  require 'prefab/auth_interceptor'
14
14
  require 'prefab/noop_cache'
15
15
  require 'prefab/noop_stats'
16
- require 'prefab/retry'
17
16
  require 'prefab/murmer3'
18
17
 
@@ -1,5 +1,9 @@
1
1
  module Prefab
2
2
  class Client
3
+
4
+ MAX_SLEEP_SEC = 10
5
+ BASE_SLEEP_SEC = 0.5
6
+
3
7
  attr_reader :account_id, :shared_cache, :stats, :namespace, :creds, :interceptor
4
8
 
5
9
  def initialize(api_key: ENV['PREFAB_API_KEY'],
@@ -21,8 +25,8 @@ module Prefab
21
25
  @namespace = namespace
22
26
 
23
27
  @interceptor = AuthInterceptor.new(api_key)
24
-
25
28
  @creds = GRPC::Core::ChannelCredentials.new(ssl_certs)
29
+ @stubs = {}
26
30
  end
27
31
 
28
32
  def channel
@@ -38,7 +42,7 @@ module Prefab
38
42
 
39
43
  def config_client(timeout: 5.0)
40
44
  @config_client ||= Prefab::ConfigClient.new(self, timeout)
41
- @config_init = true
45
+ @config_client.init
42
46
  @config_client
43
47
  end
44
48
 
@@ -51,12 +55,53 @@ module Prefab
51
55
  end
52
56
 
53
57
  def log(base_logger = @logger)
54
- return @logger if !@config_init
55
58
  @logger_client || Prefab::LoggerClient.new(self, base_logger)
56
59
  end
57
60
 
61
+ def log_internal(level, msg)
62
+ log.log_for level, msg, "prefab"
63
+ end
64
+
65
+ def request(service, method, req_options: {}, params: {})
66
+ opts = { timeout: 10 }.merge(req_options)
67
+
68
+ attempts = 0
69
+ start_time = Time.now
70
+
71
+ begin
72
+ attempts += 1
73
+ return stub_for(service).send(method, *params)
74
+ rescue => exception
75
+
76
+ log_internal :warn, exception
77
+
78
+ if Time.now - start_time > opts[:timeout]
79
+ raise exception
80
+ end
81
+ sleep_seconds = [BASE_SLEEP_SEC * (2 ** (attempts - 1)), MAX_SLEEP_SEC].min
82
+ sleep_seconds = sleep_seconds * (0.5 * (1 + rand()))
83
+ sleep_seconds = [BASE_SLEEP_SEC, sleep_seconds].max
84
+ log_internal :info, "Sleep #{sleep_seconds} and Reset #{service} #{method}"
85
+ sleep sleep_seconds
86
+ reset!
87
+ retry
88
+ end
89
+ end
90
+
58
91
  private
59
92
 
93
+ def reset!
94
+ @stubs.clear
95
+ reset_channel!
96
+ end
97
+
98
+ def stub_for(service)
99
+ @stubs[service] ||= service::Stub.new(nil,
100
+ nil,
101
+ channel_override: channel,
102
+ interceptors: [@interceptor])
103
+ end
104
+
60
105
  def ssl_certs
61
106
  ssl_certs = ""
62
107
  Dir["#{OpenSSL::X509::DEFAULT_CERT_DIR}/*.pem"].each do |cert|
@@ -7,16 +7,23 @@ module Prefab
7
7
  def initialize(base_client, timeout)
8
8
  @base_client = base_client
9
9
  @timeout = timeout
10
- @config_loader = Prefab::ConfigLoader.new(base_client)
11
- @config_resolver = Prefab::ConfigResolver.new(base_client, @config_loader)
12
- start_at_id = load_checkpoint
13
- start_api_connection_thread(start_at_id)
14
- start_checkpointing_thread
15
- start_suspenders_thread
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
16
23
  end
17
24
 
18
25
  def get(prop)
19
- @config_resolver.get(prop)
26
+ @config_resolver.get(prop) if @config_resolver
20
27
  end
21
28
 
22
29
  def upsert(key, config_value, namespace = nil, previous_key = nil)
@@ -26,7 +33,8 @@ module Prefab
26
33
  upsert_req = Prefab::UpsertRequest.new(config_delta: config_delta)
27
34
  upsert_req.previous_key = previous_key if previous_key&.present?
28
35
 
29
- Retry.it method(:stub_with_timeout), :upsert, upsert_req, @timeout, method(:reset)
36
+ @base_client.request Prefab::ConfigService, :upsert, req_options: {timeout: @timeout}, params: upsert_req
37
+
30
38
  @config_loader.set(config_delta)
31
39
  @config_loader.rm(previous_key) if previous_key&.present?
32
40
  @config_resolver.update
@@ -35,7 +43,6 @@ module Prefab
35
43
  def reset
36
44
  @base_client.reset_channel!
37
45
  @_stub = nil
38
- @_stub_with_timeout = nil
39
46
  end
40
47
 
41
48
  def to_s
@@ -56,14 +63,6 @@ module Prefab
56
63
  interceptors: [@base_client.interceptor])
57
64
  end
58
65
 
59
- def stub_with_timeout
60
- @_stub_with_timeout = Prefab::ConfigService::Stub.new(nil,
61
- nil,
62
- channel_override: @base_client.channel,
63
- timeout: @timeout,
64
- interceptors: [@base_client.interceptor])
65
- end
66
-
67
66
  def cache_key
68
67
  "prefab:config:checkpoint"
69
68
  end
@@ -77,14 +76,14 @@ module Prefab
77
76
  if checkpoint
78
77
  deltas = Prefab::ConfigDeltas.decode(checkpoint)
79
78
  deltas.deltas.each do |delta|
80
- @base_client.log.debug "checkpoint set #{delta.key} #{delta.value.int} #{delta.value.string} #{delta.id} "
79
+ @base_client.log_internal :debug, "checkpoint set #{delta.key} #{delta.value.int} #{delta.value.string} #{delta.id} "
81
80
  @config_loader.set(delta)
82
81
  start_at_id = [delta.id, start_at_id].max
83
82
  end
84
- @base_client.log.info "Found checkpoint with highwater id #{start_at_id}"
83
+ @base_client.log_internal :info, "Found checkpoint with highwater id #{start_at_id}"
85
84
  @config_resolver.update
86
85
  else
87
- @base_client.log.info "No checkpoint"
86
+ @base_client.log_internal :info, "No checkpoint"
88
87
  end
89
88
 
90
89
  start_at_id
@@ -101,10 +100,10 @@ module Prefab
101
100
  sleep(delta)
102
101
  end
103
102
  deltas = @config_resolver.export_api_deltas
104
- @base_client.log.debug "==CHECKPOINT==#{deltas.deltas.map {|d| d.id}.max}===#{Thread.current.object_id}=="
103
+ @base_client.log_internal :debug, "Save Checkpoint #{deltas.deltas.map {|d| d.id}.max} Thread #{Thread.current.object_id}"
105
104
  @base_client.shared_cache.write(cache_key, Prefab::ConfigDeltas.encode(deltas))
106
105
  rescue StandardError => exn
107
- @base_client.log.info "Issue Checkpointing #{exn.message}"
106
+ @base_client.log_internal :info, "Issue Checkpointing #{exn.message}"
108
107
  end
109
108
  end
110
109
  end
@@ -126,7 +125,7 @@ module Prefab
126
125
  @config_resolver.update
127
126
  end
128
127
  rescue => e
129
- @base_client.log.info("config client encountered #{e.message} pausing #{RECONNECT_WAIT}")
128
+ @base_client.log_internal :info, ("config client encountered #{e.message} pausing #{RECONNECT_WAIT}")
130
129
  reset
131
130
  sleep(RECONNECT_WAIT)
132
131
  end
@@ -145,7 +144,9 @@ module Prefab
145
144
  started_at = Time.now
146
145
  config_req = Prefab::ConfigServicePointer.new(account_id: @base_client.account_id,
147
146
  start_at_id: start_at_suspenders)
148
- resp = stub_with_timeout.get_config(config_req)
147
+
148
+ resp = @base_client.request Prefab::ConfigService, :get_config, req_options: {timeout: @timeout}, params: config_req
149
+
149
150
  resp.each do |r|
150
151
  r.deltas.each do |delta|
151
152
  @config_loader.set(delta)
@@ -155,7 +156,7 @@ module Prefab
155
156
  rescue GRPC::DeadlineExceeded
156
157
  # Ignore. This is a streaming endpoint, but we only need a single response
157
158
  rescue => e
158
- @base_client.log.info "Suspenders encountered an issue #{e.message}"
159
+ @base_client.log_internal :info, "Suspenders encountered an issue #{e.message}"
159
160
  end
160
161
 
161
162
  delta = SUSPENDERS_FREQ_SEC - (Time.now - started_at)
@@ -62,9 +62,10 @@ module Prefab
62
62
 
63
63
  def load(filename)
64
64
  if File.exist? filename
65
+ @base_client.log_internal :warn, "Load #{filename}"
65
66
  YAML.load_file(filename)
66
67
  else
67
- @base_client.logger.info "No file #{filename}"
68
+ @base_client.log_internal :warn, "No file #{filename}"
68
69
  {}
69
70
  end
70
71
  end
@@ -1,40 +1,58 @@
1
1
  module Prefab
2
2
  class LoggerClient
3
3
 
4
+ SEP = ".".freeze
5
+ BASE = "log_level".freeze
6
+
4
7
  def initialize(base_client, base_logger)
5
8
  @base_client = base_client
6
9
  @base_logger = base_logger
7
10
  end
8
11
 
9
- def info msg
10
- pf_log :info, msg, caller_locations(1, 1)[0]
11
- end
12
-
13
12
  def debug msg
14
13
  pf_log :debug, msg, caller_locations(1, 1)[0]
15
14
  end
16
15
 
16
+ def info msg
17
+ pf_log :info, msg, caller_locations(1, 1)[0]
18
+ end
19
+
17
20
  def warn msg
18
21
  pf_log :warn, msg, caller_locations(1, 1)[0]
19
22
  end
20
23
 
21
- def pf_log level, msg, loc
22
- path = loc.absolute_path + ""
24
+ def error msg
25
+ pf_log :error, msg, caller_locations(1, 1)[0]
26
+ end
27
+
28
+ def log_for level, msg, loc
29
+ pf_log_internal level, msg, "", loc
30
+ end
31
+
32
+ private
33
+
34
+ def pf_log(level, msg, loc)
35
+ pf_log_internal level, msg, loc.absolute_path, loc.base_label
36
+ end
37
+
38
+ def pf_log_internal(level, msg, absolute_path, base_label)
39
+
40
+ path = absolute_path + ""
23
41
  path.slice! Dir.pwd
24
42
 
25
- path = "#{path.gsub("/", ":").gsub(".rb", "")}:#{loc.base_label}"
26
- path.slice! ":"
43
+ path = "#{path.gsub("/", SEP).gsub(".rb", "")}#{SEP}#{base_label}"
44
+ path.slice! SEP
27
45
 
28
- base = "log_level"
29
- closest_log_level_match = @base_client.config_client.get(base) || :warn
30
- path.split(":").inject([base]) do |memo, n|
46
+ closest_log_level_match = @base_client.config_client.get(BASE) || :warn
47
+ path.split(SEP).inject([BASE]) do |memo, n|
31
48
  memo << n
32
- val = @base_client.config_client.get memo.join(".")
49
+ val = @base_client.config_client.get memo.join(SEP)
33
50
  unless val.nil?
34
51
  closest_log_level_match = val
35
52
  end
36
53
  memo
37
54
  end
55
+
38
56
  if val(closest_log_level_match) <= val(level)
39
57
  @base_logger.unknown "#{level.to_s.upcase.ljust(5)} #{path} #{msg}"
40
58
  end
@@ -26,7 +26,7 @@ module Prefab
26
26
  allow_partial_response: allow_partial_response
27
27
  )
28
28
 
29
- result = Retry.it(method(:stub), :limit_check, req, @timeout, method(:reset))
29
+ result = @base_client.request Prefab::RateLimitService, :limit_check, req_options: {timeout: @timeout}, params: req
30
30
 
31
31
  reset = result.limit_reset_at
32
32
  @base_client.shared_cache.write(expiry_cache_key, reset) unless reset < 1 # protobuf default int to 0
@@ -41,19 +41,6 @@ module Prefab
41
41
 
42
42
  private
43
43
 
44
- def reset
45
- @base_client.reset_channel!
46
- @_stub = nil
47
- end
48
-
49
- def stub
50
- @_stub ||= Prefab::RateLimitService::Stub.new(nil,
51
- nil,
52
- channel_override: @base_client.channel,
53
- timeout: @timeout,
54
- interceptors: [@base_client.interceptor])
55
- end
56
-
57
44
  def handle_error(e, on_error, groups)
58
45
  @base_client.stats.increment("prefab.ratelimit.error", tags: ["type:limit"])
59
46
 
@@ -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.13 ruby lib
5
+ # stub: prefab-cloud-ruby 0.0.14 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "prefab-cloud-ruby".freeze
9
- s.version = "0.0.13"
9
+ s.version = "0.0.14"
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-13"
14
+ s.date = "2018-02-20"
15
15
  s.description = "RateLimits & Config as a service".freeze
16
16
  s.email = "jdwyer@prefab.cloud".freeze
17
17
  s.extra_rdoc_files = [
@@ -37,7 +37,6 @@ Gem::Specification.new do |s|
37
37
  "lib/prefab/noop_cache.rb",
38
38
  "lib/prefab/noop_stats.rb",
39
39
  "lib/prefab/ratelimit_client.rb",
40
- "lib/prefab/retry.rb",
41
40
  "lib/prefab_pb.rb",
42
41
  "lib/prefab_services_pb.rb",
43
42
  "prefab-cloud-ruby.gemspec",
@@ -3,3 +3,4 @@ sample_int: 123
3
3
  sample_double: 12.12
4
4
  sample_bool: true
5
5
  sample_to_override: Foo
6
+ prefab.log_level: debug
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.13
4
+ version: 0.0.14
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-13 00:00:00.000000000 Z
11
+ date: 2018-02-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: grpc
@@ -154,7 +154,6 @@ files:
154
154
  - lib/prefab/noop_cache.rb
155
155
  - lib/prefab/noop_stats.rb
156
156
  - lib/prefab/ratelimit_client.rb
157
- - lib/prefab/retry.rb
158
157
  - lib/prefab_pb.rb
159
158
  - lib/prefab_services_pb.rb
160
159
  - prefab-cloud-ruby.gemspec
@@ -1,28 +0,0 @@
1
- class Retry
2
- MAX_SLEEP_SEC = 10
3
- BASE_SLEEP_SEC = 0.5
4
-
5
- # GRPC Generally handles timeouts for us
6
- # but if the connection is broken we want to retry up until the timeout
7
- def self.it(stub_factory, rpc, req, timeout, reset)
8
- attempts = 0
9
- start_time = Time.now
10
-
11
- begin
12
- attempts += 1
13
- return stub_factory.call.send(rpc, req)
14
- rescue => exception
15
-
16
- if Time.now - start_time > timeout
17
- raise exception
18
- end
19
- sleep_seconds = [BASE_SLEEP_SEC * (2 ** (attempts - 1)), MAX_SLEEP_SEC].min
20
- sleep_seconds = sleep_seconds * (0.5 * (1 + rand()))
21
- sleep_seconds = [BASE_SLEEP_SEC, sleep_seconds].max
22
- puts "Sleep #{sleep_seconds} and Reset"
23
- sleep sleep_seconds
24
- reset.call
25
- retry
26
- end
27
- end
28
- end