async-runner 0.1.2

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 33d2179d3e676bc4c06d3ded55a6828259b930ccda50633c2e3989540f94d8ed
4
+ data.tar.gz: c20f7a18ac21ccc6241925cecf7442d208d571daae6e9c168983c053f0216647
5
+ SHA512:
6
+ metadata.gz: 60afb068a72c4b93b57b304216f90e9cc5a3d1eeea68b44c1d4b45e5d4a62526fce109cdbe78c43b31425d28bb27ff5ea6b5915063ba7bd890d4507bd9b1ad70
7
+ data.tar.gz: 03dc4440efc32f65a92ac956f0368722452bbc8114e4b4a4a3410a04fc74184ccb036fb777bf9146f8f60ebb589d1b8d838238409de57a2a6f8bf012647821f2
data/exe/async-runner ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # frozen_string_literal: true
4
+
5
+ # Copyright, 2022, by Anton Sozontov.
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ # of this software and associated documentation files (the "Software"), to deal
9
+ # in the Software without restriction, including without limitation the rights
10
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ # copies of the Software, and to permit persons to whom the Software is
12
+ # furnished to do so, subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in
15
+ # all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ # THE SOFTWARE.
24
+
25
+ require_relative '../lib/async/runner'
26
+
27
+ begin
28
+ Async::Runner::Command.call
29
+ rescue Interrupt
30
+ # Ignore.
31
+ rescue => error
32
+ Console.logger.error(Async::Runner::Command) {error}
33
+ exit! 1
34
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright, 2022, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
+ # Copyright, 2022, by Anton Sozontov.
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+
24
+ require 'samovar'
25
+ require 'async/container'
26
+
27
+ module Async
28
+ module Runner
29
+ class Command < Samovar::Command
30
+ MAX_FIBERS = 1000
31
+
32
+ self.description = "Scalable multi-thread multi-process container"
33
+
34
+ # The command line options.
35
+ # @attribute [Samovar::Options]
36
+ options do
37
+ option '--verbose | --quiet', "Verbosity of output for debugging.", key: :logging
38
+ option '-h/--help', "Print out help information."
39
+ option '-v/--version', "Print out the application version."
40
+ option '--restart', "Restart containers if they fail"
41
+
42
+ option '--forked | --threaded | --hybrid', "Select a specific parallelism model.", key: :container, default: :forked
43
+
44
+ option '-n/--count <count>', "Number of instances to start.", default: Async::Container.processor_count, type: Integer
45
+
46
+ option '--forks <count>', "Number of forks (hybrid only).", type: Integer
47
+ option '--threads <count>', "Number of threads (hybrid only).", type: Integer
48
+ option '-j/--jobs <count>', "Maximum number of async, parallel jobs.", type: Integer, default: MAX_FIBERS
49
+ end
50
+
51
+ one :file, "File to run in containers", required: true
52
+
53
+ # Whether verbose logging is enabled.
54
+ # @returns [Boolean]
55
+ def verbose?
56
+ @options[:logging] == :verbose
57
+ end
58
+
59
+ # Whether quiet logging was enabled.
60
+ # @returns [Boolean]
61
+ def quiet?
62
+ @options[:logging] == :quiet
63
+ end
64
+
65
+ # Prepare the environment and invoke the sub-command.
66
+ def call
67
+ if @options[:version]
68
+ puts "#{self.name} v#{Async::Runner::VERSION}"
69
+ elsif @options[:help]
70
+ self.print_usage
71
+ else
72
+ run
73
+ end
74
+ end
75
+
76
+ # The container class to use.
77
+ def container_class
78
+ case @options[:container]
79
+ when :threaded
80
+ return Async::Container::Threaded
81
+ when :forked
82
+ return Async::Container::Forked
83
+ when :hybrid
84
+ return Async::Container::Hybrid
85
+ end
86
+ end
87
+
88
+ def container_options
89
+ if @options[:container] == :hybrid
90
+ options.slice(:count, :forks, :threads, :name, :restart, :key)
91
+ else
92
+ options.slice(:count, :name, :restart, :key)
93
+ end
94
+ end
95
+
96
+ def job_class
97
+ Async::Runner::Job
98
+ end
99
+
100
+ private
101
+
102
+ def run
103
+ Async::Runner::Controller.run(self)
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,34 @@
1
+ module Async
2
+ module Runner
3
+ class Controller < Async::Container::Controller
4
+ def self.run(command)
5
+ new(command).run
6
+ end
7
+
8
+ def initialize(command)
9
+ @command = command
10
+ super()
11
+ end
12
+
13
+ def create_container
14
+ @command.container_class.new
15
+ end
16
+
17
+ def create_job
18
+ @command.job_class.new(@command.file, **@command.options)
19
+ end
20
+
21
+ def setup(container)
22
+ @job = create_job
23
+ @job.setup
24
+
25
+ container.run name: @command.file, **@command.container_options do |instance|
26
+ instance.ready!
27
+ Sync do
28
+ @job.execute
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,70 @@
1
+ module Async
2
+ module Runner
3
+ class Job
4
+ include Console
5
+
6
+ attr_reader :block, :options
7
+
8
+ def initialize(file, **options)
9
+ path = File.realpath(file)
10
+ @options = options
11
+ @barrier = Async::Barrier.new
12
+ @semaphore = Async::Semaphore.new(options[:jobs], parent: @barrier)
13
+ instance_eval File.read(path), path
14
+ end
15
+
16
+ def before(container=nil, options=nil, &block)
17
+ if block_given?
18
+ @before_block = block
19
+ else
20
+ @before_block&.call(container, options)
21
+ end
22
+ end
23
+
24
+ def job
25
+ self
26
+ end
27
+
28
+ def run(&block)
29
+ @block = block
30
+ end
31
+
32
+ def execute
33
+ @block.call(job)
34
+ @barrier.wait
35
+ end
36
+
37
+ def limit(limit)
38
+ @semaphore = Async::Semaphore.new(limit, parent: @barrier)
39
+ end
40
+
41
+ def progress(total:)
42
+ @progress = logger.progress("jobs", total)
43
+ end
44
+
45
+ def async(&block)
46
+ @semaphore.async do
47
+ block.call
48
+ @progress&.increment
49
+ end
50
+ end
51
+
52
+ def setup(&block)
53
+ if block_given?
54
+ @setup_block = block
55
+ else
56
+ @setup_block&.call job
57
+ end
58
+ end
59
+
60
+ def intro
61
+ type = options[:container].to_s.capitalize
62
+ Console.logger.info "=> Starting #{type} async containers"
63
+ end
64
+
65
+ def self.to_s
66
+ "Runner"
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Async
4
+ module Runner
5
+ VERSION = "0.1.2"
6
+ end
7
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'async'
4
+ require 'async/container'
5
+ require 'async/barrier'
6
+ require 'async/semaphore'
7
+ require 'async/queue'
8
+ require 'console'
9
+ require_relative "runner/version"
10
+ require_relative "runner/job"
11
+ require_relative "runner/controller"
12
+ require_relative "runner/command"
13
+
14
+ module Async
15
+ module Runner
16
+ class Error < StandardError; end
17
+ # Your code goes here...
18
+ end
19
+ end
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: async-runner
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - Anton Sozontov
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2022-10-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: async
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
+ - !ruby/object:Gem::Dependency
28
+ name: async-container
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: samovar
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.1'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: async-rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.1'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: covered
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '3.6'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '3.6'
111
+ description:
112
+ email:
113
+ executables:
114
+ - async-runner
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - exe/async-runner
119
+ - lib/async/runner.rb
120
+ - lib/async/runner/command.rb
121
+ - lib/async/runner/controller.rb
122
+ - lib/async/runner/job.rb
123
+ - lib/async/runner/version.rb
124
+ homepage: https://github.com/webgago/async-runner
125
+ licenses:
126
+ - MIT
127
+ metadata: {}
128
+ post_install_message:
129
+ rdoc_options: []
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '3.1'
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ requirements: []
143
+ rubygems_version: 3.3.7
144
+ signing_key:
145
+ specification_version: 4
146
+ summary: Abstract runner with container-based parallelism using threads and processes
147
+ where appropriate.
148
+ test_files: []