istox_gruf 2.7.1

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.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +246 -0
  3. data/CODE_OF_CONDUCT.md +46 -0
  4. data/README.md +544 -0
  5. data/bin/gruf +29 -0
  6. data/lib/gruf.rb +50 -0
  7. data/lib/gruf/cli/executor.rb +99 -0
  8. data/lib/gruf/client.rb +217 -0
  9. data/lib/gruf/client/error.rb +66 -0
  10. data/lib/gruf/client/error_factory.rb +105 -0
  11. data/lib/gruf/configuration.rb +137 -0
  12. data/lib/gruf/controllers/base.rb +102 -0
  13. data/lib/gruf/controllers/request.rb +121 -0
  14. data/lib/gruf/controllers/service_binder.rb +117 -0
  15. data/lib/gruf/error.rb +230 -0
  16. data/lib/gruf/errors/debug_info.rb +56 -0
  17. data/lib/gruf/errors/field.rb +56 -0
  18. data/lib/gruf/errors/helpers.rb +44 -0
  19. data/lib/gruf/hooks/base.rb +34 -0
  20. data/lib/gruf/hooks/executor.rb +47 -0
  21. data/lib/gruf/hooks/registry.rb +159 -0
  22. data/lib/gruf/instrumentable_grpc_server.rb +64 -0
  23. data/lib/gruf/integrations/rails/railtie.rb +10 -0
  24. data/lib/gruf/interceptors/active_record/connection_reset.rb +48 -0
  25. data/lib/gruf/interceptors/authentication/basic.rb +87 -0
  26. data/lib/gruf/interceptors/base.rb +53 -0
  27. data/lib/gruf/interceptors/client_interceptor.rb +125 -0
  28. data/lib/gruf/interceptors/context.rb +56 -0
  29. data/lib/gruf/interceptors/instrumentation/output_metadata_timer.rb +61 -0
  30. data/lib/gruf/interceptors/instrumentation/request_logging/formatters/base.rb +41 -0
  31. data/lib/gruf/interceptors/instrumentation/request_logging/formatters/logstash.rb +43 -0
  32. data/lib/gruf/interceptors/instrumentation/request_logging/formatters/plain.rb +48 -0
  33. data/lib/gruf/interceptors/instrumentation/request_logging/interceptor.rb +225 -0
  34. data/lib/gruf/interceptors/instrumentation/statsd.rb +82 -0
  35. data/lib/gruf/interceptors/registry.rb +161 -0
  36. data/lib/gruf/interceptors/server_interceptor.rb +34 -0
  37. data/lib/gruf/interceptors/timer.rb +85 -0
  38. data/lib/gruf/loggable.rb +30 -0
  39. data/lib/gruf/logging.rb +53 -0
  40. data/lib/gruf/outbound/request_context.rb +71 -0
  41. data/lib/gruf/response.rb +71 -0
  42. data/lib/gruf/serializers/errors/base.rb +57 -0
  43. data/lib/gruf/serializers/errors/json.rb +43 -0
  44. data/lib/gruf/server.rb +294 -0
  45. data/lib/gruf/synchronized_client.rb +97 -0
  46. data/lib/gruf/timer.rb +78 -0
  47. data/lib/gruf/version.rb +20 -0
  48. metadata +203 -0
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2017-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 'concurrent'
19
+
20
+ module Gruf
21
+ ##
22
+ # Ensures that we only have one active call to a given endpoint with a given set of params. This can be useful
23
+ # to mitigate thundering herds.
24
+ #
25
+ class SynchronizedClient < Gruf::Client
26
+ attr_reader :unsynchronized_methods
27
+
28
+ ##
29
+ # Initialize the client and setup the stub
30
+ #
31
+ # @param [Module] service The namespace of the client Stub that is desired to load
32
+ # @param [Hash] options A hash of options for the client
33
+ # @option options [Array] :unsynchronized_methods A list of methods (as symbols) that
34
+ # should be excluded from synchronization
35
+ # @option options [Integer] :internal_cache_expiry The length of time to keep results
36
+ # around for other threads to fetch (in seconds)
37
+ # @param [Hash] client_options A hash of options to pass to the gRPC client stub
38
+ #
39
+ def initialize(service:, options: {}, client_options: {})
40
+ @unsynchronized_methods = options.delete(:unsynchronized_methods) { [] }
41
+ @expiry = options.delete(:internal_cache_expiry) { Gruf.synchronized_client_internal_cache_expiry }
42
+ @locks = Concurrent::Map.new
43
+ @results = Concurrent::Map.new
44
+ super
45
+ end
46
+
47
+ ##
48
+ # Call the client's method with given params. If another call is already active for the same endpoint and the same
49
+ # params, block until the active call is complete. When unblocked, callers will get a copy of the original result.
50
+ #
51
+ # @param [String|Symbol] request_method The method that is being requested on the service
52
+ # @param [Hash] params (Optional) A hash of parameters that will be inserted into the gRPC request
53
+ # message that is required for the given above call
54
+ # @param [Hash] metadata (Optional) A hash of metadata key/values that are transported with the client request
55
+ # @param [Hash] opts (Optional) A hash of options to send to the gRPC request_response method
56
+ # @return [Gruf::Response] The response from the server
57
+ # @raise [Gruf::Client::Error|GRPC::BadStatus] If an error occurs, an exception will be raised according to the
58
+ # error type that was returned
59
+ #
60
+ def call(request_method, params = {}, metadata = {}, opts = {}, &block)
61
+ # Allow for bypassing extra behavior for selected methods
62
+ return super if unsynchronized_methods.include?(request_method.to_sym)
63
+
64
+ # Generate a unique key based on the method and params
65
+ key = "#{request_method}.#{params.hash}"
66
+
67
+ # Create a lock for this call if we haven't seen it already, then acquire it
68
+ lock = @locks.compute_if_absent(key) { Mutex.new }
69
+ lock.synchronize do
70
+ # Return value from results cache if it exists. This occurs for callers that were
71
+ # waiting on the lock while the first caller was making the actual grpc call.
72
+ response = @results.get(lock)
73
+ if response
74
+ Gruf.logger.debug "Returning cached result for #{key}:#{lock.inspect}"
75
+ next response
76
+ end
77
+
78
+ # Make the grpc call and record response for other callers that are blocked
79
+ # on the same lock
80
+ response = super
81
+ @results.put(lock, response)
82
+
83
+ # Schedule a task to come in later and clean out result to prevent memory bloat
84
+ Concurrent::ScheduledTask.new(@expiry, args: [@results, lock]) { |h, k| h.delete(k) }.execute
85
+
86
+ # Remove the lock from the map. The next caller to come through with the
87
+ # same params will create a new lock and start the process over again.
88
+ # Anyone who was waiting on this call will be using a local reference
89
+ # to the same lock as us, and will fetch the result from the cache.
90
+ @locks.delete(key)
91
+
92
+ # Return response
93
+ response
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2017-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
+ ##
20
+ # Times a given block and returns the result and the elapsed time as a Float
21
+ #
22
+ # result = Timer.time { do_my_thing }
23
+ #
24
+ class Timer
25
+ ##
26
+ # Represents a timer result that contains both the elapsed time and the result of the block
27
+ #
28
+ # result = Timer.time { do_my_thing }
29
+ # result.time # => 1.10123
30
+ # result.result # => 'my_thing_is_done'
31
+ #
32
+ class Result
33
+ # @return [Object] result The result of the block that was called
34
+ attr_reader :result
35
+ # @return [Float] time The time, in ms, of the block execution
36
+ attr_reader :time
37
+
38
+ ##
39
+ # Initialize the result object
40
+ #
41
+ # @param [Object] result The result of the block that was called
42
+ # @param [Float] time The time, in ms, of the block execution
43
+ #
44
+ def initialize(result, time)
45
+ @result = result
46
+ @time = time.to_f
47
+ end
48
+
49
+ ##
50
+ # Was this result a successful result?
51
+ #
52
+ # @return [Boolean] Whether or not this result was a success
53
+ #
54
+ def success?
55
+ !result.is_a?(GRPC::BadStatus) && !result.is_a?(StandardError) && !result.is_a?(GRPC::Core::CallError)
56
+ end
57
+ end
58
+
59
+ ##
60
+ # Times a given block by recording start and end times
61
+ #
62
+ # result = Timer.time { do_my_thing }
63
+ #
64
+ # @return [Timer::Result] Returns the timed result of the block
65
+ #
66
+ def self.time
67
+ start_time = Time.now
68
+ begin
69
+ result = yield
70
+ rescue GRPC::BadStatus, StandardError, GRPC::Core::CallError => e
71
+ result = e
72
+ end
73
+ end_time = Time.now
74
+ elapsed = (end_time - start_time) * 1000.0
75
+ Result.new(result, elapsed)
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2017-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
+ VERSION = '2.7.1'
20
+ end
metadata ADDED
@@ -0,0 +1,203 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: istox_gruf
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.7.1
5
+ platform: ruby
6
+ authors:
7
+ - Shaun McCormick
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-06-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.11'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.11'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
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.11'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.11'
55
+ - !ruby/object:Gem::Dependency
56
+ name: grpc
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.10'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.10'
69
+ - !ruby/object:Gem::Dependency
70
+ name: grpc-tools
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.10'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.10'
83
+ - !ruby/object:Gem::Dependency
84
+ name: activesupport
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">"
88
+ - !ruby/object:Gem::Version
89
+ version: '4'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">"
95
+ - !ruby/object:Gem::Version
96
+ version: '4'
97
+ - !ruby/object:Gem::Dependency
98
+ name: concurrent-ruby
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">"
102
+ - !ruby/object:Gem::Version
103
+ version: '1'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">"
109
+ - !ruby/object:Gem::Version
110
+ version: '1'
111
+ - !ruby/object:Gem::Dependency
112
+ name: slop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '4.6'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '4.6'
125
+ description: gRPC Ruby Framework for building complex gRPC applications at scale
126
+ email:
127
+ - splittingred@gmail.com
128
+ executables:
129
+ - gruf
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - CHANGELOG.md
134
+ - CODE_OF_CONDUCT.md
135
+ - README.md
136
+ - bin/gruf
137
+ - lib/gruf.rb
138
+ - lib/gruf/cli/executor.rb
139
+ - lib/gruf/client.rb
140
+ - lib/gruf/client/error.rb
141
+ - lib/gruf/client/error_factory.rb
142
+ - lib/gruf/configuration.rb
143
+ - lib/gruf/controllers/base.rb
144
+ - lib/gruf/controllers/request.rb
145
+ - lib/gruf/controllers/service_binder.rb
146
+ - lib/gruf/error.rb
147
+ - lib/gruf/errors/debug_info.rb
148
+ - lib/gruf/errors/field.rb
149
+ - lib/gruf/errors/helpers.rb
150
+ - lib/gruf/hooks/base.rb
151
+ - lib/gruf/hooks/executor.rb
152
+ - lib/gruf/hooks/registry.rb
153
+ - lib/gruf/instrumentable_grpc_server.rb
154
+ - lib/gruf/integrations/rails/railtie.rb
155
+ - lib/gruf/interceptors/active_record/connection_reset.rb
156
+ - lib/gruf/interceptors/authentication/basic.rb
157
+ - lib/gruf/interceptors/base.rb
158
+ - lib/gruf/interceptors/client_interceptor.rb
159
+ - lib/gruf/interceptors/context.rb
160
+ - lib/gruf/interceptors/instrumentation/output_metadata_timer.rb
161
+ - lib/gruf/interceptors/instrumentation/request_logging/formatters/base.rb
162
+ - lib/gruf/interceptors/instrumentation/request_logging/formatters/logstash.rb
163
+ - lib/gruf/interceptors/instrumentation/request_logging/formatters/plain.rb
164
+ - lib/gruf/interceptors/instrumentation/request_logging/interceptor.rb
165
+ - lib/gruf/interceptors/instrumentation/statsd.rb
166
+ - lib/gruf/interceptors/registry.rb
167
+ - lib/gruf/interceptors/server_interceptor.rb
168
+ - lib/gruf/interceptors/timer.rb
169
+ - lib/gruf/loggable.rb
170
+ - lib/gruf/logging.rb
171
+ - lib/gruf/outbound/request_context.rb
172
+ - lib/gruf/response.rb
173
+ - lib/gruf/serializers/errors/base.rb
174
+ - lib/gruf/serializers/errors/json.rb
175
+ - lib/gruf/server.rb
176
+ - lib/gruf/synchronized_client.rb
177
+ - lib/gruf/timer.rb
178
+ - lib/gruf/version.rb
179
+ homepage: https://github.com/bigcommerce/gruf
180
+ licenses:
181
+ - MIT
182
+ metadata: {}
183
+ post_install_message:
184
+ rdoc_options: []
185
+ require_paths:
186
+ - lib
187
+ required_ruby_version: !ruby/object:Gem::Requirement
188
+ requirements:
189
+ - - "~>"
190
+ - !ruby/object:Gem::Version
191
+ version: '2.4'
192
+ required_rubygems_version: !ruby/object:Gem::Requirement
193
+ requirements:
194
+ - - ">="
195
+ - !ruby/object:Gem::Version
196
+ version: '0'
197
+ requirements: []
198
+ rubyforge_project:
199
+ rubygems_version: 2.7.9
200
+ signing_key:
201
+ specification_version: 4
202
+ summary: gRPC Ruby Framework
203
+ test_files: []