async 1.24.2 → 1.25.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/development.yml +55 -0
- data/README.md +1 -1
- data/Rakefile +2 -0
- data/async.gemspec +16 -18
- data/bake.rb +33 -0
- data/lib/async.rb +2 -1
- data/lib/async/node.rb +46 -9
- data/lib/async/reactor.rb +9 -10
- data/lib/async/task.rb +2 -2
- data/lib/async/version.rb +1 -1
- data/lib/kernel/sync.rb +1 -1
- data/spec/async/barrier_spec.rb +1 -1
- data/spec/async/clock_spec.rb +1 -1
- data/spec/async/node_spec.rb +78 -1
- data/spec/async/task_spec.rb +9 -3
- data/spec/kernel/sync_spec.rb +6 -3
- data/spec/spec_helper.rb +6 -0
- metadata +9 -10
- data/.github/workflows/tests.yml +0 -37
- data/.travis.yml +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0e483e124943c2ca198118249cfd157307afd86a6e9ead4b376be27ffc95b645
|
4
|
+
data.tar.gz: c460b159f280389b26237c41fd20bac56d9e5b2c525f884402f6170b85fd5053
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 482ff867811aa68736b37a50d83e5850f4a1f9a310274b8993898c5577136e7502f5c369a3c9bf4685380b88a71de2ff4ed04fbd92115e8918472522e92786ea
|
7
|
+
data.tar.gz: 37584a2af7140b2a4efa0fb60879e97ddae99879f97b137add7fb62662139300e280a9126cf24f559172ecb7ba1f2a6c21eb77adc317df9ae54f9ddb8378f928
|
@@ -0,0 +1,55 @@
|
|
1
|
+
name: Development
|
2
|
+
|
3
|
+
on: [push, pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
test:
|
7
|
+
runs-on: ${{matrix.os}}-latest
|
8
|
+
continue-on-error: ${{matrix.experimental}}
|
9
|
+
|
10
|
+
strategy:
|
11
|
+
matrix:
|
12
|
+
experimental: [false]
|
13
|
+
|
14
|
+
os:
|
15
|
+
- ubuntu
|
16
|
+
- macos
|
17
|
+
|
18
|
+
ruby:
|
19
|
+
- 2.5
|
20
|
+
- 2.6
|
21
|
+
- 2.7
|
22
|
+
|
23
|
+
include:
|
24
|
+
- experimental: true
|
25
|
+
os: ubuntu
|
26
|
+
ruby: truffleruby
|
27
|
+
env: JRUBY_OPTS="--debug -X+O"
|
28
|
+
- experimental: true
|
29
|
+
os: ubuntu
|
30
|
+
ruby: jruby
|
31
|
+
- experimental: true
|
32
|
+
os: ubuntu
|
33
|
+
ruby: head
|
34
|
+
- experimental: true
|
35
|
+
os: ubuntu
|
36
|
+
ruby: 2.6
|
37
|
+
env: COVERAGE=PartialSummary,Coveralls
|
38
|
+
|
39
|
+
steps:
|
40
|
+
- uses: actions/checkout@v1
|
41
|
+
- uses: ruby/setup-ruby@v1
|
42
|
+
with:
|
43
|
+
ruby-version: ${{matrix.ruby}}
|
44
|
+
|
45
|
+
- name: Install dependencies
|
46
|
+
run: ${{matrix.env}} bundle install
|
47
|
+
|
48
|
+
- name: Run tests
|
49
|
+
timeout-minutes: 5
|
50
|
+
run: ${{matrix.env}} bundle exec rspec
|
51
|
+
|
52
|
+
- name: Run external tests
|
53
|
+
timeout-minutes: 5
|
54
|
+
if: matrix.experimental == false && matrix.os == 'ubuntu'
|
55
|
+
run: ${{matrix.env}} bundle exec bake external
|
data/README.md
CHANGED
@@ -5,7 +5,7 @@ Async is a composable asynchronous I/O framework for Ruby based on [nio4r] and [
|
|
5
5
|
[timers]: https://github.com/socketry/timers
|
6
6
|
[nio4r]: https://github.com/socketry/nio4r
|
7
7
|
|
8
|
-
[![
|
8
|
+
[![Actions Status](https://github.com/socketry/async/workflows/Development/badge.svg)](https://github.com/socketry/async/actions?workflow=Development)
|
9
9
|
[![Code Climate](https://codeclimate.com/github/socketry/async.svg)](https://codeclimate.com/github/socketry/async)
|
10
10
|
[![Coverage Status](https://coveralls.io/repos/socketry/async/badge.svg)](https://coveralls.io/r/socketry/async)
|
11
11
|
[![Gitter](https://badges.gitter.im/join.svg)](https://gitter.im/socketry/async)
|
data/Rakefile
CHANGED
@@ -15,6 +15,8 @@ def clone_and_test(name)
|
|
15
15
|
sh("git clone https://git@github.com/socketry/#{name} #{path}")
|
16
16
|
|
17
17
|
# I tried using `bundle config --local local.async ../` but it simply doesn't work.
|
18
|
+
# system("bundle", "config", "--local", "local.async", __dir__, chdir: path)
|
19
|
+
|
18
20
|
File.open("#{path}/Gemfile", "a") do |file|
|
19
21
|
file.puts('gem "async", path: "../../"')
|
20
22
|
end
|
data/async.gemspec
CHANGED
@@ -2,25 +2,24 @@
|
|
2
2
|
require_relative 'lib/async/version'
|
3
3
|
|
4
4
|
Gem::Specification.new do |spec|
|
5
|
-
spec.name
|
6
|
-
spec.version
|
7
|
-
spec.authors
|
8
|
-
spec.email
|
9
|
-
spec.description
|
10
|
-
Async
|
11
|
-
|
12
|
-
based events.
|
5
|
+
spec.name = "async"
|
6
|
+
spec.version = Async::VERSION
|
7
|
+
spec.authors = ["Samuel Williams"]
|
8
|
+
spec.email = ["samuel.williams@oriontransfer.co.nz"]
|
9
|
+
spec.description = <<-EOF
|
10
|
+
Async is a modern concurrency framework for Ruby. It implements the
|
11
|
+
reactor pattern, providing both non-blocking I/O and timer events.
|
13
12
|
EOF
|
14
|
-
spec.summary
|
15
|
-
spec.homepage
|
16
|
-
spec.license
|
17
|
-
|
18
|
-
spec.files
|
19
|
-
spec.executables
|
20
|
-
spec.test_files
|
13
|
+
spec.summary = "Async is an concurrency framework based for Ruby."
|
14
|
+
spec.homepage = "https://github.com/socketry/async"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files`.split($/)
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
20
|
spec.require_paths = ["lib"]
|
22
21
|
|
23
|
-
spec.required_ruby_version = ">= 2.
|
22
|
+
spec.required_ruby_version = ">= 2.5.0"
|
24
23
|
|
25
24
|
spec.add_runtime_dependency "nio4r", "~> 2.3"
|
26
25
|
spec.add_runtime_dependency "timers", "~> 4.1"
|
@@ -29,8 +28,7 @@ Gem::Specification.new do |spec|
|
|
29
28
|
spec.add_development_dependency "async-rspec", "~> 1.1"
|
30
29
|
|
31
30
|
spec.add_development_dependency "covered", "~> 0.10"
|
32
|
-
|
33
31
|
spec.add_development_dependency "bundler"
|
34
32
|
spec.add_development_dependency "rspec", "~> 3.6"
|
35
|
-
spec.add_development_dependency "
|
33
|
+
spec.add_development_dependency "bake-bundler"
|
36
34
|
end
|
data/bake.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
def external
|
4
|
+
require 'bundler'
|
5
|
+
|
6
|
+
Bundler.with_clean_env do
|
7
|
+
clone_and_test("async-io")
|
8
|
+
clone_and_test("async-websocket")
|
9
|
+
clone_and_test("async-dns")
|
10
|
+
clone_and_test("async-http")
|
11
|
+
clone_and_test("falcon")
|
12
|
+
clone_and_test("async-rest")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def clone_and_test(name)
|
19
|
+
path = "external/#{name}"
|
20
|
+
FileUtils.rm_rf path
|
21
|
+
FileUtils.mkdir_p path
|
22
|
+
|
23
|
+
system("git clone https://git@github.com/socketry/#{name} #{path}")
|
24
|
+
|
25
|
+
# I tried using `bundle config --local local.async ../` but it simply doesn't work.
|
26
|
+
# system("bundle", "config", "--local", "local.async", __dir__, chdir: path)
|
27
|
+
|
28
|
+
File.open("#{path}/Gemfile", "a") do |file|
|
29
|
+
file.puts('gem "async", path: "../../"')
|
30
|
+
end
|
31
|
+
|
32
|
+
system("cd #{path} && bundle install && bundle exec rspec")
|
33
|
+
end
|
data/lib/async.rb
CHANGED
@@ -25,10 +25,11 @@ require_relative "async/logger"
|
|
25
25
|
require_relative "async/reactor"
|
26
26
|
|
27
27
|
require_relative "kernel/async"
|
28
|
+
require_relative "kernel/sync"
|
28
29
|
|
29
30
|
module Async
|
30
31
|
# Invoke `Reactor.run` with all arguments/block.
|
31
32
|
def self.run(*arguments, &block)
|
32
33
|
Reactor.run(*arguments, &block)
|
33
34
|
end
|
34
|
-
end
|
35
|
+
end
|
data/lib/async/node.rb
CHANGED
@@ -27,13 +27,18 @@ module Async
|
|
27
27
|
class Node
|
28
28
|
# Create a new node in the tree.
|
29
29
|
# @param parent [Node, nil] This node will attach to the given parent.
|
30
|
-
def initialize(parent = nil)
|
30
|
+
def initialize(parent = nil, annotation: nil, transient: false)
|
31
31
|
@children = nil
|
32
32
|
@parent = nil
|
33
33
|
|
34
|
-
|
34
|
+
# The number of transient children:
|
35
|
+
@transients = 0
|
36
|
+
|
37
|
+
@annotation = annotation
|
35
38
|
@object_name = nil
|
36
39
|
|
40
|
+
@transient = transient
|
41
|
+
|
37
42
|
if parent
|
38
43
|
self.parent = parent
|
39
44
|
end
|
@@ -48,6 +53,16 @@ module Async
|
|
48
53
|
# A useful identifier for the current node.
|
49
54
|
attr :annotation
|
50
55
|
|
56
|
+
# Is this node transient?
|
57
|
+
def transient?
|
58
|
+
@transient
|
59
|
+
end
|
60
|
+
|
61
|
+
# Does this node have (direct) transient children?
|
62
|
+
def transients?
|
63
|
+
@transients > 0
|
64
|
+
end
|
65
|
+
|
51
66
|
def annotate(annotation)
|
52
67
|
if block_given?
|
53
68
|
previous_annotation = @annotation
|
@@ -60,7 +75,7 @@ module Async
|
|
60
75
|
end
|
61
76
|
|
62
77
|
def description
|
63
|
-
@object_name ||= "#{self.class}:0x#{object_id.to_s(16)}"
|
78
|
+
@object_name ||= "#{self.class}:0x#{object_id.to_s(16)}#{@transient ? ' transient' : nil}"
|
64
79
|
|
65
80
|
if @annotation
|
66
81
|
"#{@object_name} #{@annotation}"
|
@@ -73,10 +88,6 @@ module Async
|
|
73
88
|
"\#<#{description}>"
|
74
89
|
end
|
75
90
|
|
76
|
-
def inspect
|
77
|
-
to_s
|
78
|
-
end
|
79
|
-
|
80
91
|
# Change the parent of this node.
|
81
92
|
# @param parent [Node, nil] the parent to attach to, or nil to detach.
|
82
93
|
# @return [self]
|
@@ -96,23 +107,36 @@ module Async
|
|
96
107
|
return self
|
97
108
|
end
|
98
109
|
|
110
|
+
protected def set_parent parent
|
111
|
+
@parent = parent
|
112
|
+
end
|
113
|
+
|
99
114
|
protected def add_child child
|
100
115
|
@children ||= Set.new
|
101
116
|
@children << child
|
117
|
+
|
118
|
+
if child.transient?
|
119
|
+
@transients += 1
|
120
|
+
end
|
102
121
|
end
|
103
122
|
|
104
123
|
# Whether the node can be consumed safely. By default, checks if the
|
105
124
|
# children set is empty.
|
106
125
|
# @return [Boolean]
|
107
126
|
def finished?
|
108
|
-
@children.nil?
|
127
|
+
@children.nil? || @children.empty? || (@children.size == @transients)
|
109
128
|
end
|
110
129
|
|
111
130
|
# If the node has a parent, and is {finished?}, then remove this node from
|
112
131
|
# the parent.
|
113
132
|
def consume
|
114
|
-
if @parent
|
133
|
+
if @parent && finished?
|
115
134
|
@parent.reap(self)
|
135
|
+
|
136
|
+
# After reaping self, children are all moved elsewhere.
|
137
|
+
@children = nil
|
138
|
+
@transients = 0
|
139
|
+
|
116
140
|
@parent.consume
|
117
141
|
@parent = nil
|
118
142
|
end
|
@@ -122,6 +146,19 @@ module Async
|
|
122
146
|
# @param child [Node]
|
123
147
|
def reap(child)
|
124
148
|
@children.delete(child)
|
149
|
+
|
150
|
+
if child.transient?
|
151
|
+
@transients -= 1
|
152
|
+
end
|
153
|
+
|
154
|
+
child.children&.each do |grand_child|
|
155
|
+
if grand_child.finished?
|
156
|
+
grand_child.set_parent(nil)
|
157
|
+
else
|
158
|
+
grand_child.set_parent(self)
|
159
|
+
add_child(grand_child)
|
160
|
+
end
|
161
|
+
end
|
125
162
|
end
|
126
163
|
|
127
164
|
# Traverse the tree.
|
data/lib/async/reactor.rb
CHANGED
@@ -164,7 +164,7 @@ module Async
|
|
164
164
|
# @param timeout [Float | nil] the maximum timeout, or if nil, indefinite.
|
165
165
|
# @return [Boolean] whether there is more work to do.
|
166
166
|
def run_once(timeout = nil)
|
167
|
-
logger.debug(self) {"@ready = #{@ready} @running = #{@running}"}
|
167
|
+
# logger.debug(self) {"@ready = #{@ready} @running = #{@running}"}
|
168
168
|
|
169
169
|
if @ready.any?
|
170
170
|
# running used to correctly answer on `finished?`, and to reuse Array object.
|
@@ -184,13 +184,13 @@ module Async
|
|
184
184
|
interval = 0
|
185
185
|
end
|
186
186
|
|
187
|
+
# If we are finished, we stop the task tree and exit:
|
188
|
+
if self.finished?
|
189
|
+
return false
|
190
|
+
end
|
191
|
+
|
187
192
|
# If there is no interval to wait (thus no timers), and no tasks, we could be done:
|
188
193
|
if interval.nil?
|
189
|
-
if self.finished?
|
190
|
-
# If there is nothing to do, then finish:
|
191
|
-
return false
|
192
|
-
end
|
193
|
-
|
194
194
|
# Allow the user to specify a maximum interval if we would otherwise be sleeping indefinitely:
|
195
195
|
interval = timeout
|
196
196
|
elsif interval < 0
|
@@ -200,7 +200,7 @@ module Async
|
|
200
200
|
interval = timeout
|
201
201
|
end
|
202
202
|
|
203
|
-
logger.debug(self) {"Selecting with #{@children&.size} children with interval = #{interval ? interval.round(2) : 'infinite'}..."}
|
203
|
+
# logger.debug(self) {"Selecting with #{@children&.size} children with interval = #{interval ? interval.round(2) : 'infinite'}..."}
|
204
204
|
if monitors = @selector.select(interval)
|
205
205
|
monitors.each do |monitor|
|
206
206
|
monitor.value.resume
|
@@ -215,11 +215,10 @@ module Async
|
|
215
215
|
@interrupted = false
|
216
216
|
end
|
217
217
|
|
218
|
-
self.stop
|
219
|
-
|
220
218
|
return false
|
221
219
|
end
|
222
220
|
|
221
|
+
# The reactor still has work to do:
|
223
222
|
return true
|
224
223
|
end
|
225
224
|
|
@@ -244,9 +243,9 @@ module Async
|
|
244
243
|
#
|
245
244
|
# @return [void]
|
246
245
|
def close
|
246
|
+
# This is a critical step. Because tasks could be stored as instance variables, and since the reactor is (probably) going out of scope, we need to ensure they are stopped. Otherwise, the tasks will belong to a reactor that will never run again and are not stopped.
|
247
247
|
self.stop
|
248
248
|
|
249
|
-
# TODO Should we also clear all timers?
|
250
249
|
@selector.close
|
251
250
|
@selector = nil
|
252
251
|
end
|
data/lib/async/task.rb
CHANGED
@@ -72,8 +72,8 @@ module Async
|
|
72
72
|
# Create a new task.
|
73
73
|
# @param reactor [Async::Reactor] the reactor this task will run within.
|
74
74
|
# @param parent [Async::Task] the parent task.
|
75
|
-
def initialize(reactor, parent = Task.current?, logger: nil, &block)
|
76
|
-
super(parent || reactor)
|
75
|
+
def initialize(reactor, parent = Task.current?, logger: nil, **options, &block)
|
76
|
+
super(parent || reactor, **options)
|
77
77
|
|
78
78
|
@reactor = reactor
|
79
79
|
|
data/lib/async/version.rb
CHANGED
data/lib/kernel/sync.rb
CHANGED
data/spec/async/barrier_spec.rb
CHANGED
data/spec/async/clock_spec.rb
CHANGED
data/spec/async/node_spec.rb
CHANGED
@@ -20,7 +20,7 @@
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
21
|
# THE SOFTWARE.
|
22
22
|
|
23
|
-
require '
|
23
|
+
require 'async/node'
|
24
24
|
|
25
25
|
RSpec.describe Async::Node do
|
26
26
|
describe '#parent=' do
|
@@ -95,4 +95,81 @@ RSpec.describe Async::Node do
|
|
95
95
|
expect(subject.annotation).to be == annotation
|
96
96
|
end
|
97
97
|
end
|
98
|
+
|
99
|
+
describe '#transient' do
|
100
|
+
it 'can move transient child to parent' do
|
101
|
+
# This example represents a persistent web connection (middle) with a background reader (child). We look at how when that connection goes out of scope, what happens to the child.
|
102
|
+
|
103
|
+
# subject -> middle -> child (transient)
|
104
|
+
|
105
|
+
middle = Async::Node.new(subject)
|
106
|
+
child = Async::Node.new(middle, transient: true)
|
107
|
+
|
108
|
+
expect(child).to be_transient
|
109
|
+
expect(middle).to be_finished
|
110
|
+
|
111
|
+
allow(child).to receive(:finished?).and_return(false)
|
112
|
+
|
113
|
+
middle.consume
|
114
|
+
|
115
|
+
# subject -> child (transient)
|
116
|
+
expect(child.parent).to be subject
|
117
|
+
expect(subject.children).to include(child)
|
118
|
+
expect(subject.children).to_not include(middle)
|
119
|
+
|
120
|
+
expect(child).to_not be_finished
|
121
|
+
expect(subject).to be_finished
|
122
|
+
|
123
|
+
expect(child).to receive(:stop)
|
124
|
+
subject.stop
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'can move transient sibling to parent' do
|
128
|
+
# This example represents a server task (middle) which has a single task listening on incoming connections (child2), and a transient task which is monitoring those connections/some shared resource (child1). We look at what happens when the server listener finishes.
|
129
|
+
|
130
|
+
# subject -> middle -> child1 (transient)
|
131
|
+
# -> child2
|
132
|
+
middle = Async::Node.new(subject)
|
133
|
+
child1 = Async::Node.new(middle, transient: true)
|
134
|
+
child2 = Async::Node.new(middle)
|
135
|
+
|
136
|
+
allow(child1).to receive(:finished?).and_return(false)
|
137
|
+
|
138
|
+
middle.consume
|
139
|
+
|
140
|
+
# subject -> middle -> child1 (transient)
|
141
|
+
# -> child2
|
142
|
+
expect(child1.parent).to be middle
|
143
|
+
expect(child2.parent).to be middle
|
144
|
+
expect(middle.parent).to be subject
|
145
|
+
expect(subject.children).to include(middle)
|
146
|
+
expect(middle.children).to include(child1)
|
147
|
+
expect(middle.children).to include(child2)
|
148
|
+
|
149
|
+
child2.consume
|
150
|
+
|
151
|
+
# subject -> child1 (transient)
|
152
|
+
expect(child1.parent).to be subject
|
153
|
+
expect(child2.parent).to be_nil
|
154
|
+
expect(middle.parent).to be_nil
|
155
|
+
expect(subject.children).to include(child1)
|
156
|
+
expect(middle.children).to be_nil
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'ignores non-transient children of transient parent' do
|
160
|
+
# subject -> middle (transient) -> child
|
161
|
+
middle = Async::Node.new(subject, transient: true)
|
162
|
+
child = Async::Node.new(middle)
|
163
|
+
|
164
|
+
allow(middle).to receive(:finished?).and_return(false)
|
165
|
+
|
166
|
+
child.consume
|
167
|
+
|
168
|
+
# subject -> middle (transient)
|
169
|
+
expect(child.parent).to be_nil
|
170
|
+
expect(middle.parent).to be subject
|
171
|
+
expect(subject.children).to include(middle)
|
172
|
+
expect(middle.children).to be_empty
|
173
|
+
end
|
174
|
+
end
|
98
175
|
end
|
data/spec/async/task_spec.rb
CHANGED
@@ -58,7 +58,7 @@ RSpec.describe Async::Task do
|
|
58
58
|
|
59
59
|
expect(parent).to_not be_nil
|
60
60
|
expect(child).to_not be_nil
|
61
|
-
expect(child.parent).
|
61
|
+
expect(child.parent).to_not be_nil
|
62
62
|
end
|
63
63
|
|
64
64
|
it "can pass in arguments" do
|
@@ -69,6 +69,12 @@ RSpec.describe Async::Task do
|
|
69
69
|
end.wait
|
70
70
|
end
|
71
71
|
|
72
|
+
it "can set initial annotation" do
|
73
|
+
reactor.async(annotation: "Hello World") do |task|
|
74
|
+
expect(task.annotation).to be == "Hello World"
|
75
|
+
end.wait
|
76
|
+
end
|
77
|
+
|
72
78
|
it "can raise exceptions" do
|
73
79
|
expect do
|
74
80
|
reactor.async do |task|
|
@@ -316,11 +322,11 @@ RSpec.describe Async::Task do
|
|
316
322
|
task.with_timeout(0.2) do |timer|
|
317
323
|
task.sleep(0.1)
|
318
324
|
|
319
|
-
expect(timer.fires_in).to be_within(10).percent_of(0.1)
|
325
|
+
expect(timer.fires_in).to be_within(10 * Q).percent_of(0.1)
|
320
326
|
|
321
327
|
timer.reset
|
322
328
|
|
323
|
-
expect(timer.fires_in).to be_within(10).percent_of(0.2)
|
329
|
+
expect(timer.fires_in).to be_within(10 * Q).percent_of(0.2)
|
324
330
|
end
|
325
331
|
end
|
326
332
|
|
data/spec/kernel/sync_spec.rb
CHANGED
@@ -20,6 +20,7 @@
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
21
|
# THE SOFTWARE.
|
22
22
|
|
23
|
+
require 'kernel/async'
|
23
24
|
require 'kernel/sync'
|
24
25
|
|
25
26
|
RSpec.describe Kernel do
|
@@ -27,8 +28,9 @@ RSpec.describe Kernel do
|
|
27
28
|
let(:value) {10}
|
28
29
|
|
29
30
|
it "can run a synchronous task" do
|
30
|
-
result = Sync do
|
31
|
+
result = Sync do |task|
|
31
32
|
expect(Async::Task.current).to_not be nil
|
33
|
+
expect(Async::Task.current).to be task
|
32
34
|
|
33
35
|
next value
|
34
36
|
end
|
@@ -38,9 +40,10 @@ RSpec.describe Kernel do
|
|
38
40
|
|
39
41
|
it "can run inside reactor" do
|
40
42
|
Async do |task|
|
41
|
-
result = Sync do
|
43
|
+
result = Sync do |sync_task|
|
42
44
|
expect(Async::Task.current).to be task
|
43
|
-
|
45
|
+
expect(sync_task).to be task
|
46
|
+
|
44
47
|
next value
|
45
48
|
end
|
46
49
|
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: async
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.25.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-04-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nio4r
|
@@ -109,7 +109,7 @@ dependencies:
|
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '3.6'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
112
|
+
name: bake-bundler
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - ">="
|
@@ -122,9 +122,8 @@ dependencies:
|
|
122
122
|
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
|
-
description: "\t\tAsync
|
126
|
-
|
127
|
-
events.\n"
|
125
|
+
description: "\t\tAsync is a modern concurrency framework for Ruby. It implements
|
126
|
+
the\n\t\treactor pattern, providing both non-blocking I/O and timer events.\n"
|
128
127
|
email:
|
129
128
|
- samuel.williams@oriontransfer.co.nz
|
130
129
|
executables: []
|
@@ -132,16 +131,16 @@ extensions: []
|
|
132
131
|
extra_rdoc_files: []
|
133
132
|
files:
|
134
133
|
- ".editorconfig"
|
135
|
-
- ".github/workflows/
|
134
|
+
- ".github/workflows/development.yml"
|
136
135
|
- ".gitignore"
|
137
136
|
- ".rspec"
|
138
|
-
- ".travis.yml"
|
139
137
|
- ".yardopts"
|
140
138
|
- Gemfile
|
141
139
|
- Guardfile
|
142
140
|
- README.md
|
143
141
|
- Rakefile
|
144
142
|
- async.gemspec
|
143
|
+
- bake.rb
|
145
144
|
- benchmark/async_vs_lightio.rb
|
146
145
|
- benchmark/fiber_count.rb
|
147
146
|
- benchmark/rubies/README.md
|
@@ -211,7 +210,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
211
210
|
requirements:
|
212
211
|
- - ">="
|
213
212
|
- !ruby/object:Gem::Version
|
214
|
-
version: 2.
|
213
|
+
version: 2.5.0
|
215
214
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
216
215
|
requirements:
|
217
216
|
- - ">="
|
@@ -221,7 +220,7 @@ requirements: []
|
|
221
220
|
rubygems_version: 3.1.2
|
222
221
|
signing_key:
|
223
222
|
specification_version: 4
|
224
|
-
summary: Async is an
|
223
|
+
summary: Async is an concurrency framework based for Ruby.
|
225
224
|
test_files:
|
226
225
|
- spec/async/barrier_spec.rb
|
227
226
|
- spec/async/chainable_async_examples.rb
|
data/.github/workflows/tests.yml
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
name: Tests
|
2
|
-
|
3
|
-
on: [push]
|
4
|
-
|
5
|
-
jobs:
|
6
|
-
build:
|
7
|
-
strategy:
|
8
|
-
matrix:
|
9
|
-
os:
|
10
|
-
- ubuntu
|
11
|
-
# - macos
|
12
|
-
|
13
|
-
ruby:
|
14
|
-
- 2.4
|
15
|
-
- 2.5
|
16
|
-
- 2.6
|
17
|
-
|
18
|
-
include:
|
19
|
-
- os: 'ubuntu'
|
20
|
-
ruby: '2.6'
|
21
|
-
env: COVERAGE=PartialSummary,Coveralls
|
22
|
-
|
23
|
-
runs-on: ${{matrix.os}}-latest
|
24
|
-
|
25
|
-
steps:
|
26
|
-
- uses: actions/checkout@v1
|
27
|
-
- uses: actions/setup-ruby@v1
|
28
|
-
with:
|
29
|
-
ruby-version: ${{matrix.ruby}}
|
30
|
-
- name: Install dependencies
|
31
|
-
run: |
|
32
|
-
gem install bundler
|
33
|
-
bundle install
|
34
|
-
- name: Run tests
|
35
|
-
run: ${{matrix.env}} bundle exec rspec
|
36
|
-
- name: Run external tests
|
37
|
-
run: bundle exec rake external
|
data/.travis.yml
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
language: ruby
|
2
|
-
dist: xenial
|
3
|
-
cache: bundler
|
4
|
-
|
5
|
-
addons:
|
6
|
-
apt:
|
7
|
-
packages:
|
8
|
-
- bind9
|
9
|
-
|
10
|
-
before_script:
|
11
|
-
- sudo sh -c 'echo 0 > /proc/sys/net/ipv6/conf/all/disable_ipv6'
|
12
|
-
|
13
|
-
after_success:
|
14
|
-
- unset COVERAGE
|
15
|
-
- bundle exec rake external
|
16
|
-
|
17
|
-
matrix:
|
18
|
-
include:
|
19
|
-
- rvm: 2.3
|
20
|
-
- rvm: 2.4
|
21
|
-
- rvm: 2.5
|
22
|
-
- rvm: 2.6
|
23
|
-
- rvm: 2.7
|
24
|
-
- rvm: 2.6
|
25
|
-
gemfile: gems/event.gemfile
|
26
|
-
- rvm: 2.6
|
27
|
-
env: COVERAGE=PartialSummary,Coveralls
|
28
|
-
- rvm: jruby-head
|
29
|
-
env: JRUBY_OPTS="--debug -X+O"
|
30
|
-
- rvm: truffleruby
|
31
|
-
- rvm: ruby-head
|
32
|
-
allow_failures:
|
33
|
-
- rvm: truffleruby
|
34
|
-
- rvm: ruby-head
|
35
|
-
- rvm: jruby-head
|