multi_process 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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.