async 2.44.0 → 2.45.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/getting-started.md +36 -0
- data/context/index.yaml +2 -0
- data/lib/async/condition.rb +1 -1
- data/lib/async/scheduler.rb +17 -2
- data/lib/async/version.rb +1 -1
- data/lib/kernel/async.rb +1 -1
- data/lib/kernel/sync.rb +1 -1
- data/readme.md +4 -5
- data/releases.md +4 -0
- data.tar.gz.sig +0 -0
- metadata +5 -3
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3d9408068579f9a742c20019cf9024bbc4c545c239c4c5178e929c377ac06b6c
|
|
4
|
+
data.tar.gz: 699c17d5dbff6502e1611252982c3595b7b84d57284010222462b838e683d1ac
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a40ca6a441ad341267c5782d089d512b45b36765afbdd1c6382ebb7f931e273cdf29d08ae3a446a0b624618981730c2ee69e15d39adb0956dc44fc1d2ccd2ab9
|
|
7
|
+
data.tar.gz: 325d951d894d7c2fb9cc042534e5e8d76c3edbeb81c061993204ef345af499cfd0fd71ebaae0a6fbbdfd62afdf99a859564554c9cb97dcd730111385948aebf1
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/context/getting-started.md
CHANGED
|
@@ -74,6 +74,42 @@ end
|
|
|
74
74
|
puts "The number was: #{task.wait}"
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
+
### Comparing `Async` and `Sync`
|
|
78
|
+
|
|
79
|
+
If you are familiar with JavaScript's `async`/`await`, `Async{...}` is similar to calling an asynchronous function: it starts the work and returns a promise-like {ruby Async::Task} that you can wait on later.
|
|
80
|
+
|
|
81
|
+
```ruby
|
|
82
|
+
task = Async do
|
|
83
|
+
bar
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
task.wait # Returns the value of bar.
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
This is similar to JavaScript code that keeps the promise:
|
|
90
|
+
|
|
91
|
+
```javascript
|
|
92
|
+
const promise = bar();
|
|
93
|
+
|
|
94
|
+
await promise; // Returns the value of bar.
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
`Sync{...}` is similar to immediately awaiting that work: it runs the block in an event loop and returns the block's value directly.
|
|
98
|
+
|
|
99
|
+
```ruby
|
|
100
|
+
result = Sync do
|
|
101
|
+
bar
|
|
102
|
+
end
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
This is similar to:
|
|
106
|
+
|
|
107
|
+
```javascript
|
|
108
|
+
const result = await bar();
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The main difference is that JavaScript starts with an event loop already available, while Ruby code needs one to be provided by a fiber scheduler. `Sync{...}` is the usual way to create or reuse that event loop when the caller wants a direct return value instead of a task.
|
|
112
|
+
|
|
77
113
|
## Creating a Fiber Scheduler
|
|
78
114
|
|
|
79
115
|
The first (top level) async block will also create an instance of {ruby Async::Reactor} which is a subclass of {ruby Async::Scheduler} to handle the event loop. You can also do this directly using {ruby Fiber.set_scheduler}:
|
data/context/index.yaml
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
---
|
|
4
4
|
description: A concurrency framework for Ruby.
|
|
5
5
|
metadata:
|
|
6
|
+
bug_tracker_uri: https://github.com/socketry/async/issues
|
|
7
|
+
changelog_uri: https://github.com/socketry/async/blob/main/releases.md
|
|
6
8
|
documentation_uri: https://socketry.github.io/async/
|
|
7
9
|
funding_uri: https://github.com/sponsors/ioquatix/
|
|
8
10
|
source_code_uri: https://github.com/socketry/async.git
|
data/lib/async/condition.rb
CHANGED
data/lib/async/scheduler.rb
CHANGED
|
@@ -309,10 +309,12 @@ module Async
|
|
|
309
309
|
# @parameter timeout [Float | Nil] The maximum time to wait, or if nil, indefinitely.
|
|
310
310
|
def io_wait(io, events, timeout = nil)
|
|
311
311
|
fiber = Fiber.current
|
|
312
|
+
expired = false
|
|
312
313
|
|
|
313
314
|
if timeout
|
|
314
315
|
# If an explicit timeout is specified, we expect that the user will handle it themselves:
|
|
315
316
|
timer = @timers.after(timeout) do
|
|
317
|
+
expired = true
|
|
316
318
|
fiber.transfer
|
|
317
319
|
end
|
|
318
320
|
elsif timeout = io.timeout
|
|
@@ -322,7 +324,13 @@ module Async
|
|
|
322
324
|
end
|
|
323
325
|
end
|
|
324
326
|
|
|
325
|
-
return
|
|
327
|
+
# A selector wait may return a falsy result when the fiber is resumed without the requested IO becoming ready. For example, a deferred unblock from a previous blocking operation may arrive after the fiber has moved on to this wait. Retry these stale or spurious wake-ups without resetting the original timer.
|
|
328
|
+
until result = @selector.io_wait(fiber, io, events)
|
|
329
|
+
# If the original timer resumed the fiber, the falsy result represents the timeout rather than a spurious wake-up:
|
|
330
|
+
return nil if expired
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
return result
|
|
326
334
|
ensure
|
|
327
335
|
timer&.cancel!
|
|
328
336
|
end
|
|
@@ -415,7 +423,14 @@ module Async
|
|
|
415
423
|
# @returns [Process::Status] A process status instance.
|
|
416
424
|
# @asynchronous May be non-blocking..
|
|
417
425
|
def process_wait(pid, flags)
|
|
418
|
-
|
|
426
|
+
fiber = Fiber.current
|
|
427
|
+
|
|
428
|
+
# A native process wait may be interrupted before the child exits. io-event reports this as `false` and leaves the retry policy to the scheduler. Retry only `false`, since `nil` is a legitimate result for `Process::WNOHANG`.
|
|
429
|
+
while true
|
|
430
|
+
status = @selector.process_wait(fiber, pid, flags)
|
|
431
|
+
|
|
432
|
+
return status unless status == false
|
|
433
|
+
end
|
|
419
434
|
end
|
|
420
435
|
|
|
421
436
|
# Wait for the specified IOs to become ready for the specified events.
|
data/lib/async/version.rb
CHANGED
data/lib/kernel/async.rb
CHANGED
data/lib/kernel/sync.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
|
-
# Copyright, 2019-
|
|
4
|
+
# Copyright, 2019-2026, by Samuel Williams.
|
|
5
5
|
# Copyright, 2020, by Brian Morearty.
|
|
6
6
|
# Copyright, 2024, by Patrik Wenger.
|
|
7
7
|
# Copyright, 2025-2026, by Shopify Inc.
|
data/readme.md
CHANGED
|
@@ -35,6 +35,10 @@ Please see the [project documentation](https://socketry.github.io/async/) for mo
|
|
|
35
35
|
|
|
36
36
|
Please see the [project releases](https://socketry.github.io/async/releases/index) for all releases.
|
|
37
37
|
|
|
38
|
+
### v2.45.0
|
|
39
|
+
|
|
40
|
+
- Fixed scheduler I/O and process waits returning prematurely after stale or interrupted wake-ups. I/O waits now preserve their original timeout, while blocking process waits retry and non-blocking `Process::WNOHANG` waits still return `nil`.
|
|
41
|
+
|
|
38
42
|
### v2.44.0
|
|
39
43
|
|
|
40
44
|
- Fixed scheduler cleanup after forking while other fibers are blocked.
|
|
@@ -73,11 +77,6 @@ Please see the [project releases](https://socketry.github.io/async/releases/inde
|
|
|
73
77
|
- Introduce `Async::Loop` for robust, time-aligned loops.
|
|
74
78
|
- Add support for `Async::Promise#wait(timeout: N)`.
|
|
75
79
|
|
|
76
|
-
### v2.36.0
|
|
77
|
-
|
|
78
|
-
- Introduce `Task#wait_all` which recursively waits for all children and self, excepting the current task.
|
|
79
|
-
- Introduce `Task#join` as an alias for `Task#wait` for compatibility with `Thread#join` and similar interfaces.
|
|
80
|
-
|
|
81
80
|
## See Also
|
|
82
81
|
|
|
83
82
|
- [async-http](https://github.com/socketry/async-http) — Asynchronous HTTP client/server.
|
data/releases.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Releases
|
|
2
2
|
|
|
3
|
+
## v2.45.0
|
|
4
|
+
|
|
5
|
+
- Fixed scheduler I/O and process waits returning prematurely after stale or interrupted wake-ups. I/O waits now preserve their original timeout, while blocking process waits retry and non-blocking `Process::WNOHANG` waits still return `nil`.
|
|
6
|
+
|
|
3
7
|
## v2.44.0
|
|
4
8
|
|
|
5
9
|
- Fixed scheduler cleanup after forking while other fibers are blocked.
|
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.45.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Samuel Williams
|
|
@@ -109,14 +109,14 @@ dependencies:
|
|
|
109
109
|
requirements:
|
|
110
110
|
- - "~>"
|
|
111
111
|
- !ruby/object:Gem::Version
|
|
112
|
-
version: '1.
|
|
112
|
+
version: '1.21'
|
|
113
113
|
type: :runtime
|
|
114
114
|
prerelease: false
|
|
115
115
|
version_requirements: !ruby/object:Gem::Requirement
|
|
116
116
|
requirements:
|
|
117
117
|
- - "~>"
|
|
118
118
|
- !ruby/object:Gem::Version
|
|
119
|
-
version: '1.
|
|
119
|
+
version: '1.21'
|
|
120
120
|
executables: []
|
|
121
121
|
extensions: []
|
|
122
122
|
extra_rdoc_files: []
|
|
@@ -173,6 +173,8 @@ homepage: https://github.com/socketry/async
|
|
|
173
173
|
licenses:
|
|
174
174
|
- MIT
|
|
175
175
|
metadata:
|
|
176
|
+
bug_tracker_uri: https://github.com/socketry/async/issues
|
|
177
|
+
changelog_uri: https://github.com/socketry/async/blob/main/releases.md
|
|
176
178
|
documentation_uri: https://socketry.github.io/async/
|
|
177
179
|
funding_uri: https://github.com/sponsors/ioquatix/
|
|
178
180
|
source_code_uri: https://github.com/socketry/async.git
|
metadata.gz.sig
CHANGED
|
Binary file
|