rufus-scheduler 2.0.11 → 2.0.12

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.txt CHANGED
@@ -2,6 +2,13 @@
2
2
  = rufus-scheduler CHANGELOG.txt
3
3
 
4
4
 
5
+ == rufus-scheduler - 2.0.12 released 2011/10/28
6
+
7
+ - hardened exception handling. Thanks Sam Gibson
8
+ - accepting #handle_exception, #log_exception or #on_exception
9
+ - scheduler.in '1s', :mutex => 'that_mutex_name'
10
+
11
+
5
12
  == rufus-scheduler - 2.0.11 released 2011/09/30
6
13
 
7
14
  - require 'rufus-scheduler' works
data/CREDITS.txt CHANGED
@@ -14,6 +14,7 @@
14
14
 
15
15
  == Feedback
16
16
 
17
+ - Sam Gibson - https://github.com/samfoo - exception handling hardening
17
18
  - sha1dy - https://github.com/sha1dy - every and overlapping exception issue
18
19
  - Defusal - unschedule_by_tag
19
20
  - pickerel - https://github.com/pickerel
data/README.rdoc CHANGED
@@ -174,25 +174,82 @@ Jobs scheduled with the :blocking parameter will run in the thread of the schedu
174
174
 
175
175
  Hence, our espresso will come in 22 minutes instead of 21.
176
176
 
177
+ Warning, 'cron' behaves a bit differently than 'in' and 'at', if the scheduler is blocked working on a task, it may skip crons (while ins and ats get scheduled after).
178
+
179
+ scheduler.cron '0 16 * * * *' do
180
+ puts "four o'clock tea"
181
+ end
182
+
183
+ If at 4pm the scheduler is in a blocking task, there will be no four o'clock tea.
184
+
185
+
186
+ == :mutex => 'that_mutex'
187
+
188
+ :blocking is nice but it is blocking the whole scheduler. What about something more fine-grained ? And also something that can be used with in, at, every and cron ?
189
+
190
+ scheduler.in '20m', :mutex => 'that_mutex' do
191
+ puts "order ristretto"
192
+ sleep 2 * 60
193
+ puts "ah, that was delicious"
194
+ end
195
+ scheduler.in '21m' :mutex => 'that_mutex' do
196
+ puts "order espresso"
197
+ end
198
+
199
+ the "order espresso" will only get triggered once the ristretto has been consumed. Rufus-scheduler, will create a 'that_mutex' mutex and keep track of it. Don't go on passing too many different mutex names, rufus-scheduler will keep track of each of them (they won't get garbage collected).
200
+
201
+ It's OK to use a mutex directly:
202
+
203
+ m = Mutex.new
204
+ # ...
205
+ scheduler.cron '0 18 * * *', :mutex => m do
206
+ # ...
207
+ end
208
+ scheduler.in '21m' :mutex => m do
209
+ # ...
210
+ end
211
+
212
+ It can be handy for even more fine-grained control:
213
+
214
+ m = Mutex.new
215
+ # ...
216
+ scheduler.cron '0 18 * * *', :mutex => m do
217
+ # ...
218
+ end
219
+ scheduler.in '21m' do
220
+ # non-critical
221
+ m.synchronize do
222
+ # critical
223
+ end
224
+ # non-critical
225
+ end
226
+
177
227
 
178
228
  == :allow_overlapping => false
179
229
 
180
- By default, every and cron jobs will "overlap" :
230
+ By default, every and cron jobs will "overlap":
181
231
 
182
232
  scheduler.every '3s' do
183
- 4.times do
184
- puts "hello!"
233
+ 4.times do |i|
234
+ puts "hello #{i}"
185
235
  sleep 1
186
236
  end
187
237
  end
188
238
 
189
- This every job, will have overlaps. To prevent that :
239
+ You mind end up with something that looks like
240
+
241
+ hello 0
242
+ hello 1
243
+ hello 2
244
+ hello 3
245
+ hello 3
246
+ hello 4
247
+ ...
248
+
249
+ This every job, will have overlaps. To prevent that:
190
250
 
191
251
  scheduler.every '3s', :allow_overlapping => false do
192
- 4.times do
193
- puts "hello!"
194
- sleep 1
195
- end
252
+ # ...
196
253
  end
197
254
 
198
255
 
@@ -347,6 +404,17 @@ It's easy to customize that behaviour :
347
404
  puts "job #{job.job_id} caught exception '#{exception}'"
