procrastinate 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY.txt +2 -1
- data/Rakefile +8 -11
- data/examples/server.rb +31 -0
- data/lib/procrastinate.rb +2 -1
- data/lib/procrastinate/implicit.rb +19 -16
- data/lib/procrastinate/process_manager.rb +20 -5
- data/lib/procrastinate/scheduler.rb +59 -13
- data/lib/procrastinate/server.rb +78 -0
- data/lib/procrastinate/task/callable.rb +1 -1
- metadata +88 -40
data/HISTORY.txt
CHANGED
data/Rakefile
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require "rubygems"
|
2
|
-
require "rdoc/task"
|
3
2
|
require 'rspec/core/rake_task'
|
4
3
|
require 'rubygems/package_task'
|
4
|
+
require 'rake/clean'
|
5
5
|
|
6
6
|
desc "Run all tests: Exhaustive."
|
7
7
|
RSpec::Core::RakeTask.new
|
@@ -15,19 +15,14 @@ task :stats do
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
rdoc.options << '--fmt' << 'shtml' # explictly set shtml generator
|
23
|
-
rdoc.template = 'direct' # lighter template used on railsapi.com
|
24
|
-
rdoc.main = "README"
|
25
|
-
rdoc.rdoc_files.include("README", "lib/**/*.rb")
|
26
|
-
rdoc.rdoc_dir = "rdoc"
|
18
|
+
require 'yard'
|
19
|
+
YARD::Rake::YardocTask.new do |t|
|
20
|
+
# t.files = ['lib/**/*.rb']
|
21
|
+
# t.options = ['--any', '--extra', '--opts'] # optional
|
27
22
|
end
|
28
23
|
|
29
24
|
desc 'Clear out RDoc'
|
30
|
-
task :clean => [:
|
25
|
+
task :clean => [:clobber_package]
|
31
26
|
|
32
27
|
# This task actually builds the gem.
|
33
28
|
task :gem => :spec
|
@@ -37,3 +32,5 @@ desc "Generate the gem package."
|
|
37
32
|
Gem::PackageTask.new(spec) do |pkg|
|
38
33
|
# pkg.need_tar = true
|
39
34
|
end
|
35
|
+
|
36
|
+
CLEAN << 'doc'
|
data/examples/server.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
$:.unshift File.dirname(__FILE__) + '/../lib'
|
3
|
+
|
4
|
+
require 'procrastinate'
|
5
|
+
|
6
|
+
# * murder lazies
|
7
|
+
# * maintain worker count
|
8
|
+
|
9
|
+
scheduler = Procrastinate::Scheduler.start
|
10
|
+
scheduler.spawn_workers(6) {
|
11
|
+
# Worker body
|
12
|
+
loop do
|
13
|
+
puts "Hiho from worker #{Process.pid}."
|
14
|
+
sleep rand(1.0) * 3
|
15
|
+
end
|
16
|
+
}
|
17
|
+
|
18
|
+
# Wait around until something important happens
|
19
|
+
r, w = IO.pipe
|
20
|
+
trap('QUIT') { w.write '.' }
|
21
|
+
|
22
|
+
loop do
|
23
|
+
IO.select([r], nil, nil)
|
24
|
+
r.read_nonblock(1000)
|
25
|
+
|
26
|
+
# When we reach this point, a QUIT signal has been sent to the process.
|
27
|
+
# Abort.
|
28
|
+
break
|
29
|
+
end
|
30
|
+
|
31
|
+
scheduler.shutdown
|
data/lib/procrastinate.rb
CHANGED
@@ -2,57 +2,58 @@
|
|
2
2
|
require 'procrastinate'
|
3
3
|
|
4
4
|
module Procrastinate
|
5
|
-
# call-seq:
|
6
|
-
# Procrastinate.scheduler => scheduler
|
7
|
-
#
|
8
5
|
# Returns the scheduler instance. When using procrastinate/implicit, there
|
9
6
|
# is one global scheduler to your ruby process, this one.
|
7
|
+
#
|
8
|
+
# @return [Scheduler] singleton scheduler for implicit scheduling.
|
10
9
|
#
|
11
10
|
def scheduler
|
12
11
|
@scheduler ||= Scheduler.start
|
13
12
|
end
|
14
13
|
module_function :scheduler
|
15
14
|
|
16
|
-
# call-seq:
|
17
|
-
# Procrastinate.proxy(obj) => proxy
|
18
|
-
#
|
19
15
|
# Creates a proxy that will execute methods called on obj in a child process.
|
20
16
|
#
|
21
|
-
#
|
22
|
-
#
|
17
|
+
# @example
|
23
18
|
# proxy = Procrastinate.proxy("foo")
|
24
19
|
# r = proxy += "bar"
|
25
20
|
# r.value # => 'foobar'
|
26
21
|
#
|
22
|
+
# @param obj [Object] Ruby object that the calls need to be proxied to
|
23
|
+
# @return [Proxy] proxy object that will execute method calls in child
|
24
|
+
# processes
|
25
|
+
#
|
27
26
|
def proxy(obj)
|
28
27
|
scheduler.proxy(obj)
|
29
28
|
end
|
30
29
|
module_function :proxy
|
31
30
|
|
32
|
-
# call-seq:
|
33
|
-
# Procrastinate.schedule { some_work }
|
34
|
-
#
|
35
31
|
# Schedules a block to be executed in its own thread. Returns the future that
|
36
32
|
# will return the blocks return value.
|
37
33
|
#
|
34
|
+
# @example
|
35
|
+
# r = Procrastinate.schedule { do_some_work }
|
36
|
+
# r.value # => the blocks return value
|
37
|
+
#
|
38
|
+
# @param block [Proc] block that will be executed in a child process
|
39
|
+
# @return [Task::Result] a promise for the blocks return value
|
40
|
+
#
|
38
41
|
def schedule(&block)
|
39
42
|
scheduler.schedule(&block)
|
40
43
|
end
|
41
44
|
module_function :schedule
|
42
45
|
|
43
|
-
# call-seq:
|
44
|
-
# Procrastinate.join
|
45
|
-
#
|
46
46
|
# Waits for all currently scheduled tasks to complete. This is like calling
|
47
47
|
# #value on all result objects, except that nothing is returned.
|
48
48
|
#
|
49
|
-
#
|
50
|
-
#
|
49
|
+
# @example
|
51
50
|
# proxy = Procrastinate.proxy("foo")
|
52
51
|
# r = proxy += "bar"
|
53
52
|
# Procrastinate.join
|
54
53
|
# r.ready? # => true
|
55
54
|
#
|
55
|
+
# @return [void]
|
56
|
+
#
|
56
57
|
def join
|
57
58
|
scheduler.join
|
58
59
|
end
|
@@ -62,6 +63,8 @@ module Procrastinate
|
|
62
63
|
# since it consumes almost no resources when not active. This is mainly
|
63
64
|
# useful in tests to achieve isolation.
|
64
65
|
#
|
66
|
+
# @private
|
67
|
+
#
|
65
68
|
def shutdown
|
66
69
|
scheduler.shutdown
|
67
70
|
end
|
@@ -166,13 +166,18 @@ class Procrastinate::ProcessManager
|
|
166
166
|
# Ignore: This means that no childs remain.
|
167
167
|
end
|
168
168
|
|
169
|
-
# Spawns a process to work on +task+. If a block is given, it is called
|
170
|
-
#
|
169
|
+
# Spawns a process to work on +task+. If a block is given, it is called when
|
170
|
+
# the task completes. This method should only be called from a strategy
|
171
171
|
# inside the dispatchers thread. Otherwise it will expose threading issues.
|
172
172
|
#
|
173
|
-
#
|
174
|
-
#
|
175
|
-
#
|
173
|
+
# @example
|
174
|
+
# create_process(wi) { puts "Task is complete" }
|
175
|
+
#
|
176
|
+
# @param task [Procrastinate::Task::Callable] task to be run inside the
|
177
|
+
# forked process
|
178
|
+
# @param completion_handler [Proc] completion handler that is called when
|
179
|
+
# the process exits
|
180
|
+
# @return [void]
|
176
181
|
#
|
177
182
|
def create_process(task, &completion_handler)
|
178
183
|
# Tasks that are interested in getting messages from their childs must
|
@@ -224,4 +229,14 @@ class Procrastinate::ProcessManager
|
|
224
229
|
finalize_children
|
225
230
|
end
|
226
231
|
end
|
232
|
+
|
233
|
+
# Kills all running processes by sending them a QUIT signal.
|
234
|
+
#
|
235
|
+
# @param signal [String] signal to send to the forked processes.
|
236
|
+
#
|
237
|
+
def kill_processes(signal='QUIT')
|
238
|
+
children.each do |pid, process|
|
239
|
+
Process.kill(signal, pid)
|
240
|
+
end
|
241
|
+
end
|
227
242
|
end
|
@@ -3,16 +3,41 @@ require 'thread'
|
|
3
3
|
|
4
4
|
# API Frontend for the procrastinate library. Allows scheduling of tasks and
|
5
5
|
# workers in seperate processes and provides minimal locking primitives.
|
6
|
+
#
|
7
|
+
# == Synopsis
|
8
|
+
# scheduler = Procrastinate::Scheduler.start
|
9
|
+
#
|
10
|
+
# Schedule a block to run in its own process:
|
11
|
+
# result = scheduler.schedule { Process.pid }
|
12
|
+
# result.value # => child process pid
|
6
13
|
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
14
|
+
# Or schedule a message call to an object to be run in another process:
|
15
|
+
# proxy = scheduler.proxy(1)
|
16
|
+
# result = proxy + 2
|
17
|
+
# result.value # => 3
|
18
|
+
#
|
19
|
+
# You can ask the result value if it is ready yet:
|
20
|
+
# result.ready? # true/false
|
21
|
+
#
|
22
|
+
# Stop the scheduler, waiting for all scheduled work to finish:
|
23
|
+
# scheduler.shutdown
|
24
|
+
#
|
25
|
+
# Or shutting down hard, doesn't wait for work to finish:
|
26
|
+
# scheduler.shutting(true)
|
27
|
+
#
|
28
|
+
# @note Each scheduler owns its own thread that does all the processing. The
|
29
|
+
# interface between your main thread and the procrastinate thread is defined
|
30
|
+
# in this class.
|
10
31
|
#
|
11
32
|
class Procrastinate::Scheduler
|
33
|
+
# Process manager associated with this scheduler
|
12
34
|
attr_reader :manager
|
35
|
+
# Schedule strategy associated with this scheduler
|
13
36
|
attr_reader :strategy
|
14
|
-
|
37
|
+
# Task queue
|
38
|
+
attr_reader :task_producer
|
15
39
|
|
40
|
+
# @see Scheduler.start
|
16
41
|
def initialize(strategy)
|
17
42
|
@strategy = strategy || Procrastinate::SpawnStrategy::Default.new
|
18
43
|
@manager = Procrastinate::ProcessManager.new
|
@@ -20,11 +45,18 @@ class Procrastinate::Scheduler
|
|
20
45
|
# State takes three values: :running, :soft_shutdown, :real_shutdown
|
21
46
|
# :soft_shutdown will not accept any new tasks and wait for completion
|
22
47
|
# :real_shutdown will stop as soon as possible (still closing down nicely)
|
23
|
-
@state
|
24
|
-
|
48
|
+
@state = :running
|
49
|
+
|
50
|
+
# If we're used in server mode, this will be replaced with a task producer
|
51
|
+
# that produces new worker processes.
|
52
|
+
@task_producer = Queue.new
|
25
53
|
end
|
26
54
|
|
27
|
-
# Starts a new scheduler
|
55
|
+
# Starts a new scheduler.
|
56
|
+
#
|
57
|
+
# @param strategy [SpawnStrategy] strategy to use when spawning new processes.
|
58
|
+
# Will default to {SpawnStrategy::Default}.
|
59
|
+
# @return [Scheduler]
|
28
60
|
#
|
29
61
|
def self.start(strategy=nil)
|
30
62
|
new(strategy).
|
@@ -37,11 +69,13 @@ class Procrastinate::Scheduler
|
|
37
69
|
# Returns a proxy for the +worker+ instance that will allow executing its
|
38
70
|
# methods in a new process.
|
39
71
|
#
|
40
|
-
#
|
41
|
-
#
|
72
|
+
# @example
|
42
73
|
# proxy = scheduler.proxy(worker)
|
43
74
|
# status = proxy.do_some_work # will execute later and in its own process
|
44
75
|
#
|
76
|
+
# @param worker [Object] Ruby object that executes the work
|
77
|
+
# @return [Proxy]
|
78
|
+
#
|
45
79
|
def proxy(worker)
|
46
80
|
return Procrastinate::Proxy.new(worker, self)
|
47
81
|
end
|
@@ -50,6 +84,8 @@ class Procrastinate::Scheduler
|
|
50
84
|
# used inside task execution processes; If you call it from your main
|
51
85
|
# process, the result is undefined.
|
52
86
|
#
|
87
|
+
# @return [Runtime]
|
88
|
+
#
|
53
89
|
def runtime
|
54
90
|
Procrastinate::Runtime.new
|
55
91
|
end
|
@@ -57,6 +93,16 @@ class Procrastinate::Scheduler
|
|
57
93
|
# Called by the proxy to schedule work. You can implement your own Task
|
58
94
|
# classes; the relevant interface consists of only a #run method.
|
59
95
|
#
|
96
|
+
# @overload schedule(task=nil)
|
97
|
+
# Runs task in its own worker process.
|
98
|
+
# @param task [#run] task to be run in its own worker process
|
99
|
+
# @return [Task::Result]
|
100
|
+
#
|
101
|
+
# @overload schedule(&block)
|
102
|
+
# Executes the Ruby block in its own worker process.
|
103
|
+
# @param block [Proc] block to be executed in worker process
|
104
|
+
# @return [Task::Result]
|
105
|
+
#
|
60
106
|
def schedule(task=nil, &block)
|
61
107
|
fail "Shutting down..." if @state != :running
|
62
108
|
|
@@ -67,7 +113,7 @@ class Procrastinate::Scheduler
|
|
67
113
|
task = Procrastinate::Task::Callable.new(block)
|
68
114
|
end
|
69
115
|
|
70
|
-
|
116
|
+
task_producer << task
|
71
117
|
|
72
118
|
# Create an occasion for spawning
|
73
119
|
manager.wakeup
|
@@ -87,7 +133,7 @@ class Procrastinate::Scheduler
|
|
87
133
|
# Wait until all tasks are done.
|
88
134
|
loop do
|
89
135
|
manager.wakeup
|
90
|
-
break if
|
136
|
+
break if task_producer.empty? && manager.process_count==0
|
91
137
|
sleep 0.01
|
92
138
|
end
|
93
139
|
|
@@ -115,8 +161,8 @@ private
|
|
115
161
|
# *control thread*
|
116
162
|
#
|
117
163
|
def spawn
|
118
|
-
while strategy.should_spawn? && !
|
119
|
-
task =
|
164
|
+
while strategy.should_spawn? && !task_producer.empty?
|
165
|
+
task = task_producer.pop
|
120
166
|
strategy.notify_spawn
|
121
167
|
manager.create_process(task) do
|
122
168
|
strategy.notify_dead
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Procrastinate
|
2
|
+
class Server
|
3
|
+
def initialize
|
4
|
+
@manager = Procrastinate::ProcessManager.new
|
5
|
+
@state = :new
|
6
|
+
end
|
7
|
+
|
8
|
+
def start(n, activity_check_interval=nil, &block)
|
9
|
+
fail "Already running server." unless @state == :new
|
10
|
+
|
11
|
+
@block = block
|
12
|
+
@strategy = Procrastinate::SpawnStrategy::Throttled.new(n)
|
13
|
+
@state = :running
|
14
|
+
@check_interval = activity_check_interval
|
15
|
+
|
16
|
+
start_thread
|
17
|
+
end
|
18
|
+
|
19
|
+
def shutdown
|
20
|
+
fail "For shutdown, server must be running." unless @state == :running
|
21
|
+
|
22
|
+
@state = :shutdown
|
23
|
+
@manager.wakeup
|
24
|
+
|
25
|
+
@thread.join if @thread
|
26
|
+
|
27
|
+
@thread = nil
|
28
|
+
@state = :new
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def start_thread
|
33
|
+
@thread = Thread.start(&method(:control_thread_main))
|
34
|
+
end
|
35
|
+
|
36
|
+
# @note This method runs in the control thread only.
|
37
|
+
#
|
38
|
+
def spawn_new_workers
|
39
|
+
while @strategy.should_spawn?
|
40
|
+
task = Procrastinate::Task::Callable.new(@block)
|
41
|
+
|
42
|
+
@strategy.notify_spawn
|
43
|
+
@manager.create_process(task) do
|
44
|
+
@strategy.notify_dead
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# @note This method runs in the control thread only.
|
50
|
+
#
|
51
|
+
def control_thread_main
|
52
|
+
# Start managers work
|
53
|
+
@manager.setup
|
54
|
+
|
55
|
+
# Loop until someone requests a shutdown.
|
56
|
+
loop do
|
57
|
+
spawn_new_workers
|
58
|
+
|
59
|
+
@manager.step
|
60
|
+
|
61
|
+
break if @state == :shutdown
|
62
|
+
end
|
63
|
+
|
64
|
+
@manager.kill_processes
|
65
|
+
@manager.teardown
|
66
|
+
rescue => ex
|
67
|
+
# Sometimes exceptions vanish silently. This will avoid that, even though
|
68
|
+
# they should abort the whole process.
|
69
|
+
|
70
|
+
warn "Exception #{ex.inspect} caught."
|
71
|
+
ex.backtrace.first(5).each do |line|
|
72
|
+
warn line
|
73
|
+
end
|
74
|
+
|
75
|
+
raise
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: procrastinate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,85 +10,136 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-
|
13
|
+
date: 2012-12-18 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: state_machine
|
17
|
-
|
18
|
-
|
17
|
+
prerelease: false
|
18
|
+
requirement: !ruby/object:Gem::Requirement
|
19
19
|
requirements:
|
20
20
|
- - ~>
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version:
|
22
|
+
version: '1.1'
|
23
|
+
none: false
|
23
24
|
type: :runtime
|
24
|
-
|
25
|
-
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.1'
|
30
|
+
none: false
|
26
31
|
- !ruby/object:Gem::Dependency
|
27
32
|
name: cod
|
28
|
-
|
29
|
-
|
33
|
+
prerelease: false
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
30
35
|
requirements:
|
31
36
|
- - ~>
|
32
37
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0.
|
38
|
+
version: '0.5'
|
39
|
+
none: false
|
34
40
|
type: :runtime
|
35
|
-
|
36
|
-
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0.5'
|
46
|
+
none: false
|
37
47
|
- !ruby/object:Gem::Dependency
|
38
48
|
name: rake
|
39
|
-
|
40
|
-
|
49
|
+
prerelease: false
|
50
|
+
requirement: !ruby/object:Gem::Requirement
|
41
51
|
requirements:
|
42
52
|
- - ! '>='
|
43
53
|
- !ruby/object:Gem::Version
|
44
54
|
version: '0'
|
55
|
+
none: false
|
45
56
|
type: :development
|
46
|
-
|
47
|
-
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
none: false
|
48
63
|
- !ruby/object:Gem::Dependency
|
49
64
|
name: rspec
|
50
|
-
|
51
|
-
|
65
|
+
prerelease: false
|
66
|
+
requirement: !ruby/object:Gem::Requirement
|
52
67
|
requirements:
|
53
68
|
- - ! '>='
|
54
69
|
- !ruby/object:Gem::Version
|
55
70
|
version: '0'
|
71
|
+
none: false
|
56
72
|
type: :development
|
57
|
-
|
58
|
-
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
none: false
|
59
79
|
- !ruby/object:Gem::Dependency
|
60
80
|
name: flexmock
|
61
|
-
|
62
|
-
|
81
|
+
prerelease: false
|
82
|
+
requirement: !ruby/object:Gem::Requirement
|
63
83
|
requirements:
|
64
84
|
- - ! '>='
|
65
85
|
- !ruby/object:Gem::Version
|
66
86
|
version: '0'
|
87
|
+
none: false
|
67
88
|
type: :development
|
68
|
-
|
69
|
-
|
89
|
+
version_requirements: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
none: false
|
70
95
|
- !ruby/object:Gem::Dependency
|
71
96
|
name: guard
|
72
|
-
|
73
|
-
|
97
|
+
prerelease: false
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
74
99
|
requirements:
|
75
100
|
- - ! '>='
|
76
101
|
- !ruby/object:Gem::Version
|
77
102
|
version: '0'
|
103
|
+
none: false
|
78
104
|
type: :development
|
79
|
-
|
80
|
-
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
none: false
|
81
111
|
- !ruby/object:Gem::Dependency
|
82
112
|
name: growl
|
83
|
-
|
84
|
-
|
113
|
+
prerelease: false
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
85
115
|
requirements:
|
86
116
|
- - ! '>='
|
87
117
|
- !ruby/object:Gem::Version
|
88
118
|
version: '0'
|
119
|
+
none: false
|
89
120
|
type: :development
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
none: false
|
127
|
+
- !ruby/object:Gem::Dependency
|
128
|
+
name: yard
|
90
129
|
prerelease: false
|
91
|
-
|
130
|
+
requirement: !ruby/object:Gem::Requirement
|
131
|
+
requirements:
|
132
|
+
- - ! '>='
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: '0'
|
135
|
+
none: false
|
136
|
+
type: :development
|
137
|
+
version_requirements: !ruby/object:Gem::Requirement
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
none: false
|
92
143
|
description:
|
93
144
|
email:
|
94
145
|
- kaspar.schiess@absurd.li
|
@@ -109,6 +160,7 @@ files:
|
|
109
160
|
- lib/procrastinate/proxy.rb
|
110
161
|
- lib/procrastinate/runtime.rb
|
111
162
|
- lib/procrastinate/scheduler.rb
|
163
|
+
- lib/procrastinate/server.rb
|
112
164
|
- lib/procrastinate/spawn_strategy/default.rb
|
113
165
|
- lib/procrastinate/spawn_strategy/simple.rb
|
114
166
|
- lib/procrastinate/spawn_strategy/throttled.rb
|
@@ -122,6 +174,7 @@ files:
|
|
122
174
|
- lib/procrastinate.rb
|
123
175
|
- examples/locking.rb
|
124
176
|
- examples/pascal.rb
|
177
|
+
- examples/server.rb
|
125
178
|
- examples/simple.rb
|
126
179
|
- examples/throttled.rb
|
127
180
|
homepage: http://github.com/kschiess/procrastinate
|
@@ -133,27 +186,22 @@ rdoc_options:
|
|
133
186
|
require_paths:
|
134
187
|
- lib
|
135
188
|
required_ruby_version: !ruby/object:Gem::Requirement
|
136
|
-
none: false
|
137
189
|
requirements:
|
138
190
|
- - ! '>='
|
139
191
|
- !ruby/object:Gem::Version
|
140
192
|
version: '0'
|
141
|
-
segments:
|
142
|
-
- 0
|
143
|
-
hash: 3407763989240963082
|
144
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
193
|
none: false
|
194
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
146
195
|
requirements:
|
147
196
|
- - ! '>='
|
148
197
|
- !ruby/object:Gem::Version
|
149
198
|
version: '0'
|
150
|
-
|
151
|
-
- 0
|
152
|
-
hash: 3407763989240963082
|
199
|
+
none: false
|
153
200
|
requirements: []
|
154
201
|
rubyforge_project:
|
155
|
-
rubygems_version: 1.8.
|
202
|
+
rubygems_version: 1.8.24
|
156
203
|
signing_key:
|
157
204
|
specification_version: 3
|
158
205
|
summary: Framework to run tasks in separate processes.
|
159
206
|
test_files: []
|
207
|
+
has_rdoc:
|