philiprehberger-task_queue 0.2.1 → 0.2.3
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 +9 -0
- data/README.md +75 -19
- data/lib/philiprehberger/task_queue/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '088f95205b874279733ad703f517d81cb5f7694e7fc9ed2248c481869384e423'
|
|
4
|
+
data.tar.gz: 9d3940ad0849cd7ecbeaa7f5cb7afa3c1a19e49d95ce3ca7cd4ce2b23afd4679
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d8043a08aebd40789f3da64d6d88aa65342dee25cbc70aa4cadaae94400a60ba23158fcab58eb822916d04af4ce596645f6b018b57df16b77fef57a7be8b5da7
|
|
7
|
+
data.tar.gz: f4b653d153a61fb6f8126969aa0763e8f0d22c4694dffcb352d82120b53e81a85de924b7ee1b0fc6a1983a7cf60ad0b4035a83513c5344f561dd51b6847ddd65
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
|
@@ -20,7 +20,7 @@ gem "philiprehberger-task_queue"
|
|
|
20
20
|
|
|
21
21
|
Or install directly:
|
|
22
22
|
|
|
23
|
-
```
|
|
23
|
+
```bash
|
|
24
24
|
gem install philiprehberger-task_queue
|
|
25
25
|
```
|
|
26
26
|
|
|
@@ -49,44 +49,100 @@ queue << -> { puts "Hello from a task!" }
|
|
|
49
49
|
|
|
50
50
|
### Error handling
|
|
51
51
|
|
|
52
|
+
Register a callback to handle exceptions raised inside tasks. The callback receives the exception and the original task (callable) that failed. Unhandled errors are silently swallowed when no callback is registered.
|
|
53
|
+
|
|
52
54
|
```ruby
|
|
53
|
-
queue = Philiprehberger::TaskQueue.new
|
|
55
|
+
queue = Philiprehberger::TaskQueue.new(concurrency: 2)
|
|
54
56
|
|
|
55
57
|
queue.on_error do |exception, task|
|
|
56
|
-
|
|
58
|
+
warn "[TaskQueue] #{exception.class}: #{exception.message}"
|
|
59
|
+
warn exception.backtrace.first(5).join("\n")
|
|
57
60
|
end
|
|
58
61
|
|
|
59
|
-
queue.push {
|
|
62
|
+
queue.push { Integer("not_a_number") }
|
|
63
|
+
queue.push { File.read("/nonexistent") }
|
|
64
|
+
|
|
65
|
+
queue.drain(timeout: 5)
|
|
66
|
+
puts queue.stats
|
|
67
|
+
# => { completed: 0, failed: 2, pending: 0 }
|
|
60
68
|
```
|
|
61
69
|
|
|
62
70
|
### Statistics
|
|
63
71
|
|
|
72
|
+
`stats` returns a snapshot of completed, failed, and pending counts. All counters are thread-safe and updated atomically after each task finishes.
|
|
73
|
+
|
|
74
|
+
```ruby
|
|
75
|
+
queue = Philiprehberger::TaskQueue.new(concurrency: 4)
|
|
76
|
+
|
|
77
|
+
20.times { |i| queue.push { sleep(0.01); raise "boom" if i == 5 } }
|
|
78
|
+
queue.drain(timeout: 10)
|
|
79
|
+
|
|
80
|
+
stats = queue.stats
|
|
81
|
+
puts "Completed: #{stats[:completed]}"
|
|
82
|
+
puts "Failed: #{stats[:failed]}"
|
|
83
|
+
puts "Pending: #{stats[:pending]}"
|
|
84
|
+
# Completed: 19
|
|
85
|
+
# Failed: 1
|
|
86
|
+
# Pending: 0
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### FIFO ordering guarantees
|
|
90
|
+
|
|
91
|
+
Tasks are stored in an internal array and dequeued in FIFO order. When `concurrency` is `1`, tasks execute strictly in the order they were pushed. With higher concurrency, dequeue order is still FIFO but tasks may complete out of order depending on individual execution time.
|
|
92
|
+
|
|
93
|
+
```ruby
|
|
94
|
+
results = Queue.new # stdlib thread-safe queue for collecting output
|
|
95
|
+
queue = Philiprehberger::TaskQueue.new(concurrency: 1)
|
|
96
|
+
|
|
97
|
+
5.times { |i| queue.push { results << i } }
|
|
98
|
+
queue.drain(timeout: 5)
|
|
99
|
+
|
|
100
|
+
puts results.size.times.map { results.pop }
|
|
101
|
+
# => [0, 1, 2, 3, 4]
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Graceful shutdown
|
|
105
|
+
|
|
106
|
+
`shutdown` signals all worker threads to stop accepting new tasks, lets in-flight tasks finish, then drains any remaining enqueued tasks before joining threads. The `timeout` parameter caps total wait time; workers that exceed the deadline are abandoned.
|
|
107
|
+
|
|
64
108
|
```ruby
|
|
65
|
-
queue.
|
|
66
|
-
|
|
109
|
+
queue = Philiprehberger::TaskQueue.new(concurrency: 4)
|
|
110
|
+
|
|
111
|
+
100.times { |i| queue.push { sleep(0.05) } }
|
|
112
|
+
|
|
113
|
+
queue.shutdown(timeout: 10)
|
|
114
|
+
puts queue.running? # => false
|
|
115
|
+
# queue.push { ... } would now raise "queue is shut down"
|
|
67
116
|
```
|
|
68
117
|
|
|
69
118
|
### Draining
|
|
70
119
|
|
|
120
|
+
`drain` blocks the calling thread until all pending and in-flight tasks finish, but keeps the queue running so new tasks can still be pushed afterwards.
|
|
121
|
+
|
|
71
122
|
```ruby
|
|
123
|
+
queue = Philiprehberger::TaskQueue.new(concurrency: 4)
|
|
124
|
+
|
|
72
125
|
10.times { |i| queue.push { process(i) } }
|
|
73
126
|
queue.drain(timeout: 10) # waits for all tasks to finish
|
|
74
|
-
|
|
127
|
+
puts queue.running? # => true — still accepting new tasks
|
|
128
|
+
|
|
129
|
+
queue.push { process(:extra) }
|
|
130
|
+
queue.shutdown(timeout: 5)
|
|
75
131
|
```
|
|
76
132
|
|
|
77
133
|
## API
|
|
78
134
|
|
|
79
|
-
| Method | Description |
|
|
80
|
-
|
|
81
|
-
| `.new(concurrency: 4)` | Create a new queue with the given
|
|
82
|
-
| `#push(&block)` | Enqueue a
|
|
83
|
-
| `#<<
|
|
84
|
-
| `#size` | Number of pending (not yet started) tasks |
|
|
85
|
-
| `#running?` | Whether the queue is accepting new tasks |
|
|
86
|
-
| `#shutdown(timeout: 30)` |
|
|
87
|
-
| `#on_error(&block)` | Register error callback
|
|
88
|
-
| `#stats` | Returns
|
|
89
|
-
| `#drain(timeout: 30)` | Block until all pending tasks complete
|
|
135
|
+
| Method | Parameters | Returns | Description |
|
|
136
|
+
|---|---|---|---|
|
|
137
|
+
| `.new(concurrency:)` | `concurrency` — max worker threads (Integer, default `4`) | `Queue` | Create a new queue with the given concurrency limit |
|
|
138
|
+
| `#push(&block)` | `&block` — the task to execute | `self` | Enqueue a block for async execution; raises `ArgumentError` if no block given, raises `RuntimeError` if the queue is shut down |
|
|
139
|
+
| `#<<(callable)` | `callable` — any object responding to `#call` | `self` | Alias for `#push`; convenient for lambdas and procs |
|
|
140
|
+
| `#size` | _(none)_ | `Integer` | Number of pending (not yet started) tasks |
|
|
141
|
+
| `#running?` | _(none)_ | `Boolean` | Whether the queue is accepting new tasks |
|
|
142
|
+
| `#shutdown(timeout:)` | `timeout` — seconds to wait for workers (Numeric, default `30`) | `nil` | Signal workers to stop, drain remaining tasks, join threads up to `timeout` seconds |
|
|
143
|
+
| `#on_error(&block)` | `&block` — callback receiving `(exception, task)` | `self` | Register an error callback invoked when a task raises a `StandardError` |
|
|
144
|
+
| `#stats` | _(none)_ | `Hash` | Returns `{ completed:, failed:, pending: }` with Integer counts |
|
|
145
|
+
| `#drain(timeout:)` | `timeout` — seconds to wait (Numeric, default `30`) | `nil` | Block until all pending and in-flight tasks complete without shutting down |
|
|
90
146
|
|
|
91
147
|
|
|
92
148
|
## Development
|
|
@@ -99,4 +155,4 @@ bundle exec rubocop
|
|
|
99
155
|
|
|
100
156
|
## License
|
|
101
157
|
|
|
102
|
-
|
|
158
|
+
MIT
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: philiprehberger-task_queue
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Philip Rehberger
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-03-
|
|
11
|
+
date: 2026-03-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: A lightweight, zero-dependency, thread-safe in-process async job queue
|
|
14
14
|
with configurable concurrency for Ruby applications.
|
|
@@ -32,6 +32,7 @@ metadata:
|
|
|
32
32
|
homepage_uri: https://github.com/philiprehberger/rb-task-queue
|
|
33
33
|
source_code_uri: https://github.com/philiprehberger/rb-task-queue
|
|
34
34
|
changelog_uri: https://github.com/philiprehberger/rb-task-queue/blob/main/CHANGELOG.md
|
|
35
|
+
bug_tracker_uri: https://github.com/philiprehberger/rb-task-queue/issues
|
|
35
36
|
rubygems_mfa_required: 'true'
|
|
36
37
|
post_install_message:
|
|
37
38
|
rdoc_options: []
|
|
@@ -41,7 +42,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
41
42
|
requirements:
|
|
42
43
|
- - ">="
|
|
43
44
|
- !ruby/object:Gem::Version
|
|
44
|
-
version:
|
|
45
|
+
version: 3.1.0
|
|
45
46
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
46
47
|
requirements:
|
|
47
48
|
- - ">="
|