348
405
  end
349
406
 
407
+ These are OK too:
408
+
409
+ def scheduler.on_exception(job, exception)
410
+ puts "job #{job.job_id} caught exception '#{exception}'"
411
+ end
412
+
413
+ # or
414
+
415
+ def scheduler.on_exception(exception)
416
+ puts "caught exception '#{exception}'"
417
+
350
418
  For backward compatibility, overriding #log_exception is still OK :
351
419
 
352
420
  def scheduler.log_exception(exception)
@@ -398,8 +466,7 @@ https://github.com/jmettraux/rufus-scheduler/issues/issue/10
398
466
  == tested with
399
467
 
400
468
  * 1.8.7-p249
401
- * 1.9.1-p378
402
- * 1.9.2-p0
469
+ * 1.9.2-p290
403
470
  * jruby-1.5.1
404
471
 
405
472
  on Mac OS X (Snow Leopard).
data/lib/rufus/sc/jobs.rb CHANGED
@@ -133,7 +133,7 @@ module Scheduler
133
133
 
134
134
  @running = true
135
135
 
136
- @scheduler.send(:trigger_job, @params[:blocking]) do
136
+ @scheduler.send(:trigger_job, @params) do
137
137
  #
138
138
  # Note that #trigger_job is protected, hence the #send
139
139
  # (Only jobs know about this method of the scheduler)
@@ -153,7 +153,7 @@ module Scheduler
153
153
 
154
154
  rescue Exception => e
155
155
 
156
- @scheduler.handle_exception(self, e)
156
+ @scheduler.do_handle_exception(self, e)
157
157
  end
158
158
 
159
159
  @running = false
@@ -105,6 +105,8 @@ module Rufus::Scheduler
105
105
  @cron_jobs = get_queue(:cron, opts)
106
106
 
107
107
  @frequency = @options[:frequency] || 0.330
108
+
109
+ @mutexes = {}
108
110
  end
109
111
 
110
112
  # Instantiates and starts a new Rufus::Scheduler.
@@ -198,25 +200,42 @@ module Rufus::Scheduler
198
200
  # MISC
199
201
  #++
200
202
 
201
- # Feel free to override this method. The default implementation simply
202
- # outputs the error message to STDOUT
203
+ # Determines if there is #log_exception, #handle_exception or #on_exception
204
+ # method. If yes, hands the exception to it, else defaults to outputting
205
+ # details to $stderr.
203
206
  #
204
- def handle_exception(job, exception)
207
+ def do_handle_exception(job, exception)
205
208
 
206
- if self.respond_to?(:log_exception)
207
- #
208
- # some kind of backward compatibility
209
+ begin
209
210
 
210
- log_exception(exception)
211
+ [ :log_exception, :handle_exception, :on_exception ].each do |m|
211
212
 
212
- else
213
+ next unless self.respond_to?(m)
214
+
215
+ if method(m).arity == 1
216
+ self.send(m, exception)
217
+ else
218
+ self.send(m, job, exception)
219
+ end
220
+
221
+ return
222
+ # exception was handled successfully
223
+ end
213
224
 
214
- puts '=' * 80
215
- puts "scheduler caught exception :"
216
- puts exception
217
- exception.backtrace.each { |l| puts l }
218
- puts '=' * 80
225
+ rescue Exception => e
226
+
227
+ $stderr.puts '*' * 80
228
+ $stderr.puts 'the exception handling method itself had an issue:'
229
+ $stderr.puts e
230
+ $stderr.puts *e.backtrace
231
+ $stderr.puts '*' * 80
219
232
  end
233
+
234
+ $stderr.puts '=' * 80
235
+ $stderr.puts 'scheduler caught exception:'
236
+ $stderr.puts exception
237
+ $stderr.puts *exception.backtrace
238
+ $stderr.puts '=' * 80
220
239
  end
221
240
 
222
241
  #--
@@ -339,10 +358,13 @@ module Rufus::Scheduler
339
358
  # TODO : clarify, the blocking here blocks the whole scheduler, while
340
359
  # EmScheduler blocking triggers for the next tick. Not the same thing ...
341
360
  #
342
- def trigger_job(blocking, &block)
361
+ def trigger_job(params, &block)
343
362
 
344
- if blocking
363
+ if params[:blocking]
345
364
  block.call
