multi_process 0.4.0 → 0.5.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0ed246c253f6ea4749f55ee0fecb88362b14f4ee
4
- data.tar.gz: 3dc45356e8af8de981bf7aa55ba01e15d0e94af5
3
+ metadata.gz: b79dfed9809a87ffa684f477aa18f52ab0874998
4
+ data.tar.gz: a2499bf8685aaa502893af7848d7de805e104e5a
5
5
  SHA512:
6
- metadata.gz: a1d41519fa0047ed43402b2999183dcf5a38f75a1ed21081d81c3720877c4186d60fc66e845050bc28a4b3e1d9d2edae05f68cc4e57376a5e1601dd0adf5d471
7
- data.tar.gz: b12e9cd8912107d2e0cf63401c7c11dbd0a20c92573ecf5a1c9191e8191dcccecaba7742049f85d5ee49b64e3b39b576ded43e903ca7417528c98c1bb5b9f3b6
6
+ metadata.gz: 12f8ae434f79b4168460722d3cff268ae2b230084e89ff000e9c758a3d8f625d47bf3a7d0a8169db4e2e6df36e61e1e0920f8192c89cdb526a814f4d3789d07d
7
+ data.tar.gz: 10e081ebeb820e7563fd9c91c50c962216283c7cee939da51b8adbcc74e49d72d983e6df9e4415c71f6b383e4ebaa5e8069b3968fdbff76b9e17e2a1fce19f0a
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # MultiProcess
2
2
 
3
- Handle multiple processes.
3
+ Handle multiple processes. Ruby >= 2.0.
4
4
 
5
5
  TODO: Just experiment.
6
6
 
data/Rakefile CHANGED
@@ -2,4 +2,4 @@ require 'bundler/gem_tasks'
2
2
  require 'rspec/core/rake_task'
3
3
 
4
4
  RSpec::Core::RakeTask.new(:spec)
5
- task :default => :spec
5
+ task default: :spec
@@ -1,9 +1,9 @@
1
1
  module MultiProcess
2
-
2
+ #
3
3
  # Store and run a group of processes.
4
4
  #
5
5
  class Group
6
-
6
+ #
7
7
  # Return list of processes.
8
8
  attr_reader :processes
9
9
 
@@ -22,10 +22,10 @@ module MultiProcess
22
22
  # @option otps [ Receiver ] :receiver Receiver to use for new added
23
23
  # processes. Defaults to `MultiProcess::Logger.global`.
24
24
  #
25
- def initialize(opts = {})
25
+ def initialize(receiver: nil, partition: nil)
26
26
  @processes = []
27
- @receiver = opts[:receiver] ? opts[:receiver] : MultiProcess::Logger.global
28
- @partition = opts[:partition] ? opts[:partition].to_i : 0
27
+ @receiver = receiver ? receiver : MultiProcess::Logger.global
28
+ @partition = partition ? partition.to_i : 0
29
29
  @mutex = Mutex.new
30
30
  end
31
31
 
@@ -35,14 +35,12 @@ module MultiProcess
35
35
  #
36
36
  # @param process [Process, Array<Process>] New process or processes.
37
37
  #
38
- def <<(process)
39
- Array(process).flatten.each do |process|
38
+ def <<(processes)
39
+ Array(processes).flatten.each do |process|
40
40
  processes << process
41
41
  process.receiver = receiver
42
42
 
43
- if started?
44
- start process
45
- end
43
+ start process if started?
46
44
  end
47
45
  end
48
46
 
@@ -50,15 +48,14 @@ module MultiProcess
50
48
  #
51
49
  # Call blocks until all processes are started.
52
50
  #
53
- # @param opts [ Hash ] Options.
54
- # @option opts [ Integer ] :delay Delay in seconds between starting processes.
51
+ # @option delay [Integer] Delay in seconds between starting processes.
55
52
  #
56
- def start(opts = {})
53
+ def start(delay: nil)
57
54
  processes.each do |process|
58
- unless process.started?
59
- process.start
60
- sleep opts[:delay] if opts[:delay]
61
- end
55
+ next if process.started?
56
+
57
+ process.start
58
+ sleep delay if delay
62
59
  end
63
60
  end
64
61
 
