async 2.5.1 → 2.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/async/node.rb +15 -6
- data/lib/async/scheduler.rb +12 -1
- data/lib/async/task.rb +46 -6
- data/lib/async/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +17 -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: 0f62c8150ba7dba6f26532b080a4c99ecde97d86cf5f31746aec706d12644550
|
4
|
+
data.tar.gz: 99bbe4f65da2c18ab75bc67377896b7b6c26f6056eb789ef22d5601f43526228
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c6a7fee5fb6d429b7533afb80dd38ad499c8dd313ee5f881cdd19479a8f1f28072f16f07f83305f6d2e6ddaa7907859938fcd69e2fc7b0e945b194588fd22e2
|
7
|
+
data.tar.gz: f10a739ba6013c928199c4abe884e9dbf9d4d48d7f8329ed3977bb9230584d100505d617a859c113bf04c25cbf9ae4353e525221563f930227467cbaebf153b1
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/lib/async/node.rb
CHANGED
@@ -5,6 +5,8 @@
|
|
5
5
|
# Copyright, 2017, by Kent Gruber.
|
6
6
|
# Copyright, 2022, by Shannon Skipper.
|
7
7
|
|
8
|
+
require 'fiber/annotation'
|
9
|
+
|
8
10
|
require_relative 'list'
|
9
11
|
|
10
12
|
module Async
|
@@ -109,20 +111,27 @@ module Async
|
|
109
111
|
|
110
112
|
def annotate(annotation)
|
111
113
|
if block_given?
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
114
|
+
begin
|
115
|
+
current_annotation = @annotation
|
116
|
+
@annotation = annotation
|
117
|
+
return yield
|
118
|
+
ensure
|
119
|
+
@annotation = current_annotation
|
120
|
+
end
|
116
121
|
else
|
117
122
|
@annotation = annotation
|
118
123
|
end
|
119
124
|
end
|
120
125
|
|
126
|
+
def annotation
|
127
|
+
@annotation
|
128
|
+
end
|
129
|
+
|
121
130
|
def description
|
122
131
|
@object_name ||= "#{self.class}:#{format '%#018x', object_id}#{@transient ? ' transient' : nil}"
|
123
132
|
|
124
|
-
if
|
125
|
-
"#{@object_name} #{
|
133
|
+
if annotation = self.annotation
|
134
|
+
"#{@object_name} #{annotation}"
|
126
135
|
elsif line = self.backtrace(0, 1)&.first
|
127
136
|
"#{@object_name} #{line}"
|
128
137
|
else
|
data/lib/async/scheduler.rb
CHANGED
@@ -17,6 +17,12 @@ require 'resolv'
|
|
17
17
|
module Async
|
18
18
|
# Handles scheduling of fibers. Implements the fiber scheduler interface.
|
19
19
|
class Scheduler < Node
|
20
|
+
class ClosedError < RuntimeError
|
21
|
+
def initialize(message = "Scheduler is closed!")
|
22
|
+
super
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
20
26
|
# Whether the fiber scheduler is supported.
|
21
27
|
# @public Since `stable-v1`.
|
22
28
|
def self.supported?
|
@@ -150,6 +156,9 @@ module Async
|
|
150
156
|
|
151
157
|
# @asynchronous May be non-blocking..
|
152
158
|
def address_resolve(hostname)
|
159
|
+
# On some platforms, hostnames may contain a device-specific suffix (e.g. %en0). We need to strip this before resolving.
|
160
|
+
# See <https://github.com/socketry/async/issues/180> for more details.
|
161
|
+
hostname = hostname.split("%", 2).first
|
153
162
|
::Resolv.getaddresses(hostname)
|
154
163
|
end
|
155
164
|
|
@@ -233,7 +242,7 @@ module Async
|
|
233
242
|
|
234
243
|
# Run the reactor until all tasks are finished. Proxies arguments to {#async} immediately before entering the loop, if a block is provided.
|
235
244
|
def run(...)
|
236
|
-
Kernel::raise
|
245
|
+
Kernel::raise ClosedError if @selector.nil?
|
237
246
|
|
238
247
|
initial_task = self.async(...) if block_given?
|
239
248
|
|
@@ -260,6 +269,8 @@ module Async
|
|
260
269
|
# @returns [Task] The task that was scheduled into the reactor.
|
261
270
|
# @deprecated With no replacement.
|
262
271
|
def async(*arguments, **options, &block)
|
272
|
+
Kernel::raise ClosedError if @selector.nil?
|
273
|
+
|
263
274
|
task = Task.new(Task.current? || self, **options, &block)
|
264
275
|
|
265
276
|
# I want to take a moment to explain the logic of this.
|
data/lib/async/task.rb
CHANGED
@@ -59,6 +59,12 @@ module Async
|
|
59
59
|
#
|
60
60
|
# @public Since `stable-v1`.
|
61
61
|
class Task < Node
|
62
|
+
class FinishedError < RuntimeError
|
63
|
+
def initialize(message = "Cannot create child task within a task that has finished execution!")
|
64
|
+
super
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
62
68
|
# @deprecated With no replacement.
|
63
69
|
def self.yield
|
64
70
|
Fiber.scheduler.transfer
|
@@ -90,6 +96,22 @@ module Async
|
|
90
96
|
@fiber&.backtrace(*arguments)
|
91
97
|
end
|
92
98
|
|
99
|
+
def annotate(annotation, &block)
|
100
|
+
if @fiber
|
101
|
+
@fiber.annotate(annotation, &block)
|
102
|
+
else
|
103
|
+
super
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def annotation
|
108
|
+
if @fiber
|
109
|
+
@fiber.annotation
|
110
|
+
else
|
111
|
+
super
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
93
115
|
def to_s
|
94
116
|
"\#<#{self.description} (#{@status})>"
|
95
117
|
end
|
@@ -164,7 +186,7 @@ module Async
|
|
164
186
|
|
165
187
|
# Run an asynchronous task as a child of the current task.
|
166
188
|
def async(*arguments, **options, &block)
|
167
|
-
raise
|
189
|
+
raise FinishedError if self.finished?
|
168
190
|
|
169
191
|
task = Task.new(self, **options, &block)
|
170
192
|
|
@@ -199,6 +221,10 @@ module Async
|
|
199
221
|
attr :result
|
200
222
|
|
201
223
|
# Stop the task and all of its children.
|
224
|
+
#
|
225
|
+
# 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.
|
226
|
+
#
|
227
|
+
# @parameter later [Boolean] Whether to stop the task later, or immediately.
|
202
228
|
def stop(later = false)
|
203
229
|
if self.stopped?
|
204
230
|
# If we already stopped this task... don't try to stop it again:
|
@@ -208,6 +234,7 @@ module Async
|
|
208
234
|
# If the fiber is alive, we need to stop it:
|
209
235
|
if @fiber&.alive?
|
210
236
|
if self.current?
|
237
|
+
# 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`:
|
211
238
|
if later
|
212
239
|
# If the fiber is the current fiber and we want to stop it later, schedule it:
|
213
240
|
Fiber.scheduler.push(Stop::Later.new(self))
|
@@ -218,6 +245,7 @@ module Async
|
|
218
245
|
else
|
219
246
|
# If the fiber is not curent, we can raise the exception directly:
|
220
247
|
begin
|
248
|
+
# 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.
|
221
249
|
Fiber.scheduler.raise(@fiber, Stop)
|
222
250
|
rescue FiberError
|
223
251
|
# In some cases, this can cause a FiberError (it might be resumed already), so we schedule it to be stopped later:
|
@@ -244,7 +272,7 @@ module Async
|
|
244
272
|
end
|
245
273
|
|
246
274
|
def current?
|
247
|
-
|
275
|
+
Fiber.current.equal?(@fiber)
|
248
276
|
end
|
249
277
|
|
250
278
|
private
|
@@ -289,11 +317,23 @@ module Async
|
|
289
317
|
end
|
290
318
|
|
291
319
|
def stopped!
|
292
|
-
# Console.logger.info(self,
|
320
|
+
# Console.logger.info(self, status:) {"Task #{self} was stopped with #{@children&.size.inspect} children!"}
|
293
321
|
@status = :stopped
|
294
322
|
|
295
|
-
|
296
|
-
|
323
|
+
stopped = false
|
324
|
+
|
325
|
+
begin
|
326
|
+
# We are bnot running, but children might be so we should stop them:
|
327
|
+
stop_children(true)
|
328
|
+
rescue Stop
|
329
|
+
stopped = true
|
330
|
+
# If we are stopping children, and one of them tries to stop the current task, we should ignore it. We will be stopped later.
|
331
|
+
retry
|
332
|
+
end
|
333
|
+
|
334
|
+
if stopped
|
335
|
+
raise Stop, "Stopping current task!"
|
336
|
+
end
|
297
337
|
end
|
298
338
|
|
299
339
|
def stop!
|
@@ -303,7 +343,7 @@ module Async
|
|
303
343
|
end
|
304
344
|
|
305
345
|
def schedule(&block)
|
306
|
-
@fiber = Fiber.new do
|
346
|
+
@fiber = Fiber.new(annotation: self.annotation) do
|
307
347
|
set!
|
308
348
|
|
309
349
|
begin
|
data/lib/async/version.rb
CHANGED
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.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
@@ -56,7 +56,7 @@ cert_chain:
|
|
56
56
|
Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
|
57
57
|
voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
|
58
58
|
-----END CERTIFICATE-----
|
59
|
-
date: 2023-
|
59
|
+
date: 2023-06-07 00:00:00.000000000 Z
|
60
60
|
dependencies:
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
62
|
name: console
|
@@ -100,6 +100,20 @@ dependencies:
|
|
100
100
|
- - "~>"
|
101
101
|
- !ruby/object:Gem::Version
|
102
102
|
version: '4.1'
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: fiber-annotation
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
type: :runtime
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
103
117
|
- !ruby/object:Gem::Dependency
|
104
118
|
name: bake-test
|
105
119
|
requirement: !ruby/object:Gem::Requirement
|
@@ -247,7 +261,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
247
261
|
- !ruby/object:Gem::Version
|
248
262
|
version: '0'
|
249
263
|
requirements: []
|
250
|
-
rubygems_version: 3.
|
264
|
+
rubygems_version: 3.4.7
|
251
265
|
signing_key:
|
252
266
|
specification_version: 4
|
253
267
|
summary: A concurrency framework for Ruby.
|
metadata.gz.sig
CHANGED
Binary file
|