async-container 0.16.5 → 0.16.6

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.
@@ -1,34 +0,0 @@
1
-
2
- require_relative 'lib/async/container/version'
3
-
4
- Gem::Specification.new do |spec|
5
- spec.name = "async-container"
6
- spec.version = Async::Container::VERSION
7
- spec.authors = ["Samuel Williams"]
8
- spec.email = ["samuel.williams@oriontransfer.co.nz"]
9
- spec.description = <<-EOF
10
- Provides containers for servers which provide concurrency policies, e.g. threads, processes.
11
- EOF
12
- spec.summary = "Async is an asynchronous I/O framework based on nio4r."
13
- spec.homepage = "https://github.com/socketry/async-container"
14
- spec.license = "MIT"
15
-
16
- spec.files = `git ls-files`.split($/)
17
- spec.executables = spec.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ["lib"]
20
-
21
- spec.required_ruby_version = "~> 2.0"
22
-
23
- spec.add_runtime_dependency "process-group"
24
-
25
- spec.add_runtime_dependency "async", "~> 1.0"
26
- spec.add_runtime_dependency "async-io", "~> 1.26"
27
-
28
- spec.add_development_dependency "async-rspec", "~> 1.1"
29
-
30
- spec.add_development_dependency "covered"
31
- spec.add_development_dependency "bundler"
32
- spec.add_development_dependency "rspec", "~> 3.6"
33
- spec.add_development_dependency "bake-bundler"
34
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'kernel/sync'
4
-
5
- class Worker
6
- def initialize(&block)
7
-
8
- end
9
- end
10
-
11
- Sync do
12
- count.times do
13
- worker = Worker.new(&block)
14
-
15
- status = worker.wait do |message|
16
-
17
- end
18
-
19
- status.success?
20
- status.failed?
21
- end
22
- end
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'json'
4
-
5
- class Channel
6
- def initialize
7
- @in, @out = IO.pipe
8
- end
9
-
10
- def after_fork
11
- @out.close
12
- end
13
-
14
- def receive
15
- if data = @in.gets
16
- JSON.parse(data, symbolize_names: true)
17
- end
18
- end
19
-
20
- def send(**message)
21
- data = JSON.dump(message)
22
-
23
- @out.puts(data)
24
- end
25
- end
26
-
27
- status = Channel.new
28
-
29
- pid = fork do
30
- status.send(ready: false, status: "Initializing...")
31
-
32
- # exit(-1) # crash
33
-
34
- status.send(ready: true, status: "Initialization Complete!")
35
- end
36
-
37
- status.after_fork
38
-
39
- while message = status.receive
40
- pp message
41
- end
42
-
43
- pid, status = Process.waitpid2(pid)
44
-
45
- puts "Status: #{status}"
@@ -1,103 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'msgpack'
4
- require 'async/io'
5
- require 'async/io/stream'
6
- require 'async/container'
7
-
8
- # class Bus
9
- # def initialize
10
- #
11
- # end
12
- #
13
- # def << object
14
- # :object
15
- # end
16
- #
17
- # def [] key
18
- # return
19
- # end
20
- # end
21
- #
22
- # class Proxy < BasicObject
23
- # def initialize(bus, name)
24
- # @bus = bus
25
- # @name = name
26
- # end
27
- #
28
- # def inspect
29
- # "[Proxy #{method_missing(:inspect)}]"
30
- # end
31
- #
32
- # def method_missing(*args, &block)
33
- # @bus.invoke(@name, args, &block)
34
- # end
35
- #
36
- # def respond_to?(*args)
37
- # @bus.invoke(@name, ["respond_to?", *args])
38
- # end
39
- # end
40
- #
41
- # class Wrapper < MessagePack::Factory
42
- # def initialize(bus)
43
- # super()
44
- #
45
- # self.register_type(0x00, Object,
46
- # packer: @bus.method(:<<),
47
- # unpacker: @bus.method(:[])
48
- # )
49
- #
50
- # self.register_type(0x01, Symbol)
51
- # self.register_type(0x02, Exception,
52
- # packer: ->(exception){Marshal.dump(exception)},
53
- # unpacker: ->(data){Marshal.load(data)},
54
- # )
55
- #
56
- # self.register_type(0x03, Class,
57
- # packer: ->(klass){Marshal.dump(klass)},
58
- # unpacker: ->(data){Marshal.load(data)},
59
- # )
60
- # end
61
- # end
62
- #
63
- # class Channel
64
- # def self.pipe
65
- # input, output = Async::IO.pipe
66
- # end
67
- #
68
- # def initialize(input, output)
69
- # @input = input
70
- # @output = output
71
- # end
72
- #
73
- # def read
74
- # @input.read
75
- # end
76
- #
77
- # def write
78
- # end
79
- # end
80
-
81
- container = Async::Container.new
82
- input, output = Async::IO.pipe
83
-
84
- container.async do |instance|
85
- stream = Async::IO::Stream.new(input)
86
- output.close
87
-
88
- while message = stream.gets
89
- puts "Hello World from #{instance}: #{message}"
90
- end
91
-
92
- puts "exiting"
93
- end
94
-
95
- stream = Async::IO::Stream.new(output)
96
-
97
- 5.times do |i|
98
- stream.puts "#{i}"
99
- end
100
-
101
- stream.close
102
-
103
- container.wait
@@ -1,33 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require '../lib/async/container/controller'
5
- require '../lib/async/container/forked'
6
-
7
- Async.logger.debug!
8
-
9
- Async.logger.debug(self, "Starting up...")
10
-
11
- controller = Async::Container::Controller.new do |container|
12
- Async.logger.debug(self, "Setting up container...")
13
-
14
- container.run(count: 1, restart: true) do
15
- Async.logger.debug(self, "Child process started.")
16
-
17
- while true
18
- sleep 1
19
-
20
- if rand < 0.1
21
- exit(1)
22
- end
23
- end
24
- ensure
25
- Async.logger.debug(self, "Child process exiting:", $!)
26
- end
27
- end
28
-
29
- begin
30
- controller.run
31
- ensure
32
- Async.logger.debug(controller, "Parent process exiting:", $!)
33
- end
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # We define end of life-cycle in terms of "Interrupt" (SIGINT), "Terminate" (SIGTERM) and "Kill" (SIGKILL, does not invoke user code).
4
- class Terminate < Interrupt
5
- end
6
-
7
- class Isolate
8
- def initialize(&block)
9
-
10
- end
11
- end
12
-
13
-
14
- parent = Isolate.new do |parent|
15
- preload_user_code
16
- server = bind_socket
17
- children = 4.times.map do
18
- Isolate.new do |worker|
19
- app = load_user_application
20
- worker.ready!
21
- server.accept do |peer|
22
- app.handle_request(peer)
23
- end
24
- end
25
- end
26
- while status = parent.wait
27
- # Status is not just exit status of process but also can be `:ready` or something else.
28
- end
29
- end
30
-
31
- # Similar to Process.wait(pid)
32
- status = parent.wait
33
- # Life cycle controls
34
- parent.interrupt!
35
- parent.terminate!
36
- parent.kill!
@@ -1,94 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Threaded
4
- def initialize(&block)
5
- @channel = Channel.new
6
- @thread = Thread.new(&block)
7
-
8
- @waiter = Thread.new do
9
- begin
10
- @thread.join
11
- rescue Exception => error
12
- finished(error)
13
- else
14
- finished
15
- end
16
- end
17
- end
18
-
19
- attr :channel
20
-
21
- def close
22
- self.terminate!
23
- self.wait
24
- ensure
25
- @channel.close
26
- end
27
-
28
- def interrupt!
29
- @thread.raise(Interrupt)
30
- end
31
-
32
- def terminate!
33
- @thread.raise(Terminate)
34
- end
35
-
36
- def wait
37
- if @waiter
38
- @waiter.join
39
- @waiter = nil
40
- end
41
-
42
- @status
43
- end
44
-
45
- protected
46
-
47
- def finished(error = nil)
48
- @status = Status.new(error)
49
- @channel.out.close
50
- end
51
- end
52
-
53
- class Forked
54
- def initialize(&block)
55
- @channel = Channel.new
56
- @status = nil
57
-
58
- @pid = Process.fork do
59
- Signal.trap(:INT) {raise Interrupt}
60
- Signal.trap(:INT) {raise Terminate}
61
-
62
- @channel.in.close
63
-
64
- yield
65
- end
66
-
67
- @channel.out.close
68
- end
69
-
70
- attr :channel
71
-
72
- def close
73
- self.terminate!
74
- self.wait
75
- ensure
76
- @channel.close
77
- end
78
-
79
- def interrupt!
80
- Process.kill(:INT, @pid)
81
- end
82
-
83
- def terminate!
84
- Process.kill(:TERM, @pid)
85
- end
86
-
87
- def wait
88
- unless @status
89
- _pid, @status = ::Process.wait(@pid)
90
- end
91
-
92
- @status
93
- end
94
- end
@@ -1,51 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'group'
4
- require_relative 'thread'
5
- require_relative 'process'
6
-
7
- group = Async::Container::Group.new
8
-
9
- thread_monitor = Fiber.new do
10
- while true
11
- thread = Async::Container::Thread.fork do |instance|
12
- if rand < 0.2
13
- raise "Random Failure!"
14
- end
15
-
16
- instance.send(ready: true, status: "Started Thread")
17
-
18
- sleep(1)
19
- end
20
-
21
- status = group.wait_for(thread) do |message|
22
- puts "Thread message: #{message}"
23
- end
24
-
25
- puts "Thread status: #{status}"
26
- end
27
- end.resume
28
-
29
- process_monitor = Fiber.new do
30
- while true
31
- # process = Async::Container::Process.fork do |instance|
32
- # if rand < 0.2
33
- # raise "Random Failure!"
34
- # end
35
- #
36
- # instance.send(ready: true, status: "Started Process")
37
- #
38
- # sleep(1)
39
- # end
40
-
41
- process = Async::Container::Process.spawn('bash -c "sleep 1; echo foobar; sleep 1; exit -1"')
42
-
43
- status = group.wait_for(process) do |message|
44
- puts "Process message: #{message}"
45
- end
46
-
47
- puts "Process status: #{status}"
48
- end
49
- end.resume
50
-
51
- group.wait
@@ -1,25 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- puts "Process pid: #{Process.pid}"
5
-
6
- threads = 10.times.collect do
7
- Thread.new do
8
- begin
9
- sleep
10
- rescue Exception
11
- puts "Thread: #{$!}"
12
- end
13
- end
14
- end
15
-
16
- while true
17
- begin
18
- threads.each(&:join)
19
- exit(0)
20
- rescue Exception
21
- puts "Join: #{$!}"
22
- end
23
- end
24
-
25
- puts "Done"