365
+ elsif m = params[:mutex]
366
+ m = (@mutexes[m.to_s] ||= Mutex.new) unless m.is_a?(Mutex)
367
+ Thread.new { m.synchronize { block.call } }
346
368
  else
347
369
  Thread.new { block.call }
348
370
  end
@@ -471,14 +493,20 @@ module Rufus::Scheduler
471
493
  # If 'blocking' is set to true, the block will get called at the
472
494
  # 'next_tick'. Else the block will get called via 'defer' (own thread).
473
495
  #
474
- def trigger_job(blocking, &block)
496
+ def trigger_job(params, &block)
475
497
 
476
- m = blocking ? :next_tick : :defer
477
- #
478
- # :next_tick monopolizes the EM
479
- # :defer executes its block in another thread
498
+ # :next_tick monopolizes the EM
499
+ # :defer executes its block in another thread
500
+ # (if I read the doc carefully...)
480
501
 
481
- EM.send(m) { block.call }
502
+ if params[:blocking]
503
+ EM.next_tick { block.call }
504
+ elsif m = params[:mutex]
505
+ m = (@mutexes[m.to_s] ||= Mutex.new) unless m.is_a?(Mutex)
506
+ EM.defer { m.synchronize { block.call } }
507
+ else
508
+ EM.defer { block.call }
509
+ end
482
510
  end
483
511
  end
484
512
 
@@ -26,7 +26,7 @@
26
26
  module Rufus
27
27
  module Scheduler
28
28
 
29
- VERSION = '2.0.11'
29
+ VERSION = '2.0.12'
30
30
  end
31
31
  end
32
32
 
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2006-2010, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2006-2011, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
data/release.txt ADDED
@@ -0,0 +1,9 @@
1
+ Rufus-scheduler is a thread-based scheduler written in Ruby. It lets you write code like
2
+
3
+ [sourcecode language="ruby"]
4
+ Rufus::Scheduler.start
5
+
6
+ Rufus::Scheduler.every '10m' do
7
+ end
8
+ [/sourcecode]
9
+
@@ -28,7 +28,7 @@ job scheduler for Ruby (at, cron, in and every jobs).
28
28
  s.add_runtime_dependency 'tzinfo', '>= 0.3.23'
29
29
 
30
30
  s.add_development_dependency 'rake'
31
- s.add_development_dependency 'rspec', '>= 2.0'
31
+ s.add_development_dependency 'rspec', '>= 2.7.0'
32
32
 
33
33
  s.require_path = 'lib'
34
34
  end
data/spec/at_in_spec.rb CHANGED
@@ -5,7 +5,7 @@
5
5
  # Sun Mar 22 16:47:28 JST 2009
6
6
  #
7
7
 
8
- require File.join(File.dirname(__FILE__), 'spec_base')
8
+ require 'spec_base'
9
9
 
10
10
 
11
11
  describe SCHEDULER_CLASS do
data/spec/at_spec.rb CHANGED
@@ -5,7 +5,7 @@
5
5
  # Sat Mar 21 20:19:30 JST 2009
6
6
  #
7
7
 
8
- require File.join(File.dirname(__FILE__), 'spec_base')
8
+ require 'spec_base'
9
9
 
10
10
 
11
11
  describe "#{SCHEDULER_CLASS}#schedule_at" do
@@ -5,7 +5,7 @@
5
5
  # Sat Mar 21 17:36:36 JST 2009
6
6
  #
7
7
 
8
- require File.join(File.dirname(__FILE__), 'spec_base')
8
+ require 'spec_base'
9
9
 
10
10
 
11
11
  describe SCHEDULER_CLASS do
@@ -29,26 +29,32 @@ describe SCHEDULER_CLASS do
29
29
  end
30
30
  end
31
31
 
32
- it "doesn't block when :blocking => nil" do
32
+ context ':blocking => nil' do
33
33
 
34
- $var = []
35
- @s.in('1s') { JOB.call(1) }
36
- @s.in('1s') { JOB.call(2) }
34
+ it "doesn't block" do
37
35
 
38
- sleep 5.0
36
+ $var = []
37
+ @s.in('1s') { JOB.call(1) }
38
+ @s.in('1s') { JOB.call(2) }
39
39
 
40
- [ %w{ a1 a2 b1 b2 }, %w{ a1 a2 b2 b1 } ].should include($var)
40
+ sleep 5.0
41
+
42
+ [ %w{ a1 a2 b1 b2 }, %w{ a1 a2 b2 b1 } ].should include($var)
43
+ end
41
44
  end
