async 2.14.2 → 2.23.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/lib/async/barrier.md +1 -1
- data/lib/async/barrier.rb +5 -5
- data/lib/async/clock.rb +10 -1
- data/lib/async/condition.md +1 -1
- data/lib/async/condition.rb +4 -4
- data/lib/async/console.rb +42 -0
- data/lib/async/idler.rb +4 -2
- data/lib/async/limited_queue.rb +7 -0
- data/lib/async/list.rb +1 -1
- data/lib/async/node.rb +29 -3
- data/lib/async/notification.rb +3 -3
- data/lib/async/queue.rb +17 -7
- data/lib/async/reactor.rb +2 -2
- data/lib/async/scheduler.rb +202 -75
- data/lib/async/semaphore.rb +3 -3
- data/lib/async/task.rb +59 -24
- data/lib/async/variable.rb +11 -6
- data/lib/async/version.rb +1 -1
- data/lib/async/waiter.rb +2 -1
- data/lib/async/worker_pool.rb +182 -0
- data/lib/async/wrapper.rb +3 -1
- data/lib/async.rb +1 -1
- data/lib/kernel/async.rb +4 -2
- data/lib/kernel/sync.rb +12 -5
- data/lib/metrics/provider/async/task.rb +20 -0
- data/lib/metrics/provider/async.rb +6 -0
- data/lib/traces/provider/async/barrier.rb +17 -0
- data/lib/traces/provider/async/task.rb +40 -0
- data/lib/traces/provider/async.rb +7 -0
- data/license.md +2 -1
- data/readme.md +46 -12
- data/releases.md +121 -0
- data.tar.gz.sig +0 -0
- metadata +45 -24
- 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: 36ac96ecf26e32e4804f8e89909dcb7b5f8cdfbed24a4da1a189d027586bd0b1
|
4
|
+
data.tar.gz: 35fb378abd8183a2a4950a2b57fd4ba6360c740b51a12ff3e67af5a2c443583c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5ff90e092ac86b1dd3e5991e48d44d2b6a9abaa1b72d785d3e9419630f3f8fadd241ab21837bbd5ddd4038792e3ac970bf2aa4b2f67f5a473d4be1caa067f1d5
|
7
|
+
data.tar.gz: 5b71b8eae39aee81b3918f1012c76a4306529292626bf6dc95e79ecebcfa53cda304840655eee56c3392b5a912478ff3178ab4624a2f519ad02d6ce70098f1e2
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/lib/async/barrier.md
CHANGED
data/lib/async/barrier.rb
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2019-
|
4
|
+
# Copyright, 2019-2024, by Samuel Williams.
|
5
5
|
|
6
|
-
require_relative
|
7
|
-
require_relative
|
6
|
+
require_relative "list"
|
7
|
+
require_relative "task"
|
8
8
|
|
9
9
|
module Async
|
10
10
|
# A general purpose synchronisation primitive, which allows one task to wait for a number of other tasks to complete. It can be used in conjunction with {Semaphore}.
|
11
11
|
#
|
12
|
-
# @public Since
|
12
|
+
# @public Since *Async v1*.
|
13
13
|
class Barrier
|
14
14
|
# Initialize the barrier.
|
15
15
|
# @parameter parent [Task | Semaphore | Nil] The parent for holding any children tasks.
|
16
|
-
# @public Since
|
16
|
+
# @public Since *Async v1*.
|
17
17
|
def initialize(parent: nil)
|
18
18
|
@tasks = List.new
|
19
19
|
|
data/lib/async/clock.rb
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
module Async
|
7
7
|
# A convenient wrapper around the internal monotonic clock.
|
8
|
-
# @public Since
|
8
|
+
# @public Since *Async v1*.
|
9
9
|
class Clock
|
10
10
|
# Get the current elapsed monotonic time.
|
11
11
|
def self.now
|
@@ -61,5 +61,14 @@ module Async
|
|
61
61
|
|
62
62
|
return total
|
63
63
|
end
|
64
|
+
|
65
|
+
# Reset the total elapsed time. If the clock is currently running, reset the start time to now.
|
66
|
+
def reset!
|
67
|
+
@total = 0
|
68
|
+
|
69
|
+
if @started
|
70
|
+
@started = Clock.now
|
71
|
+
end
|
72
|
+
end
|
64
73
|
end
|
65
74
|
end
|
data/lib/async/condition.md
CHANGED
data/lib/async/condition.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2017-
|
4
|
+
# Copyright, 2017-2024, by Samuel Williams.
|
5
5
|
# Copyright, 2017, by Kent Gruber.
|
6
6
|
|
7
|
-
require
|
8
|
-
require_relative
|
7
|
+
require "fiber"
|
8
|
+
require_relative "list"
|
9
9
|
|
10
10
|
module Async
|
11
11
|
# A synchronization primitive, which allows fibers to wait until a particular condition is (edge) triggered.
|
12
|
-
# @public Since
|
12
|
+
# @public Since *Async v1*.
|
13
13
|
class Condition
|
14
14
|
# Create a new condition.
|
15
15
|
def initialize
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2024, by Samuel Williams.
|
5
|
+
|
6
|
+
module Async
|
7
|
+
# Shims for the console gem, redirecting warnings and above to `Kernel#warn`.
|
8
|
+
#
|
9
|
+
# If you require this file, the `async` library will not depend on the `console` gem.
|
10
|
+
#
|
11
|
+
# That includes any gems that sit within the `Async` namespace.
|
12
|
+
#
|
13
|
+
# This is an experimental feature.
|
14
|
+
module Console
|
15
|
+
# Log a message at the debug level. The shim is silent.
|
16
|
+
def self.debug(...)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Log a message at the info level. The shim is silent.
|
20
|
+
def self.info(...)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Log a message at the warn level. The shim redirects to `Kernel#warn`.
|
24
|
+
def self.warn(*arguments, exception: nil, **options)
|
25
|
+
if exception
|
26
|
+
super(*arguments, exception.full_message, **options)
|
27
|
+
else
|
28
|
+
super(*arguments, **options)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Log a message at the error level. The shim redirects to `Kernel#warn`.
|
33
|
+
def self.error(...)
|
34
|
+
self.warn(...)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Log a message at the fatal level. The shim redirects to `Kernel#warn`.
|
38
|
+
def self.fatal(...)
|
39
|
+
self.warn(...)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/async/idler.rb
CHANGED
@@ -7,7 +7,8 @@ module Async
|
|
7
7
|
# A load balancing mechanism that can be used process work when the system is idle.
|
8
8
|
class Idler
|
9
9
|
# Create a new idler.
|
10
|
-
#
|
10
|
+
#
|
11
|
+
# @public Since *Async v2*.
|
11
12
|
#
|
12
13
|
# @parameter maximum_load [Numeric] The maximum load before we start shedding work.
|
13
14
|
# @parameter backoff [Numeric] The initial backoff time, used for delaying work.
|
@@ -41,7 +42,8 @@ module Async
|
|
41
42
|
backoff = nil
|
42
43
|
|
43
44
|
while true
|
44
|
-
load = scheduler.load
|
45
|
+
load = scheduler.load
|
46
|
+
|
45
47
|
break if load < @maximum_load
|
46
48
|
|
47
49
|
if backoff
|
data/lib/async/list.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2022, by Samuel Williams.
|
4
|
+
# Copyright, 2022-2024, by Samuel Williams.
|
5
5
|
|
6
6
|
module Async
|
7
7
|
# A general doublely linked list. This is used internally by {Async::Barrier} and {Async::Condition} to manage child tasks.
|
data/lib/async/node.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2017-
|
4
|
+
# Copyright, 2017-2024, by Samuel Williams.
|
5
5
|
# Copyright, 2017, by Kent Gruber.
|
6
6
|
# Copyright, 2022, by Shannon Skipper.
|
7
7
|
|
8
|
-
require
|
8
|
+
require "fiber/annotation"
|
9
9
|
|
10
|
-
require_relative
|
10
|
+
require_relative "list"
|
11
11
|
|
12
12
|
module Async
|
13
13
|
# A list of children tasks.
|
@@ -34,6 +34,19 @@ module Async
|
|
34
34
|
empty?
|
35
35
|
end
|
36
36
|
|
37
|
+
# Adjust the number of transient children, assuming it has changed.
|
38
|
+
#
|
39
|
+
# Despite being public, this is not intended to be called directly. It is used internally by {Node#transient=}.
|
40
|
+
#
|
41
|
+
# @parameter transient [Boolean] Whether to increment or decrement the transient count.
|
42
|
+
def adjust_transient_count(transient)
|
43
|
+
if transient
|
44
|
+
@transient_count += 1
|
45
|
+
else
|
46
|
+
@transient_count -= 1
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
37
50
|
private
|
38
51
|
|
39
52
|
def added(node)
|
@@ -110,6 +123,19 @@ module Async
|
|
110
123
|
@transient
|
111
124
|
end
|
112
125
|
|
126
|
+
# Change the transient state of the node.
|
127
|
+
#
|
128
|
+
# A transient node is not considered when determining if a node is finished, and propagates up if the parent is consumed.
|
129
|
+
#
|
130
|
+
# @parameter value [Boolean] Whether the node is transient.
|
131
|
+
def transient=(value)
|
132
|
+
if @transient != value
|
133
|
+
@transient = value
|
134
|
+
|
135
|
+
@parent&.children&.adjust_transient_count(value)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
113
139
|
# Annotate the node with a description.
|
114
140
|
#
|
115
141
|
# @parameter annotation [String] The description to annotate the node with.
|
data/lib/async/notification.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2018-
|
4
|
+
# Copyright, 2018-2024, by Samuel Williams.
|
5
5
|
|
6
|
-
require_relative
|
6
|
+
require_relative "condition"
|
7
7
|
|
8
8
|
module Async
|
9
9
|
# A synchronization primitive, which allows fibers to wait until a notification is received. Does not block the task which signals the notification. Waiting tasks are resumed on next iteration of the reactor.
|
10
|
-
# @public Since
|
10
|
+
# @public Since *Async v1*.
|
11
11
|
class Notification < Condition
|
12
12
|
# Signal to a given task that it should resume operations.
|
13
13
|
def signal(value = nil, task: Task.current)
|
data/lib/async/queue.rb
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2018-
|
4
|
+
# Copyright, 2018-2024, by Samuel Williams.
|
5
5
|
# Copyright, 2019, by Ryan Musgrave.
|
6
6
|
# Copyright, 2020-2022, by Bruno Sutic.
|
7
7
|
|
8
|
-
require_relative
|
8
|
+
require_relative "notification"
|
9
9
|
|
10
10
|
module Async
|
11
11
|
# A queue which allows items to be processed in order.
|
12
12
|
#
|
13
13
|
# It has a compatible interface with {Notification} and {Condition}, except that it's multi-value.
|
14
14
|
#
|
15
|
-
# @public Since
|
15
|
+
# @public Since *Async v1*.
|
16
16
|
class Queue
|
17
17
|
# Create a new queue.
|
18
18
|
#
|
@@ -38,12 +38,17 @@ module Async
|
|
38
38
|
end
|
39
39
|
|
40
40
|
# Add an item to the queue.
|
41
|
-
def
|
41
|
+
def push(item)
|
42
42
|
@items << item
|
43
43
|
|
44
44
|
@available.signal unless self.empty?
|
45
45
|
end
|
46
46
|
|
47
|
+
# Compatibility with {::Queue#push}.
|
48
|
+
def <<(item)
|
49
|
+
self.push(item)
|
50
|
+
end
|
51
|
+
|
47
52
|
# Add multiple items to the queue.
|
48
53
|
def enqueue(*items)
|
49
54
|
@items.concat(items)
|
@@ -60,6 +65,11 @@ module Async
|
|
60
65
|
@items.shift
|
61
66
|
end
|
62
67
|
|
68
|
+
# Compatibility with {::Queue#pop}.
|
69
|
+
def pop
|
70
|
+
self.dequeue
|
71
|
+
end
|
72
|
+
|
63
73
|
# Process each item in the queue.
|
64
74
|
#
|
65
75
|
# @asynchronous Executes the given block concurrently for each item.
|
@@ -82,7 +92,7 @@ module Async
|
|
82
92
|
end
|
83
93
|
|
84
94
|
# Signal the queue with a value, the same as {#enqueue}.
|
85
|
-
def signal(value)
|
95
|
+
def signal(value = nil)
|
86
96
|
self.enqueue(value)
|
87
97
|
end
|
88
98
|
|
@@ -93,7 +103,7 @@ module Async
|
|
93
103
|
end
|
94
104
|
|
95
105
|
# A queue which limits the number of items that can be enqueued.
|
96
|
-
# @public Since
|
106
|
+
# @public Since *Async v1*.
|
97
107
|
class LimitedQueue < Queue
|
98
108
|
# Create a new limited queue.
|
99
109
|
#
|
@@ -119,7 +129,7 @@ module Async
|
|
119
129
|
# If the queue is full, this method will block until there is space available.
|
120
130
|
#
|
121
131
|
# @parameter item [Object] The item to add to the queue.
|
122
|
-
def
|
132
|
+
def push(item)
|
123
133
|
while limited?
|
124
134
|
@full.wait
|
125
135
|
end
|
data/lib/async/reactor.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2017-
|
4
|
+
# Copyright, 2017-2024, by Samuel Williams.
|
5
5
|
# Copyright, 2017, by Kent Gruber.
|
6
6
|
# Copyright, 2018, by Sokolov Yura.
|
7
7
|
|
8
|
-
require_relative
|
8
|
+
require_relative "scheduler"
|
9
9
|
|
10
10
|
module Async
|
11
11
|
# A wrapper around the the scheduler which binds it to the current thread automatically.
|