async 2.24.0 → 2.28.1
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/agent.md +63 -0
- data/context/best-practices.md +188 -0
- data/context/debugging.md +63 -0
- data/context/getting-started.md +177 -0
- data/context/index.yaml +29 -0
- data/context/scheduler.md +109 -0
- data/context/tasks.md +448 -0
- data/context/thread-safety.md +651 -0
- data/lib/async/barrier.md +0 -1
- data/lib/async/barrier.rb +31 -8
- data/lib/async/clock.rb +1 -1
- data/lib/async/condition.rb +3 -1
- data/lib/async/limited_queue.rb +7 -1
- data/lib/async/list.rb +16 -8
- data/lib/async/node.rb +3 -1
- data/lib/async/notification.rb +5 -3
- data/lib/async/queue.rb +57 -2
- data/lib/async/reactor.rb +3 -1
- data/lib/async/scheduler.rb +76 -7
- data/lib/async/stop.rb +82 -0
- data/lib/async/task.rb +21 -32
- data/lib/async/variable.rb +1 -1
- data/lib/async/version.rb +2 -2
- data/lib/async/waiter.rb +4 -1
- data/lib/metrics/provider/async/task.rb +1 -1
- data/lib/traces/provider/async/barrier.rb +1 -1
- data/lib/traces/provider/async/task.rb +4 -4
- data/license.md +8 -1
- data/readme.md +39 -23
- data/releases.md +140 -2
- data.tar.gz.sig +2 -2
- metadata +28 -14
- metadata.gz.sig +0 -0
- data/lib/async/waiter.md +0 -50
- data/lib/async/worker_pool.rb +0 -182
data/lib/async/task.rb
CHANGED
@@ -1,44 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2017-
|
4
|
+
# Copyright, 2017-2025, by Samuel Williams.
|
5
5
|
# Copyright, 2017, by Kent Gruber.
|
6
6
|
# Copyright, 2017, by Devin Christensen.
|
7
7
|
# Copyright, 2020, by Patrik Wenger.
|
8
8
|
# Copyright, 2023, by Math Ieu.
|
9
|
+
# Copyright, 2025, by Shigeru Nakajima.
|
9
10
|
|
10
11
|
require "fiber"
|
11
12
|
require "console"
|
12
13
|
|
13
14
|
require_relative "node"
|
14
15
|
require_relative "condition"
|
16
|
+
require_relative "stop"
|
15
17
|
|
16
18
|
Fiber.attr_accessor :async_task
|
17
19
|
|
18
20
|
module Async
|
19
|
-
# Raised when a task is explicitly stopped.
|
20
|
-
class Stop < Exception
|
21
|
-
# Used to defer stopping the current task until later.
|
22
|
-
class Later
|
23
|
-
# Create a new stop later operation.
|
24
|
-
#
|
25
|
-
# @parameter task [Task] The task to stop later.
|
26
|
-
def initialize(task)
|
27
|
-
@task = task
|
28
|
-
end
|
29
|
-
|
30
|
-
# @returns [Boolean] Whether the task is alive.
|
31
|
-
def alive?
|
32
|
-
true
|
33
|
-
end
|
34
|
-
|
35
|
-
# Transfer control to the operation - this will stop the task.
|
36
|
-
def transfer
|
37
|
-
@task.stop
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
21
|
# Raised if a timeout occurs on a specific Fiber. Handled gracefully by `Task`.
|
43
22
|
# @public Since *Async v1*.
|
44
23
|
class TimeoutError < StandardError
|
@@ -64,6 +43,8 @@ module Async
|
|
64
43
|
|
65
44
|
# @deprecated With no replacement.
|
66
45
|
def self.yield
|
46
|
+
warn("`Async::Task.yield` is deprecated with no replacement.", uplevel: 1, category: :deprecated) if $VERBOSE
|
47
|
+
|
67
48
|
Fiber.scheduler.transfer
|
68
49
|
end
|
69
50
|
|
@@ -133,6 +114,8 @@ module Async
|
|
133
114
|
|
134
115
|
# @deprecated Prefer {Kernel#sleep} except when compatibility with `stable-v1` is required.
|
135
116
|
def sleep(duration = nil)
|
117
|
+
Kernel.warn("`Async::Task#sleep` is deprecated, use `Kernel#sleep` instead.", uplevel: 1, category: :deprecated) if $VERBOSE
|
118
|
+
|
136
119
|
super
|
137
120
|
end
|
138
121
|
|
@@ -266,7 +249,13 @@ module Async
|
|
266
249
|
# If `later` is false, it means that `stop` has been invoked directly. When `later` is true, it means that `stop` is invoked by `stop_children` or some other indirect mechanism. In that case, if we encounter the "current" fiber, we can't stop it right away, as it's currently performing `#stop`. Stopping it immediately would interrupt the current stop traversal, so we need to schedule the stop to occur later.
|
267
250
|
#
|
268
251
|
# @parameter later [Boolean] Whether to stop the task later, or immediately.
|
269
|
-
|
252
|
+
# @parameter cause [Exception] The cause of the stop operation.
|
253
|
+
def stop(later = false, cause: $!)
|
254
|
+
# If no cause is given, we generate one from the current call stack:
|
255
|
+
unless cause
|
256
|
+
cause = Stop::Cause.for("Stopping task!")
|
257
|
+
end
|
258
|
+
|
270
259
|
if self.stopped?
|
271
260
|
# If the task is already stopped, a `stop` state transition re-enters the same state which is a no-op. However, we will also attempt to stop any running children too. This can happen if the children did not stop correctly the first time around. Doing this should probably be considered a bug, but it's better to be safe than sorry.
|
272
261
|
return stopped!
|
@@ -280,7 +269,7 @@ module Async
|
|
280
269
|
# If we are deferring stop...
|
281
270
|
if @defer_stop == false
|
282
271
|
# Don't stop now... but update the state so we know we need to stop later.
|
283
|
-
@defer_stop =
|
272
|
+
@defer_stop = cause
|
284
273
|
return false
|
285
274
|
end
|
286
275
|
|
@@ -288,19 +277,19 @@ module Async
|
|
288
277
|
# If the fiber is current, and later is `true`, we need to schedule the fiber to be stopped later, as it's currently invoking `stop`:
|
289
278
|
if later
|
290
279
|
# If the fiber is the current fiber and we want to stop it later, schedule it:
|
291
|
-
Fiber.scheduler.push(Stop::Later.new(self))
|
280
|
+
Fiber.scheduler.push(Stop::Later.new(self, cause))
|
292
281
|
else
|
293
282
|
# Otherwise, raise the exception directly:
|
294
|
-
raise Stop, "Stopping current task!"
|
283
|
+
raise Stop, "Stopping current task!", cause: cause
|
295
284
|
end
|
296
285
|
else
|
297
286
|
# If the fiber is not curent, we can raise the exception directly:
|
298
287
|
begin
|
299
288
|
# There is a chance that this will stop the fiber that originally called stop. If that happens, the exception handling in `#stopped` will rescue the exception and re-raise it later.
|
300
|
-
Fiber.scheduler.raise(@fiber, Stop)
|
289
|
+
Fiber.scheduler.raise(@fiber, Stop, cause: cause)
|
301
290
|
rescue FiberError
|
302
291
|
# In some cases, this can cause a FiberError (it might be resumed already), so we schedule it to be stopped later:
|
303
|
-
Fiber.scheduler.push(Stop::Later.new(self))
|
292
|
+
Fiber.scheduler.push(Stop::Later.new(self, cause))
|
304
293
|
end
|
305
294
|
end
|
306
295
|
else
|
@@ -340,7 +329,7 @@ module Async
|
|
340
329
|
|
341
330
|
# If we were asked to stop, we should do so now:
|
342
331
|
if defer_stop
|
343
|
-
raise Stop, "Stopping current task (was deferred)!"
|
332
|
+
raise Stop, "Stopping current task (was deferred)!", cause: defer_stop
|
344
333
|
end
|
345
334
|
end
|
346
335
|
else
|
@@ -351,7 +340,7 @@ module Async
|
|
351
340
|
|
352
341
|
# @returns [Boolean] Whether stop has been deferred.
|
353
342
|
def stop_deferred?
|
354
|
-
|
343
|
+
!!@defer_stop
|
355
344
|
end
|
356
345
|
|
357
346
|
# Lookup the {Task} for the current fiber. Raise `RuntimeError` if none is available.
|
data/lib/async/variable.rb
CHANGED
data/lib/async/version.rb
CHANGED
data/lib/async/waiter.rb
CHANGED
@@ -1,17 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2022-
|
4
|
+
# Copyright, 2022-2025, by Samuel Williams.
|
5
5
|
# Copyright, 2024, by Patrik Wenger.
|
6
6
|
|
7
7
|
module Async
|
8
8
|
# A composable synchronization primitive, which allows one task to wait for a number of other tasks to complete. It can be used in conjunction with {Semaphore} and/or {Barrier}.
|
9
|
+
# @deprecated `Async::Waiter` is deprecated, use `Async::Barrier` instead.
|
9
10
|
class Waiter
|
10
11
|
# Create a waiter instance.
|
11
12
|
#
|
12
13
|
# @parameter parent [Interface(:async) | Nil] The parent task to use for asynchronous operations.
|
13
14
|
# @parameter finished [Async::Condition] The condition to signal when a task completes.
|
14
15
|
def initialize(parent: nil, finished: Async::Condition.new)
|
16
|
+
warn("`Async::Waiter` is deprecated, use `Async::Barrier` instead.", uplevel: 1, category: :deprecated) if $VERBOSE
|
17
|
+
|
15
18
|
@finished = finished
|
16
19
|
@done = []
|
17
20
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright,
|
4
|
+
# Copyright, 2024-2025, by Samuel Williams.
|
5
5
|
|
6
6
|
require_relative "../../../async/task"
|
7
7
|
require "traces/provider"
|
@@ -14,18 +14,18 @@ Traces::Provider(Async::Task) do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
unless self.transient?
|
17
|
-
trace_context = Traces.
|
17
|
+
trace_context = Traces.current_context
|
18
18
|
end
|
19
19
|
|
20
20
|
attributes = {
|
21
21
|
# We use the instance variable as it corresponds to the user-provided block.
|
22
|
-
"block" => @block,
|
22
|
+
"block" => @block.to_s,
|
23
23
|
"transient" => self.transient?,
|
24
24
|
}
|
25
25
|
|
26
26
|
# Run the trace in the context of the child task:
|
27
27
|
super do
|
28
|
-
Traces.trace_context
|
28
|
+
Traces.with_context(trace_context)
|
29
29
|
|
30
30
|
if annotation = self.annotation
|
31
31
|
attributes["annotation"] = annotation
|
data/license.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# MIT License
|
2
2
|
|
3
|
-
Copyright, 2017-
|
3
|
+
Copyright, 2017-2025, by Samuel Williams.
|
4
4
|
Copyright, 2017, by Kent Gruber.
|
5
5
|
Copyright, 2017, by Devin Christensen.
|
6
6
|
Copyright, 2018, by Sokolov Yura.
|
@@ -27,6 +27,13 @@ Copyright, 2023, by Emil Tin.
|
|
27
27
|
Copyright, 2023, by Gert Goet.
|
28
28
|
Copyright, 2024, by Dimitar Peychinov.
|
29
29
|
Copyright, 2024, by Jamie McCarthy.
|
30
|
+
Copyright, 2025, by Jahfer Husain.
|
31
|
+
Copyright, 2025, by Mark Montroy.
|
32
|
+
Copyright, 2025, by Shigeru Nakajima.
|
33
|
+
Copyright, 2025, by Alan Wu.
|
34
|
+
Copyright, 2025, by Shopify Inc.
|
35
|
+
Copyright, 2025, by Josh Teeter.
|
36
|
+
Copyright, 2025, by Jatin Goyal.
|
30
37
|
|
31
38
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
32
39
|
of this software and associated documentation files (the "Software"), to deal
|
data/readme.md
CHANGED
@@ -21,55 +21,71 @@ Please see the [project documentation](https://socketry.github.io/async/) for mo
|
|
21
21
|
|
22
22
|
- [Getting Started](https://socketry.github.io/async/guides/getting-started/index) - This guide shows how to add async to your project and run code asynchronously.
|
23
23
|
|
24
|
-
- [Asynchronous Tasks](https://socketry.github.io/async/guides/asynchronous-tasks/index) - This guide explains how asynchronous tasks work and how to use them.
|
25
|
-
|
26
24
|
- [Scheduler](https://socketry.github.io/async/guides/scheduler/index) - This guide gives an overview of how the scheduler is implemented.
|
27
25
|
|
28
|
-
- [
|
26
|
+
- [Tasks](https://socketry.github.io/async/guides/tasks/index) - This guide explains how asynchronous tasks work and how to use them.
|
29
27
|
|
30
28
|
- [Best Practices](https://socketry.github.io/async/guides/best-practices/index) - This guide gives an overview of best practices for using Async.
|
31
29
|
|
32
30
|
- [Debugging](https://socketry.github.io/async/guides/debugging/index) - This guide explains how to debug issues with programs that use Async.
|
33
31
|
|
32
|
+
- [Thread safety](https://socketry.github.io/async/guides/thread-safety/index) - This guide explains thread safety in Ruby, focusing on fibers and threads, common pitfalls, and best practices to avoid problems like data corruption, race conditions, and deadlocks.
|
33
|
+
|
34
34
|
## Releases
|
35
35
|
|
36
36
|
Please see the [project releases](https://socketry.github.io/async/releases/index) for all releases.
|
37
37
|
|
38
|
-
### v2.
|
38
|
+
### v2.28.1
|
39
39
|
|
40
|
-
-
|
41
|
-
|
42
|
-
|
40
|
+
- Fix race condition between `Async::Barrier#stop` and finish signalling.
|
41
|
+
|
42
|
+
### v2.28.0
|
43
43
|
|
44
|
-
|
44
|
+
- Use `Traces.current_context` and `Traces.with_context` for better integration with OpenTelemetry.
|
45
45
|
|
46
|
-
|
47
|
-
- [Fiber Stall Profiler](https://socketry.github.io/async/releases/index#fiber-stall-profiler)
|
46
|
+
### v2.27.4
|
48
47
|
|
49
|
-
|
48
|
+
- Suppress excessive warning in `Async::Scheduler#async`.
|
50
49
|
|
51
|
-
|
50
|
+
### v2.27.3
|
52
51
|
|
53
|
-
|
52
|
+
- Ensure trace attributes are strings, fixes integration with OpenTelemetry.
|
54
53
|
|
55
|
-
|
54
|
+
### v2.27.2
|
56
55
|
|
57
|
-
|
56
|
+
- Fix `context/index.yaml` schema.
|
58
57
|
|
59
|
-
|
60
|
-
- [Console Shims](https://socketry.github.io/async/releases/index#console-shims)
|
58
|
+
### v2.27.1
|
61
59
|
|
62
|
-
|
60
|
+
- Updated documentation and agent context.
|
63
61
|
|
64
|
-
|
62
|
+
### v2.27.0
|
65
63
|
|
66
|
-
|
64
|
+
- `Async::Task#stop` supports an optional `cause:` argument (that defaults to `$!`), which allows you to specify the cause (exception) for stopping the task.
|
65
|
+
- Add thread-safety agent context.
|
67
66
|
|
68
|
-
|
67
|
+
### v2.26.0
|
69
68
|
|
70
|
-
|
69
|
+
- `Async::Notification#signal` now returns `true` if a task was signaled, `false` otherwise, providing better feedback for notification operations.
|
70
|
+
- `require "async/limited_queue"` is required to use `Async::LimitedQueue` without a deprecation warning. `Async::LimitedQueue` is not deprecated, but it's usage via `async/queue` is deprecated.
|
71
|
+
- `Async::Task#sleep` is deprecated with no replacement.
|
72
|
+
- `Async::Task.yield` is deprecated with no replacement.
|
73
|
+
- `Async::Scheduler#async` is deprecated, use `Async{}`, `Sync{}` or `Async::Task#async` instead.
|
74
|
+
- Agent context is now available, via the [`agent-context` gem](https://github.com/ioquatix/agent-context).
|
75
|
+
- [`Async::Barrier` Improvements](https://socketry.github.io/async/releases/index#async::barrier-improvements)
|
76
|
+
- [Introduce `Async::Queue#close`](https://socketry.github.io/async/releases/index#introduce-async::queue#close)
|
71
77
|
|
72
|
-
|
78
|
+
### v2.25.0
|
79
|
+
|
80
|
+
- 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.
|
81
|
+
- [Use `IO::Event::WorkerPool` for Blocking Operations](https://socketry.github.io/async/releases/index#use-io::event::workerpool-for-blocking-operations)
|
82
|
+
- [Better handling of `IO#close` using `fiber_interrupt`](https://socketry.github.io/async/releases/index#better-handling-of-io#close-using-fiber_interrupt)
|
83
|
+
|
84
|
+
### v2.24.0
|
85
|
+
|
86
|
+
- Ruby v3.1 support is dropped.
|
87
|
+
- `Async::Wrapper` which was previously deprecated, is now removed.
|
88
|
+
- [Flexible Timeouts](https://socketry.github.io/async/releases/index#flexible-timeouts)
|
73
89
|
|
74
90
|
## See Also
|
75
91
|
|
data/releases.md
CHANGED
@@ -1,5 +1,143 @@
|
|
1
1
|
# Releases
|
2
2
|
|
3
|
+
## v2.28.1
|
4
|
+
|
5
|
+
- Fix race condition between `Async::Barrier#stop` and finish signalling.
|
6
|
+
|
7
|
+
## v2.28.0
|
8
|
+
|
9
|
+
- Use `Traces.current_context` and `Traces.with_context` for better integration with OpenTelemetry.
|
10
|
+
|
11
|
+
## v2.27.4
|
12
|
+
|
13
|
+
- Suppress excessive warning in `Async::Scheduler#async`.
|
14
|
+
|
15
|
+
## v2.27.3
|
16
|
+
|
17
|
+
- Ensure trace attributes are strings, fixes integration with OpenTelemetry.
|
18
|
+
|
19
|
+
## v2.27.2
|
20
|
+
|
21
|
+
- Fix `context/index.yaml` schema.
|
22
|
+
|
23
|
+
## v2.27.1
|
24
|
+
|
25
|
+
- Updated documentation and agent context.
|
26
|
+
|
27
|
+
## v2.27.0
|
28
|
+
|
29
|
+
- `Async::Task#stop` supports an optional `cause:` argument (that defaults to `$!`), which allows you to specify the cause (exception) for stopping the task.
|
30
|
+
- Add thread-safety agent context.
|
31
|
+
|
32
|
+
## v2.26.0
|
33
|
+
|
34
|
+
- `Async::Notification#signal` now returns `true` if a task was signaled, `false` otherwise, providing better feedback for notification operations.
|
35
|
+
- `require "async/limited_queue"` is required to use `Async::LimitedQueue` without a deprecation warning. `Async::LimitedQueue` is not deprecated, but it's usage via `async/queue` is deprecated.
|
36
|
+
- `Async::Task#sleep` is deprecated with no replacement.
|
37
|
+
- `Async::Task.yield` is deprecated with no replacement.
|
38
|
+
- `Async::Scheduler#async` is deprecated, use `Async{}`, `Sync{}` or `Async::Task#async` instead.
|
39
|
+
- Agent context is now available, via the [`agent-context` gem](https://github.com/ioquatix/agent-context).
|
40
|
+
|
41
|
+
### `Async::Barrier` Improvements
|
42
|
+
|
43
|
+
`Async::Barrier` now provides more flexible and predictable behavior for waiting on task completion:
|
44
|
+
|
45
|
+
- **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.
|
46
|
+
- **Block-based waiting**: `barrier.wait` now accepts an optional block that yields each task as it completes, allowing for custom handling of individual tasks:
|
47
|
+
|
48
|
+
<!-- end list -->
|
49
|
+
|
50
|
+
``` ruby
|
51
|
+
barrier = Async::Barrier.new
|
52
|
+
|
53
|
+
# Start several tasks
|
54
|
+
3.times do |i|
|
55
|
+
barrier.async do |task|
|
56
|
+
sleep(rand * 0.1) # Random completion time
|
57
|
+
"result_#{i}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Wait for all tasks, processing them as they complete
|
62
|
+
barrier.wait do |task|
|
63
|
+
result = task.wait
|
64
|
+
puts "Task completed with: #{result}"
|
65
|
+
end
|
66
|
+
```
|
67
|
+
|
68
|
+
- **Partial completion support**: The new block-based interface allows you to wait for only the first N tasks to complete:
|
69
|
+
|
70
|
+
<!-- end list -->
|
71
|
+
|
72
|
+
``` ruby
|
73
|
+
# Wait for only the first 3 tasks to complete
|
74
|
+
count = 0
|
75
|
+
barrier.wait do |task|
|
76
|
+
task.wait
|
77
|
+
count += 1
|
78
|
+
break if count >= 3
|
79
|
+
end
|
80
|
+
```
|
81
|
+
|
82
|
+
This makes `Async::Barrier` a superset of `Async::Waiter` functionality, providing more flexible task coordination patterns, and therrefore, `Async::Waiter` is now deprecated.
|
83
|
+
|
84
|
+
### Introduce `Async::Queue#close`
|
85
|
+
|
86
|
+
`Async::Queue` and `Async::LimitedQueue` can now be closed, which provides better resource management and error handling:
|
87
|
+
|
88
|
+
- **New `close` method**: Both queue types now have a `close` method that prevents further items from being added and signals any waiting tasks.
|
89
|
+
- **Consistent error handling**: All queue modification methods (`push`, `enqueue`, `<<`) now raise `Async::Queue::ClosedError` when called on a closed queue.
|
90
|
+
- **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.
|
91
|
+
|
92
|
+
<!-- end list -->
|
93
|
+
|
94
|
+
``` ruby
|
95
|
+
queue = Async::Queue.new
|
96
|
+
|
97
|
+
# Start a task waiting for items:
|
98
|
+
waiting_task = Async do
|
99
|
+
queue.dequeue
|
100
|
+
end
|
101
|
+
|
102
|
+
# Close the queue - this signals the waiting task
|
103
|
+
queue.close
|
104
|
+
|
105
|
+
# These will raise Async::Queue::ClosedError
|
106
|
+
queue.push(:item) # => raises ClosedError
|
107
|
+
queue.enqueue(:item) # => raises ClosedError
|
108
|
+
queue << :item # => raises ClosedError
|
109
|
+
|
110
|
+
# Dequeue returns nil when closed and empty
|
111
|
+
queue.dequeue # => nil
|
112
|
+
```
|
113
|
+
|
114
|
+
## v2.25.0
|
115
|
+
|
116
|
+
- 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.
|
117
|
+
|
118
|
+
### Use `IO::Event::WorkerPool` for Blocking Operations
|
119
|
+
|
120
|
+
The `Async::WorkerPool` implementation has been removed in favor of using `IO::Event::WorkerPool` directly. This change simplifies the codebase by delegating worker pool functionality to the `io-event` gem, which provides a more efficient and well-tested implementation.
|
121
|
+
|
122
|
+
To enable the worker pool, you can set the `ASYNC_SCHEDULER_WORKER_POOL` environment variable to `true`. This will allow the scheduler to use a worker pool for blocking operations, which can help improve performance in applications that perform a lot of CPU-bound operations (e.g. `rb_nogvl`).
|
123
|
+
|
124
|
+
### Better handling of `IO#close` using `fiber_interrupt`
|
125
|
+
|
126
|
+
`IO#close` interrupts fibers that are waiting on the IO using the new `fiber_interrupt` hook introduced in Ruby 3.5/4.0. This means that if you close an IO while a fiber is waiting on it, the fiber will be interrupted and will raise an `IOError`. This is a change from previous versions of Ruby, where closing an IO would not interrupt fibers waiting on it, and would instead interrupt the entire event loop (essentially a bug).
|
127
|
+
|
128
|
+
``` ruby
|
129
|
+
r, w = IO.pipe
|
130
|
+
|
131
|
+
Async do
|
132
|
+
child = Async do
|
133
|
+
r.gets
|
134
|
+
end
|
135
|
+
|
136
|
+
r.close # This will interrupt the child fiber.
|
137
|
+
child.wait # This will raise an `IOError` because the IO was closed.
|
138
|
+
end
|
139
|
+
```
|
140
|
+
|
3
141
|
## v2.24.0
|
4
142
|
|
5
143
|
- Ruby v3.1 support is dropped.
|
@@ -7,7 +145,7 @@
|
|
7
145
|
|
8
146
|
### Flexible Timeouts
|
9
147
|
|
10
|
-
When
|
148
|
+
When `Async::Scheduler#with_timeout` is invoked with a block, it can receive a `Async::Timeout` instance. This allows you to adjust or cancel the timeout while the block is executing. This is useful for long-running tasks that may need to adjust their timeout based on external factors.
|
11
149
|
|
12
150
|
``` ruby
|
13
151
|
Async do
|
@@ -81,7 +219,7 @@ To take advantage of this feature, you will need to introduce your own `config/t
|
|
81
219
|
|
82
220
|
## v2.19.0
|
83
221
|
|
84
|
-
### Async::Scheduler Debugging
|
222
|
+
### `Async::Scheduler` Debugging
|
85
223
|
|
86
224
|
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.
|
87
225
|
|
data.tar.gz.sig
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
=����6���{�/�hܯ+�t��������y����%��h�AY�|�uc{��Y'����Z�<;0����E�#d&�xw�f���� �J?���5�r��S��o���R0��4��3H����yD��Ɨ<���d��h�7�~"Ê�~�?[�#�XU�+l{�
|
2
|
+
��Pz;��
|
metadata
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: async
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.28.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
8
|
+
- Shopify Inc.
|
8
9
|
- Bruno Sutic
|
9
10
|
- Jeremy Jung
|
10
11
|
- Olle Jonsson
|
@@ -13,21 +14,27 @@ authors:
|
|
13
14
|
- Emil Tin
|
14
15
|
- Jamie McCarthy
|
15
16
|
- Kent Gruber
|
17
|
+
- Alan Wu
|
16
18
|
- Brian Morearty
|
17
19
|
- Colin Kelley
|
18
20
|
- Dimitar Peychinov
|
19
21
|
- Gert Goet
|
22
|
+
- Jahfer Husain
|
23
|
+
- Jatin Goyal
|
20
24
|
- Jiang Jinyang
|
25
|
+
- Josh Teeter
|
21
26
|
- Julien Portalier
|
22
27
|
- Jun Jiang
|
23
28
|
- Ken Muryoi
|
24
29
|
- Leon Löchner
|
30
|
+
- Mark Montroy
|
25
31
|
- Masafumi Okura
|
26
32
|
- Masayuki Yamamoto
|
27
33
|
- Math Ieu
|
28
34
|
- Ryan Musgrave
|
29
35
|
- Salim Semaoune
|
30
36
|
- Shannon Skipper
|
37
|
+
- Shigeru Nakajima
|
31
38
|
- Sokolov Yura
|
32
39
|
- Stefan Wrobel
|
33
40
|
- Trevor Turk
|
@@ -62,7 +69,7 @@ cert_chain:
|
|
62
69
|
Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
|
63
70
|
voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
|
64
71
|
-----END CERTIFICATE-----
|
65
|
-
date:
|
72
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
66
73
|
dependencies:
|
67
74
|
- !ruby/object:Gem::Dependency
|
68
75
|
name: console
|
@@ -98,46 +105,54 @@ dependencies:
|
|
98
105
|
requirements:
|
99
106
|
- - "~>"
|
100
107
|
- !ruby/object:Gem::Version
|
101
|
-
version: '1.
|
108
|
+
version: '1.11'
|
102
109
|
type: :runtime
|
103
110
|
prerelease: false
|
104
111
|
version_requirements: !ruby/object:Gem::Requirement
|
105
112
|
requirements:
|
106
113
|
- - "~>"
|
107
114
|
- !ruby/object:Gem::Version
|
108
|
-
version: '1.
|
115
|
+
version: '1.11'
|
109
116
|
- !ruby/object:Gem::Dependency
|
110
|
-
name:
|
117
|
+
name: metrics
|
111
118
|
requirement: !ruby/object:Gem::Requirement
|
112
119
|
requirements:
|
113
120
|
- - "~>"
|
114
121
|
- !ruby/object:Gem::Version
|
115
|
-
version: '0.
|
122
|
+
version: '0.12'
|
116
123
|
type: :runtime
|
117
124
|
prerelease: false
|
118
125
|
version_requirements: !ruby/object:Gem::Requirement
|
119
126
|
requirements:
|
120
127
|
- - "~>"
|
121
128
|
- !ruby/object:Gem::Version
|
122
|
-
version: '0.
|
129
|
+
version: '0.12'
|
123
130
|
- !ruby/object:Gem::Dependency
|
124
|
-
name:
|
131
|
+
name: traces
|
125
132
|
requirement: !ruby/object:Gem::Requirement
|
126
133
|
requirements:
|
127
134
|
- - "~>"
|
128
135
|
- !ruby/object:Gem::Version
|
129
|
-
version: '0.
|
136
|
+
version: '0.18'
|
130
137
|
type: :runtime
|
131
138
|
prerelease: false
|
132
139
|
version_requirements: !ruby/object:Gem::Requirement
|
133
140
|
requirements:
|
134
141
|
- - "~>"
|
135
142
|
- !ruby/object:Gem::Version
|
136
|
-
version: '0.
|
143
|
+
version: '0.18'
|
137
144
|
executables: []
|
138
145
|
extensions: []
|
139
146
|
extra_rdoc_files: []
|
140
147
|
files:
|
148
|
+
- agent.md
|
149
|
+
- context/best-practices.md
|
150
|
+
- context/debugging.md
|
151
|
+
- context/getting-started.md
|
152
|
+
- context/index.yaml
|
153
|
+
- context/scheduler.md
|
154
|
+
- context/tasks.md
|
155
|
+
- context/thread-safety.md
|
141
156
|
- lib/async.rb
|
142
157
|
- lib/async/barrier.md
|
143
158
|
- lib/async/barrier.rb
|
@@ -155,14 +170,13 @@ files:
|
|
155
170
|
- lib/async/scheduler.rb
|
156
171
|
- lib/async/semaphore.md
|
157
172
|
- lib/async/semaphore.rb
|
173
|
+
- lib/async/stop.rb
|
158
174
|
- lib/async/task.md
|
159
175
|
- lib/async/task.rb
|
160
176
|
- lib/async/timeout.rb
|
161
177
|
- lib/async/variable.rb
|
162
178
|
- lib/async/version.rb
|
163
|
-
- lib/async/waiter.md
|
164
179
|
- lib/async/waiter.rb
|
165
|
-
- lib/async/worker_pool.rb
|
166
180
|
- lib/kernel/async.rb
|
167
181
|
- lib/kernel/sync.rb
|
168
182
|
- lib/metrics/provider/async.rb
|
@@ -187,14 +201,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
187
201
|
requirements:
|
188
202
|
- - ">="
|
189
203
|
- !ruby/object:Gem::Version
|
190
|
-
version: '3.
|
204
|
+
version: '3.2'
|
191
205
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
192
206
|
requirements:
|
193
207
|
- - ">="
|
194
208
|
- !ruby/object:Gem::Version
|
195
209
|
version: '0'
|
196
210
|
requirements: []
|
197
|
-
rubygems_version: 3.6.
|
211
|
+
rubygems_version: 3.6.9
|
198
212
|
specification_version: 4
|
199
213
|
summary: A concurrency framework for Ruby.
|
200
214
|
test_files: []
|
metadata.gz.sig
CHANGED
Binary file
|