gruf-balancer 0.1.0

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
+ SHA256:
3
+ metadata.gz: da7ba1903a2be65d647577b24642f3e80f53154920c7749ce74a9af4e11e93cb
4
+ data.tar.gz: 7bde6baf890ce9946b0c0e1928b331c1bd9556f3410fbf78fc3ab6cb1bca4900
5
+ SHA512:
6
+ metadata.gz: 9f1d38a8f68166702292758d93c8835e8cc40bb3b790ba6a978d8529c1f256d81413cc56b5761792c60a6289fb4c90260bc4dd39f96304fc8640543bb9022614
7
+ data.tar.gz: 42bcffa2238c48cc51bb5d727ef9eee791d9035f3d7400489b3710f6a54b41506316a891534b5ab2edab33dfef52d6a26ffc1c30f629f4a8cb739585fdd088dd
data/CHANGELOG.md ADDED
@@ -0,0 +1,15 @@
1
+ Changelog for the gruf-balancer gem.
2
+
3
+ ### Pending release
4
+
5
+ ### 0.1.0
6
+
7
+ - Add Ruby 3.0 support
8
+
9
+ ### 0.0.2
10
+
11
+ - Allow configuring the client class when adding a client
12
+
13
+ ### 0.0.1
14
+
15
+ - Initial release
@@ -0,0 +1,46 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6
+
7
+ ## Our Standards
8
+
9
+ Examples of behavior that contributes to creating a positive environment include:
10
+
11
+ * Using welcoming and inclusive language
12
+ * Being respectful of differing viewpoints and experiences
13
+ * Gracefully accepting constructive criticism
14
+ * Focusing on what is best for the community
15
+ * Showing empathy towards other community members
16
+
17
+ Examples of unacceptable behavior by participants include:
18
+
19
+ * The use of sexualized language or imagery and unwelcome sexual attention or advances
20
+ * Trolling, insulting/derogatory comments, and personal or political attacks
21
+ * Public or private harassment
22
+ * Publishing others' private information, such as a physical or electronic address, without explicit permission
23
+ * Other conduct which could reasonably be considered inappropriate in a professional setting
24
+
25
+ ## Our Responsibilities
26
+
27
+ Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28
+
29
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30
+
31
+ ## Scope
32
+
33
+ This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34
+
35
+ ## Enforcement
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at engineering@bigcommerce.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38
+
39
+ Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40
+
41
+ ## Attribution
42
+
43
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44
+
45
+ [homepage]: http://contributor-covenant.org
46
+ [version]: http://contributor-covenant.org/version/1/4/
data/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # gruf-balancer - Testing framework for Gruf Clients
2
+
3
+ [![CircleCI](https://circleci.com/gh/bigcommerce/gruf-balancer/tree/main.svg?style=svg)](https://circleci.com/gh/bigcommerce/gruf-balancer/tree/main) [![Gem Version](https://badge.fury.io/rb/gruf-scientist.svg)](https://badge.fury.io/rb/gruf-balancer) [![Documentation](https://inch-ci.org/github/bigcommerce/gruf-balancer.svg?branch=main)](https://inch-ci.org/github/bigcommerce/gruf-balancer?branch=main)
4
+
5
+ Provides a framework for testing various outbound `Gruf::Client` calls on a percentage-basis, letting you balance
6
+ requests between multiple clients for testing new services, code paths, or networking operations.
7
+
8
+ ## Installation
9
+
10
+ ```ruby
11
+ gem 'gruf-balancer'
12
+ ```
13
+
14
+ ## Usage
15
+
16
+ Instead of creating a normal `Gruf::Client`, simply add clients to a `Gruf::Balancer::Client`, via passing in
17
+ a percentage of requests and client options (similarly to how you'd create `Gruf::Client` objects).
18
+
19
+ ```ruby
20
+ client = Gruf::Balancer::Client.new(service: MyService)
21
+ client.add_client(percentage: 60, options: { hostname: '127.0.0.1:8000' })
22
+ client.add_client(percentage: 40, options: { hostname: '127.0.0.1:8001' })
23
+ # @type [Gruf::Response] resp
24
+ resp = client.call(:GetThing, id: 123)
25
+ ```
26
+
27
+ This uses a weighted random sampling algorithm under the hood to balance the requests to the method on the defined
28
+ percentage weights. In the example above, 60% of requests would go to our service on port 8000, and 40% on port 8001.
29
+
30
+ `Gruf::Balancer::Client` acts similarly to a `Gruf::Client`, in terms of its `call` method signature. It maintains
31
+ a thread-safe pool of clients. Note, similarly to gRPC core, that clients are not fork-safe; please instantiate
32
+ any balanced client pools _after_ forking.
33
+
34
+ ### Use Cases
35
+
36
+ Some use cases for gruf-balancer can be:
37
+
38
+ * Testing a new application service that serves the same gRPC Service, but on a different hostname
39
+ * Testing different hostnames, routing rules, network infrastructure, or service meshes via different hostnames
40
+ * Testing new client options, such as timeouts, credentials, channels, or channel arguments
41
+ * Testing new client interceptors, since they are configured per-client
42
+
43
+ ## License
44
+
45
+ Copyright (c) 2021-present, BigCommerce Pty. Ltd. All rights reserved
46
+
47
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
48
+ documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
49
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
50
+ persons to whom the Software is furnished to do so, subject to the following conditions:
51
+
52
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
53
+ Software.
54
+
55
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
56
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
57
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
58
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2021-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ $LOAD_PATH.push File.expand_path('lib', __dir__)
19
+ require 'gruf/balancer/version'
20
+
21
+ Gem::Specification.new do |spec|
22
+ spec.name = 'gruf-balancer'
23
+ spec.version = Gruf::Balancer::VERSION
24
+ spec.authors = ['Shaun McCormick']
25
+ spec.email = ['splittingred@gmail.com']
26
+ spec.licenses = ['MIT']
27
+
28
+ spec.summary = 'Allows for percentage-based balancing of gruf client calls'
29
+ spec.description = spec.summary
30
+ spec.homepage = 'https://github.com/bigcommerce/gruf-balancer'
31
+
32
+ spec.files = Dir['README.md', 'CHANGELOG.md', 'CODE_OF_CONDUCT.md', 'lib/**/*', 'gruf-balancer.gemspec']
33
+ spec.require_paths = ['lib']
34
+
35
+ spec.required_ruby_version = '>= 2.6'
36
+
37
+ spec.add_development_dependency 'benchmark-memory', '0.1.2'
38
+ spec.add_development_dependency 'bundler-audit', '>= 0.6'
39
+ spec.add_development_dependency 'pry', '>= 0.12'
40
+ spec.add_development_dependency 'pry-byebug', '>= 3.9'
41
+ spec.add_development_dependency 'rspec', '>= 3.8'
42
+ spec.add_development_dependency 'rspec_junit_formatter', '>= 0.4'
43
+ spec.add_development_dependency 'rubocop', '>= 1.0'
44
+ spec.add_development_dependency 'rubocop-performance', '>= 0.0.1'
45
+ spec.add_development_dependency 'rubocop-rspec', '>= 2.0'
46
+ spec.add_development_dependency 'rubocop-thread_safety', '>= 0.3'
47
+ spec.add_development_dependency 'simplecov', '>= 0.16'
48
+
49
+ spec.add_runtime_dependency 'concurrent-ruby', '> 1'
50
+ spec.add_runtime_dependency 'gruf', '> 2.8'
51
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2021-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ module Gruf
19
+ module Balancer
20
+ ##
21
+ # Thread-safe class that allows percentage-based balancing of calls to a given pool of clients
22
+ #
23
+ class Client
24
+ ##
25
+ # @param [GRPC::GenericService] service The gRPC Service stub to use when creating clients in this pool
26
+ # @param [Hash] options A default set of options to pass through to all Gruf::Clients in this balanced pool
27
+ # @param [Hash] client_options A default set of gRPC client options to pass through to all Gruf::Clients in this
28
+ # balanced pool
29
+ #
30
+ def initialize(service:, options: {}, client_options: {})
31
+ super()
32
+ @service = service
33
+ @options = options
34
+ @client_options = client_options
35
+ @pool = ::Concurrent::Hash.new
36
+ @sampler = ->(pool) { pool.max_by { |_, w| rand**(1.0 / w) }.first }
37
+ end
38
+
39
+ ##
40
+ # Create a client and add it to the pool at a given percentage of requests. If the percentage given is outside of
41
+ # 0-100, it will automatically constrain it to the max of 100.0 or minimum of 0.0.
42
+ #
43
+ # @param [Float] percentage The percentage of requests to weight by (0-100)
44
+ # @param [Hash] options Options to pass-through to the Gruf::Client
45
+ # @param [Hash] client_options gRPC Client Options to pass-through to the Gruf::Client
46
+ # @param [Class] client_class The client class to use. Useful if wanting to create a Gruf::SynchronizedClient or
47
+ # other derivative client
48
+ #
49
+ def add_client(percentage:, options: {}, client_options: {}, client_class: nil)
50
+ client_class ||= ::Gruf::Client
51
+ percentage = percentage > 100.0 ? 100.0 : percentage.to_f
52
+ percentage = percentage < 0.0 ? 0.0 : percentage
53
+ cl = client_class.new(
54
+ service: @service,
55
+ options: @options.merge(options),
56
+ client_options: @client_options.merge(client_options)
57
+ )
58
+ @pool[cl] = percentage.to_f / 100.0
59
+ end
60
+
61
+ ##
62
+ # Pick a sampled client from the pool based on the weighted percentages entered
63
+ #
64
+ # @return [::Gruf::Client]
65
+ #
66
+ def pick
67
+ @sampler[@pool]
68
+ end
69
+
70
+ ##
71
+ # Delegate the call to the sampled client
72
+ #
73
+ # @return [Gruf::Response]
74
+ #
75
+ def call(*args, &block)
76
+ pick.call(*args, &block)
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2021-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ module Gruf
19
+ module Balancer
20
+ ##
21
+ # Represents configuration settings for the system
22
+ #
23
+ module Configuration
24
+ VALID_CONFIG_KEYS = {}.freeze
25
+
26
+ attr_accessor(* VALID_CONFIG_KEYS.keys)
27
+
28
+ ##
29
+ # Whenever this is extended into a class, setup the defaults
30
+ #
31
+ def self.extended(base)
32
+ base.reset
33
+ end
34
+
35
+ ##
36
+ # Yield self for ruby-style initialization
37
+ #
38
+ # @yields [Gruf::Balancer::Configuration] The configuration object
39
+ # @return [Gruf::Balancer::Configuration] The configuration object
40
+ #
41
+ def configure
42
+ yield self
43
+ end
44
+
45
+ ##
46
+ # Return the current configuration options as a Hash
47
+ #
48
+ # @return [Hash] The configuration represented as a Hash
49
+ #
50
+ def options
51
+ opts = {}
52
+ VALID_CONFIG_KEYS.each_key do |k|
53
+ opts.merge!(k => send(k))
54
+ end
55
+ opts
56
+ end
57
+
58
+ ##
59
+ # Set the default configuration onto the extended class
60
+ #
61
+ # @return [Hash] options The reset options hash
62
+ #
63
+ def reset
64
+ VALID_CONFIG_KEYS.each do |k, v|
65
+ send("#{k}=", v)
66
+ end
67
+ options
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2021-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ module Gruf
19
+ module Balancer
20
+ VERSION = '0.1.0'
21
+ end
22
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2021-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ require 'gruf'
19
+ require 'concurrent'
20
+ require_relative 'balancer/version'
21
+ require_relative 'balancer/configuration'
22
+ require_relative 'balancer/client'
23
+
24
+ module Gruf
25
+ ##
26
+ # gruf-balancer top-level module
27
+ #
28
+ module Balancer
29
+ extend ::Gruf::Balancer::Configuration
30
+ end
31
+ end
metadata ADDED
@@ -0,0 +1,233 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gruf-balancer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Shaun McCormick
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-10-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: benchmark-memory
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.1.2
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.1.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler-audit
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0.6'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0.12'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0.12'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry-byebug
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '3.9'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '3.9'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '3.8'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '3.8'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec_junit_formatter
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0.4'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0.4'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '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: '1.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop-performance
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: 0.0.1
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: 0.0.1
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubocop-rspec
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '2.0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '2.0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rubocop-thread_safety
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0.3'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0.3'
153
+ - !ruby/object:Gem::Dependency
154
+ name: simplecov
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0.16'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0.16'
167
+ - !ruby/object:Gem::Dependency
168
+ name: concurrent-ruby
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">"
172
+ - !ruby/object:Gem::Version
173
+ version: '1'
174
+ type: :runtime
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">"
179
+ - !ruby/object:Gem::Version
180
+ version: '1'
181
+ - !ruby/object:Gem::Dependency
182
+ name: gruf
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">"
186
+ - !ruby/object:Gem::Version
187
+ version: '2.8'
188
+ type: :runtime
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">"
193
+ - !ruby/object:Gem::Version
194
+ version: '2.8'
195
+ description: Allows for percentage-based balancing of gruf client calls
196
+ email:
197
+ - splittingred@gmail.com
198
+ executables: []
199
+ extensions: []
200
+ extra_rdoc_files: []
201
+ files:
202
+ - CHANGELOG.md
203
+ - CODE_OF_CONDUCT.md
204
+ - README.md
205
+ - gruf-balancer.gemspec
206
+ - lib/gruf/balancer.rb
207
+ - lib/gruf/balancer/client.rb
208
+ - lib/gruf/balancer/configuration.rb
209
+ - lib/gruf/balancer/version.rb
210
+ homepage: https://github.com/bigcommerce/gruf-balancer
211
+ licenses:
212
+ - MIT
213
+ metadata: {}
214
+ post_install_message:
215
+ rdoc_options: []
216
+ require_paths:
217
+ - lib
218
+ required_ruby_version: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - ">="
221
+ - !ruby/object:Gem::Version
222
+ version: '2.6'
223
+ required_rubygems_version: !ruby/object:Gem::Requirement
224
+ requirements:
225
+ - - ">="
226
+ - !ruby/object:Gem::Version
227
+ version: '0'
228
+ requirements: []
229
+ rubygems_version: 3.2.17
230
+ signing_key:
231
+ specification_version: 4
232
+ summary: Allows for percentage-based balancing of gruf client calls
233
+ test_files: []