lean_pool 0.1.0
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 +7 -0
- data/.rspec +3 -0
- data/.rspec_status +195 -0
- data/.rubocop.yml +14 -0
- data/CHANGELOG.md +19 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +21 -0
- data/PUBLISH.md +66 -0
- data/QUICKSTART.md +88 -0
- data/README.md +324 -0
- data/Rakefile +11 -0
- data/examples/basic_usage.rb +73 -0
- data/lean_pool.gemspec +38 -0
- data/lib/lean_pool/errors.rb +69 -0
- data/lib/lean_pool/http_pool.rb +206 -0
- data/lib/lean_pool/pool.rb +441 -0
- data/lib/lean_pool/version.rb +14 -0
- data/lib/lean_pool.rb +62 -0
- metadata +78 -0
data/README.md
ADDED
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
# LeanPool
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/rb/lean_pool)
|
|
4
|
+
[](https://github.com/half-blood-labs/lean_pool/actions)
|
|
5
|
+
[](https://rubygems.org/gems/lean_pool)
|
|
6
|
+
[](LICENSE.txt)
|
|
7
|
+
[](https://www.ruby-lang.org/)
|
|
8
|
+
|
|
9
|
+
A lightweight, process-free resource pool for Ruby using `concurrent-ruby`. Inspired by Elixir's `nimble_pool`, LeanPool provides efficient resource management without per-resource processes, making it perfect for managing sockets, HTTP connections, ports, and other resources.
|
|
10
|
+
|
|
11
|
+
**Author:** [Junaid Farooq](mailto:fjunaid252@gmail.com) | **Repository:** [half-blood-labs/lean_pool](https://github.com/half-blood-labs/lean_pool)
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- 🚀 **Zero Overhead**: Direct resource access without data copying between processes
|
|
16
|
+
- 🔒 **Thread-Safe**: Built on `concurrent-ruby` for reliable thread safety
|
|
17
|
+
- ⚡ **Efficient**: Lazy initialization and smart resource reuse
|
|
18
|
+
- 🎯 **Simple API**: Clean, Ruby-idiomatic interface
|
|
19
|
+
- 🔧 **Flexible**: Works with any resource type (sockets, connections, ports, etc.)
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
Add this line to your application's Gemfile:
|
|
24
|
+
|
|
25
|
+
```ruby
|
|
26
|
+
gem 'lean_pool'
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
And then execute:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
$ bundle install
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Or install it yourself as:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
$ gem install lean_pool
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Usage
|
|
42
|
+
|
|
43
|
+
### Basic Example
|
|
44
|
+
|
|
45
|
+
```ruby
|
|
46
|
+
require 'lean_pool'
|
|
47
|
+
|
|
48
|
+
# Create a pool of Redis connections
|
|
49
|
+
pool = LeanPool::Pool.new(size: 5) do
|
|
50
|
+
Redis.new(host: "localhost", port: 6379)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Use the pool
|
|
54
|
+
pool.checkout do |redis|
|
|
55
|
+
redis.get("my_key")
|
|
56
|
+
redis.set("my_key", "value")
|
|
57
|
+
end
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### HTTP Connection Pool
|
|
61
|
+
|
|
62
|
+
LeanPool includes a built-in HTTP connection pool for easy HTTP/HTTPS requests:
|
|
63
|
+
|
|
64
|
+
```ruby
|
|
65
|
+
require 'lean_pool'
|
|
66
|
+
|
|
67
|
+
# Create an HTTP pool
|
|
68
|
+
http_pool = LeanPool::HTTPPool.new("api.example.com", 443, size: 10, use_ssl: true)
|
|
69
|
+
|
|
70
|
+
# Perform GET requests
|
|
71
|
+
response = http_pool.get("/users")
|
|
72
|
+
puts response[:status] # => 200
|
|
73
|
+
puts response[:body]
|
|
74
|
+
puts response[:headers]
|
|
75
|
+
|
|
76
|
+
# Perform POST requests with JSON
|
|
77
|
+
response = http_pool.post(
|
|
78
|
+
"/users",
|
|
79
|
+
body: '{"name":"John","email":"john@example.com"}',
|
|
80
|
+
headers: { "Content-Type" => "application/json" }
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
# With custom timeout
|
|
84
|
+
response = http_pool.get("/slow-endpoint", timeout: 30.0)
|
|
85
|
+
|
|
86
|
+
# Check pool statistics
|
|
87
|
+
stats = http_pool.stats
|
|
88
|
+
# => { size: 10, available: 8, in_use: 2, total: 10 }
|
|
89
|
+
|
|
90
|
+
# Shutdown when done
|
|
91
|
+
http_pool.shutdown
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Custom HTTP Pool Implementation
|
|
95
|
+
|
|
96
|
+
You can also create your own HTTP pool wrapper:
|
|
97
|
+
|
|
98
|
+
```ruby
|
|
99
|
+
require 'lean_pool'
|
|
100
|
+
require 'net/http'
|
|
101
|
+
|
|
102
|
+
class CustomHTTPPool
|
|
103
|
+
def self.new_pool(host, port, size: 10)
|
|
104
|
+
LeanPool::Pool.new(
|
|
105
|
+
size: size,
|
|
106
|
+
timeout: 5.0,
|
|
107
|
+
lazy: true,
|
|
108
|
+
pool_state: { host: host, port: port }
|
|
109
|
+
) do |state|
|
|
110
|
+
Net::HTTP.new(state[:host], state[:port])
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def self.get(pool, path, opts = {})
|
|
115
|
+
pool.checkout(timeout: opts[:timeout] || 5.0) do |http|
|
|
116
|
+
http.start unless http.started?
|
|
117
|
+
response = http.get(path)
|
|
118
|
+
|
|
119
|
+
if response.code == "200"
|
|
120
|
+
{ status: response.code.to_i, body: response.body, headers: response.to_hash }
|
|
121
|
+
else
|
|
122
|
+
{ remove: true }
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Usage
|
|
129
|
+
pool = CustomHTTPPool.new_pool("api.example.com", 443)
|
|
130
|
+
result = CustomHTTPPool.get(pool, "/users")
|
|
131
|
+
puts result[:body]
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### With Custom State
|
|
135
|
+
|
|
136
|
+
```ruby
|
|
137
|
+
pool = LeanPool::Pool.new(
|
|
138
|
+
size: 10,
|
|
139
|
+
pool_state: { database: "production", timeout: 30 }
|
|
140
|
+
) do |state|
|
|
141
|
+
DatabaseConnection.new(
|
|
142
|
+
database: state[:database],
|
|
143
|
+
timeout: state[:timeout]
|
|
144
|
+
)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
pool.checkout do |db|
|
|
148
|
+
db.query("SELECT * FROM users")
|
|
149
|
+
end
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Pool Statistics
|
|
153
|
+
|
|
154
|
+
```ruby
|
|
155
|
+
pool = LeanPool::Pool.new(size: 5) { Redis.new }
|
|
156
|
+
|
|
157
|
+
stats = pool.stats
|
|
158
|
+
# => { size: 5, available: 3, in_use: 2, total: 5 }
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Shutdown and Reload
|
|
162
|
+
|
|
163
|
+
```ruby
|
|
164
|
+
# Gracefully shutdown the pool
|
|
165
|
+
pool.shutdown do |resource|
|
|
166
|
+
resource.close if resource.respond_to?(:close)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Reload the pool (useful after forking)
|
|
170
|
+
pool.reload do |resource|
|
|
171
|
+
resource.quit if resource.respond_to?(:quit)
|
|
172
|
+
end
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Error Handling
|
|
176
|
+
|
|
177
|
+
```ruby
|
|
178
|
+
begin
|
|
179
|
+
pool.checkout(timeout: 2.0) do |resource|
|
|
180
|
+
resource.perform_operation
|
|
181
|
+
end
|
|
182
|
+
rescue LeanPool::TimeoutError => e
|
|
183
|
+
puts "Pool is busy, try again later"
|
|
184
|
+
rescue LeanPool::ShutdownError => e
|
|
185
|
+
puts "Pool is shutdown"
|
|
186
|
+
rescue LeanPool::ResourceError => e
|
|
187
|
+
puts "Failed to create resource: #{e.message}"
|
|
188
|
+
end
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Comparison with Other Pooling Solutions
|
|
192
|
+
|
|
193
|
+
| Feature | LeanPool | connection_pool | pond |
|
|
194
|
+
|---------|----------|-----------------|------|
|
|
195
|
+
| Process-free | ✅ | ❌ | ❌ |
|
|
196
|
+
| Direct resource access | ✅ | ❌ | ❌ |
|
|
197
|
+
| Zero data copying | ✅ | ❌ | ❌ |
|
|
198
|
+
| Thread-safe | ✅ | ✅ | ✅ |
|
|
199
|
+
| Lazy initialization | ✅ | ✅ | ✅ |
|
|
200
|
+
| Built on concurrent-ruby | ✅ | ❌ | ❌ |
|
|
201
|
+
|
|
202
|
+
## When to Use LeanPool
|
|
203
|
+
|
|
204
|
+
**Use LeanPool when:**
|
|
205
|
+
- You need direct access to resources (sockets, ports, HTTP connections)
|
|
206
|
+
- You want to avoid data copying between processes
|
|
207
|
+
- You're managing resources that don't need per-resource processes
|
|
208
|
+
- You need high-performance resource pooling
|
|
209
|
+
|
|
210
|
+
**Don't use LeanPool when:**
|
|
211
|
+
- You're managing processes (use process-based pools instead)
|
|
212
|
+
- You need multiplexing (HTTP/2, etc.)
|
|
213
|
+
- Resources require per-resource process isolation
|
|
214
|
+
|
|
215
|
+
## Requirements
|
|
216
|
+
|
|
217
|
+
- Ruby >= 3.0.0
|
|
218
|
+
- concurrent-ruby >= 1.3.0
|
|
219
|
+
|
|
220
|
+
## Development
|
|
221
|
+
|
|
222
|
+
After checking out the repo, run:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
$ bundle install
|
|
226
|
+
$ bundle exec rspec
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Running Tests Locally
|
|
230
|
+
|
|
231
|
+
**Quick test run:**
|
|
232
|
+
```bash
|
|
233
|
+
$ bundle exec rspec
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
**With documentation format:**
|
|
237
|
+
```bash
|
|
238
|
+
$ bundle exec rspec --format documentation
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**Run specific test files:**
|
|
242
|
+
```bash
|
|
243
|
+
$ bundle exec rspec spec/lean_pool/pool_spec.rb
|
|
244
|
+
$ bundle exec rspec spec/lean_pool/http_pool_spec.rb
|
|
245
|
+
$ bundle exec rspec spec/lean_pool/errors_spec.rb
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
**Simulate CI locally:**
|
|
249
|
+
```bash
|
|
250
|
+
$ ./.github/workflows/test-local.sh
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
This script will:
|
|
254
|
+
- Check Ruby version
|
|
255
|
+
- Install dependencies
|
|
256
|
+
- Validate syntax of all Ruby files
|
|
257
|
+
- Run RuboCop linting
|
|
258
|
+
- Run the full test suite
|
|
259
|
+
- Display test summary
|
|
260
|
+
|
|
261
|
+
**Using Rake:**
|
|
262
|
+
```bash
|
|
263
|
+
$ bundle exec rake # Runs tests + linting
|
|
264
|
+
$ bundle exec rake spec # Runs only tests
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## Testing
|
|
268
|
+
|
|
269
|
+
The project includes comprehensive test coverage with over 198 test cases covering:
|
|
270
|
+
|
|
271
|
+
- Pool initialization and configuration
|
|
272
|
+
- Resource checkout and lifecycle management
|
|
273
|
+
- Thread safety and concurrent operations
|
|
274
|
+
- Timeout handling and error recovery
|
|
275
|
+
- HTTP connection pooling
|
|
276
|
+
- Integration scenarios and real-world use cases
|
|
277
|
+
- Edge cases and boundary conditions
|
|
278
|
+
|
|
279
|
+
Run the full test suite:
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
$ bundle exec rspec
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
## Project Status
|
|
286
|
+
|
|
287
|
+
- ✅ **CI/CD**: Automated testing with GitHub Actions (testing on Ruby 3.0, 3.1, 3.2, 3.3)
|
|
288
|
+
- ✅ **Test Coverage**: Comprehensive test suite with 198+ test cases
|
|
289
|
+
- ✅ **Documentation**: Complete YARD documentation for all modules
|
|
290
|
+
- ✅ **Thread Safety**: Built on concurrent-ruby for reliable concurrency
|
|
291
|
+
- ✅ **Production Ready**: Suitable for production use
|
|
292
|
+
- ✅ **Code Quality**: RuboCop linting and syntax validation
|
|
293
|
+
|
|
294
|
+
## CI/CD Status
|
|
295
|
+
|
|
296
|
+
The project uses GitHub Actions for continuous integration:
|
|
297
|
+
|
|
298
|
+
- **Test Matrix**: Tests run on Ruby 3.0, 3.1, 3.2, and 3.3
|
|
299
|
+
- **Linting**: RuboCop code quality checks
|
|
300
|
+
- **Syntax Validation**: Automatic Ruby syntax checking
|
|
301
|
+
- **Status Badge**: [](https://github.com/half-blood-labs/lean_pool/actions)
|
|
302
|
+
|
|
303
|
+
View the latest CI runs: [GitHub Actions](https://github.com/half-blood-labs/lean_pool/actions)
|
|
304
|
+
|
|
305
|
+
**Note**: After publishing the gem to RubyGems, the badges will automatically update to show download counts and build status.
|
|
306
|
+
|
|
307
|
+
## Contributing
|
|
308
|
+
|
|
309
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/half-blood-labs/lean_pool.
|
|
310
|
+
|
|
311
|
+
## Author
|
|
312
|
+
|
|
313
|
+
**Junaid Farooq**
|
|
314
|
+
|
|
315
|
+
- Email: fjunaid252@gmail.com
|
|
316
|
+
- GitHub: [@half-blood-labs](https://github.com/half-blood-labs)
|
|
317
|
+
|
|
318
|
+
## License
|
|
319
|
+
|
|
320
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
321
|
+
|
|
322
|
+
## Inspiration
|
|
323
|
+
|
|
324
|
+
This gem is inspired by [nimble_pool](https://github.com/dashbitco/nimble_pool) from the Elixir ecosystem, adapted for Ruby's concurrency model using `concurrent-ruby`.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "../lib/lean_pool"
|
|
5
|
+
|
|
6
|
+
# Example 1: Basic resource pool
|
|
7
|
+
puts "=== Example 1: Basic Resource Pool ==="
|
|
8
|
+
pool = LeanPool::Pool.new(size: 3) do
|
|
9
|
+
{ id: rand(1000), created_at: Time.now }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
3.times do |i|
|
|
13
|
+
result = pool.checkout do |resource|
|
|
14
|
+
puts "Using resource #{i + 1}: #{resource[:id]}"
|
|
15
|
+
resource[:id] * 2
|
|
16
|
+
end
|
|
17
|
+
puts "Result: #{result}"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
puts "\nPool stats: #{pool.stats}"
|
|
21
|
+
|
|
22
|
+
# Example 2: HTTP Pool
|
|
23
|
+
puts "\n=== Example 2: HTTP Pool ==="
|
|
24
|
+
begin
|
|
25
|
+
http_pool = LeanPool::HTTPPool.new("httpbin.org", 80, size: 5)
|
|
26
|
+
|
|
27
|
+
response = http_pool.get("/get")
|
|
28
|
+
puts "Status: #{response[:status]}"
|
|
29
|
+
puts "Response size: #{response[:body]&.length || 0} bytes"
|
|
30
|
+
|
|
31
|
+
puts "\nHTTP Pool stats: #{http_pool.stats}"
|
|
32
|
+
|
|
33
|
+
http_pool.shutdown
|
|
34
|
+
rescue => e
|
|
35
|
+
puts "HTTP example failed (network may be unavailable): #{e.message}"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Example 3: Custom resource with state
|
|
39
|
+
puts "\n=== Example 3: Custom Resource with State ==="
|
|
40
|
+
class SimpleCounter
|
|
41
|
+
def initialize(initial_value = 0)
|
|
42
|
+
@value = initial_value
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def increment
|
|
46
|
+
@value += 1
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def value
|
|
50
|
+
@value
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
counter_pool = LeanPool::Pool.new(
|
|
55
|
+
size: 2,
|
|
56
|
+
pool_state: { start: 10 }
|
|
57
|
+
) do |state|
|
|
58
|
+
SimpleCounter.new(state[:start])
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
results = []
|
|
62
|
+
2.times do
|
|
63
|
+
result = counter_pool.checkout do |counter|
|
|
64
|
+
counter.increment
|
|
65
|
+
counter.value
|
|
66
|
+
end
|
|
67
|
+
results << result
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
puts "Counter results: #{results}"
|
|
71
|
+
puts "Counter pool stats: #{counter_pool.stats}"
|
|
72
|
+
|
|
73
|
+
puts "\n=== All examples completed! ==="
|
data/lean_pool.gemspec
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "lib/lean_pool/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = "lean_pool"
|
|
7
|
+
spec.version = LeanPool::VERSION
|
|
8
|
+
spec.authors = ["Junaid Farooq"]
|
|
9
|
+
spec.email = ["fjunaid252@gmail.com"]
|
|
10
|
+
|
|
11
|
+
spec.summary = "A lightweight, process-free resource pool for Ruby using concurrent-ruby"
|
|
12
|
+
spec.description = <<~DESC
|
|
13
|
+
LeanPool is a tiny, efficient resource pool implementation for Ruby that provides
|
|
14
|
+
direct resource access without per-resource processes. Inspired by Elixir's nimble_pool,
|
|
15
|
+
it's perfect for managing sockets, HTTP connections, ports, and other resources that
|
|
16
|
+
need efficient pooling with minimal overhead.
|
|
17
|
+
DESC
|
|
18
|
+
spec.homepage = "https://github.com/half-blood-labs/lean_pool"
|
|
19
|
+
spec.license = "MIT"
|
|
20
|
+
spec.required_ruby_version = ">= 3.0.0"
|
|
21
|
+
|
|
22
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
|
23
|
+
spec.metadata["source_code_uri"] = "https://github.com/half-blood-labs/lean_pool"
|
|
24
|
+
spec.metadata["changelog_uri"] = "https://github.com/half-blood-labs/lean_pool/blob/main/CHANGELOG.md"
|
|
25
|
+
|
|
26
|
+
# Specify which files should be added to the gem when it is released.
|
|
27
|
+
spec.files = Dir.chdir(__dir__) do
|
|
28
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
|
29
|
+
(File.expand_path(f) == __FILE__) ||
|
|
30
|
+
f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
spec.bindir = "exe"
|
|
34
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
35
|
+
spec.require_paths = ["lib"]
|
|
36
|
+
|
|
37
|
+
spec.add_dependency "concurrent-ruby", "~> 1.3"
|
|
38
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LeanPool
|
|
4
|
+
# Base error class for all LeanPool errors.
|
|
5
|
+
#
|
|
6
|
+
# All LeanPool-specific errors inherit from this class, allowing you to
|
|
7
|
+
# catch all LeanPool errors with a single rescue clause.
|
|
8
|
+
#
|
|
9
|
+
# @example Catching all LeanPool errors
|
|
10
|
+
# begin
|
|
11
|
+
# pool.checkout { |r| r.operation }
|
|
12
|
+
# rescue LeanPool::Error => e
|
|
13
|
+
# puts "LeanPool error: #{e.message}"
|
|
14
|
+
# end
|
|
15
|
+
#
|
|
16
|
+
# @since 0.1.0
|
|
17
|
+
class Error < StandardError; end
|
|
18
|
+
|
|
19
|
+
# Raised when a pool checkout operation times out.
|
|
20
|
+
#
|
|
21
|
+
# This error is raised when attempting to checkout a resource from a pool
|
|
22
|
+
# that is at capacity and no resources become available within the specified
|
|
23
|
+
# timeout period.
|
|
24
|
+
#
|
|
25
|
+
# @example Handling timeout errors
|
|
26
|
+
# begin
|
|
27
|
+
# pool.checkout(timeout: 1.0) { |r| r.operation }
|
|
28
|
+
# rescue LeanPool::TimeoutError => e
|
|
29
|
+
# puts "Pool is busy, try again later"
|
|
30
|
+
# end
|
|
31
|
+
#
|
|
32
|
+
# @since 0.1.0
|
|
33
|
+
class TimeoutError < Error; end
|
|
34
|
+
|
|
35
|
+
# Raised when attempting to use a pool that has been shutdown.
|
|
36
|
+
#
|
|
37
|
+
# This error is raised when attempting to checkout a resource from a pool
|
|
38
|
+
# that has been shut down. Once a pool is shutdown, it cannot be used for
|
|
39
|
+
# new operations unless it is reloaded.
|
|
40
|
+
#
|
|
41
|
+
# @example Handling shutdown errors
|
|
42
|
+
# begin
|
|
43
|
+
# pool.checkout { |r| r.operation }
|
|
44
|
+
# rescue LeanPool::ShutdownError => e
|
|
45
|
+
# puts "Pool has been shutdown"
|
|
46
|
+
# end
|
|
47
|
+
#
|
|
48
|
+
# @see Pool#shutdown
|
|
49
|
+
# @see Pool#reload
|
|
50
|
+
# @since 0.1.0
|
|
51
|
+
class ShutdownError < Error; end
|
|
52
|
+
|
|
53
|
+
# Raised when resource initialization fails.
|
|
54
|
+
#
|
|
55
|
+
# This error is raised when the resource initializer block raises an exception
|
|
56
|
+
# during resource creation. The original error is preserved and can be accessed
|
|
57
|
+
# via the `cause` attribute.
|
|
58
|
+
#
|
|
59
|
+
# @example Handling resource errors
|
|
60
|
+
# begin
|
|
61
|
+
# pool.checkout { |r| r.operation }
|
|
62
|
+
# rescue LeanPool::ResourceError => e
|
|
63
|
+
# puts "Failed to create resource: #{e.message}"
|
|
64
|
+
# puts "Original error: #{e.cause}"
|
|
65
|
+
# end
|
|
66
|
+
#
|
|
67
|
+
# @since 0.1.0
|
|
68
|
+
class ResourceError < Error; end
|
|
69
|
+
end
|