42
45
 
43
- it 'blocks when :blocking => true' do
46
+ context ':blocking => true' do
44
47
 
45
- $var = []
46
- @s.in('1s', :blocking => true) { JOB.call(8) }
47
- @s.in('1s', :blocking => true) { JOB.call(9) }
48
+ it 'blocks' do
48
49
 
49
- sleep 4.5
50
+ $var = []
51
+ @s.in('1s', :blocking => true) { JOB.call(8) }
52
+ @s.in('1s', :blocking => true) { JOB.call(9) }
50
53
 
51
- $var.should == %w[ a8 b8 a9 b9 ]
54
+ sleep 4.5
55
+
56
+ $var.should == %w[ a8 b8 a9 b9 ]
57
+ end
52
58
  end
53
59
  end
54
60
 
data/spec/cron_spec.rb CHANGED
@@ -5,7 +5,7 @@
5
5
  # Sun Mar 22 19:59:12 JST 2009
6
6
  #
7
7
 
8
- require File.join(File.dirname(__FILE__), 'spec_base')
8
+ require 'spec_base'
9
9
 
10
10
 
11
11
  describe "#{SCHEDULER_CLASS}#cron" do
@@ -5,7 +5,7 @@
5
5
  # Sat Mar 21 12:55:27 JST 2009
6
6
  #
7
7
 
8
- require File.join(File.dirname(__FILE__), 'spec_base')
8
+ require 'spec_base'
9
9
 
10
10
 
11
11
  describe Rufus::CronLine do
data/spec/every_spec.rb CHANGED
@@ -5,7 +5,7 @@
5
5
  # Sun Mar 22 12:26:07 JST 2009
6
6
  #
7
7
 
8
- require File.join(File.dirname(__FILE__), 'spec_base')
8
+ require 'spec_base'
9
9
 
10
10
 
11
11
  describe "#{SCHEDULER_CLASS}#every" do
@@ -5,7 +5,7 @@
5
5
  # Mon May 4 17:07:17 JST 2009
6
6
  #
7
7
 
8
- require File.join(File.dirname(__FILE__), '/spec_base')
8
+ require 'spec_base'
9
9
 
10
10
 
11
11
  describe SCHEDULER_CLASS do
@@ -17,13 +17,13 @@ describe SCHEDULER_CLASS do
17
17
  stop_scheduler(@s)
18
18
  end
19
19
 
20
- it 'emits exception messages to stdout' do
20
+ it 'emits exception messages to stderr' do
21
21
 
22
22
  require 'stringio' unless defined?(StringIO) # ruby 1.9
23
23
 
24
- stdout = $stdout
24
+ stderr = $stderr
25
25
  s = StringIO.new
26
- $stdout = s
26
+ $stderr = s
27
27
 
28
28
  @s.in 0.400 do
29
29
  raise 'Houston we have a problem'
@@ -31,7 +31,7 @@ describe SCHEDULER_CLASS do
31
31
 
32
32
  sleep 0.500
33
33
  sleep 0.500
34
- $stdout = stdout
34
+ $stderr = stderr
35
35
  s.close
36
36
 
37
37
  s.string.should match(/Houston we have a problem/)
@@ -55,7 +55,7 @@ describe SCHEDULER_CLASS do
55
55
  $job.class.should == Rufus::Scheduler::InJob
56
56
  end
57
57
 
58
- it 'accepts overriding #log_exception' do
58
+ it 'accepts defining #log_exception' do
59
59
 
60
60
  $e = nil
61
61
 
@@ -72,5 +72,26 @@ describe SCHEDULER_CLASS do
72
72
 
73
73
  $e.to_s.should == 'Houston we have a problem'
74
74
  end
75
+
76
+ it 'accepts defining #on_exception' do
77
+
78
+ $j = nil
79
+ $e = nil
80
+
81
+ def @s.on_exception(j, e)
82
+ $j = j
83
+ $e = e
84
+ end
85
+
86
+ @s.in 0.400 do
87
+ raise 'Houston we have a problem'
88
+ end
89
+
90
+ sleep 0.500
91
+ sleep 0.500
92
+
93
+ $j.class.should == Rufus::Scheduler::InJob
94
+ $e.to_s.should == 'Houston we have a problem'
95
+ end
75
96
  end
76
97
 
