async-container 0.16.4 → 0.16.9
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
- data/lib/async/container.rb +0 -1
- data/lib/async/container/best.rb +9 -3
- data/lib/async/container/channel.rb +13 -0
- data/lib/async/container/controller.rb +49 -25
- data/lib/async/container/error.rb +21 -0
- data/lib/async/container/forked.rb +5 -1
- data/lib/async/container/generic.rb +57 -19
- data/lib/async/container/group.rb +19 -2
- data/lib/async/container/hybrid.rb +16 -2
- data/lib/async/container/keyed.rb +12 -0
- data/lib/async/container/notify.rb +4 -5
- data/lib/async/container/notify/client.rb +16 -1
- data/lib/async/container/notify/console.rb +8 -21
- data/lib/async/container/notify/pipe.rb +8 -22
- data/lib/async/container/notify/server.rb +0 -1
- data/lib/async/container/notify/socket.rb +14 -1
- data/lib/async/container/process.rb +28 -2
- data/lib/async/container/statistics.rb +16 -0
- data/lib/async/container/thread.rb +42 -6
- data/lib/async/container/threaded.rb +5 -1
- data/lib/async/container/version.rb +1 -1
- metadata +13 -88
- data/.editorconfig +0 -6
- data/.github/workflows/development.yml +0 -36
- data/.gitignore +0 -21
- data/.rspec +0 -3
- data/.travis.yml +0 -21
- data/.yardopts +0 -1
- data/Gemfile +0 -19
- data/Guardfile +0 -14
- data/README.md +0 -140
- data/Rakefile +0 -8
- data/async-container.gemspec +0 -34
- data/examples/async.rb +0 -22
- data/examples/channel.rb +0 -45
- data/examples/channels/client.rb +0 -103
- data/examples/container.rb +0 -33
- data/examples/isolate.rb +0 -36
- data/examples/minimal.rb +0 -94
- data/examples/test.rb +0 -51
- data/examples/threads.rb +0 -25
- data/examples/title.rb +0 -13
- data/examples/udppipe.rb +0 -35
- data/spec/async/container/controller_spec.rb +0 -105
- data/spec/async/container/dots.rb +0 -34
- data/spec/async/container/forked_spec.rb +0 -61
- data/spec/async/container/hybrid_spec.rb +0 -36
- data/spec/async/container/notify/notify.rb +0 -19
- data/spec/async/container/notify/pipe_spec.rb +0 -48
- data/spec/async/container/notify_spec.rb +0 -56
- data/spec/async/container/shared_examples.rb +0 -80
- data/spec/async/container/signal_spec.rb +0 -66
- data/spec/async/container/threaded_spec.rb +0 -35
- data/spec/async/container_spec.rb +0 -41
- data/spec/spec_helper.rb +0 -21
@@ -24,6 +24,7 @@ require 'async/reactor'
|
|
24
24
|
|
25
25
|
module Async
|
26
26
|
module Container
|
27
|
+
# Tracks various statistics relating to child instances in a container.
|
27
28
|
class Statistics
|
28
29
|
def initialize
|
29
30
|
@spawns = 0
|
@@ -31,26 +32,41 @@ module Async
|
|
31
32
|
@failures = 0
|
32
33
|
end
|
33
34
|
|
35
|
+
# How many child instances have been spawned.
|
36
|
+
# @attribute [Integer]
|
34
37
|
attr :spawns
|
38
|
+
|
39
|
+
# How many child instances have been restarted.
|
40
|
+
# @attribute [Integer]
|
35
41
|
attr :restarts
|
42
|
+
|
43
|
+
# How many child instances have failed.
|
44
|
+
# @attribute [Integer]
|
36
45
|
attr :failures
|
37
46
|
|
47
|
+
# Increment the number of spawns by 1.
|
38
48
|
def spawn!
|
39
49
|
@spawns += 1
|
40
50
|
end
|
41
51
|
|
52
|
+
# Increment the number of restarts by 1.
|
42
53
|
def restart!
|
43
54
|
@restarts += 1
|
44
55
|
end
|
45
56
|
|
57
|
+
# Increment the number of failures by 1.
|
46
58
|
def failure!
|
47
59
|
@failures += 1
|
48
60
|
end
|
49
61
|
|
62
|
+
# Whether there have been any failures.
|
63
|
+
# @returns [Boolean] If the failure count is greater than 0.
|
50
64
|
def failed?
|
51
65
|
@failures > 0
|
52
66
|
end
|
53
67
|
|
68
|
+
# Append another statistics instance into this one.
|
69
|
+
# @parameter other [Statistics] The statistics to append.
|
54
70
|
def << other
|
55
71
|
@spawns += other.spawns
|
56
72
|
@restarts += other.restarts
|
@@ -21,20 +21,27 @@
|
|
21
21
|
# THE SOFTWARE.
|
22
22
|
|
23
23
|
require_relative 'channel'
|
24
|
+
require_relative 'error'
|
24
25
|
require_relative 'notify/pipe'
|
25
26
|
|
26
|
-
require 'async/logger'
|
27
|
-
|
28
27
|
module Async
|
29
28
|
module Container
|
29
|
+
# Represents a running child thread from the point of view of the parent container.
|
30
30
|
class Thread < Channel
|
31
|
+
# Used to propagate the exit status of a child process invoked by {Instance#exec}.
|
31
32
|
class Exit < Exception
|
33
|
+
# Initialize the exit status.
|
34
|
+
# @parameter status [::Process::Status] The process exit status.
|
32
35
|
def initialize(status)
|
33
36
|
@status = status
|
34
37
|
end
|
35
38
|
|
39
|
+
# The process exit status.
|
40
|
+
# @attribute [::Process::Status]
|
36
41
|
attr :status
|
37
42
|
|
43
|
+
# The process exit status if it was an error.
|
44
|
+
# @returns [::Process::Status | Nil]
|
38
45
|
def error
|
39
46
|
unless status.success?
|
40
47
|
status
|
@@ -42,7 +49,10 @@ module Async
|
|
42
49
|
end
|
43
50
|
end
|
44
51
|
|
52
|
+
# Represents a running child thread from the point of view of the child thread.
|
45
53
|
class Instance < Notify::Pipe
|
54
|
+
# Wrap an instance around the {Thread} instance from within the threaded child.
|
55
|
+
# @parameter thread [Thread] The thread intance to wrap.
|
46
56
|
def self.for(thread)
|
47
57
|
instance = self.new(thread.out)
|
48
58
|
|
@@ -56,14 +66,20 @@ module Async
|
|
56
66
|
super
|
57
67
|
end
|
58
68
|
|
69
|
+
# Set the name of the thread.
|
70
|
+
# @parameter value [String] The name to set.
|
59
71
|
def name= value
|
60
72
|
@thread.name = value
|
61
73
|
end
|
62
74
|
|
75
|
+
# Get the name of the thread.
|
76
|
+
# @returns [String]
|
63
77
|
def name
|
64
78
|
@thread.name
|
65
79
|
end
|
66
80
|
|
81
|
+
# Execute a child process using {::Process.spawn}. In order to simulate {::Process.exec}, an {Exit} instance is raised to propagage exit status.
|
82
|
+
# This creates the illusion that this method does not return (normally).
|
67
83
|
def exec(*arguments, ready: true, **options)
|
68
84
|
if ready
|
69
85
|
self.ready!(status: "(spawn)") if ready
|
@@ -90,6 +106,8 @@ module Async
|
|
90
106
|
end
|
91
107
|
end
|
92
108
|
|
109
|
+
# Initialize the thread.
|
110
|
+
# @parameter name [String] The name to use for the child thread.
|
93
111
|
def initialize(name: nil)
|
94
112
|
super()
|
95
113
|
|
@@ -115,18 +133,25 @@ module Async
|
|
115
133
|
end
|
116
134
|
end
|
117
135
|
|
136
|
+
# Set the name of the thread.
|
137
|
+
# @parameter value [String] The name to set.
|
118
138
|
def name= value
|
119
139
|
@thread.name = value
|
120
140
|
end
|
121
141
|
|
142
|
+
# Get the name of the thread.
|
143
|
+
# @returns [String]
|
122
144
|
def name
|
123
145
|
@thread.name
|
124
146
|
end
|
125
147
|
|
148
|
+
# A human readable representation of the thread.
|
149
|
+
# @returns [String]
|
126
150
|
def to_s
|
127
151
|
"\#<#{self.class} #{@thread.name}>"
|
128
152
|
end
|
129
153
|
|
154
|
+
# Invoke {#terminate!} and then {#wait} for the child thread to exit.
|
130
155
|
def close
|
131
156
|
self.terminate!
|
132
157
|
self.wait
|
@@ -134,14 +159,18 @@ module Async
|
|
134
159
|
super
|
135
160
|
end
|
136
161
|
|
162
|
+
# Raise {Interrupt} in the child thread.
|
137
163
|
def interrupt!
|
138
164
|
@thread.raise(Interrupt)
|
139
165
|
end
|
140
166
|
|
167
|
+
# Raise {Terminate} in the child thread.
|
141
168
|
def terminate!
|
142
169
|
@thread.raise(Terminate)
|
143
170
|
end
|
144
171
|
|
172
|
+
# Wait for the thread to exit and return he exit status.
|
173
|
+
# @returns [Status]
|
145
174
|
def wait
|
146
175
|
if @waiter
|
147
176
|
@waiter.join
|
@@ -151,15 +180,21 @@ module Async
|
|
151
180
|
return @status
|
152
181
|
end
|
153
182
|
|
183
|
+
# A pseudo exit-status wrapper.
|
154
184
|
class Status
|
155
|
-
|
156
|
-
|
185
|
+
# Initialise the status.
|
186
|
+
# @parameter error [::Process::Status] The exit status of the child thread.
|
187
|
+
def initialize(error = nil)
|
188
|
+
@error = error
|
157
189
|
end
|
158
190
|
|
191
|
+
# Whether the status represents a successful outcome.
|
192
|
+
# @returns [Boolean]
|
159
193
|
def success?
|
160
|
-
@
|
194
|
+
@error.nil?
|
161
195
|
end
|
162
196
|
|
197
|
+
# A human readable representation of the status.
|
163
198
|
def to_s
|
164
199
|
"\#<#{self.class} #{success? ? "success" : "failure"}>"
|
165
200
|
end
|
@@ -167,9 +202,10 @@ module Async
|
|
167
202
|
|
168
203
|
protected
|
169
204
|
|
205
|
+
# Invoked by the @waiter thread to indicate the outcome of the child thread.
|
170
206
|
def finished(error = nil)
|
171
207
|
if error
|
172
|
-
|
208
|
+
Console.logger.error(self) {error}
|
173
209
|
end
|
174
210
|
|
175
211
|
@status = Status.new(error)
|
@@ -24,13 +24,17 @@ require_relative 'generic'
|
|
24
24
|
require_relative 'thread'
|
25
25
|
|
26
26
|
module Async
|
27
|
-
# Manages a reactor within one or more threads.
|
28
27
|
module Container
|
28
|
+
# A multi-thread container which uses {Thread.fork}.
|
29
29
|
class Threaded < Generic
|
30
|
+
# Indicates that this is not a multi-process container.
|
30
31
|
def self.multiprocess?
|
31
32
|
false
|
32
33
|
end
|
33
34
|
|
35
|
+
# Start a named child thread and execute the provided block in it.
|
36
|
+
# @parameter name [String] The name (title) of the child process.
|
37
|
+
# @parameter block [Proc] The block to execute in the child process.
|
34
38
|
def start(name, &block)
|
35
39
|
Thread.fork(name: name, &block)
|
36
40
|
end
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: async-container
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.16.
|
4
|
+
version: 0.16.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-05-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: process-group
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: async
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -67,7 +53,7 @@ dependencies:
|
|
67
53
|
- !ruby/object:Gem::Version
|
68
54
|
version: '1.1'
|
69
55
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
56
|
+
name: bundler
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
72
58
|
requirements:
|
73
59
|
- - ">="
|
@@ -81,7 +67,7 @@ dependencies:
|
|
81
67
|
- !ruby/object:Gem::Version
|
82
68
|
version: '0'
|
83
69
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
70
|
+
name: covered
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
86
72
|
requirements:
|
87
73
|
- - ">="
|
@@ -108,49 +94,12 @@ dependencies:
|
|
108
94
|
- - "~>"
|
109
95
|
- !ruby/object:Gem::Version
|
110
96
|
version: '3.6'
|
111
|
-
|
112
|
-
name: rake
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
114
|
-
requirements:
|
115
|
-
- - ">="
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: '0'
|
118
|
-
type: :development
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
requirements:
|
122
|
-
- - ">="
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
version: '0'
|
125
|
-
description: "\t\tProvides containers for servers which provide concurrency policies,
|
126
|
-
e.g. threads, processes.\n"
|
97
|
+
description:
|
127
98
|
email:
|
128
|
-
- samuel.williams@oriontransfer.co.nz
|
129
99
|
executables: []
|
130
100
|
extensions: []
|
131
101
|
extra_rdoc_files: []
|
132
102
|
files:
|
133
|
-
- ".editorconfig"
|
134
|
-
- ".github/workflows/development.yml"
|
135
|
-
- ".gitignore"
|
136
|
-
- ".rspec"
|
137
|
-
- ".travis.yml"
|
138
|
-
- ".yardopts"
|
139
|
-
- Gemfile
|
140
|
-
- Guardfile
|
141
|
-
- README.md
|
142
|
-
- Rakefile
|
143
|
-
- async-container.gemspec
|
144
|
-
- examples/async.rb
|
145
|
-
- examples/channel.rb
|
146
|
-
- examples/channels/client.rb
|
147
|
-
- examples/container.rb
|
148
|
-
- examples/isolate.rb
|
149
|
-
- examples/minimal.rb
|
150
|
-
- examples/test.rb
|
151
|
-
- examples/threads.rb
|
152
|
-
- examples/title.rb
|
153
|
-
- examples/udppipe.rb
|
154
103
|
- lib/async/container.rb
|
155
104
|
- lib/async/container/best.rb
|
156
105
|
- lib/async/container/channel.rb
|
@@ -172,51 +121,27 @@ files:
|
|
172
121
|
- lib/async/container/thread.rb
|
173
122
|
- lib/async/container/threaded.rb
|
174
123
|
- lib/async/container/version.rb
|
175
|
-
- spec/async/container/controller_spec.rb
|
176
|
-
- spec/async/container/dots.rb
|
177
|
-
- spec/async/container/forked_spec.rb
|
178
|
-
- spec/async/container/hybrid_spec.rb
|
179
|
-
- spec/async/container/notify/notify.rb
|
180
|
-
- spec/async/container/notify/pipe_spec.rb
|
181
|
-
- spec/async/container/notify_spec.rb
|
182
|
-
- spec/async/container/shared_examples.rb
|
183
|
-
- spec/async/container/signal_spec.rb
|
184
|
-
- spec/async/container/threaded_spec.rb
|
185
|
-
- spec/async/container_spec.rb
|
186
|
-
- spec/spec_helper.rb
|
187
124
|
homepage: https://github.com/socketry/async-container
|
188
125
|
licenses:
|
189
126
|
- MIT
|
190
127
|
metadata: {}
|
191
|
-
post_install_message:
|
128
|
+
post_install_message:
|
192
129
|
rdoc_options: []
|
193
130
|
require_paths:
|
194
131
|
- lib
|
195
132
|
required_ruby_version: !ruby/object:Gem::Requirement
|
196
133
|
requirements:
|
197
|
-
- - "
|
134
|
+
- - ">="
|
198
135
|
- !ruby/object:Gem::Version
|
199
|
-
version: '2.
|
136
|
+
version: '2.5'
|
200
137
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
201
138
|
requirements:
|
202
139
|
- - ">="
|
203
140
|
- !ruby/object:Gem::Version
|
204
141
|
version: '0'
|
205
142
|
requirements: []
|
206
|
-
rubygems_version: 3.
|
207
|
-
signing_key:
|
143
|
+
rubygems_version: 3.2.3
|
144
|
+
signing_key:
|
208
145
|
specification_version: 4
|
209
|
-
summary:
|
210
|
-
test_files:
|
211
|
-
- spec/async/container/controller_spec.rb
|
212
|
-
- spec/async/container/dots.rb
|
213
|
-
- spec/async/container/forked_spec.rb
|
214
|
-
- spec/async/container/hybrid_spec.rb
|
215
|
-
- spec/async/container/notify/notify.rb
|
216
|
-
- spec/async/container/notify/pipe_spec.rb
|
217
|
-
- spec/async/container/notify_spec.rb
|
218
|
-
- spec/async/container/shared_examples.rb
|
219
|
-
- spec/async/container/signal_spec.rb
|
220
|
-
- spec/async/container/threaded_spec.rb
|
221
|
-
- spec/async/container_spec.rb
|
222
|
-
- spec/spec_helper.rb
|
146
|
+
summary: Abstract container-based parallelism using threads and processes where appropriate.
|
147
|
+
test_files: []
|
data/.editorconfig
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
name: Development
|
2
|
-
|
3
|
-
on: [push]
|
4
|
-
|
5
|
-
jobs:
|
6
|
-
test:
|
7
|
-
strategy:
|
8
|
-
matrix:
|
9
|
-
os:
|
10
|
-
- ubuntu
|
11
|
-
- macos
|
12
|
-
|
13
|
-
ruby:
|
14
|
-
- 2.4
|
15
|
-
- 2.5
|
16
|
-
- 2.6
|
17
|
-
- 2.7
|
18
|
-
|
19
|
-
include:
|
20
|
-
- os: 'ubuntu'
|
21
|
-
ruby: '2.6'
|
22
|
-
env: COVERAGE=PartialSummary,Coveralls
|
23
|
-
|
24
|
-
runs-on: ${{matrix.os}}-latest
|
25
|
-
|
26
|
-
steps:
|
27
|
-
- uses: actions/checkout@v1
|
28
|
-
- uses: actions/setup-ruby@v1
|
29
|
-
with:
|
30
|
-
ruby-version: ${{matrix.ruby}}
|
31
|
-
- name: Install dependencies
|
32
|
-
run: |
|
33
|
-
command -v bundler || gem install bundler
|
34
|
-
bundle install
|
35
|
-
- name: Run tests
|
36
|
-
run: ${{matrix.env}} bundle exec rspec
|
data/.gitignore
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
*.gem
|
2
|
-
*.rbc
|
3
|
-
.bundle
|
4
|
-
.config
|
5
|
-
.yardoc
|
6
|
-
Gemfile.lock
|
7
|
-
InstalledFiles
|
8
|
-
_yardoc
|
9
|
-
coverage
|
10
|
-
doc/
|
11
|
-
lib/bundler/man
|
12
|
-
pkg
|
13
|
-
rdoc
|
14
|
-
spec/reports
|
15
|
-
test/tmp
|
16
|
-
test/version_tmp
|
17
|
-
tmp
|
18
|
-
.tags*
|
19
|
-
documentation/run/*
|
20
|
-
documentation/public/code/*
|
21
|
-
.rspec_status
|