Skip to content

Commit 48a22e3

Browse files
Update release notes.
1 parent afe1af1 commit 48a22e3

File tree

1 file changed

+100
-29
lines changed

1 file changed

+100
-29
lines changed

releases.md

Lines changed: 100 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,79 @@
11
# Releases
22

3+
## Unreleased
4+
5+
- `Async::Notification#signal` now returns `true` if a task was signaled, `false` otherwise, providing better feedback for notification operations.
6+
7+
### Async::Barrier Improvements
8+
9+
`Async::Barrier` now provides more flexible and predictable behavior for waiting on task completion:
10+
11+
- **Completion-order waiting**: `barrier.wait` now processes tasks in the order they complete rather than the order they were created. This provides more predictable behavior when tasks have different execution times.
12+
- **Block-based waiting**: `barrier.wait` now accepts an optional block that yields each task as it completes, allowing for custom handling of individual tasks:
13+
14+
```ruby
15+
barrier = Async::Barrier.new
16+
17+
# Start several tasks
18+
3.times do |i|
19+
barrier.async do |task|
20+
sleep(rand * 0.1) # Random completion time
21+
"result_#{i}"
22+
end
23+
end
24+
25+
# Wait for all tasks, processing them as they complete
26+
barrier.wait do |task|
27+
result = task.wait
28+
puts "Task completed with: #{result}"
29+
end
30+
```
31+
32+
- **Partial completion support**: The new block-based interface allows you to wait for only the first N tasks to complete:
33+
34+
```ruby
35+
# Wait for only the first 3 tasks to complete
36+
count = 0
37+
barrier.wait do |task|
38+
task.wait
39+
count += 1
40+
break if count >= 3
41+
end
42+
```
43+
44+
This makes `Async::Barrier` a superset of `Async::Waiter` functionality, providing more flexible task coordination patterns.
45+
46+
### Queue Closing Functionality
47+
48+
`Async::Queue` and `Async::LimitedQueue` now support closing, which provides better resource management and error handling:
49+
50+
- **New `close` method**: Both queue types now have a `close` method that prevents further items from being added and signals any waiting tasks.
51+
- **Consistent error handling**: All queue modification methods (`push`, `enqueue`, `<<`) now raise `Async::Queue::ClosedError` when called on a closed queue.
52+
- **Waiting task signaling**: When a queue is closed, any tasks waiting on `dequeue` (for regular queues) or `enqueue` (for limited queues) are properly signaled and can complete.
53+
54+
```ruby
55+
queue = Async::Queue.new
56+
57+
# Start a task waiting for items:
58+
waiting_task = Async do
59+
queue.dequeue
60+
end
61+
62+
# Close the queue - this signals the waiting task
63+
queue.close
64+
65+
# These will raise Async::Queue::ClosedError
66+
queue.push(:item) # => raises ClosedError
67+
queue.enqueue(:item) # => raises ClosedError
68+
queue << :item # => raises ClosedError
69+
70+
# Dequeue returns nil when closed and empty
71+
queue.dequeue # => nil
72+
```
73+
374
## v2.25.0
475

5-
- Added support for `io_select` hook in the fiber scheduler, allowing non-blocking `IO.select` operations. This enables better integration with code that uses `IO.select` for multiplexing IO operations.
76+
- Added support for `io_select` hook in the fiber scheduler, allowing non-blocking `IO.select` operations. This enables better integration with code that uses `IO.select` for multiplexing IO operations.
677

778
### Use `IO::Event::WorkerPool` for Blocking Operations
879

@@ -29,9 +100,9 @@ end
29100

30101
## v2.24.0
31102

32-
- Ruby v3.1 support is dropped.
33-
- `Async::Wrapper` which was previously deprecated, is now removed.
34-
- `Async::Barrier` now waits in order of completion rather than order of creation. This means that if you create a barrier with 3 tasks, and one of them completes (or fails) before the others, it will be the first to be yielded to the barrier.
103+
- Ruby v3.1 support is dropped.
104+
- `Async::Wrapper` which was previously deprecated, is now removed.
105+
- `Async::Barrier` now waits in order of completion rather than order of creation. This means that if you create a barrier with 3 tasks, and one of them completes (or fails) before the others, it will be the first to be yielded to the barrier.
35106

36107
### Flexible Timeouts
37108

@@ -63,7 +134,7 @@ end
63134

64135
## v2.23.0
65136

66-
- Rename `ASYNC_SCHEDULER_DEFAULT_WORKER_POOL` to `ASYNC_SCHEDULER_WORKER_POOL`.
137+
- Rename `ASYNC_SCHEDULER_DEFAULT_WORKER_POOL` to `ASYNC_SCHEDULER_WORKER_POOL`.
67138

68139
### Fiber Stall Profiler
69140

@@ -93,7 +164,7 @@ Ruby 3.4 will feature a new fiber scheduler hook, `blocking_operation_wait` whic
93164

94165
The Async scheduler optionally supports this feature using a worker pool, by using the following environment variable:
95166

96-
ASYNC_SCHEDULER_WORKER_POOL=true
167+
ASYNC_SCHEDULER_WORKER_POOL=true
97168

98169
This will cause the scheduler to use a worker pool for general blocking operations, rather than blocking the event loop.
99170