data/spec/in_spec.rb CHANGED
@@ -5,7 +5,7 @@
5
5
  # Sat Mar 21 17:36:36 JST 2009
6
6
  #
7
7
 
8
- require File.join(File.dirname(__FILE__), 'spec_base')
8
+ require 'spec_base'
9
9
 
10
10
 
11
11
  describe "#{SCHEDULER_CLASS}#in" do
data/spec/job_spec.rb CHANGED
@@ -5,7 +5,7 @@
5
5
  # Wed Apr 27 00:51:07 JST 2011
6
6
  #
7
7
 
8
- require File.join(File.dirname(__FILE__), 'spec_base')
8
+ require 'spec_base'
9
9
 
10
10
 
11
11
  describe 'job classes' do
@@ -0,0 +1,93 @@
1
+
2
+ #
3
+ # Specifying rufus-scheduler
4
+ #
5
+ # Fri Oct 7 17:30:45 JST 2011
6
+ #
7
+
8
+ require 'spec_base'
9
+
10
+
11
+ describe SCHEDULER_CLASS do
12
+
13
+ before(:each) do
14
+ @s = start_scheduler
15
+ end
16
+ after(:each) do
17
+ stop_scheduler(@s)
18
+ end
19
+
20
+ MJOB = Proc.new do |x|
21
+ begin
22
+ $var << "in#{x}"
23
+ sleep 0.500
24
+ $var << "out#{x}"
25
+ rescue Exception => e
26
+ puts '=' * 80
27
+ p e
28
+ puts '=' * 80
29
+ end
30
+ end
31
+
32
+ context ':mutex => String' do
33
+
34
+ it 'prevents overlapping' do
35
+
36
+ $var = ''
37
+
38
+ @s.in('1s', :mutex => 'toto') { MJOB.call(0) }
39
+ @s.in('1s', :mutex => 'toto') { MJOB.call(1) }
40
+
41
+ sleep 3.0
42
+
43
+ %w[ in0out0in1out1 in1out1in0out0 ].should include($var)
44
+ end
45
+
46
+ it 'creates a new mutex when the name is first encountered' do
47
+
48
+ @s.instance_variable_get(:@mutexes).size.should == 0
49
+
50
+ @s.in('1s', :mutex => 'fruit') { sleep 0.1 }
51
+
52
+ sleep 1.5
53
+
54
+ @s.instance_variable_get(:@mutexes).size.should == 1
55
+ end
56
+
57
+ it 'creates a unique mutex for a given name' do
58
+
59
+ @s.in('1s', :mutex => 'gum') { sleep 0.1 }
60
+ @s.in('1s', :mutex => 'gum') { sleep 0.1 }
61
+
62
+ sleep 1.5
63
+
64
+ @s.instance_variable_get(:@mutexes).size.should == 1
65
+ end
66
+ end
67
+
68
+ context ':mutex => Mutex' do
69
+
70
+ it 'prevents overlapping' do
71
+
72
+ $var = ''
73
+ m = Mutex.new
74
+
75
+ @s.in('1s', :mutex => m) { MJOB.call(0) }
76
+ @s.in('1s', :mutex => m) { MJOB.call(1) }
77
+
78
+ sleep 3.0
79
+
80
+ %w[ in0out0in1out1 in1out1in0out0 ].should include($var)
81
+ end
82
+
83
+ it 'does not register the mutex' do
84
+
85
+ @s.in('1s', :mutex => Mutex.new) { sleep 0.1 }
86
+
87
+ sleep 1.5
88
+
89
+ @s.instance_variable_get(:@mutexes).size.should == 0
90
+ end
91
+ end
92
+ end
93
+
data/spec/rtime_spec.rb CHANGED
@@ -5,7 +5,7 @@
5
5
  # Fri Mar 20 23:46:32 JST 2009
6
6
  #
7
7
 
8
- require File.join(File.dirname(__FILE__), 'spec_base')
8
+ require 'spec_base'
9
9
 
10
10
 
11
11
  describe 'rufus/otime' do
@@ -5,7 +5,7 @@
5
5
  # Tue May 5 14:47:16 JST 2009
6
6
  #
7
7
 
8
- require File.join(File.dirname(__FILE__), '/spec_base')
8
+ require 'spec_base'
9
9
 
10
10
 
11
11
  describe Rufus::Scheduler::Schedulable do
@@ -5,7 +5,7 @@
5
5
  # Sat Mar 21 17:43:23 JST 2009
