prefab-cloud-ruby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9a9979df2d96ea510b54c6b479cba724e0ef1ae7
4
+ data.tar.gz: 8a73500c4c42dac6f4955b6bd6ff395ddf43511f
5
+ SHA512:
6
+ metadata.gz: '0937e68bf543c496e25e9dff6ab471b5f73bc626a95899c930251dfa9cc5ccd193414e9b9aa88557dbf7716d93af569d09caf6d7be7f686a64f5a7bc6b2c68f3'
7
+ data.tar.gz: c92bb4500b4321334be5d288f99baeaba8d19ffd7d1af3b7a7e84d6b6d96e052ca88f91030498558e2af3438a168e434d333d89e2722e2a23f6fcb3637d27e0d
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.4.2
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "grpc"
4
+ gem "concurrent-ruby"
5
+
6
+ group :development do
7
+ gem "grpc-tools"
8
+ gem "shoulda", ">= 0"
9
+ gem "rdoc", "~> 3.12"
10
+ gem "bundler", "~> 1.0"
11
+ gem "juwelier", "~> 2.1.0"
12
+ gem "simplecov", ">= 0"
13
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,116 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ activesupport (5.1.4)
5
+ concurrent-ruby (~> 1.0, >= 1.0.2)
6
+ i18n (~> 0.7)
7
+ minitest (~> 5.1)
8
+ tzinfo (~> 1.1)
9
+ addressable (2.5.2)
10
+ public_suffix (>= 2.0.2, < 4.0)
11
+ builder (3.2.3)
12
+ concurrent-ruby (1.0.5)
13
+ descendants_tracker (0.0.4)
14
+ thread_safe (~> 0.3, >= 0.3.1)
15
+ docile (1.1.5)
16
+ faraday (0.12.2)
17
+ multipart-post (>= 1.2, < 3)
18
+ git (1.3.0)
19
+ github_api (0.18.2)
20
+ addressable (~> 2.4)
21
+ descendants_tracker (~> 0.0.4)
22
+ faraday (~> 0.8)
23
+ hashie (~> 3.5, >= 3.5.2)
24
+ oauth2 (~> 1.0)
25
+ google-protobuf (3.5.0)
26
+ googleapis-common-protos-types (1.0.1)
27
+ google-protobuf (~> 3.0)
28
+ googleauth (0.6.2)
29
+ faraday (~> 0.12)
30
+ jwt (>= 1.4, < 3.0)
31
+ logging (~> 2.0)
32
+ memoist (~> 0.12)
33
+ multi_json (~> 1.11)
34
+ os (~> 0.9)
35
+ signet (~> 0.7)
36
+ grpc (1.7.2)
37
+ google-protobuf (~> 3.1)
38
+ googleapis-common-protos-types (~> 1.0.0)
39
+ googleauth (>= 0.5.1, < 0.7)
40
+ grpc-tools (1.7.2)
41
+ hashie (3.5.6)
42
+ highline (1.7.10)
43
+ i18n (0.9.1)
44
+ concurrent-ruby (~> 1.0)
45
+ json (1.8.6)
46
+ juwelier (2.1.3)
47
+ builder
48
+ bundler (>= 1.13)
49
+ git (>= 1.2.5)
50
+ github_api
51
+ highline (>= 1.6.15)
52
+ nokogiri (>= 1.5.10)
53
+ rake
54
+ rdoc
55
+ semver
56
+ jwt (1.5.6)
57
+ little-plugger (1.1.4)
58
+ logging (2.2.2)
59
+ little-plugger (~> 1.1)
60
+ multi_json (~> 1.10)
61
+ memoist (0.16.0)
62
+ mini_portile2 (2.3.0)
63
+ minitest (5.10.3)
64
+ multi_json (1.12.2)
65
+ multi_xml (0.6.0)
66
+ multipart-post (2.0.0)
67
+ nokogiri (1.8.1)
68
+ mini_portile2 (~> 2.3.0)
69
+ oauth2 (1.4.0)
70
+ faraday (>= 0.8, < 0.13)
71
+ jwt (~> 1.0)
72
+ multi_json (~> 1.3)
73
+ multi_xml (~> 0.5)
74
+ rack (>= 1.2, < 3)
75
+ os (0.9.6)
76
+ public_suffix (3.0.1)
77
+ rack (2.0.3)
78
+ rake (12.3.0)
79
+ rdoc (3.12.2)
80
+ json (~> 1.4)
81
+ semver (1.0.1)
82
+ shoulda (3.5.0)
83
+ shoulda-context (~> 1.0, >= 1.0.1)
84
+ shoulda-matchers (>= 1.4.1, < 3.0)
85
+ shoulda-context (1.2.2)
86
+ shoulda-matchers (2.8.0)
87
+ activesupport (>= 3.0.0)
88
+ signet (0.8.1)
89
+ addressable (~> 2.3)
90
+ faraday (~> 0.9)
91
+ jwt (>= 1.5, < 3.0)
92
+ multi_json (~> 1.10)
93
+ simplecov (0.15.1)
94
+ docile (~> 1.1.0)
95
+ json (>= 1.8, < 3)
96
+ simplecov-html (~> 0.10.0)
97
+ simplecov-html (0.10.2)
98
+ thread_safe (0.3.6)
99
+ tzinfo (1.2.4)
100
+ thread_safe (~> 0.1)
101
+
102
+ PLATFORMS
103
+ ruby
104
+
105
+ DEPENDENCIES
106
+ bundler (~> 1.0)
107
+ concurrent-ruby
108
+ grpc
109
+ grpc-tools
110
+ juwelier (~> 2.1.0)
111
+ rdoc (~> 3.12)
112
+ shoulda
113
+ simplecov
114
+
115
+ BUNDLED WITH
116
+ 1.16.0
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2017 Jeff Dwyer
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+ require 'juwelier'
14
+ Juwelier::Tasks.new do |gem|
15
+ # gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
16
+ gem.name = "prefab-cloud-ruby"
17
+ gem.homepage = "http://github.com/prefab-cloud/prefab-cloud-ruby"
18
+ gem.license = "MIT"
19
+ gem.summary = %Q{Prefab Ruby Infrastructure}
20
+ gem.description = %Q{RateLimits & Config as a service}
21
+ gem.email = "jdwyer@prefab.cloud"
22
+ gem.authors = ["Jeff Dwyer"]
23
+
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Juwelier::RubygemsDotOrgTasks.new
27
+ require 'rake/testtask'
28
+ Rake::TestTask.new(:test) do |test|
29
+ test.libs << 'lib' << 'test'
30
+ test.pattern = 'test/**/test_*.rb'
31
+ test.verbose = true
32
+ end
33
+
34
+ desc "Code coverage detail"
35
+ task :simplecov do
36
+ ENV['COVERAGE'] = "true"
37
+ Rake::Task['test'].execute
38
+ end
39
+
40
+ task :default => :test
41
+
42
+ require 'rdoc/task'
43
+ Rake::RDocTask.new do |rdoc|
44
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
45
+
46
+ rdoc.rdoc_dir = 'rdoc'
47
+ rdoc.title = "prefab-cloud-ruby #{version}"
48
+ rdoc.rdoc_files.include('README*')
49
+ rdoc.rdoc_files.include('lib/**/*.rb')
50
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,25 @@
1
+ class AuthInterceptor < GRPC::ClientInterceptor
2
+ def initialize(api_key)
3
+ @api_key = api_key
4
+ end
5
+
6
+ def request_response(request:, call:, method:, metadata:)
7
+ metadata['auth'] = @api_key
8
+ yield
9
+ end
10
+
11
+ def client_streamer(requests:, call:, method:, metadata:)
12
+ metadata['auth'] = @api_key
13
+ yield
14
+ end
15
+
16
+ def server_streamer(request:, call:, method:, metadata:)
17
+ metadata['auth'] = @api_key
18
+ yield
19
+ end
20
+
21
+ def bidi_streamer(requests:, call:, method:, metadata:)
22
+ metadata['auth'] = @api_key
23
+ yield
24
+ end
25
+ end
@@ -0,0 +1,48 @@
1
+ module Prefab
2
+ class Client
3
+
4
+ attr_reader :account_id, :shared_cache, :stats, :namespace, :logger
5
+
6
+ def initialize(api_key:,
7
+ ssl_certs: "/usr/local/etc/openssl/cert.pem",
8
+ logger: nil,
9
+ stats: nil, # receives increment("prefab.limitcheck", {:tags=>["policy_group:page_view", "pass:true"]})
10
+ shared_cache: nil, # Something that quacks like Rails.cache ideally memcached
11
+ local: false,
12
+ namespace: ""
13
+ )
14
+ @logger = (logger || Logger.new($stdout)).tap do |log|
15
+ log.progname = "Prefab" if log.respond_to? :progname=
16
+ end
17
+ @stats = (stats || NoopStats.new)
18
+ @shared_cache = (shared_cache || NoopCache.new)
19
+ @account_id = api_key.split("|")[0].to_i
20
+ @namespace = namespace
21
+
22
+ @interceptor = AuthInterceptor.new(api_key)
23
+ @creds = GRPC::Core::ChannelCredentials.new(File.open(ssl_certs).read)
24
+
25
+ @channel = GRPC::Core::Channel.new('api.prefab.cloud:8443', nil, @creds)
26
+ if local
27
+ @channel = GRPC::Core::Channel.new('localhost:8443', nil, :this_channel_is_insecure)
28
+ end
29
+ end
30
+
31
+ def config_client
32
+ @config_client ||= Prefab::ConfigClient.new(Prefab::ConfigService::Stub.new(nil,
33
+ @creds,
34
+ channel_override: @channel,
35
+ interceptors: [@interceptor]),
36
+ self)
37
+ end
38
+
39
+ def ratelimit_client
40
+ @ratelimit_client ||= Prefab::RateLimitClient.new(Prefab::RateLimitService::Stub.new(nil,
41
+ @creds,
42
+ channel_override: @channel,
43
+ interceptors: [@interceptor]),
44
+ self)
45
+ end
46
+ end
47
+ end
48
+
@@ -0,0 +1,40 @@
1
+ module Prefab
2
+ class ConfigClient
3
+ def initialize(config_service, client)
4
+ @client = client
5
+ @config_service = config_service
6
+ @config_resolver = EzConfig::ConfigResolver.new(client)
7
+ boot_resolver(@config_service)
8
+ end
9
+
10
+ def get(prop)
11
+ @config_resolver.get(prop)
12
+ end
13
+
14
+ def set(config_value)
15
+ @config_service.upsert(config_value)
16
+ end
17
+
18
+ private
19
+
20
+ def boot_resolver(config_service)
21
+ config_req = Prefab::ConfigServicePointer.new(account_id: 1,
22
+ start_at_id: 0)
23
+
24
+ Thread.new do
25
+ begin
26
+ resp = config_service.get_config(config_req)
27
+ resp.each do |r|
28
+ r.deltas.each do |delta|
29
+ @config_resolver.set(delta)
30
+ end
31
+ @config_resolver.update
32
+ end
33
+ rescue => e
34
+ @client.logger.warn(e)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+
@@ -0,0 +1,51 @@
1
+ require 'yaml'
2
+ module EzConfig
3
+ class ConfigLoader
4
+ def initialize(logger)
5
+ @logger = logger
6
+ load_ez_config
7
+ load_project_config
8
+ load_local_overrides
9
+ @api_config = Concurrent::Map.new
10
+ @immutable_config = @ez_config.merge(@project_config)
11
+ end
12
+
13
+ def calc_config
14
+ rtn = @immutable_config.clone
15
+ @api_config.each_key do |k|
16
+ rtn[k] = @api_config[k]
17
+ end
18
+ rtn = rtn.merge(@local_overrides)
19
+ rtn
20
+ end
21
+
22
+ def set(delta)
23
+ @api_config[delta.key] = delta.value
24
+ end
25
+
26
+ private
27
+
28
+ def load_ez_config
29
+ @ez_config = load(".ezconfig.yaml")
30
+ end
31
+
32
+ def load_project_config
33
+ @project_config = load(".projectconfig.yaml")
34
+ end
35
+
36
+ def load_local_overrides
37
+ @local_overrides = load(".ezconfig.overrides.yaml")
38
+ end
39
+
40
+ def load(filename)
41
+ if File.exist? filename
42
+
43
+ YAML.load_file(filename)
44
+ else
45
+ @logger.info "No file #{filename}"
46
+ {}
47
+ end
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,64 @@
1
+ module EzConfig
2
+ class ConfigResolver
3
+
4
+ def initialize(client)
5
+ @lock = Concurrent::ReadWriteLock.new
6
+ @local_store = {}
7
+ @namespace = client.namespace
8
+ @config_loader = EzConfig::ConfigLoader.new(client.logger)
9
+ make_local
10
+ end
11
+
12
+ def get(property)
13
+ value = @lock.with_read_lock do
14
+ @local_store[property][:value]
15
+ end
16
+ case value.type
17
+ when :string then
18
+ puts "SSString"
19
+ value.string
20
+ when :int then
21
+ puts "INT"
22
+ value.int
23
+ end
24
+ end
25
+
26
+ def set(delta)
27
+ @config_loader.set(delta)
28
+ end
29
+
30
+ def update
31
+ make_local
32
+ end
33
+
34
+ private
35
+
36
+ def make_local
37
+ store = {}
38
+ @config_loader.calc_config.each do |prop, value|
39
+ property = prop
40
+ namespace = ""
41
+ split = prop.split(":")
42
+
43
+ if split.size > 1
44
+ property = split[1..-1].join
45
+ namespace = split[0]
46
+ end
47
+
48
+ if (namespace == "") || namespace.start_with?(@namespace)
49
+ existing = store[property]
50
+ if existing.nil?
51
+ store[property] = { namespace: namespace, value: value }
52
+ elsif existing[:namespace].split(".").size < namespace.split(".").size
53
+ store[property] = { namespace: namespace, value: value }
54
+ end
55
+ end
56
+
57
+ puts "prop #{property} namespace #{namespace} value #{value}"
58
+ end
59
+ @lock.with_write_lock do
60
+ @local_store = store
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,13 @@
1
+ module Prefab
2
+ class NoopCache
3
+ def fetch(name, opts, &method)
4
+ yield
5
+ end
6
+
7
+ def write(name, value, opts=nil)
8
+ end
9
+
10
+ def read(name)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ module Prefab
2
+
3
+ class NoopStats
4
+ # receives increment("prefab.ratelimit.limitcheck", {:tags=>["policy_group:page_view", "pass:true"]})
5
+ def increment(name, opts)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,39 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: prefab.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ require 'google/protobuf/wrappers_pb'
7
+ require 'ratelimit_pb'
8
+ Google::Protobuf::DescriptorPool.generated_pool.build do
9
+ add_message "prefab.ConfigServicePointer" do
10
+ optional :account_id, :int64, 1
11
+ optional :start_at_id, :int64, 2
12
+ end
13
+ add_message "prefab.ConfigDelta" do
14
+ optional :account_id, :int64, 1
15
+ optional :id, :int64, 2
16
+ optional :key, :string, 3
17
+ optional :value, :message, 4, "prefab.ConfigValue"
18
+ end
19
+ add_message "prefab.ConfigValue" do
20
+ oneof :type do
21
+ optional :int, :int64, 1
22
+ optional :string, :string, 2
23
+ optional :bytes, :bytes, 3
24
+ optional :double, :double, 4
25
+ optional :bool, :bool, 5
26
+ optional :feature_flag, :message, 6, "it.ratelim.data.FeatureFlag"
27
+ end
28
+ end
29
+ add_message "prefab.ConfigDeltas" do
30
+ repeated :deltas, :message, 1, "prefab.ConfigDelta"
31
+ end
32
+ end
33
+
34
+ module Prefab
35
+ ConfigServicePointer = Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigServicePointer").msgclass
36
+ ConfigDelta = Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigDelta").msgclass
37
+ ConfigValue = Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigValue").msgclass
38
+ ConfigDeltas = Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigDeltas").msgclass
39
+ end
@@ -0,0 +1,37 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # Source: prefab.proto for package 'prefab'
3
+
4
+ require 'grpc'
5
+ require 'prefab_pb'
6
+
7
+ module Prefab
8
+ module RateLimitService
9
+ class Service
10
+
11
+ include GRPC::GenericService
12
+
13
+ self.marshal_class_method = :encode
14
+ self.unmarshal_class_method = :decode
15
+ self.service_name = 'prefab.RateLimitService'
16
+
17
+ rpc :LimitCheck, It::Ratelim::Data::LimitRequest, It::Ratelim::Data::LimitResponse
18
+ end
19
+
20
+ Stub = Service.rpc_stub_class
21
+ end
22
+ module ConfigService
23
+ class Service
24
+
25
+ include GRPC::GenericService
26
+
27
+ self.marshal_class_method = :encode
28
+ self.unmarshal_class_method = :decode
29
+ self.service_name = 'prefab.ConfigService'
30
+
31
+ rpc :GetConfig, ConfigServicePointer, stream(ConfigDeltas)
32
+ rpc :Upsert, ConfigDelta, ConfigServicePointer
33
+ end
34
+
35
+ Stub = Service.rpc_stub_class
36
+ end
37
+ end
@@ -0,0 +1,58 @@
1
+ module Prefab
2
+ class RateLimitClient
3
+ def initialize(ratelimit_service, client)
4
+ @ratelimit_service = ratelimit_service
5
+ @client = client
6
+ end
7
+
8
+ def pass?(group)
9
+ result = acquire([group], 1)
10
+ return result.passed
11
+ end
12
+
13
+ def acquire(groups, acquire_amount, allow_partial_response: false, on_error: :log_and_pass)
14
+ expiry_cache_key = "prefab.ratelimit.expiry:#{groups.join(".")}"
15
+ expiry = @client.shared_cache.read(expiry_cache_key)
16
+ if !expiry.nil? && Integer(expiry) > Time.now.utc.to_f * 1000
17
+ @client.stats.increment("prefab.ratelimit.limitcheck.expirycache.hit", tags: [])
18
+ return It::Ratelim::Data::LimitResponse.new(passed: false, amount: 0)
19
+ end
20
+
21
+ req = It::Ratelim::Data::LimitRequest.new(
22
+ account_id: @client.account_id,
23
+ acquire_amount: acquire_amount,
24
+ groups: groups,
25
+ allow_partial_response: allow_partial_response
26
+ )
27
+
28
+ result = @ratelimit_service.limit_check(req)
29
+
30
+ reset = result.limit_reset_at
31
+ @client.shared_cache.write(expiry_cache_key, reset) unless reset < 1
32
+
33
+ @client.stats.increment("prefab.ratelimit.limitcheck", tags: ["policy_group:#{result.policy_group}", "pass:#{result.passed}"])
34
+
35
+ result
36
+
37
+ rescue => e
38
+ handle_error(e, on_error)
39
+ end
40
+
41
+ private
42
+
43
+ def handle_error(e, on_error)
44
+ @client.stats.increment("prefab.ratelimit.error", tags: ["type:limit"])
45
+ case on_error
46
+ when :log_and_pass
47
+ @client.logger.warn(e)
48
+ It::Ratelim::Data::LimitResponse.new(passed: true, amount: 0)
49
+ when :log_and_hit
50
+ @client.logger.warn(e)
51
+ It::Ratelim::Data::LimitResponse.new(passed: false, amount: 0)
52
+ when :throw
53
+ raise e
54
+ end
55
+ end
56
+ end
57
+ end
58
+
@@ -0,0 +1,125 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: ratelimit.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ require 'google/protobuf/wrappers_pb'
7
+ Google::Protobuf::DescriptorPool.generated_pool.build do
8
+ add_message "it.ratelim.data.LimitResponse" do
9
+ optional :passed, :bool, 1
10
+ optional :expires_at, :int64, 2
11
+ optional :enforced_group, :string, 3
12
+ optional :current_bucket, :int64, 4
13
+ optional :policy_group, :string, 5
14
+ optional :policy_name, :enum, 6, "it.ratelim.data.LimitResponse.LimitPolicyNames"
15
+ optional :policy_limit, :int32, 7
16
+ optional :amount, :int64, 8
17
+ optional :limit_reset_at, :int64, 9
18
+ optional :safety_level, :enum, 10, "it.ratelim.data.LimitDefinition.SafetyLevel"
19
+ end
20
+ add_enum "it.ratelim.data.LimitResponse.LimitPolicyNames" do
21
+ value :NOT_SET, 0
22
+ value :SECONDLY_ROLLING, 1
23
+ value :MINUTELY_ROLLING, 3
24
+ value :HOURLY_ROLLING, 5
25
+ value :DAILY_ROLLING, 7
26
+ value :MONTHLY_ROLLING, 8
27
+ value :INFINITE, 9
28
+ value :YEARLY_ROLLING, 10
29
+ end
30
+ add_message "it.ratelim.data.LimitRequest" do
31
+ optional :account_id, :int64, 1
32
+ optional :acquire_amount, :int32, 2
33
+ repeated :groups, :string, 3
34
+ optional :limit_combiner, :enum, 4, "it.ratelim.data.LimitRequest.LimitCombiner"
35
+ optional :allow_partial_response, :bool, 5
36
+ end
37
+ add_enum "it.ratelim.data.LimitRequest.LimitCombiner" do
38
+ value :NOT_SET, 0
39
+ value :MINIMUM, 1
40
+ value :MAXIMUM, 2
41
+ end
42
+ add_message "it.ratelim.data.FeatureFlag" do
43
+ optional :account_id, :int64, 1
44
+ optional :feature, :string, 2
45
+ optional :pct, :double, 3
46
+ repeated :whitelisted, :string, 4
47
+ optional :prior_feature_name, :string, 5
48
+ end
49
+ add_message "it.ratelim.data.LimitDefinition" do
50
+ optional :group, :string, 1
51
+ optional :policy_name, :enum, 2, "it.ratelim.data.LimitResponse.LimitPolicyNames"
52
+ optional :limit, :int32, 3
53
+ optional :burst, :int32, 4
54
+ optional :account_id, :int64, 5
55
+ optional :last_modified, :int64, 6
56
+ optional :returnable, :bool, 7
57
+ optional :safety_level, :enum, 8, "it.ratelim.data.LimitDefinition.SafetyLevel"
58
+ end
59
+ add_enum "it.ratelim.data.LimitDefinition.SafetyLevel" do
60
+ value :NOT_SET, 0
61
+ value :L4_BEST_EFFORT, 4
62
+ value :L5_BOMBPROOF, 5
63
+ end
64
+ add_message "it.ratelim.data.LimitDefinitions" do
65
+ repeated :definitions, :message, 1, "it.ratelim.data.LimitDefinition"
66
+ end
67
+ add_message "it.ratelim.data.FeatureFlags" do
68
+ repeated :flags, :message, 1, "it.ratelim.data.FeatureFlag"
69
+ optional :cache_expiry, :int64, 2
70
+ end
71
+ add_message "it.ratelim.data.BucketWrite" do
72
+ optional :tokenBucket, :message, 1, "it.ratelim.data.TokenBucket"
73
+ optional :bucket, :string, 2
74
+ end
75
+ add_message "it.ratelim.data.TokenBucket" do
76
+ optional :current_value, :int64, 1
77
+ optional :time_key, :int64, 2
78
+ repeated :expiries, :int64, 3
79
+ end
80
+ add_message "it.ratelim.data.BufferedRequest" do
81
+ optional :account_id, :int64, 1
82
+ optional :method, :string, 2
83
+ optional :uri, :string, 3
84
+ optional :body, :string, 4
85
+ repeated :limit_groups, :string, 5
86
+ optional :content_type, :string, 6
87
+ optional :fifo, :bool, 7
88
+ end
89
+ add_message "it.ratelim.data.BatchRequest" do
90
+ optional :account_id, :int64, 1
91
+ optional :method, :string, 2
92
+ optional :uri, :string, 3
93
+ optional :body, :string, 4
94
+ repeated :limit_groups, :string, 5
95
+ optional :batch_template, :string, 6
96
+ optional :batch_separator, :string, 7
97
+ end
98
+ add_enum "it.ratelim.data.OnFailure" do
99
+ value :NOT_SET, 0
100
+ value :LOG_AND_PASS, 1
101
+ value :LOG_AND_FAIL, 2
102
+ value :THROW, 3
103
+ end
104
+ end
105
+
106
+ module It
107
+ module Ratelim
108
+ module Data
109
+ LimitResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("it.ratelim.data.LimitResponse").msgclass
110
+ LimitResponse::LimitPolicyNames = Google::Protobuf::DescriptorPool.generated_pool.lookup("it.ratelim.data.LimitResponse.LimitPolicyNames").enummodule
111
+ LimitRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("it.ratelim.data.LimitRequest").msgclass
112
+ LimitRequest::LimitCombiner = Google::Protobuf::DescriptorPool.generated_pool.lookup("it.ratelim.data.LimitRequest.LimitCombiner").enummodule
113
+ FeatureFlag = Google::Protobuf::DescriptorPool.generated_pool.lookup("it.ratelim.data.FeatureFlag").msgclass
114
+ LimitDefinition = Google::Protobuf::DescriptorPool.generated_pool.lookup("it.ratelim.data.LimitDefinition").msgclass
115
+ LimitDefinition::SafetyLevel = Google::Protobuf::DescriptorPool.generated_pool.lookup("it.ratelim.data.LimitDefinition.SafetyLevel").enummodule
116
+ LimitDefinitions = Google::Protobuf::DescriptorPool.generated_pool.lookup("it.ratelim.data.LimitDefinitions").msgclass
117
+ FeatureFlags = Google::Protobuf::DescriptorPool.generated_pool.lookup("it.ratelim.data.FeatureFlags").msgclass
118
+ BucketWrite = Google::Protobuf::DescriptorPool.generated_pool.lookup("it.ratelim.data.BucketWrite").msgclass
119
+ TokenBucket = Google::Protobuf::DescriptorPool.generated_pool.lookup("it.ratelim.data.TokenBucket").msgclass
120
+ BufferedRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("it.ratelim.data.BufferedRequest").msgclass
121
+ BatchRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("it.ratelim.data.BatchRequest").msgclass
122
+ OnFailure = Google::Protobuf::DescriptorPool.generated_pool.lookup("it.ratelim.data.OnFailure").enummodule
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,29 @@
1
+ require "concurrent/atomics"
2
+
3
+ module EzConfig
4
+ class Store
5
+ def initialize
6
+ @store = Concurrent::Map
7
+ @lock = Concurrent::ReadWriteLock.new
8
+ end
9
+
10
+ def get(key)
11
+ @lock.with_read_lock do
12
+ @store[key]
13
+ end
14
+ end
15
+
16
+ def all
17
+ @lock.with_read_lock do
18
+ @store.all
19
+ end
20
+ end
21
+
22
+ def init(fs)
23
+ @lock.with_write_lock do
24
+ @store.replace(fs)
25
+ @initialized.make_true
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,35 @@
1
+
2
+ require 'rubygems'
3
+ require 'bundler'
4
+ Bundler.require(:default, :development)
5
+ require "concurrent/atomics"
6
+ require 'concurrent'
7
+ require_relative 'prefab/prefab_pb'
8
+ require_relative 'prefab/prefab_services_pb'
9
+ require_relative 'prefab/ratelimit_pb'
10
+ require_relative 'prefab/config_loader'
11
+ require_relative 'prefab/config_resolver'
12
+ require_relative 'prefab/client'
13
+ require_relative 'prefab/ratelimit_client'
14
+ require_relative 'prefab/config_client'
15
+ require_relative 'prefab/auth_interceptor'
16
+ require_relative 'prefab/noop_cache'
17
+ require_relative 'prefab/noop_stats'
18
+
19
+
20
+ client = Prefab::Client.new(api_key: ENV["RATELIMIT_API_KEY"], local: false)
21
+
22
+ start = Time.now
23
+ puts "pass? #{client.ratelimit_client.pass? "hubtest.secondly"}"
24
+ puts "pass? #{client.ratelimit_client.pass? "hubtest.secondly"}"
25
+ puts "pass? #{client.ratelimit_client.pass? "hubtest.secondly"}"
26
+ puts "pass? #{client.ratelimit_client.pass? "hubtest.secondly"}"
27
+ puts "pass? #{client.ratelimit_client.pass? "hubtest.secondly"}"
28
+ puts "pass? #{client.ratelimit_client.pass? "hubtest.secondly"}"
29
+ puts "pass? #{client.ratelimit_client.pass? "hubtest.secondly"}"
30
+ puts "pass? #{client.ratelimit_client.pass? "hubtest.secondly"}"
31
+
32
+ puts "took #{Time.now - start}"
33
+
34
+ # @@prefab = Prefab::Client.new(api_key: ENV["RATELIMIT_API_KEY"], local: true)
35
+ # @@prefab.rate_limits.check()
metadata ADDED
@@ -0,0 +1,175 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: prefab-cloud-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jeff Dwyer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-12-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: grpc
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: concurrent-ruby
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: grpc-tools
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: shoulda
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rdoc
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.12'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.12'
83
+ - !ruby/object:Gem::Dependency
84
+ name: bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: juwelier
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 2.1.0
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 2.1.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: simplecov
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: RateLimits & Config as a service
126
+ email: jdwyer@prefab.cloud
127
+ executables: []
128
+ extensions: []
129
+ extra_rdoc_files:
130
+ - LICENSE.txt
131
+ files:
132
+ - ".ruby-version"
133
+ - Gemfile
134
+ - Gemfile.lock
135
+ - LICENSE.txt
136
+ - Rakefile
137
+ - VERSION
138
+ - lib/prefab/auth_interceptor.rb
139
+ - lib/prefab/client.rb
140
+ - lib/prefab/config_client.rb
141
+ - lib/prefab/config_loader.rb
142
+ - lib/prefab/config_resolver.rb
143
+ - lib/prefab/noop_cache.rb
144
+ - lib/prefab/noop_stats.rb
145
+ - lib/prefab/prefab_pb.rb
146
+ - lib/prefab/prefab_services_pb.rb
147
+ - lib/prefab/ratelimit_client.rb
148
+ - lib/prefab/ratelimit_pb.rb
149
+ - lib/prefab/store.rb
150
+ - lib/prefab_client.rb
151
+ homepage: http://github.com/prefab-cloud/prefab-cloud-ruby
152
+ licenses:
153
+ - MIT
154
+ metadata: {}
155
+ post_install_message:
156
+ rdoc_options: []
157
+ require_paths:
158
+ - lib
159
+ required_ruby_version: !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - ">="
162
+ - !ruby/object:Gem::Version
163
+ version: '0'
164
+ required_rubygems_version: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - ">="
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
169
+ requirements: []
170
+ rubyforge_project:
171
+ rubygems_version: 2.6.14
172
+ signing_key:
173
+ specification_version: 4
174
+ summary: Prefab Ruby Infrastructure
175
+ test_files: []