prefab-cloud-ruby 0.0.8 → 0.0.9
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-cloud-ruby.rb +2 -0
- data/lib/prefab/client.rb +4 -0
- data/lib/prefab/config_client.rb +11 -10
- data/lib/prefab/config_resolver.rb +21 -17
- data/lib/prefab/feature_flag_client.rb +54 -0
- data/lib/prefab/murmer3.rb +50 -0
- data/lib/prefab/ratelimit_client.rb +12 -12
- data/prefab-cloud-ruby.gemspec +4 -2
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bedbb49cbc2b12ed093d5740ddbcfa26398faefe
|
4
|
+
data.tar.gz: fcd3d2e87c37927243f2ad475e0564d3a99eecc0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4cf667a4d6495d12a19af12018f50d423b8dd5b32dcbe0b95fcbfbded7ddfa127ae1d804d3fc44db7df5bb4e2a6c3d8c4d25255b9e274b7e4a469b629b5ed08
|
7
|
+
data.tar.gz: ad6a8ffb65d448f35a7276910cc36825491f4ee467bd7fd02e4486f1ee68fe1d27d28848a2c9c8be3189aa8339662a83b64960a2b7c5a255574634c656cbca00
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.9
|
data/lib/prefab-cloud-ruby.rb
CHANGED
@@ -8,8 +8,10 @@ require 'prefab/config_resolver'
|
|
8
8
|
require 'prefab/client'
|
9
9
|
require 'prefab/ratelimit_client'
|
10
10
|
require 'prefab/config_client'
|
11
|
+
require 'prefab/feature_flag_client'
|
11
12
|
require 'prefab/auth_interceptor'
|
12
13
|
require 'prefab/noop_cache'
|
13
14
|
require 'prefab/noop_stats'
|
14
15
|
require 'prefab/retry'
|
16
|
+
require 'prefab/murmer3'
|
15
17
|
|
data/lib/prefab/client.rb
CHANGED
data/lib/prefab/config_client.rb
CHANGED
@@ -2,10 +2,10 @@ module Prefab
|
|
2
2
|
class ConfigClient
|
3
3
|
RECONNECT_WAIT = 5
|
4
4
|
|
5
|
-
def initialize(
|
6
|
-
@
|
5
|
+
def initialize(base_client, timeout)
|
6
|
+
@base_client = base_client
|
7
7
|
@timeout = timeout
|
8
|
-
@config_resolver = EzConfig::ConfigResolver.new(
|
8
|
+
@config_resolver = EzConfig::ConfigResolver.new(base_client)
|
9
9
|
boot_resolver
|
10
10
|
end
|
11
11
|
|
@@ -15,6 +15,7 @@ module Prefab
|
|
15
15
|
|
16
16
|
def set(config_delta)
|
17
17
|
Retry.it method(:stub_with_timout), :upsert, config_delta, @timeout
|
18
|
+
@config_resolver.set(config_delta)
|
18
19
|
end
|
19
20
|
|
20
21
|
def to_s
|
@@ -26,20 +27,20 @@ module Prefab
|
|
26
27
|
def stub
|
27
28
|
Prefab::ConfigService::Stub.new(nil,
|
28
29
|
nil,
|
29
|
-
channel_override: @
|
30
|
-
interceptors: [@
|
30
|
+
channel_override: @base_client.channel,
|
31
|
+
interceptors: [@base_client.interceptor])
|
31
32
|
end
|
32
33
|
|
33
34
|
def stub_with_timout
|
34
35
|
Prefab::ConfigService::Stub.new(nil,
|
35
36
|
nil,
|
36
|
-
channel_override: @
|
37
|
+
channel_override: @base_client.channel,
|
37
38
|
timeout: @timeout,
|
38
|
-
interceptors: [@
|
39
|
+
interceptors: [@base_client.interceptor])
|
39
40
|
end
|
40
41
|
|
41
42
|
def boot_resolver
|
42
|
-
config_req = Prefab::ConfigServicePointer.new(account_id: @
|
43
|
+
config_req = Prefab::ConfigServicePointer.new(account_id: @base_client.account_id,
|
43
44
|
start_at_id: 0)
|
44
45
|
|
45
46
|
Thread.new do
|
@@ -48,13 +49,13 @@ module Prefab
|
|
48
49
|
resp = stub.get_config(config_req)
|
49
50
|
resp.each do |r|
|
50
51
|
r.deltas.each do |delta|
|
51
|
-
@config_resolver.set(delta)
|
52
|
+
@config_resolver.set(delta, do_update: false)
|
52
53
|
end
|
53
54
|
@config_resolver.update
|
54
55
|
end
|
55
56
|
rescue => e
|
56
57
|
sleep(RECONNECT_WAIT)
|
57
|
-
@
|
58
|
+
@base_client.logger.info("config client encountered #{e.message} pausing #{RECONNECT_WAIT}")
|
58
59
|
end
|
59
60
|
end
|
60
61
|
end
|
@@ -15,31 +15,22 @@ module EzConfig
|
|
15
15
|
@lock.with_read_lock do
|
16
16
|
@local_store.each do |k, v|
|
17
17
|
value = v[:value]
|
18
|
-
|
19
|
-
when :string then
|
20
|
-
str << "#{k} #{value.string}"
|
21
|
-
when :int then
|
22
|
-
str << "#{k} #{value.int}"
|
23
|
-
end
|
18
|
+
str << "|#{k}| |#{value_of(value)}|\n"
|
24
19
|
end
|
25
20
|
end
|
26
21
|
str
|
27
22
|
end
|
28
23
|
|
29
24
|
def get(property)
|
30
|
-
|
31
|
-
@local_store[property]
|
32
|
-
end
|
33
|
-
case value.type
|
34
|
-
when :string then
|
35
|
-
value.string
|
36
|
-
when :int then
|
37
|
-
value.int
|
25
|
+
config = @lock.with_read_lock do
|
26
|
+
@local_store[property]
|
38
27
|
end
|
28
|
+
config ? value_of(config[:value]) : nil
|
39
29
|
end
|
40
30
|
|
41
|
-
def set(delta)
|
31
|
+
def set(delta, do_update: true)
|
42
32
|
@config_loader.set(delta)
|
33
|
+
update if do_update
|
43
34
|
end
|
44
35
|
|
45
36
|
def update
|
@@ -48,6 +39,21 @@ module EzConfig
|
|
48
39
|
|
49
40
|
private
|
50
41
|
|
42
|
+
def value_of(config_value)
|
43
|
+
case config_value.type
|
44
|
+
when :string
|
45
|
+
config_value.string
|
46
|
+
when :int
|
47
|
+
config_value.int
|
48
|
+
when :double
|
49
|
+
config_value.double
|
50
|
+
when :bool
|
51
|
+
config_value.bool
|
52
|
+
when :feature_flag
|
53
|
+
config_value.feature_flag
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
51
57
|
def make_local
|
52
58
|
store = {}
|
53
59
|
@config_loader.calc_config.each do |prop, value|
|
@@ -72,8 +78,6 @@ module EzConfig
|
|
72
78
|
@lock.with_write_lock do
|
73
79
|
@local_store = store
|
74
80
|
end
|
75
|
-
|
76
|
-
@logger.info "Updated to #{to_s}"
|
77
81
|
end
|
78
82
|
end
|
79
83
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Prefab
|
2
|
+
class FeatureFlagClient
|
3
|
+
MAX_32_FLOAT = 4294967294.0
|
4
|
+
|
5
|
+
def initialize(base_client)
|
6
|
+
@base_client = base_client
|
7
|
+
end
|
8
|
+
|
9
|
+
def upsert(feature_obj)
|
10
|
+
delta = Prefab::ConfigDelta.new(account_id: @base_client.account_id,
|
11
|
+
key: feature_config_name(feature_obj.feature),
|
12
|
+
value: Prefab::ConfigValue.new(feature_flag: feature_obj))
|
13
|
+
@base_client.config_client.set(delta)
|
14
|
+
end
|
15
|
+
|
16
|
+
def feature_is_on?(feature_name)
|
17
|
+
feature_is_on_for?(feature_name, nil)
|
18
|
+
end
|
19
|
+
|
20
|
+
def feature_is_on_for?(feature_name, lookup_key, attributes: [])
|
21
|
+
@base_client.stats.increment("prefab.featureflag.on", tags: ["feature:#{feature_name}"])
|
22
|
+
|
23
|
+
feature_obj = @base_client.config_client.get(feature_config_name(feature_name))
|
24
|
+
if feature_obj.nil?
|
25
|
+
return false
|
26
|
+
end
|
27
|
+
|
28
|
+
attributes << lookup_key if lookup_key
|
29
|
+
if (attributes & feature_obj.whitelisted).size > 0
|
30
|
+
return true
|
31
|
+
end
|
32
|
+
|
33
|
+
if lookup_key
|
34
|
+
return get_user_pct(feature_name, lookup_key) < feature_obj.pct
|
35
|
+
end
|
36
|
+
|
37
|
+
return feature_obj.pct > rand()
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
|
43
|
+
def get_user_pct(feature, lookup_key)
|
44
|
+
int_value = Murmur3.murmur3_32("#{@account_id}#{feature}#{lookup_key}")
|
45
|
+
int_value / MAX_32_FLOAT
|
46
|
+
end
|
47
|
+
|
48
|
+
def feature_config_name(feature)
|
49
|
+
"Feature.#{feature}"
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class Murmur3
|
2
|
+
## MurmurHash3 was written by Austin Appleby, and is placed in the public
|
3
|
+
## domain. The author hereby disclaims copyright to this source code.
|
4
|
+
|
5
|
+
MASK32 = 0xffffffff
|
6
|
+
|
7
|
+
def self.murmur3_32_rotl(x, r)
|
8
|
+
((x << r) | (x >> (32 - r))) & MASK32
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
def self.murmur3_32_fmix(h)
|
13
|
+
h &= MASK32
|
14
|
+
h ^= h >> 16
|
15
|
+
h = (h * 0x85ebca6b) & MASK32
|
16
|
+
h ^= h >> 13
|
17
|
+
h = (h * 0xc2b2ae35) & MASK32
|
18
|
+
h ^ (h >> 16)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.murmur3_32__mmix(k1)
|
22
|
+
k1 = (k1 * 0xcc9e2d51) & MASK32
|
23
|
+
k1 = murmur3_32_rotl(k1, 15)
|
24
|
+
(k1 * 0x1b873593) & MASK32
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.murmur3_32(str, seed=0)
|
28
|
+
h1 = seed
|
29
|
+
numbers = str.unpack('V*C*')
|
30
|
+
tailn = str.length % 4
|
31
|
+
tail = numbers.slice!(numbers.size - tailn, tailn)
|
32
|
+
for k1 in numbers
|
33
|
+
h1 ^= murmur3_32__mmix(k1)
|
34
|
+
h1 = murmur3_32_rotl(h1, 13)
|
35
|
+
h1 = (h1*5 + 0xe6546b64) & MASK32
|
36
|
+
end
|
37
|
+
|
38
|
+
unless tail.empty?
|
39
|
+
k1 = 0
|
40
|
+
tail.reverse_each do |c1|
|
41
|
+
k1 = (k1 << 8) | c1
|
42
|
+
end
|
43
|
+
h1 ^= murmur3_32__mmix(k1)
|
44
|
+
end
|
45
|
+
|
46
|
+
h1 ^= str.length
|
47
|
+
murmur3_32_fmix(h1)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module Prefab
|
2
2
|
class RateLimitClient
|
3
3
|
|
4
|
-
def initialize(
|
4
|
+
def initialize(base_client, timeout)
|
5
5
|
@timeout = timeout
|
6
|
-
@
|
6
|
+
@base_client = base_client
|
7
7
|
end
|
8
8
|
|
9
9
|
def pass?(group)
|
@@ -13,14 +13,14 @@ module Prefab
|
|
13
13
|
|
14
14
|
def acquire(groups, acquire_amount, allow_partial_response: false, on_error: :log_and_pass)
|
15
15
|
expiry_cache_key = "prefab.ratelimit.expiry:#{groups.join(".")}"
|
16
|
-
expiry = @
|
16
|
+
expiry = @base_client.shared_cache.read(expiry_cache_key)
|
17
17
|
if !expiry.nil? && Integer(expiry) > Time.now.utc.to_f * 1000
|
18
|
-
@
|
18
|
+
@base_client.stats.increment("prefab.ratelimit.limitcheck.expirycache.hit", tags: [])
|
19
19
|
return Prefab::LimitResponse.new(passed: false, amount: 0)
|
20
20
|
end
|
21
21
|
|
22
22
|
req = Prefab::LimitRequest.new(
|
23
|
-
account_id: @
|
23
|
+
account_id: @base_client.account_id,
|
24
24
|
acquire_amount: acquire_amount,
|
25
25
|
groups: groups,
|
26
26
|
allow_partial_response: allow_partial_response
|
@@ -29,9 +29,9 @@ module Prefab
|
|
29
29
|
result = Retry.it(method(:stub), :limit_check, req, @timeout)
|
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
|
33
33
|
|
34
|
-
@
|
34
|
+
@base_client.stats.increment("prefab.ratelimit.limitcheck", tags: ["policy_group:#{result.policy_group}", "pass:#{result.passed}"])
|
35
35
|
|
36
36
|
result
|
37
37
|
|
@@ -44,21 +44,21 @@ module Prefab
|
|
44
44
|
def stub
|
45
45
|
Prefab::RateLimitService::Stub.new(nil,
|
46
46
|
nil,
|
47
|
-
channel_override: @
|
47
|
+
channel_override: @base_client.channel,
|
48
48
|
timeout: @timeout,
|
49
|
-
interceptors: [@
|
49
|
+
interceptors: [@base_client.interceptor])
|
50
50
|
end
|
51
51
|
|
52
52
|
def handle_error(e, on_error, groups)
|
53
|
-
@
|
53
|
+
@base_client.stats.increment("prefab.ratelimit.error", tags: ["type:limit"])
|
54
54
|
|
55
55
|
message = "ratelimit for #{groups} error: #{e.message}"
|
56
56
|
case on_error
|
57
57
|
when :log_and_pass
|
58
|
-
@
|
58
|
+
@base_client.logger.warn(message)
|
59
59
|
Prefab::LimitResponse.new(passed: true, amount: 0)
|
60
60
|
when :log_and_hit
|
61
|
-
@
|
61
|
+
@base_client.logger.warn(message)
|
62
62
|
Prefab::LimitResponse.new(passed: false, amount: 0)
|
63
63
|
when :throw
|
64
64
|
raise e
|
data/prefab-cloud-ruby.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
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.9 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.9"
|
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]
|
@@ -31,6 +31,8 @@ Gem::Specification.new do |s|
|
|
31
31
|
"lib/prefab/config_client.rb",
|
32
32
|
"lib/prefab/config_loader.rb",
|
33
33
|
"lib/prefab/config_resolver.rb",
|
34
|
+
"lib/prefab/feature_flag_client.rb",
|
35
|
+
"lib/prefab/murmer3.rb",
|
34
36
|
"lib/prefab/noop_cache.rb",
|
35
37
|
"lib/prefab/noop_stats.rb",
|
36
38
|
"lib/prefab/ratelimit_client.rb",
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
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.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeff Dwyer
|
@@ -148,6 +148,8 @@ files:
|
|
148
148
|
- lib/prefab/config_client.rb
|
149
149
|
- lib/prefab/config_loader.rb
|
150
150
|
- lib/prefab/config_resolver.rb
|
151
|
+
- lib/prefab/feature_flag_client.rb
|
152
|
+
- lib/prefab/murmer3.rb
|
151
153
|
- lib/prefab/noop_cache.rb
|
152
154
|
- lib/prefab/noop_stats.rb
|
153
155
|
- lib/prefab/ratelimit_client.rb
|