@@ -67,15 +64,13 @@ module MultiProcess
67
64
  # @return [ Boolean ] True if group was already started.
68
65
  #
69
66
  def started?
70
- processes.any? &:started?
67
+ processes.any?(&:started?)
71
68
  end
72
69
 
73
70
  # Stop all processes.
74
71
  #
75
72
  def stop
76
- processes.each do |process|
77
- process.stop
78
- end
73
+ processes.each(&:stop)
79
74
  end
80
75
 
81
76
  # Wait until all process terminated.
@@ -84,11 +79,11 @@ module MultiProcess
84
79
  # @option opts [ Integer ] :timeout Timeout in seconds to wait before
85
80
  # raising {Timeout::Error}.
86
81
  #
87
- def wait(opts = {})
88
- opts[:timeout] ||= 30
89
-
90
- ::Timeout::timeout(opts[:timeout]) do
91
- processes.each{|p| p.wait}
82
+ def wait(timeout: nil)
83
+ if timeout
84
+ ::Timeout.timeout(timeout) { wait }
85
+ else
86
+ processes.each(&:wait)
92
87
  end
93
88
  end
94
89
 
@@ -100,20 +95,18 @@ module MultiProcess
100
95
  # If timeout is given process will be terminated using {#stop}
101
96
  # when timeout error is raised.
102
97
  #
103
- def run(opts = {})
98
+ def run(**kwargs)
104
99
  if partition > 0
105
- threads = Array.new
106
- partition.times do
107
- threads << Thread.new do
100
+ partition.times.map do
101
+ Thread.new do
108
102
  while (process = next_process)
109
103
  process.run
110
104
  end
111
105
  end
112
- end
113
- threads.each &:join
106
+ end.each(&:join)
114
107
  else
115
- start opts
116
- wait opts
108
+ start(**kwargs)
109
+ wait(**kwargs)
117
110
  end
118
111
  ensure
119
112
  stop
@@ -124,14 +117,14 @@ module MultiProcess
124
117
  # @return [ Boolean ] True if group is alive.
125
118
  #
126
119
  def alive?
127
- processes.any? &:alive?
120
+ processes.any?(&:alive?)
128
121
  end
129
122
 
130
123
  # Check if group is available. The group is available if all
131
124
  # processes are available.
132
125
  #
133
126
  def available?
134
- !processes.any?{|p| !p.available? }
127
+ processes.all?(:available?)
135
128
  end
136
129
 
137
130
  # Wait until group is available. This implies waiting until
@@ -143,15 +136,14 @@ module MultiProcess
143
136
  # @option opts [ Integer ] :timeout Timeout in seconds to wait for processes
144
137
  # to become available. Defaults to {MultiProcess::DEFAULT_TIMEOUT}.
145
138
  #
146
- def available!(opts = {})
147
- timeout = opts[:timeout] ? opts[:timeout].to_i : MultiProcess::DEFAULT_TIMEOUT
148
-
139
+ def available!(timeout: MultiProcess::DEFAULT_TIMEOUT)
149
140
  Timeout.timeout timeout do
150
- processes.each{|p| p.available! }
141
+ processes.each(&:available!)
151
142
  end
152
143
  end
153
144
 
154
145
  private
146
+
155
147
  def next_process
156
148
  @mutex.synchronize do
157
149
  @index ||= 0
@@ -1,11 +1,9 @@
1
1
  module MultiProcess
2
-
3
2
  # Can create pipes and multiplex pipe content to put into
4
3
  # given IO objects e.g. multiple output from multiple
5
4
  # processes to current stdout.
6
5
  #
7
6
  class Logger < Receiver
8
-
9
7
  # Create new logger.
10
8
  #
11
9
  # @param out [IO] IO to push formatted output from
@@ -14,7 +12,7 @@ module MultiProcess
14
12
  # error sources.
15
13
  #
16
14
  def initialize(*args)
17
- @opts = Hash === args.last ? args.pop : Hash.new
15
+ @opts = Hash === args.last ? args.pop : {}
18
16
  @out = args[0] || $stdout
19
17
  @err = args[1] || $stderr
20
18
 
@@ -43,14 +41,15 @@ module MultiProcess
43
41
  end
44
42
 
45
43
  private
