gruf-queue 0.1.3 → 0.1.4
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/CHANGELOG.md +23 -0
- data/README.md +18 -272
- data/lib/gruf/queue/plugin.rb +2 -31
- data/lib/gruf/queue/pool_enhancements.rb +23 -16
- data/lib/gruf/queue/version.rb +1 -1
- data/lib/gruf-queue.rb +0 -1
- metadata +1 -2
- data/lib/gruf/queue/queued_rpc_server.rb +0 -105
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cc1f1ae6ceeae244f3240289293550ac50d4817c146bdd0ae08c0ba4aac3d6b9
|
4
|
+
data.tar.gz: 510388ca36e935b14f7d727acc5f74a46969018b87cce11bfedf6a0a5723ba1b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 456159e1ad576446eb160c81a5fd285a8892c005cafc89c3607fcf8371da9e65e98481f14d44760f798cba36abda25e55c80199779e5e68339b6836faf5a32b3
|
7
|
+
data.tar.gz: 2c4e4d90a9667a860de5fb243d0d1c8d4fa8cae4499307c5f65f9e2b0dc7827973662ea24b03c1d1b000807a880645c272b93a52c8b4cd373c01e96c765028a7
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,29 @@ All notable changes to this project will be documented in this file.
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
7
|
|
8
|
+
## [0.1.4]
|
9
|
+
|
10
|
+
### Changed
|
11
|
+
- Renamed `AvaiallableQueue` to `AlwaysReadyQueue` (fixed typo)
|
12
|
+
- Improved null object pattern implementation for worker queue management
|
13
|
+
- Simplified README.md to focus on core functionality
|
14
|
+
|
15
|
+
### Added
|
16
|
+
- Graceful shutdown support with `@stopped` flag checking
|
17
|
+
- Enhanced test coverage for environment variable configuration
|
18
|
+
- Comprehensive test suite for graceful shutdown behavior
|
19
|
+
- Thread-safe shutdown handling for GRPC::Pool enhancements
|
20
|
+
|
21
|
+
### Fixed
|
22
|
+
- Fixed graceful shutdown issues that prevented proper signal handling
|
23
|
+
- Improved AlwaysReadyQueue method implementations for better compatibility
|
24
|
+
- Enhanced error handling in ready_for_work? method
|
25
|
+
|
26
|
+
### Improved
|
27
|
+
- More accurate documentation reflecting actual gem purpose
|
28
|
+
- Better test organization with focused integration tests
|
29
|
+
- Cleaner code structure with proper separation of concerns
|
30
|
+
|
8
31
|
## [0.1.3]
|
9
32
|
|
10
33
|
### Changed
|
data/README.md
CHANGED
@@ -3,287 +3,55 @@
|
|
3
3
|
[](https://badge.fury.io/rb/gruf-queue)
|
4
4
|
[](https://ruby-lang.org)
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
6
|
-
[](https://github.com/your-org/gruf-queue/actions)
|
7
6
|
|
8
|
-
|
7
|
+
Simple GRPC::Pool enhancement that replaces worker-based capacity checking with job count based threshold.
|
9
8
|
|
10
|
-
##
|
9
|
+
## What it does
|
11
10
|
|
12
|
-
|
13
|
-
-
|
14
|
-
-
|
15
|
-
-
|
16
|
-
|
17
|
-
🔌 **Plugin Architecture**
|
18
|
-
- Zero-configuration auto-installation
|
19
|
-
- Non-invasive integration with existing Gruf applications
|
20
|
-
- Modular design with configurable components
|
21
|
-
|
22
|
-
🛡️ **Reliability & Safety**
|
23
|
-
- Thread-safe operations with proper synchronization
|
24
|
-
- Graceful error handling and recovery
|
25
|
-
- Smart ActiveRecord connection management
|
26
|
-
|
27
|
-
📊 **Observability**
|
28
|
-
- Structured logging with metadata for monitoring
|
29
|
-
- Thread naming for better debugging
|
30
|
-
- Comprehensive error reporting with context
|
11
|
+
- Replaces `GRPC::Pool` worker queue management with a simple job count check
|
12
|
+
- Uses `jobs_waiting < threshold` instead of tracking actual worker availability
|
13
|
+
- Configurable threshold via `GRUF_MAX_WAITING_REQUESTS` (default: 60)
|
14
|
+
- Supports graceful shutdown
|
31
15
|
|
32
16
|
## Installation
|
33
17
|
|
34
|
-
Add this line to your application's Gemfile:
|
35
|
-
|
36
18
|
```ruby
|
37
19
|
gem 'gruf-queue'
|
38
20
|
```
|
39
21
|
|
40
|
-
|
41
|
-
|
42
|
-
```bash
|
43
|
-
$ bundle install
|
44
|
-
```
|
45
|
-
|
46
|
-
## Quick Start
|
47
|
-
|
48
|
-
### Zero Configuration Setup
|
49
|
-
|
50
|
-
The simplest way to use gruf-queue is to just require it:
|
22
|
+
## Usage
|
51
23
|
|
52
24
|
```ruby
|
53
25
|
require 'gruf-queue'
|
54
26
|
|
55
|
-
#
|
56
|
-
|
27
|
+
# Optional: Set threshold (default is 60)
|
28
|
+
ENV['GRUF_MAX_WAITING_REQUESTS'] = '100'
|
29
|
+
|
30
|
+
# Start server normally
|
57
31
|
Gruf::Server.new(
|
58
32
|
hostname: '0.0.0.0:9001',
|
59
33
|
services: [YourService]
|
60
34
|
).start
|
61
35
|
```
|
62
36
|
|
63
|
-
|
64
|
-
- ✅ Configures Gruf to use `QueuedRpcServer`
|
65
|
-
- ✅ Registers the `ConnectionReset` interceptor (if ActiveRecord is available)
|
66
|
-
- ✅ Sets up enhanced thread pool management
|
67
|
-
- ✅ Enables structured logging
|
68
|
-
|
69
|
-
### Manual Installation Control
|
70
|
-
|
71
|
-
To disable auto-installation and configure manually:
|
37
|
+
## Configuration
|
72
38
|
|
73
39
|
```ruby
|
74
40
|
# Disable auto-installation
|
75
41
|
ENV['GRUF_QUEUE_NO_AUTO_INSTALL'] = 'true'
|
76
42
|
|
77
|
-
require 'gruf-queue'
|
78
|
-
|
79
43
|
# Manual installation
|
80
44
|
Gruf::Queue::Plugin.install!
|
81
|
-
|
82
|
-
# Or configure components individually
|
83
|
-
Gruf.configure do |config|
|
84
|
-
config.rpc_server = Gruf::Queue::QueuedRpcServer
|
85
|
-
|
86
|
-
config.interceptors.use(
|
87
|
-
Gruf::Interceptors::ActiveRecord::ConnectionReset,
|
88
|
-
enabled: true,
|
89
|
-
target_classes: [ActiveRecord::Base]
|
90
|
-
)
|
91
|
-
end
|
92
|
-
```
|
93
|
-
|
94
|
-
## Configuration
|
95
|
-
|
96
|
-
### Server Configuration
|
97
|
-
|
98
|
-
```ruby
|
99
|
-
# Configure the QueuedRpcServer with custom settings
|
100
|
-
Gruf.configure do |config|
|
101
|
-
config.rpc_server = Gruf::Queue::QueuedRpcServer
|
102
|
-
config.rpc_server_options = {
|
103
|
-
pool_size: 10, # Thread pool size
|
104
|
-
max_waiting_requests: 20, # Queue capacity
|
105
|
-
pool_keep_alive: 300, # Thread keep-alive time
|
106
|
-
poll_period: 1 # Polling interval
|
107
|
-
}
|
108
|
-
end
|
109
45
|
```
|
110
46
|
|
111
|
-
|
112
|
-
|
113
|
-
For custom server instances with specific options:
|
47
|
+
## How it works
|
114
48
|
|
115
49
|
```ruby
|
116
|
-
#
|
117
|
-
|
118
|
-
pool_size: 15,
|
119
|
-
max_waiting_requests: 30
|
120
|
-
)
|
50
|
+
# Before: GRPC::Pool tracks actual worker availability
|
51
|
+
pool.ready_for_work? # Complex worker state checking
|
121
52
|
|
122
|
-
|
123
|
-
|
124
|
-
services: [YourService],
|
125
|
-
rpc_server: server
|
126
|
-
).start
|
127
|
-
```
|
128
|
-
|
129
|
-
### ActiveRecord Connection Management
|
130
|
-
|
131
|
-
The `ConnectionReset` interceptor automatically manages database connections:
|
132
|
-
|
133
|
-
```ruby
|
134
|
-
# Automatically registered when ActiveRecord is detected
|
135
|
-
# Customizable with additional target classes:
|
136
|
-
Gruf.configure do |config|
|
137
|
-
config.interceptors.use(
|
138
|
-
Gruf::Interceptors::ActiveRecord::ConnectionReset,
|
139
|
-
enabled: true,
|
140
|
-
target_classes: [ActiveRecord::Base, CustomConnectionClass]
|
141
|
-
)
|
142
|
-
end
|
143
|
-
```
|
144
|
-
|
145
|
-
## Architecture
|
146
|
-
|
147
|
-
### Core Components
|
148
|
-
|
149
|
-
#### `Gruf::Queue::QueuedRpcServer`
|
150
|
-
Enhanced gRPC server with intelligent resource management:
|
151
|
-
- Monitors thread pool capacity
|
152
|
-
- Automatically sends `RESOURCE_EXHAUSTED` when overloaded
|
153
|
-
- Provides structured error handling
|
154
|
-
|
155
|
-
#### `Gruf::Queue::Pool`
|
156
|
-
Advanced thread pool implementation:
|
157
|
-
- Extends `GRPC::Pool` with enhanced job scheduling
|
158
|
-
- Structured logging with thread identification
|
159
|
-
- Comprehensive error isolation and recovery
|
160
|
-
|
161
|
-
#### `Gruf::Interceptors::ActiveRecord::ConnectionReset`
|
162
|
-
Smart database connection management:
|
163
|
-
- Automatically resets ActiveRecord connections after each request
|
164
|
-
- Validates connection handlers before attempting reset
|
165
|
-
- Graceful error handling to prevent request failures
|
166
|
-
|
167
|
-
#### `Gruf::Queue::Plugin`
|
168
|
-
Plugin management system:
|
169
|
-
- Idempotent installation process
|
170
|
-
- Comprehensive error handling during setup
|
171
|
-
- Validation of dependencies and requirements
|
172
|
-
|
173
|
-
### Plugin Lifecycle
|
174
|
-
|
175
|
-
```ruby
|
176
|
-
# Plugin installation process
|
177
|
-
Gruf::Queue::Plugin.install! # => true (success) or false (failure)
|
178
|
-
|
179
|
-
# Check installation status
|
180
|
-
Gruf::Queue::Plugin.installed? # => true/false
|
181
|
-
|
182
|
-
# Reset for testing (test environments only)
|
183
|
-
Gruf::Queue::Plugin.reset!
|
184
|
-
```
|
185
|
-
|
186
|
-
## Advanced Usage
|
187
|
-
|
188
|
-
### Custom Server Implementation
|
189
|
-
|
190
|
-
```ruby
|
191
|
-
# Create a custom server class
|
192
|
-
class MyCustomServer < Gruf::Queue::QueuedRpcServer
|
193
|
-
def initialize(*)
|
194
|
-
super
|
195
|
-
# Custom initialization logic
|
196
|
-
end
|
197
|
-
|
198
|
-
private
|
199
|
-
|
200
|
-
def handle_custom_logic
|
201
|
-
# Your custom server logic
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
# Use with gruf-queue
|
206
|
-
Gruf.configure do |config|
|
207
|
-
config.rpc_server = MyCustomServer
|
208
|
-
end
|
209
|
-
```
|
210
|
-
|
211
|
-
### Monitoring and Observability
|
212
|
-
|
213
|
-
```ruby
|
214
|
-
# Structured logging is automatically enabled
|
215
|
-
# Logs include contextual information:
|
216
|
-
# - Thread IDs for debugging
|
217
|
-
# - Error details with full context
|
218
|
-
# - Performance metrics
|
219
|
-
# - Resource utilization info
|
220
|
-
|
221
|
-
# Example log output:
|
222
|
-
# [INFO] Starting thread pool target_size=10
|
223
|
-
# [DEBUG] Worker thread started thread_id=47185656920560
|
224
|
-
# [WARN] Job execution failed error=SomeError error_class=StandardError
|
225
|
-
```
|
226
|
-
|
227
|
-
### Environment-specific Configuration
|
228
|
-
|
229
|
-
```ruby
|
230
|
-
# Production settings
|
231
|
-
if Rails.env.production?
|
232
|
-
Gruf.configure do |config|
|
233
|
-
config.rpc_server_options = {
|
234
|
-
pool_size: 20,
|
235
|
-
max_waiting_requests: 50,
|
236
|
-
pool_keep_alive: 600
|
237
|
-
}
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
# Development settings
|
242
|
-
if Rails.env.development?
|
243
|
-
Gruf.configure do |config|
|
244
|
-
config.rpc_server_options = {
|
245
|
-
pool_size: 5,
|
246
|
-
max_waiting_requests: 10,
|
247
|
-
pool_keep_alive: 60
|
248
|
-
}
|
249
|
-
end
|
250
|
-
end
|
251
|
-
```
|
252
|
-
|
253
|
-
## Performance Considerations
|
254
|
-
|
255
|
-
- **Thread Pool Sizing**: Set `pool_size` based on your server's CPU cores and expected load
|
256
|
-
- **Queue Capacity**: Configure `max_waiting_requests` to handle traffic spikes
|
257
|
-
- **Connection Management**: The `ConnectionReset` interceptor prevents connection leaks in threaded environments
|
258
|
-
- **Resource Monitoring**: Use structured logs to monitor resource utilization
|
259
|
-
|
260
|
-
## Troubleshooting
|
261
|
-
|
262
|
-
### Common Issues
|
263
|
-
|
264
|
-
**Server not starting with custom configuration:**
|
265
|
-
```ruby
|
266
|
-
# Ensure plugin is installed before configuration
|
267
|
-
Gruf::Queue::Plugin.install!
|
268
|
-
# Then configure...
|
269
|
-
```
|
270
|
-
|
271
|
-
**ActiveRecord connection issues:**
|
272
|
-
```ruby
|
273
|
-
# Verify ActiveRecord is loaded before gruf-queue
|
274
|
-
require 'active_record'
|
275
|
-
require 'gruf-queue'
|
276
|
-
```
|
277
|
-
|
278
|
-
**High memory usage:**
|
279
|
-
```ruby
|
280
|
-
# Adjust pool size and keep-alive settings
|
281
|
-
Gruf.configure do |config|
|
282
|
-
config.rpc_server_options = {
|
283
|
-
pool_size: 8, # Reduce if memory constrained
|
284
|
-
pool_keep_alive: 60 # Shorter keep-alive
|
285
|
-
}
|
286
|
-
end
|
53
|
+
# After: Simple job count threshold
|
54
|
+
pool.ready_for_work? # jobs_waiting < max_waiting_requests
|
287
55
|
```
|
288
56
|
|
289
57
|
## Requirements
|
@@ -292,28 +60,6 @@ end
|
|
292
60
|
- Gruf >= 2.21.0
|
293
61
|
- gRPC >= 1.0
|
294
62
|
|
295
|
-
## Development
|
296
|
-
|
297
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests.
|
298
|
-
|
299
|
-
```bash
|
300
|
-
# Install dependencies
|
301
|
-
$ bundle install
|
302
|
-
|
303
|
-
# Run tests
|
304
|
-
$ bundle exec rspec
|
305
|
-
|
306
|
-
# Run linting
|
307
|
-
$ bundle exec rubocop
|
308
|
-
|
309
|
-
# Install locally
|
310
|
-
$ bundle exec rake install
|
311
|
-
```
|
312
|
-
|
313
|
-
## Contributing
|
314
|
-
|
315
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/ether-moon/gruf-queue. This project is intended to be a safe, welcoming space for collaboration.
|
316
|
-
|
317
63
|
## License
|
318
64
|
|
319
|
-
|
65
|
+
MIT License
|
data/lib/gruf/queue/plugin.rb
CHANGED
@@ -13,17 +13,11 @@ module Gruf
|
|
13
13
|
return false if @installed
|
14
14
|
|
15
15
|
enhance_grpc_pool
|
16
|
-
configure_gruf
|
17
|
-
@installed = true
|
18
|
-
true
|
19
|
-
rescue StandardError
|
20
|
-
false
|
21
|
-
end
|
22
16
|
|
23
|
-
|
24
|
-
!!@installed
|
17
|
+
@installed = true
|
25
18
|
end
|
26
19
|
|
20
|
+
# Reset installation state for testing
|
27
21
|
def reset!
|
28
22
|
@installed = false
|
29
23
|
end
|
@@ -35,29 +29,6 @@ module Gruf
|
|
35
29
|
|
36
30
|
::GRPC::Pool.prepend(Gruf::Queue::PoolEnhancements)
|
37
31
|
end
|
38
|
-
|
39
|
-
def configure_gruf
|
40
|
-
Gruf.configure do |config|
|
41
|
-
# Set default server options compatible with QueuedRpcServer
|
42
|
-
config.rpc_server_options = {
|
43
|
-
pool_size: QueuedRpcServer::DEFAULT_POOL_SIZE,
|
44
|
-
max_waiting_requests: QueuedRpcServer::DEFAULT_MAX_WAITING_REQUESTS,
|
45
|
-
poll_period: QueuedRpcServer::DEFAULT_POLL_PERIOD,
|
46
|
-
pool_keep_alive: PoolEnhancements::DEFAULT_KEEP_ALIVE,
|
47
|
-
}
|
48
|
-
|
49
|
-
if defined?(ActiveRecord)
|
50
|
-
require 'gruf/interceptors/active_record/connection_reset'
|
51
|
-
# Configure interceptors at the global level
|
52
|
-
if Gruf.respond_to?(:interceptors)
|
53
|
-
Gruf.interceptors.use(
|
54
|
-
Gruf::Interceptors::ActiveRecord::ConnectionReset,
|
55
|
-
target_classes: [ActiveRecord::Base],
|
56
|
-
)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
32
|
end
|
62
33
|
end
|
63
34
|
end
|
@@ -2,27 +2,34 @@
|
|
2
2
|
|
3
3
|
module Gruf
|
4
4
|
module Queue
|
5
|
-
#
|
6
|
-
#
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
5
|
+
# Null object implementation for worker queue management.
|
6
|
+
# Provides clean interface without complex worker state tracking.
|
7
|
+
class AlwaysReadyQueue
|
8
|
+
def empty? = false
|
9
|
+
|
10
|
+
def <<(*) = self
|
11
|
+
|
12
|
+
def push(*) = self
|
13
|
+
|
14
|
+
def pop = ::Queue.new
|
15
|
+
|
16
|
+
def size = 1
|
17
|
+
end
|
18
|
+
|
19
|
+
# Enhanced GRPC::Pool with job count based capacity management
|
12
20
|
module PoolEnhancements
|
13
|
-
|
14
|
-
DEFAULT_KEEP_ALIVE = 600
|
21
|
+
DEFAULT_MAX_WAITING_REQUESTS = 60
|
15
22
|
|
16
|
-
def
|
17
|
-
|
23
|
+
def initialize(...)
|
24
|
+
super
|
25
|
+
@ready_workers = AlwaysReadyQueue.new
|
26
|
+
@max_waiting_requests = ENV.fetch('GRUF_MAX_WAITING_REQUESTS', DEFAULT_MAX_WAITING_REQUESTS).to_i
|
18
27
|
end
|
19
28
|
|
20
|
-
def
|
21
|
-
return false if
|
29
|
+
def ready_for_work?
|
30
|
+
return false if @stopped
|
22
31
|
|
23
|
-
|
24
|
-
rescue StandardError
|
25
|
-
false
|
32
|
+
jobs_waiting < @max_waiting_requests
|
26
33
|
end
|
27
34
|
end
|
28
35
|
end
|
data/lib/gruf/queue/version.rb
CHANGED
data/lib/gruf-queue.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gruf-queue
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ether Moon
|
@@ -137,7 +137,6 @@ files:
|
|
137
137
|
- lib/gruf-queue.rb
|
138
138
|
- lib/gruf/queue/plugin.rb
|
139
139
|
- lib/gruf/queue/pool_enhancements.rb
|
140
|
-
- lib/gruf/queue/queued_rpc_server.rb
|
141
140
|
- lib/gruf/queue/version.rb
|
142
141
|
homepage: https://github.com/ether-moon/gruf-queue
|
143
142
|
licenses:
|
@@ -1,105 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'pool_enhancements'
|
4
|
-
|
5
|
-
module Gruf
|
6
|
-
module Queue
|
7
|
-
# Enhanced gRPC server with queue-based request handling and resource exhaustion protection.
|
8
|
-
#
|
9
|
-
# Extends GRPC::RpcServer to provide intelligent thread pool management with
|
10
|
-
# automatic RESOURCE_EXHAUSTED responses when the server is overloaded.
|
11
|
-
#
|
12
|
-
# @example Basic usage
|
13
|
-
# server = Gruf::Queue::QueuedRpcServer.new(pool_size: 20)
|
14
|
-
# server.handle(MyService)
|
15
|
-
# server.run_till_terminated
|
16
|
-
class QueuedRpcServer < ::GRPC::RpcServer
|
17
|
-
# Default pool size for the thread pool
|
18
|
-
DEFAULT_POOL_SIZE = 30
|
19
|
-
|
20
|
-
# Default maximum number of waiting requests
|
21
|
-
DEFAULT_MAX_WAITING_REQUESTS = 60
|
22
|
-
|
23
|
-
# Default poll period for the server
|
24
|
-
DEFAULT_POLL_PERIOD = 1
|
25
|
-
|
26
|
-
# No-op procedure for gRPC active call creation
|
27
|
-
NOOP_PROC = proc { |x| x }.freeze
|
28
|
-
private_constant :NOOP_PROC
|
29
|
-
|
30
|
-
# Error message for resource exhaustion
|
31
|
-
RESOURCE_EXHAUSTED_MESSAGE = 'No free threads in thread pool'
|
32
|
-
|
33
|
-
def initialize(pool_size: DEFAULT_POOL_SIZE,
|
34
|
-
max_waiting_requests: DEFAULT_MAX_WAITING_REQUESTS,
|
35
|
-
pool_keep_alive: PoolEnhancements::DEFAULT_KEEP_ALIVE,
|
36
|
-
poll_period: DEFAULT_POLL_PERIOD,
|
37
|
-
**args)
|
38
|
-
super
|
39
|
-
|
40
|
-
@pool_size = pool_size
|
41
|
-
@max_waiting_requests = max_waiting_requests
|
42
|
-
@pool_keep_alive = pool_keep_alive
|
43
|
-
@poll_period = poll_period
|
44
|
-
end
|
45
|
-
|
46
|
-
def available?(an_rpc)
|
47
|
-
job_count = safe_job_count
|
48
|
-
return an_rpc if job_count < @max_waiting_requests
|
49
|
-
|
50
|
-
send_resource_exhausted_response(an_rpc)
|
51
|
-
false
|
52
|
-
end
|
53
|
-
|
54
|
-
private
|
55
|
-
|
56
|
-
def safe_job_count
|
57
|
-
return 0 unless @pool
|
58
|
-
|
59
|
-
@pool.jobs_waiting
|
60
|
-
rescue StandardError => e
|
61
|
-
Gruf.logger.warn("Failed to get job count: #{e.message}") if defined?(Gruf) && Gruf.respond_to?(:logger)
|
62
|
-
@max_waiting_requests
|
63
|
-
end
|
64
|
-
|
65
|
-
def send_resource_exhausted_response(an_rpc)
|
66
|
-
Gruf.logger.warn('no free worker threads currently') if defined?(Gruf) && Gruf.respond_to?(:logger)
|
67
|
-
|
68
|
-
begin
|
69
|
-
if an_rpc.respond_to?(:send_status)
|
70
|
-
an_rpc.send_status(
|
71
|
-
::GRPC::Core::StatusCodes::RESOURCE_EXHAUSTED,
|
72
|
-
RESOURCE_EXHAUSTED_MESSAGE,
|
73
|
-
{},
|
74
|
-
)
|
75
|
-
return
|
76
|
-
end
|
77
|
-
|
78
|
-
active_call = ::GRPC::ActiveCall.new(
|
79
|
-
an_rpc.call,
|
80
|
-
NOOP_PROC,
|
81
|
-
NOOP_PROC,
|
82
|
-
an_rpc.deadline,
|
83
|
-
metadata_received: true,
|
84
|
-
started: false,
|
85
|
-
)
|
86
|
-
|
87
|
-
active_call.send_status(
|
88
|
-
::GRPC::Core::StatusCodes::RESOURCE_EXHAUSTED,
|
89
|
-
RESOURCE_EXHAUSTED_MESSAGE,
|
90
|
-
)
|
91
|
-
rescue TypeError => e
|
92
|
-
raise unless e.message.include?('Core::Call')
|
93
|
-
|
94
|
-
warn "RESOURCE_EXHAUSTED: #{RESOURCE_EXHAUSTED_MESSAGE}" if defined?(RSpec)
|
95
|
-
end
|
96
|
-
rescue StandardError => e
|
97
|
-
if defined?(Gruf) && Gruf.respond_to?(:logger)
|
98
|
-
Gruf.logger.error("Failed to send resource exhausted response: #{e.message}")
|
99
|
-
else
|
100
|
-
warn "Failed to send resource exhausted response: #{e.message}"
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|