procrastinate 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/HISTORY.txt +6 -0
- data/README +1 -1
- data/lib/procrastinate/process_manager.rb +20 -36
- data/lib/procrastinate/process_manager/child_process.rb +21 -0
- metadata +28 -60
- data/Rakefile +0 -36
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d211f3ecc75813707fd6acdb559783e5b1aa7124
|
4
|
+
data.tar.gz: 863ff06f3edb224c5edca1f38d88455a7c1c844f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7adc67259467bdfc350ea453de21574447deabff894ad65d80586b096a6306390be1729a06e5bdd00c61423ebd6bcb31835ef2efcdb1515b7057fd32acdac8a4
|
7
|
+
data.tar.gz: 62e94303c101c092b49efdb3f759169075f03e2972a3ec3ffe4d9c77d2973e0b12fe1137dc5cf98fc19a3ff9f2c0927bf03cc916aeb8cdebedc34fa855b517e7
|
data/HISTORY.txt
CHANGED
data/README
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
|
2
2
|
require 'state_machine'
|
3
|
-
require 'cod'
|
4
3
|
|
5
4
|
# Dispatches and handles tasks and task completion. Only low level unixy
|
6
5
|
# manipulation here, no strategy. The only methods you should call from the
|
@@ -23,9 +22,6 @@ class Procrastinate::ProcessManager
|
|
23
22
|
|
24
23
|
# All presently running children
|
25
24
|
@children = {}
|
26
|
-
|
27
|
-
# Master should read from @master, Children write to @child
|
28
|
-
@master, @child = Cod.pipe.split
|
29
25
|
end
|
30
26
|
|
31
27
|
# Sets up resource usage for dispatcher. You must call this before dispatcher
|
@@ -95,21 +91,31 @@ class Procrastinate::ProcessManager
|
|
95
91
|
cp_read_end = control_pipe.first
|
96
92
|
|
97
93
|
loop do # until we have input in the cp_read_end (control_pipe)
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
94
|
+
io_map = children.inject({}) { |map, (_, child)|
|
95
|
+
map[child.master_pipe] = child; map }
|
96
|
+
|
97
|
+
ready, _, _ = IO.select(io_map.keys + [cp_read_end], [], [], 0.1)
|
98
|
+
next unless ready
|
99
|
+
|
100
|
+
# Process all messages that were sent from our childs to us.
|
101
|
+
ready.each { |io|
|
102
|
+
next if io == cp_read_end
|
104
103
|
|
104
|
+
child = io_map[io]
|
105
|
+
|
106
|
+
fail "Assert: All IOs correspond to a child" unless child
|
107
|
+
child.read_message
|
108
|
+
}
|
109
|
+
|
105
110
|
# Send the tracking code for the child processes the final notifications
|
106
111
|
# and remove them from the children hash. At this point we know that
|
107
112
|
# no messages are waiting in the child queue.
|
108
113
|
finalize_children
|
109
114
|
|
110
|
-
if ready.
|
115
|
+
if ready.include?(cp_read_end)
|
111
116
|
# Consume the data (not important)
|
112
117
|
cp_read_end.read_nonblock(1024)
|
118
|
+
# And return to our caller. This is the event we've been waiting for.
|
113
119
|
return
|
114
120
|
end
|
115
121
|
end
|
@@ -124,28 +130,6 @@ class Procrastinate::ProcessManager
|
|
124
130
|
child.removable? }
|
125
131
|
end
|
126
132
|
|
127
|
-
def read_child_messages
|
128
|
-
loop do
|
129
|
-
ready = Cod.select(0.1, @master)
|
130
|
-
break unless ready
|
131
|
-
|
132
|
-
handle_message @master.get
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
# Called for every message sent from a child. The +msg+ param here is a string
|
137
|
-
# that still needs decoding.
|
138
|
-
#
|
139
|
-
def handle_message(msg)
|
140
|
-
pid, obj = msg
|
141
|
-
|
142
|
-
if child=children[pid]
|
143
|
-
child.incoming_message(obj)
|
144
|
-
else
|
145
|
-
warn "Communication from child #{pid} received, but child is gone."
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
133
|
# Calls completion handlers for all the childs that have now exited.
|
150
134
|
#
|
151
135
|
def reap_childs
|
@@ -183,12 +167,13 @@ class Procrastinate::ProcessManager
|
|
183
167
|
# Tasks that are interested in getting messages from their childs must
|
184
168
|
# provide a result object that handles incoming 'result' messages.
|
185
169
|
result = task.result
|
170
|
+
child_process = ChildProcess.new(completion_handler, result)
|
186
171
|
|
187
172
|
pid = fork do
|
188
173
|
cleanup
|
189
174
|
|
190
175
|
if result
|
191
|
-
endpoint = lambda { |obj|
|
176
|
+
endpoint = lambda { |obj| child_process.send_message(obj) }
|
192
177
|
task.run(endpoint)
|
193
178
|
else
|
194
179
|
task.run(nil)
|
@@ -204,8 +189,7 @@ class Procrastinate::ProcessManager
|
|
204
189
|
# The spawning is done in the same thread as the reaping is done. This is
|
205
190
|
# why no race condition to the following line exists. (or in other code,
|
206
191
|
# for that matter.)
|
207
|
-
children[pid] =
|
208
|
-
tap { |s| s.start }
|
192
|
+
children[pid] = child_process.tap { |s| s.start }
|
209
193
|
end
|
210
194
|
|
211
195
|
# Gets executed in child process to clean up file handles and pipes that the
|
@@ -4,9 +4,13 @@
|
|
4
4
|
#
|
5
5
|
Procrastinate::ProcessManager::ChildProcess =
|
6
6
|
Struct.new(:handler, :result, :state) do
|
7
|
+
|
8
|
+
attr_reader :master_pipe, :child_pipe
|
7
9
|
|
8
10
|
def initialize(handler, result)
|
9
11
|
super(handler, result, "new")
|
12
|
+
|
13
|
+
@master_pipe, @child_pipe = IO.pipe
|
10
14
|
end
|
11
15
|
|
12
16
|
state_machine :state, :initial => :new do
|
@@ -33,6 +37,10 @@ Procrastinate::ProcessManager::ChildProcess =
|
|
33
37
|
#
|
34
38
|
def notify_result
|
35
39
|
result.process_died if result
|
40
|
+
|
41
|
+
# The child is now officially dead, so we don't need these anymore:
|
42
|
+
@master_pipe.close
|
43
|
+
@child_pipe.close
|
36
44
|
end
|
37
45
|
|
38
46
|
# Handles incoming messages from the tasks process.
|
@@ -40,4 +48,17 @@ Procrastinate::ProcessManager::ChildProcess =
|
|
40
48
|
def incoming_message(obj)
|
41
49
|
result.incoming_message(obj) if result
|
42
50
|
end
|
51
|
+
|
52
|
+
# Read and process a message from the process that is connected to this
|
53
|
+
# object. Normally, we would make sure that such a message is indeed waiting
|
54
|
+
# on the master_pipe by means of an IO select.
|
55
|
+
#
|
56
|
+
def read_message
|
57
|
+
msg = Marshal.load(master_pipe)
|
58
|
+
incoming_message(msg)
|
59
|
+
end
|
60
|
+
|
61
|
+
def send_message obj
|
62
|
+
Marshal.dump(obj, child_pipe)
|
63
|
+
end
|
43
64
|
end
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: procrastinate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.6.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Kaspar Schiess
|
@@ -10,136 +9,106 @@ authors:
|
|
10
9
|
autorequire:
|
11
10
|
bindir: bin
|
12
11
|
cert_chain: []
|
13
|
-
date:
|
12
|
+
date: 2013-11-20 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: state_machine
|
17
|
-
prerelease: false
|
18
16
|
requirement: !ruby/object:Gem::Requirement
|
19
17
|
requirements:
|
20
18
|
- - ~>
|
21
19
|
- !ruby/object:Gem::Version
|
22
20
|
version: '1.1'
|
23
|
-
none: false
|
24
21
|
type: :runtime
|
25
|
-
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
requirements:
|
27
|
-
- - ~>
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '1.1'
|
30
|
-
none: false
|
31
|
-
- !ruby/object:Gem::Dependency
|
32
|
-
name: cod
|
33
22
|
prerelease: false
|
34
|
-
requirement: !ruby/object:Gem::Requirement
|
35
|
-
requirements:
|
36
|
-
- - ~>
|
37
|
-
- !ruby/object:Gem::Version
|
38
|
-
version: '0.5'
|
39
|
-
none: false
|
40
|
-
type: :runtime
|
41
23
|
version_requirements: !ruby/object:Gem::Requirement
|
42
24
|
requirements:
|
43
25
|
- - ~>
|
44
26
|
- !ruby/object:Gem::Version
|
45
|
-
version: '
|
46
|
-
none: false
|
27
|
+
version: '1.1'
|
47
28
|
- !ruby/object:Gem::Dependency
|
48
29
|
name: rake
|
49
|
-
prerelease: false
|
50
30
|
requirement: !ruby/object:Gem::Requirement
|
51
31
|
requirements:
|
52
|
-
- -
|
32
|
+
- - '>='
|
53
33
|
- !ruby/object:Gem::Version
|
54
34
|
version: '0'
|
55
|
-
none: false
|
56
35
|
type: :development
|
36
|
+
prerelease: false
|
57
37
|
version_requirements: !ruby/object:Gem::Requirement
|
58
38
|
requirements:
|
59
|
-
- -
|
39
|
+
- - '>='
|
60
40
|
- !ruby/object:Gem::Version
|
61
41
|
version: '0'
|
62
|
-
none: false
|
63
42
|
- !ruby/object:Gem::Dependency
|
64
43
|
name: rspec
|
65
|
-
prerelease: false
|
66
44
|
requirement: !ruby/object:Gem::Requirement
|
67
45
|
requirements:
|
68
|
-
- -
|
46
|
+
- - '>='
|
69
47
|
- !ruby/object:Gem::Version
|
70
48
|
version: '0'
|
71
|
-
none: false
|
72
49
|
type: :development
|
50
|
+
prerelease: false
|
73
51
|
version_requirements: !ruby/object:Gem::Requirement
|
74
52
|
requirements:
|
75
|
-
- -
|
53
|
+
- - '>='
|
76
54
|
- !ruby/object:Gem::Version
|
77
55
|
version: '0'
|
78
|
-
none: false
|
79
56
|
- !ruby/object:Gem::Dependency
|
80
57
|
name: flexmock
|
81
|
-
prerelease: false
|
82
58
|
requirement: !ruby/object:Gem::Requirement
|
83
59
|
requirements:
|
84
|
-
- -
|
60
|
+
- - '>='
|
85
61
|
- !ruby/object:Gem::Version
|
86
62
|
version: '0'
|
87
|
-
none: false
|
88
63
|
type: :development
|
64
|
+
prerelease: false
|
89
65
|
version_requirements: !ruby/object:Gem::Requirement
|
90
66
|
requirements:
|
91
|
-
- -
|
67
|
+
- - '>='
|
92
68
|
- !ruby/object:Gem::Version
|
93
69
|
version: '0'
|
94
|
-
none: false
|
95
70
|
- !ruby/object:Gem::Dependency
|
96
71
|
name: guard
|
97
|
-
prerelease: false
|
98
72
|
requirement: !ruby/object:Gem::Requirement
|
99
73
|
requirements:
|
100
|
-
- -
|
74
|
+
- - '>='
|
101
75
|
- !ruby/object:Gem::Version
|
102
76
|
version: '0'
|
103
|
-
none: false
|
104
77
|
type: :development
|
78
|
+
prerelease: false
|
105
79
|
version_requirements: !ruby/object:Gem::Requirement
|
106
80
|
requirements:
|
107
|
-
- -
|
81
|
+
- - '>='
|
108
82
|
- !ruby/object:Gem::Version
|
109
83
|
version: '0'
|
110
|
-
none: false
|
111
84
|
- !ruby/object:Gem::Dependency
|
112
85
|
name: growl
|
113
|
-
prerelease: false
|
114
86
|
requirement: !ruby/object:Gem::Requirement
|
115
87
|
requirements:
|
116
|
-
- -
|
88
|
+
- - '>='
|
117
89
|
- !ruby/object:Gem::Version
|
118
90
|
version: '0'
|
119
|
-
none: false
|
120
91
|
type: :development
|
92
|
+
prerelease: false
|
121
93
|
version_requirements: !ruby/object:Gem::Requirement
|
122
94
|
requirements:
|
123
|
-
- -
|
95
|
+
- - '>='
|
124
96
|
- !ruby/object:Gem::Version
|
125
97
|
version: '0'
|
126
|
-
none: false
|
127
98
|
- !ruby/object:Gem::Dependency
|
128
99
|
name: yard
|
129
|
-
prerelease: false
|
130
100
|
requirement: !ruby/object:Gem::Requirement
|
131
101
|
requirements:
|
132
|
-
- -
|
102
|
+
- - '>='
|
133
103
|
- !ruby/object:Gem::Version
|
134
104
|
version: '0'
|
135
|
-
none: false
|
136
105
|
type: :development
|
106
|
+
prerelease: false
|
137
107
|
version_requirements: !ruby/object:Gem::Requirement
|
138
108
|
requirements:
|
139
|
-
- -
|
109
|
+
- - '>='
|
140
110
|
- !ruby/object:Gem::Version
|
141
111
|
version: '0'
|
142
|
-
none: false
|
143
112
|
description:
|
144
113
|
email:
|
145
114
|
- kaspar.schiess@absurd.li
|
@@ -151,7 +120,6 @@ extra_rdoc_files:
|
|
151
120
|
files:
|
152
121
|
- HISTORY.txt
|
153
122
|
- LICENSE
|
154
|
-
- Rakefile
|
155
123
|
- README
|
156
124
|
- lib/procrastinate/implicit.rb
|
157
125
|
- lib/procrastinate/lock.rb
|
@@ -178,7 +146,9 @@ files:
|
|
178
146
|
- examples/simple.rb
|
179
147
|
- examples/throttled.rb
|
180
148
|
homepage: http://github.com/kschiess/procrastinate
|
181
|
-
licenses:
|
149
|
+
licenses:
|
150
|
+
- MIT
|
151
|
+
metadata: {}
|
182
152
|
post_install_message:
|
183
153
|
rdoc_options:
|
184
154
|
- --main
|
@@ -187,21 +157,19 @@ require_paths:
|
|
187
157
|
- lib
|
188
158
|
required_ruby_version: !ruby/object:Gem::Requirement
|
189
159
|
requirements:
|
190
|
-
- -
|
160
|
+
- - '>='
|
191
161
|
- !ruby/object:Gem::Version
|
192
162
|
version: '0'
|
193
|
-
none: false
|
194
163
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
195
164
|
requirements:
|
196
|
-
- -
|
165
|
+
- - '>='
|
197
166
|
- !ruby/object:Gem::Version
|
198
167
|
version: '0'
|
199
|
-
none: false
|
200
168
|
requirements: []
|
201
169
|
rubyforge_project:
|
202
|
-
rubygems_version:
|
170
|
+
rubygems_version: 2.0.6
|
203
171
|
signing_key:
|
204
|
-
specification_version:
|
172
|
+
specification_version: 4
|
205
173
|
summary: Framework to run tasks in separate processes.
|
206
174
|
test_files: []
|
207
175
|
has_rdoc:
|
data/Rakefile
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
require "rubygems"
|
2
|
-
require 'rspec/core/rake_task'
|
3
|
-
require 'rubygems/package_task'
|
4
|
-
require 'rake/clean'
|
5
|
-
|
6
|
-
desc "Run all tests: Exhaustive."
|
7
|
-
RSpec::Core::RakeTask.new
|
8
|
-
|
9
|
-
task :default => :spec
|
10
|
-
|
11
|
-
task :stats do
|
12
|
-
%w(lib spec).each do |path|
|
13
|
-
printf "%10s:", path
|
14
|
-
system %Q(find #{path} -name "*.rb" | xargs wc -l | grep total)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
require 'yard'
|
19
|
-
YARD::Rake::YardocTask.new do |t|
|
20
|
-
# t.files = ['lib/**/*.rb']
|
21
|
-
# t.options = ['--any', '--extra', '--opts'] # optional
|
22
|
-
end
|
23
|
-
|
24
|
-
desc 'Clear out RDoc'
|
25
|
-
task :clean => [:clobber_package]
|
26
|
-
|
27
|
-
# This task actually builds the gem.
|
28
|
-
task :gem => :spec
|
29
|
-
spec = eval(File.read('procrastinate.gemspec'))
|
30
|
-
|
31
|
-
desc "Generate the gem package."
|
32
|
-
Gem::PackageTask.new(spec) do |pkg|
|
33
|
-
# pkg.need_tar = true
|
34
|
-
end
|
35
|
-
|
36
|
-
CLEAN << 'doc'
|