44
+
46
45
  def output(process, line, opts = {})
47
46
  @mutex.synchronize do
48
47
  opts[:delimiter] ||= ' |'
49
48
  name = if opts[:name]
50
- opts[:name].to_s.dup
51
- else
52
- max = @readers.values.map{|h| h[:process] ? h[:process].title.length : 0 }.max
53
- process ? process.title.to_s.rjust(max, ' ') : (' ' * max)
49
+ opts[:name].to_s.dup
50
+ else
51
+ max = @readers.values.map { |h| h[:process] ? h[:process].title.length : 0 }.max
52
+ process ? process.title.to_s.rjust(max, ' ') : (' ' * max)
54
53
  end
55
54
 
56
55
  io = opts[:io] || @out
@@ -68,7 +67,7 @@ module MultiProcess
68
67
 
69
68
  class << self
70
69
  def global
71
- @global ||= self.new $stdout, $stderr
70
+ @global ||= new $stdout, $stderr
72
71
  end
73
72
  end
74
73
  end
@@ -1,12 +1,10 @@
1
1
  module MultiProcess
2
-
3
2
  # Receiver implementation that does nothing on every input.
4
3
  #
5
4
  class NilReceiver < Receiver
6
-
7
5
  # Do nothing.
8
6
  #
9
- def received(process, name, message)
7
+ def received(_process, _name, _message)
10
8
  nil
11
9
  end
12
10
  end
@@ -1,13 +1,13 @@
1
1
  require 'active_support/core_ext/module/delegation'
2
2
 
3
3
  module MultiProcess
4
-
4
+ #
5
5
  # Describes a single process that can be configured and run.
6
6
  #
7
7
  # {Process} basically is just a thin wrapper around {ChildProcess}.
8
8
  #
9
9
  class Process
10
- #@!group Process
10
+ # @!group Process
11
11
 
12
12
  # Process title used in e.g. logger
13
13
  attr_reader :title
@@ -23,7 +23,7 @@ module MultiProcess
23
23
  opts = (Hash === args.last ? args.pop : {})
24
24
 
25
25
  @title = opts[:title].to_s || args.first.to_s.strip.split(/\s+/, 2)[0]
