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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4b7a0a43eadc51e6ebfbd7573865ba48dd139bd1
4
- data.tar.gz: 30e99adf8c06969e29034fbff3a711838b471e0a
3
+ metadata.gz: bedbb49cbc2b12ed093d5740ddbcfa26398faefe
4
+ data.tar.gz: fcd3d2e87c37927243f2ad475e0564d3a99eecc0
5
5
  SHA512:
6
- metadata.gz: 29262f1a91dd5c7322152e27fe4352c4a6974f17d891f29bdaed79aedda4c258c13ba4576337936d6b5fcf7b22a3a0eb793e1a4ce9b1b1185dac95e9f88bb352
7
- data.tar.gz: cf12cc1441b1a8786f40cf309128129570fe061b9eb41a1c59ed8cc0159a54376cd3711809e4e76f52edefecccb5409b59c3d37ce7997bd38d1ee5da7801c1ad
6
+ metadata.gz: b4cf667a4d6495d12a19af12018f50d423b8dd5b32dcbe0b95fcbfbded7ddfa127ae1d804d3fc44db7df5bb4e2a6c3d8c4d25255b9e274b7e4a469b629b5ed08
7
+ data.tar.gz: ad6a8ffb65d448f35a7276910cc36825491f4ee467bd7fd02e4486f1ee68fe1d27d28848a2c9c8be3189aa8339662a83b64960a2b7c5a255574634c656cbca00
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.8
1
+ 0.0.9
@@ -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
@@ -34,6 +34,10 @@ module Prefab
34
34
  @ratelimit_client ||= Prefab::RateLimitClient.new(self, timeout)
35
35
  end
36
36
 
37
+ def feature_flag_client
38
+ @feature_flag_client ||= Prefab::FeatureFlagClient.new(self)
39
+ end
40
+
37
41
  private
38
42
 
39
43
  def ssl_certs
@@ -2,10 +2,10 @@ module Prefab
2
2
  class ConfigClient
3
3
  RECONNECT_WAIT = 5
4
4
 
5
- def initialize(client, timeout)
6
- @client = client
5
+ def initialize(base_client, timeout)
6
+ @base_client = base_client
7
7
  @timeout = timeout
8
- @config_resolver = EzConfig::ConfigResolver.new(client)
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: @client.channel,
30
- interceptors: [@client.interceptor])
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: @client.channel,
37
+ channel_override: @base_client.channel,
37
38
  timeout: @timeout,
38
- interceptors: [@client.interceptor])
39
+ interceptors: [@base_client.interceptor])
39
40
  end
40
41
 
41
42
  def boot_resolver
42
- config_req = Prefab::ConfigServicePointer.new(account_id: @client.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
- @client.logger.info("config client encountered #{e.message} pausing #{RECONNECT_WAIT}")
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
- case value.type
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
- value = @lock.with_read_lock do
31
- @local_store[property][:value]
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(client, timeout)
4
+ def initialize(base_client, timeout)
5
5
  @timeout = timeout
6
- @client = client
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 = @client.shared_cache.read(expiry_cache_key)
16
+ expiry = @base_client.shared_cache.read(expiry_cache_key)
17
17
  if !expiry.nil? && Integer(expiry) > Time.now.utc.to_f * 1000
18
- @client.stats.increment("prefab.ratelimit.limitcheck.expirycache.hit", tags: [])
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: @client.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
- @client.shared_cache.write(expiry_cache_key, reset) unless reset < 1 # protobuf default int to 0
32
+ @base_client.shared_cache.write(expiry_cache_key, reset) unless reset < 1 # protobuf default int to 0
33
33
 
34
- @client.stats.increment("prefab.ratelimit.limitcheck", tags: ["policy_group:#{result.policy_group}", "pass:#{result.passed}"])
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: @client.channel,
47
+ channel_override: @base_client.channel,
48
48
  timeout: @timeout,
49
- interceptors: [@client.interceptor])
49
+ interceptors: [@base_client.interceptor])
50
50
  end
51
51
 
52
52
  def handle_error(e, on_error, groups)
53
- @client.stats.increment("prefab.ratelimit.error", tags: ["type:limit"])
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
- @client.logger.warn(message)
58
+ @base_client.logger.warn(message)
59
59
  Prefab::LimitResponse.new(passed: true, amount: 0)
60
60
  when :log_and_hit
61
- @client.logger.warn(message)
61
+ @base_client.logger.warn(message)
62
62
  Prefab::LimitResponse.new(passed: false, amount: 0)
63
63
  when :throw
64
64
  raise e
@@ -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.8 ruby lib
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.8"
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.8
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