async 2.32.0 → 2.39.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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/context/best-practices.md +53 -32
- data/context/debugging.md +3 -3
- data/context/getting-started.md +6 -6
- data/context/scheduler.md +4 -4
- data/context/tasks.md +41 -36
- data/context/thread-safety.md +267 -224
- data/lib/async/barrier.rb +41 -10
- data/lib/async/cancel.rb +80 -0
- data/lib/async/clock.rb +22 -1
- data/lib/async/deadline.rb +1 -0
- data/lib/async/error.rb +17 -0
- data/lib/async/fork_handler.rb +32 -0
- data/lib/async/idler.rb +27 -15
- data/lib/async/loop.rb +84 -0
- data/lib/async/node.rb +28 -9
- data/lib/async/promise.rb +112 -37
- data/lib/async/queue.rb +1 -1
- data/lib/async/scheduler.rb +40 -17
- data/lib/async/stop.rb +3 -75
- data/lib/async/task.rb +160 -91
- data/lib/async/version.rb +3 -2
- data/lib/async.rb +3 -5
- data/lib/kernel/barrier.rb +31 -0
- data/lib/kernel/sync.rb +1 -1
- data/lib/traces/provider/async/barrier.rb +1 -1
- data/license.md +4 -2
- data/readme.md +26 -32
- data/releases.md +104 -33
- data.tar.gz.sig +0 -0
- metadata +9 -3
- metadata.gz.sig +0 -0
- data/lib/async/task.md +0 -30
data/releases.md
CHANGED
|
@@ -1,5 +1,76 @@
|
|
|
1
1
|
# Releases
|
|
2
2
|
|
|
3
|
+
## v2.39.0
|
|
4
|
+
|
|
5
|
+
- `Async::Barrier#wait` now returns the number of tasks that were waited for, or `nil` if there were no tasks to wait for. This provides better feedback about the operation, and allows you to know how many tasks were involved in the wait.
|
|
6
|
+
|
|
7
|
+
## v2.38.1
|
|
8
|
+
|
|
9
|
+
- Fix `Barrier#async` when `parent.async` yields before the child block executes. Previously, `Barrier#wait` could return early and miss tracking the task entirely, because the task had not yet appended itself to the barrier's task list.
|
|
10
|
+
|
|
11
|
+
## v2.38.0
|
|
12
|
+
|
|
13
|
+
- Rename `Task#stop` to `Task#cancel` for better clarity and consistency with common concurrency terminology. The old `stop` method is still available as an alias for backward compatibility, but it is recommended to use `cancel` going forward.
|
|
14
|
+
- Forward arguments from `Task#wait` -\> `Promise#wait`, so `task.wait(timeout: N)` is supported.
|
|
15
|
+
|
|
16
|
+
## v2.37.0
|
|
17
|
+
|
|
18
|
+
- Introduce `Async::Loop` for robust, time-aligned loops.
|
|
19
|
+
- Add support for `Async::Promise#wait(timeout: N)`.
|
|
20
|
+
|
|
21
|
+
## v2.36.0
|
|
22
|
+
|
|
23
|
+
- Introduce `Task#wait_all` which recursively waits for all children and self, excepting the current task.
|
|
24
|
+
- Introduce `Task#join` as an alias for `Task#wait` for compatibility with `Thread#join` and similar interfaces.
|
|
25
|
+
|
|
26
|
+
## v2.35.3
|
|
27
|
+
|
|
28
|
+
- `Async::Clock` now implements `#as_json` and `#to_json` for nicer log formatting.
|
|
29
|
+
|
|
30
|
+
## v2.35.2
|
|
31
|
+
|
|
32
|
+
- Improved handling of `Process.fork` on Ruby 4+.
|
|
33
|
+
- Improve `@promise` state handling in `Task#initialize`, preventing incomplete instances being visible to the scheduler.
|
|
34
|
+
|
|
35
|
+
## v2.35.1
|
|
36
|
+
|
|
37
|
+
- Fix incorrect handling of spurious wakeups in `Async::Promise#wait`, which could lead to premature (incorrect) resolution of the promise.
|
|
38
|
+
|
|
39
|
+
## v2.35.0
|
|
40
|
+
|
|
41
|
+
- `Process.fork` is now properly handled by the Async fiber scheduler, ensuring that the scheduler state is correctly reset in the child process after a fork. This prevents issues where the child process inherits the scheduler state from the parent, which could lead to unexpected behavior.
|
|
42
|
+
|
|
43
|
+
## v2.34.0
|
|
44
|
+
|
|
45
|
+
### `Kernel::Barrier` Convenience Interface
|
|
46
|
+
|
|
47
|
+
Starting multiple concurrent tasks and waiting for them to finish is a common pattern. This change introduces a small ergonomic helper, `Barrier`, defined in `Kernel`, that encapsulates this behavior: it creates an `Async::Barrier`, yields it to a block, waits for completion (using `Sync` to run a reactor if needed), and ensures remaining tasks are stopped on exit.
|
|
48
|
+
|
|
49
|
+
``` ruby
|
|
50
|
+
require "async"
|
|
51
|
+
|
|
52
|
+
Barrier do |barrier|
|
|
53
|
+
3.times do |i|
|
|
54
|
+
barrier.async do |task|
|
|
55
|
+
sleep(rand * 0.1) # Simulate work
|
|
56
|
+
puts "Task #{i} completed"
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# All tasks are guaranteed to complete or be stopped when the block exits.
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
If an exception is raised by a task, it will be propagated to the caller, and any remaining tasks will be stopped. The `parent:` parameter can be used to specify a parent task for the barrier, otherwise it will use the current task if available, or create a new reactor if not.
|
|
65
|
+
|
|
66
|
+
## v2.33.0
|
|
67
|
+
|
|
68
|
+
- Introduce `Async::Promise.fulfill` for optional promise resolution.
|
|
69
|
+
|
|
70
|
+
## v2.32.1
|
|
71
|
+
|
|
72
|
+
- Fix typo in documentation.
|
|
73
|
+
|
|
3
74
|
## v2.32.0
|
|
4
75
|
|
|
5
76
|
- Introduce `Queue#waiting_count` and `PriorityQueue#waiting_count`. Generally for statistics/testing purposes only.
|
|
@@ -35,15 +106,15 @@ This release introduces the new `Async::Promise` class and refactors `Async::Tas
|
|
|
35
106
|
<!-- end list -->
|
|
36
107
|
|
|
37
108
|
``` ruby
|
|
38
|
-
require
|
|
109
|
+
require "async/promise"
|
|
39
110
|
|
|
40
111
|
# Basic promise usage - works independently of Async framework
|
|
41
112
|
promise = Async::Promise.new
|
|
42
113
|
|
|
43
114
|
# In another thread or fiber, resolve the promise
|
|
44
115
|
Thread.new do
|
|
45
|
-
|
|
46
|
-
|
|
116
|
+
sleep(1) # Simulate some work
|
|
117
|
+
promise.resolve("Hello, World!")
|
|
47
118
|
end
|
|
48
119
|
|
|
49
120
|
# Wait for the result
|
|
@@ -62,34 +133,34 @@ Promises bridge Thread and Fiber concurrency models - a promise resolved in one
|
|
|
62
133
|
The new `Async::PriorityQueue` provides a thread-safe, fiber-aware queue where consumers can specify priority levels. Higher priority consumers are served first when items become available, with FIFO ordering maintained for equal priorities. This is useful for implementing priority-based task processing systems where critical operations need to be handled before lower priority work.
|
|
63
134
|
|
|
64
135
|
``` ruby
|
|
65
|
-
require
|
|
66
|
-
require
|
|
136
|
+
require "async"
|
|
137
|
+
require "async/priority_queue"
|
|
67
138
|
|
|
68
139
|
Async do
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
140
|
+
queue = Async::PriorityQueue.new
|
|
141
|
+
|
|
142
|
+
# Start consumers with different priorities
|
|
143
|
+
low_priority = async do
|
|
144
|
+
puts "Low priority consumer got: #{queue.dequeue(priority: 1)}"
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
medium_priority = async do
|
|
148
|
+
puts "Medium priority consumer got: #{queue.dequeue(priority: 5)}"
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
high_priority = async do
|
|
152
|
+
puts "High priority consumer got: #{queue.dequeue(priority: 10)}"
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Add items to the queue
|
|
156
|
+
queue.push("first item")
|
|
157
|
+
queue.push("second item")
|
|
158
|
+
queue.push("third item")
|
|
159
|
+
|
|
160
|
+
# Output:
|
|
161
|
+
# High priority consumer got: first item
|
|
162
|
+
# Medium priority consumer got: second item
|
|
163
|
+
# Low priority consumer got: third item
|
|
93
164
|
end
|
|
94
165
|
```
|
|
95
166
|
|
|
@@ -339,10 +410,10 @@ This gives better visibility into what the scheduler is doing, and should help d
|
|
|
339
410
|
The `async` gem depends on `console` gem, because my goal was to have good logging by default without thinking about it too much. However, some users prefer to avoid using the `console` gem for logging, so I've added an experimental set of shims which should allow you to bypass the `console` gem entirely.
|
|
340
411
|
|
|
341
412
|
``` ruby
|
|
342
|
-
require
|
|
343
|
-
require
|
|
413
|
+
require "async/console"
|
|
414
|
+
require "async"
|
|
344
415
|
|
|
345
|
-
Async{raise "Boom"}
|
|
416
|
+
Async {raise "Boom"}
|
|
346
417
|
```
|
|
347
418
|
|
|
348
419
|
Will now use `Kernel#warn` to print the task failure warning:
|
|
@@ -376,7 +447,7 @@ reactor = Async::Reactor.new # internally calls Fiber.set_scheduler
|
|
|
376
447
|
|
|
377
448
|
# This should run in the above reactor, rather than creating a new one.
|
|
378
449
|
Async do
|
|
379
|
-
|
|
450
|
+
puts "Hello World"
|
|
380
451
|
end
|
|
381
452
|
```
|
|
382
453
|
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: async
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.39.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Samuel Williams
|
|
@@ -37,7 +37,9 @@ authors:
|
|
|
37
37
|
- Shigeru Nakajima
|
|
38
38
|
- Sokolov Yura
|
|
39
39
|
- Stefan Wrobel
|
|
40
|
+
- Tavian Barnes
|
|
40
41
|
- Trevor Turk
|
|
42
|
+
- Yuhi Sato
|
|
41
43
|
bindir: bin
|
|
42
44
|
cert_chain:
|
|
43
45
|
- |
|
|
@@ -155,14 +157,18 @@ files:
|
|
|
155
157
|
- lib/async.rb
|
|
156
158
|
- lib/async/barrier.md
|
|
157
159
|
- lib/async/barrier.rb
|
|
160
|
+
- lib/async/cancel.rb
|
|
158
161
|
- lib/async/clock.rb
|
|
159
162
|
- lib/async/condition.md
|
|
160
163
|
- lib/async/condition.rb
|
|
161
164
|
- lib/async/console.rb
|
|
162
165
|
- lib/async/deadline.rb
|
|
166
|
+
- lib/async/error.rb
|
|
167
|
+
- lib/async/fork_handler.rb
|
|
163
168
|
- lib/async/idler.rb
|
|
164
169
|
- lib/async/limited_queue.rb
|
|
165
170
|
- lib/async/list.rb
|
|
171
|
+
- lib/async/loop.rb
|
|
166
172
|
- lib/async/node.rb
|
|
167
173
|
- lib/async/notification.rb
|
|
168
174
|
- lib/async/priority_queue.rb
|
|
@@ -173,13 +179,13 @@ files:
|
|
|
173
179
|
- lib/async/semaphore.md
|
|
174
180
|
- lib/async/semaphore.rb
|
|
175
181
|
- lib/async/stop.rb
|
|
176
|
-
- lib/async/task.md
|
|
177
182
|
- lib/async/task.rb
|
|
178
183
|
- lib/async/timeout.rb
|
|
179
184
|
- lib/async/variable.rb
|
|
180
185
|
- lib/async/version.rb
|
|
181
186
|
- lib/async/waiter.rb
|
|
182
187
|
- lib/kernel/async.rb
|
|
188
|
+
- lib/kernel/barrier.rb
|
|
183
189
|
- lib/kernel/sync.rb
|
|
184
190
|
- lib/metrics/provider/async.rb
|
|
185
191
|
- lib/metrics/provider/async/task.rb
|
|
@@ -203,7 +209,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
203
209
|
requirements:
|
|
204
210
|
- - ">="
|
|
205
211
|
- !ruby/object:Gem::Version
|
|
206
|
-
version: '3.
|
|
212
|
+
version: '3.3'
|
|
207
213
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
208
214
|
requirements:
|
|
209
215
|
- - ">="
|
metadata.gz.sig
CHANGED
|
Binary file
|
data/lib/async/task.md
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
A sequence of instructions, defined by a block, which is executed sequentially and managed by the scheduler. A task can be in one of the following states: `initialized`, `running`, `completed`, `failed`, `cancelled` or `stopped`.
|
|
2
|
-
|
|
3
|
-
```mermaid
|
|
4
|
-
stateDiagram-v2
|
|
5
|
-
[*] --> Initialized
|
|
6
|
-
Initialized --> Running : Run
|
|
7
|
-
|
|
8
|
-
Running --> Completed : Return Value
|
|
9
|
-
Running --> Failed : Exception
|
|
10
|
-
|
|
11
|
-
Completed --> [*]
|
|
12
|
-
Failed --> [*]
|
|
13
|
-
|
|
14
|
-
Running --> Stopped : Stop
|
|
15
|
-
Stopped --> [*]
|
|
16
|
-
Completed --> Stopped : Stop
|
|
17
|
-
Failed --> Stopped : Stop
|
|
18
|
-
Initialized --> Stopped : Stop
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
## Example
|
|
22
|
-
|
|
23
|
-
```ruby
|
|
24
|
-
require 'async'
|
|
25
|
-
|
|
26
|
-
# Create an asynchronous task that sleeps for 1 second:
|
|
27
|
-
Async do |task|
|
|
28
|
-
sleep(1)
|
|
29
|
-
end
|
|
30
|
-
```
|