26
- @command = args.map{ |arg| (arg =~ /\A[\s"']+\z/ ? arg.inspect : arg).gsub '"', '\"' }.join(' ')
26
+ @command = args.map { |arg| (arg =~ /\A[\s"']+\z/ ? arg.inspect : arg).gsub '"', '\"' }.join(' ')
27
27
  @childprocess = create_childprocess *args
28
28
 
29
29
  @env = opts[:env] if Hash === opts[:env]
@@ -63,7 +63,7 @@ module MultiProcess
63
63
  return false if started?
64
64
 
65
65
  at_exit { stop }
66
- receiver.message(self, :sys, self.command) if receiver
66
+ receiver.message(self, :sys, command) if receiver
67
67
  start_childprocess
68
68
  @started = true
69
69
  end
@@ -116,7 +116,7 @@ module MultiProcess
116
116
  wait opts
117
117
  end
118
118
 
119
- #@!group Working Directory
119
+ # @!group Working Directory
120
120
 
121
121
  # Working directory for child process.
122
122
  attr_reader :dir
@@ -126,10 +126,10 @@ module MultiProcess
126
126
  #
127
127
  def dir=(dir)
128
128
  @dir = ::File.expand_path(dir.to_s)
129
- self.env['PWD'] = @dir
129
+ env['PWD'] = @dir
130
130
  end
131
131
 
132
- #@!group Environment
132
+ # @!group Environment
133
133
 
134
134
  # Check if environment will be cleaned up for process.
135
135
  #
@@ -144,17 +144,17 @@ module MultiProcess
144
144
  # Return current environment.
145
145
  #
146
146
  def env
147
- @env ||= Hash.new
147
+ @env ||= {}
148
148
  end
149
149
 
150
150
  # Set environment.
151
151
  #
152
152
  def env=(env)
153
- raise ArgumentError.new 'Environment must be a Hash.' unless hash === env
153
+ fail ArgumentError.new 'Environment must be a Hash.' unless hash === env
154
154
  @env = env
155
155
  end
156
156
 
157
- #@!group Receiver
157
+ # @!group Receiver
158
158
 
159
159
  # Current receiver. Defaults to `MultiProcess::Logger.global`.
160
160
  #
@@ -186,7 +186,7 @@ module MultiProcess
186
186
  # Can be used to hook in subclasses and modules.
187
187
  #
188
188
  def start_childprocess
189
- env.each{|k, v| childprocess.environment[k.to_s] = v.to_s }
189
+ env.each { |k, v| childprocess.environment[k.to_s] = v.to_s }
190
190
  childprocess.cwd = dir
191
191
 
192
192
  if clean_env?
@@ -1,12 +1,10 @@
1
1
  class MultiProcess::Process
2
-
3
2
  # Provides functionality to wrap command in with bundle
4
3
  # execute.
5
4
  #
6
5
  module BundleExec
7
-
8
6
  def initialize(*args)
9
- opts = Hash === args.last ? args.pop : Hash.new
7
+ opts = Hash === args.last ? args.pop : {}
10
8
  super %w(bundle exec) + args, opts
11
9
  end
12
10
  end
@@ -1,5 +1,4 @@
1
1
  class MultiProcess::Process
2
-
3
2
  # Provides functionality for a process that is a rails server
4
3
  # process.
5
4
  #
@@ -9,7 +8,6 @@ class MultiProcess::Process
9
8
  # availability check based on if server socket is reachable.
10
9
  #
11
10
  module Rails
12
-
13
11
  # Server wrapper given as argument to `server` action.
14
12
  #
15
13
  attr_reader :server
@@ -44,7 +42,7 @@ class MultiProcess::Process
44
42
  end
45
43
 
46
44
  def available?
47
- raise ArgumentError.new "Cannot check availability for port #{port}." if port == 0
45
+ fail ArgumentError.new "Cannot check availability for port #{port}." if port == 0
48
46
 
49
47
  TCPSocket.new('127.0.0.1', port).close
50
48
  true
@@ -69,7 +67,7 @@ class MultiProcess::Process
69
67
 
70
68
  def free_port
71
69
  socket = Socket.new(:INET, :STREAM, 0)
72
- socket.bind(Addrinfo.tcp("127.0.0.1", 0))
70
+ socket.bind(Addrinfo.tcp('127.0.0.1', 0))
73
71
  socket.local_address.ip_port
74
72
  ensure
75
73
  socket.close if socket
@@ -1,10 +1,8 @@
1
1
  module MultiProcess
2
-
3
2
  # Can handle input from multiple processes and run custom
4
3
  # actions on event and output.
5
4
  #
6
5
  class Receiver
7
-
8
6
  # Mutex to synchronize operations.
9
7
  #
10
8
  attr_reader :mutex
@@ -21,7 +19,7 @@ module MultiProcess
21
19
  op = @readers[reader]
22
20
 
23
21
  if reader.eof?
24
- @readers.delete_if { |key, value| key == reader }
22
+ @readers.delete_if { |key, _value| key == reader }
25
23
  removed op[:process], op[:name]
26
24
  else
27
25
  received op[:process], op[:name], read(reader)
@@ -43,7 +41,7 @@ module MultiProcess
43
41
  #
44
42
  def pipe(process, name)
45
43
  reader, writer = IO.pipe
46
- @readers[reader] = {name: name, process: process}
44
+ @readers[reader] = { name: name, process: process }
47
45
  connected process, name
48
46
  writer
49
47
  end
@@ -61,8 +59,8 @@ module MultiProcess
61
59
  #
62
60
  # Must be overridden by subclass.
63
61
  #
64
- def received(process, name, message)
65
- raise NotImplementedError.new 'Subclass responsibility.'
62
+ def received(_process, _name, _message)
63
+ fail NotImplementedError.new 'Subclass responsibility.'
66
64
  end
67
65
 
68
66
  # Read content from pipe. Can be used to provide custom reading
@@ -77,14 +75,12 @@ module MultiProcess
77
75
  # Called after pipe for process and name was removed because it
78
76
  # reached EOF.
79
77
  #
80
- def removed(process, name)
81
-
78
+ def removed(_process, _name)
82
79
  end
83
80
 
84
81
  # Called after new pipe for process and name was created.
85
82
  #
86
- def connected(process, name)
87
-
83
+ def connected(_process, _name)
88
84
  end
89
85
  end
90
86
  end
@@ -1,17 +1,15 @@
1
1
  module MultiProcess
2
-
3
2
  # Receiver implementation storing process output
4
3
  # in string.
5
4
  #
6
5
  class StringReceiver < Receiver
7
-
8
- def received(process, name, message)
6
+ def received(_process, name, message)
9
7
  get(name) << message
10
8
  end
11
9
 
12
10
  def get(name)
13
- @strings ||= Hash.new
14
- @strings[name.to_s] ||= String.new
11
+ @strings ||= {}
12
+ @strings[name.to_s] ||= ''
15
13
  end
16
14
  end
17
15
  end
@@ -1,11 +1,13 @@
1
1
  module MultiProcess
2
2
  module VERSION
3
3
  MAJOR = 0
4
- MINOR = 4
4
+ MINOR = 5
5
5
  PATCH = 0
6
6
  STAGE = nil
7
7
  STRING = [MAJOR, MINOR, PATCH, STAGE].reject(&:nil?).join('.')
8
8
 
9
- def self.to_s; STRING end
9
+ def self.to_s
10
+ STRING
11
+ end
10
12
  end
11
13
  end
@@ -4,22 +4,22 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'multi_process/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.name = "multi_process"
7
+ spec.name = 'multi_process'
8
8
  spec.version = MultiProcess::VERSION
9
- spec.authors = ["Jan Graichen"]
10
- spec.email = ["jg@altimos.de"]
11
- spec.summary = %q{Handle multiple child processes.}
12
- spec.description = %q{Handle multiple child processes.}
13
- spec.homepage = "https://github.com/jgraichen/multi_process"
14
- spec.license = "GPLv3"
9
+ spec.authors = ['Jan Graichen']
10
+ spec.email = ['jg@altimos.de']
11
+ spec.summary = 'Handle multiple child processes.'
12
+ spec.description = 'Handle multiple child processes.'
13
+ spec.homepage = 'https://github.com/jgraichen/multi_process'
14
+ spec.license = 'GPLv3'
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0")
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ["lib"]
19
+ spec.require_paths = ['lib']
20
20
 
21
21
  spec.add_runtime_dependency 'activesupport', '>= 3.1'
22
22
  spec.add_runtime_dependency 'childprocess'
23
23
 
24
- spec.add_development_dependency "bundler", "~> 1.5"
24
+ spec.add_development_dependency 'bundler', '~> 1.5'
25
25
  end
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe MultiProcess do
4
-
5
4
  it 'should run processes' do
6
5
  reader, writer = IO.pipe
7
6
 
@@ -57,7 +56,7 @@ describe MultiProcess do
57
56
 
58
57
  it 'should env processes' do
59
58
  receiver = MultiProcess::StringReceiver.new
60
- process = MultiProcess::Process.new(%w(ruby spec/files/env.rb TEST), env: {'TEST' => "abc"}, receiver: receiver)
59
+ process = MultiProcess::Process.new(%w(ruby spec/files/env.rb TEST), env: { 'TEST' => 'abc' }, receiver: receiver)
61
60
  process.run
62
61
 
63
62
  expect(receiver.get(:out)).to eq "ENV: abc\n"
data/spec/spec_helper.rb CHANGED
@@ -5,7 +5,7 @@ Bundler.require
5
5
 
6
6
  require 'multi_process'
7
7
 
8
- Dir[File.expand_path('spec/support/**/*.rb')].each {|f| require f}
8
+ Dir[File.expand_path('spec/support/**/*.rb')].each { |f| require f }
9
9
 
10
10
  RSpec.configure do |config|
11
11
  # ## Mock Framework
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: multi_process
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jan Graichen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-16 00:00:00.000000000 Z
11
+ date: 2015-04-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -100,7 +100,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
100
100
  version: '0'
101
101
  requirements: []
102
102
  rubyforge_project:
103
- rubygems_version: 2.2.1
103
+ rubygems_version: 2.4.6
104
104
  signing_key:
105
105
  specification_version: 4
106
106
  summary: Handle multiple child processes.