6
6
  #
7
7
 
8
- require File.join(File.dirname(__FILE__), 'spec_base')
8
+ require 'spec_base'
9
9
 
10
10
 
11
11
  describe SCHEDULER_CLASS do
data/spec/spec_base.rb CHANGED
@@ -5,12 +5,15 @@
5
5
  # Fri Mar 20 22:53:33 JST 2009
6
6
  #
7
7
 
8
- $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')))
8
+ $:.unshift(File.expand_path('../../lib', __FILE__))
9
9
 
10
10
  require 'rubygems'
11
11
  require 'fileutils'
12
12
 
13
13
 
14
+ Thread.abort_on_exception = true
15
+
16
+
14
17
  #$:.unshift(File.expand_path('~/tmp/bacon/lib')) # my own bacon for a while
15
18
  #require 'bacon'
16
19
  #puts
@@ -22,7 +25,7 @@ require 'fileutils'
22
25
 
23
26
  # EM or plain ?
24
27
 
25
- $plain = ! ARGV.include?('--em')
28
+ $plain = ! ENV['EVENTMACHINE']
26
29
 
27
30
  require 'rufus/scheduler'
28
31
 
@@ -64,12 +67,12 @@ def stop_scheduler(s)
64
67
  end
65
68
 
66
69
  def wait_next_tick
67
- if defined?(EM)
68
- t = Thread.current
69
- EM.next_tick { t.wakeup }
70
- Thread.stop
71
- else
72
- sleep 0.500
73
- end
70
+ #if defined?(EM)
71
+ # t = Thread.current
72
+ # EM.next_tick { t.wakeup }
73
+ # Thread.stop
74
+ #else
75
+ sleep 0.500
76
+ #end
74
77
  end
75
78
 
@@ -3,7 +3,7 @@
3
3
  # a spec by Klaas Jan Wierenga
4
4
  #
5
5
 
6
- require File.join(File.dirname(__FILE__), '/spec_base')
6
+ require 'spec_base'
7
7
 
8
8
 
9
9
 
data/spec/timeout_spec.rb CHANGED
@@ -5,7 +5,7 @@
5
5
  # Sun May 3 15:44:28 JST 2009
6
6
  #
7
7
 
8
- require File.join(File.dirname(__FILE__), '/spec_base')
8
+ require 'spec_base'
9
9
 
10
10
 
11
11
  describe "#{SCHEDULER_CLASS} timeouts" do
@@ -94,10 +94,10 @@ describe "#{SCHEDULER_CLASS} timeouts" do
94
94
  end
95
95
  end
96
96
 
97
- sleep 5
97
+ sleep 5.5
98
98
 
99
99
  timeouts.size.should == 3
100
- timeouts.each { |to| (to * 10).to_i.should == 16 }
100
+ timeouts.each { |to| to.should be_within(0.5).of(1.5) }
101
101
  end
102
102
 
103
103
  it 'points to their "parent" job' do
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rufus-scheduler
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 2
8
8
  - 0
9
- - 11
10
- version: 2.0.11
9
+ - 12
10
+ version: 2.0.12
11
11
  platform: ruby
12
12
  authors:
13
13
  - John Mettraux
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-09-30 00:00:00 +09:00
18
+ date: 2011-10-28 00:00:00 +09:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -56,11 +56,12 @@ dependencies:
56
56
  requirements:
57
57
  - - ">="
58
58
  - !ruby/object:Gem::Version
59
- hash: 3
59
+ hash: 19
60
60
  segments:
61
61
  - 2
62
+ - 7
62
63
  - 0
63
- version: "2.0"
64
+ version: 2.7.0
64
65
  type: :development
65
66
  version_requirements: *id003
66
67
  description: job scheduler for Ruby (at, cron, in and every jobs).
@@ -92,6 +93,7 @@ files:
92
93
  - spec/exception_spec.rb
93
94
  - spec/in_spec.rb
94
95
  - spec/job_spec.rb
96
+ - spec/mutex_spec.rb
95
97
  - spec/rtime_spec.rb
96
98
  - spec/schedulable_spec.rb
97
99
  - spec/scheduler_spec.rb
@@ -105,6 +107,7 @@ files:
105
107
  - CREDITS.txt
106
108
  - dump.txt
107
109
  - LICENSE.txt
110
+ - release.txt
108
111
  - t.txt
109
112
  - TODO.txt
110
113
  - README.rdoc