@@ -113,21 +184,21 @@ To take advantage of this feature, you will need to introduce your own `config/t
113184

114185
Occasionally on issues, I encounter people asking for help and I need more information. Pressing Ctrl-C to exit a hung program is common, but it usually doesn't provide enough information to diagnose the problem. Setting the `CONSOLE_LEVEL=debug` environment variable will now print additional information about the scheduler when you interrupt it, including a backtrace of the current tasks.
115186

116-
> CONSOLE_LEVEL=debug bundle exec ruby ./test.rb
117-
^C 0.0s debug: Async::Reactor [oid=0x974] [ec=0x988] [pid=9116] [2024-11-08 14:12:03 +1300]
118-
| Scheduler interrupted: Interrupt
119-
| #<Async::Reactor:0x0000000000000974 1 children (running)>
120-
| #<Async::Task:0x000000000000099c /Users/samuel/Developer/socketry/async/lib/async/scheduler.rb:185:in `transfer' (running)>
121-
| → /Users/samuel/Developer/socketry/async/lib/async/scheduler.rb:185:in `transfer'
122-
| /Users/samuel/Developer/socketry/async/lib/async/scheduler.rb:185:in `block'
123-
| /Users/samuel/Developer/socketry/async/lib/async/scheduler.rb:207:in `kernel_sleep'
124-
| /Users/samuel/Developer/socketry/async/test.rb:7:in `sleep'
125-
| /Users/samuel/Developer/socketry/async/test.rb:7:in `sleepy'
126-
| /Users/samuel/Developer/socketry/async/test.rb:12:in `block in <top (required)>'
127-
| /Users/samuel/Developer/socketry/async/lib/async/task.rb:197:in `block in run'
128-
| /Users/samuel/Developer/socketry/async/lib/async/task.rb:420:in `block in schedule'
129-
/Users/samuel/Developer/socketry/async/lib/async/scheduler.rb:317:in `select': Interrupt
130-
... (backtrace continues) ...
187+
> CONSOLE_LEVEL=debug bundle exec ruby ./test.rb
188+
^C 0.0s debug: Async::Reactor [oid=0x974] [ec=0x988] [pid=9116] [2024-11-08 14:12:03 +1300]
189+
| Scheduler interrupted: Interrupt
190+
| #<Async::Reactor:0x0000000000000974 1 children (running)>
191+
| #<Async::Task:0x000000000000099c /Users/samuel/Developer/socketry/async/lib/async/scheduler.rb:185:in `transfer' (running)>
192+
| → /Users/samuel/Developer/socketry/async/lib/async/scheduler.rb:185:in `transfer'
193+
| /Users/samuel/Developer/socketry/async/lib/async/scheduler.rb:185:in `block'
194+
| /Users/samuel/Developer/socketry/async/lib/async/scheduler.rb:207:in `kernel_sleep'
195+
| /Users/samuel/Developer/socketry/async/test.rb:7:in `sleep'
196+
| /Users/samuel/Developer/socketry/async/test.rb:7:in `sleepy'
197+
| /Users/samuel/Developer/socketry/async/test.rb:12:in `block in <top (required)>'
198+
| /Users/samuel/Developer/socketry/async/lib/async/task.rb:197:in `block in run'
199+
| /Users/samuel/Developer/socketry/async/lib/async/task.rb:420:in `block in schedule'
200+
/Users/samuel/Developer/socketry/async/lib/async/scheduler.rb:317:in `select': Interrupt
201+
... (backtrace continues) ...
131202

132203
This gives better visibility into what the scheduler is doing, and should help diagnose issues.
133204

@@ -144,19 +215,19 @@ Async{raise "Boom"}
144215

145216
Will now use `Kernel#warn` to print the task failure warning:
146217

147-
#<Async::Task:0x00000000000012d4 /home/samuel/Developer/socketry/async/lib/async/task.rb:104:in `backtrace' (running)>
148-
Task may have ended with unhandled exception.
149-
(irb):4:in `block in <top (required)>': Boom (RuntimeError)
150-
from /home/samuel/Developer/socketry/async/lib/async/task.rb:197:in `block in run'
151-
from /home/samuel/Developer/socketry/async/lib/async/task.rb:420:in `block in schedule'
218+
#<Async::Task:0x00000000000012d4 /home/samuel/Developer/socketry/async/lib/async/task.rb:104:in `backtrace' (running)>
219+
Task may have ended with unhandled exception.
220+
(irb):4:in `block in <top (required)>': Boom (RuntimeError)
221+
from /home/samuel/Developer/socketry/async/lib/async/task.rb:197:in `block in run'
222+
from /home/samuel/Developer/socketry/async/lib/async/task.rb:420:in `block in schedule'
152223

153224
## v2.18.0
154225

155-
- Add support for `Sync(annotation:)`, so that you can annotate the block with a description of what it does, even if it doesn't create a new task.
226+
- Add support for `Sync(annotation:)`, so that you can annotate the block with a description of what it does, even if it doesn't create a new task.
156227

157228
## v2.17.0
158229

159-
- Introduce `Async::Queue#push` and `Async::Queue#pop` for compatibility with `::Queue`.
230+
- Introduce `Async::Queue#push` and `Async::Queue#pop` for compatibility with `::Queue`.
160231

161232
## v2.16.0
162233

@@ -173,7 +244,7 @@ reactor = Async::Reactor.new # internally calls Fiber.set_scheduler
173244

174245
# This should run in the above reactor, rather than creating a new one.
175246
Async do
176-
puts "Hello World"
247+
puts "Hello World"
177248
end
178249
```
179250

0 commit comments

Comments
 (0)