rufus-scheduler 2.0.24 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/CHANGELOG.txt +76 -0
  2. data/CREDITS.txt +23 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +1439 -0
  5. data/Rakefile +1 -5
  6. data/TODO.txt +149 -55
  7. data/lib/rufus/{sc → scheduler}/cronline.rb +167 -53
  8. data/lib/rufus/scheduler/job_array.rb +92 -0
  9. data/lib/rufus/scheduler/jobs.rb +633 -0
  10. data/lib/rufus/scheduler/locks.rb +95 -0
  11. data/lib/rufus/scheduler/util.rb +306 -0
  12. data/lib/rufus/scheduler/zones.rb +174 -0
  13. data/lib/rufus/scheduler/zotime.rb +154 -0
  14. data/lib/rufus/scheduler.rb +608 -27
  15. data/rufus-scheduler.gemspec +6 -4
  16. data/spec/basics_spec.rb +54 -0
  17. data/spec/cronline_spec.rb +479 -152
  18. data/spec/error_spec.rb +139 -0
  19. data/spec/job_array_spec.rb +39 -0
  20. data/spec/job_at_spec.rb +58 -0
  21. data/spec/job_cron_spec.rb +128 -0
  22. data/spec/job_every_spec.rb +104 -0
  23. data/spec/job_in_spec.rb +20 -0
  24. data/spec/job_interval_spec.rb +68 -0
  25. data/spec/job_repeat_spec.rb +357 -0
  26. data/spec/job_spec.rb +498 -109
  27. data/spec/lock_custom_spec.rb +47 -0
  28. data/spec/lock_flock_spec.rb +47 -0
  29. data/spec/lock_lockfile_spec.rb +61 -0
  30. data/spec/lock_spec.rb +59 -0
  31. data/spec/parse_spec.rb +263 -0
  32. data/spec/schedule_at_spec.rb +158 -0
  33. data/spec/schedule_cron_spec.rb +66 -0
  34. data/spec/schedule_every_spec.rb +109 -0
  35. data/spec/schedule_in_spec.rb +80 -0
  36. data/spec/schedule_interval_spec.rb +128 -0
  37. data/spec/scheduler_spec.rb +928 -124
  38. data/spec/spec_helper.rb +126 -0
  39. data/spec/threads_spec.rb +96 -0
  40. data/spec/zotime_spec.rb +396 -0
  41. metadata +56 -33
  42. data/README.rdoc +0 -661
  43. data/lib/rufus/otime.rb +0 -3
  44. data/lib/rufus/sc/jobqueues.rb +0 -160
  45. data/lib/rufus/sc/jobs.rb +0 -471
  46. data/lib/rufus/sc/rtime.rb +0 -363
  47. data/lib/rufus/sc/scheduler.rb +0 -636
  48. data/lib/rufus/sc/version.rb +0 -32
  49. data/spec/at_in_spec.rb +0 -47
  50. data/spec/at_spec.rb +0 -125
  51. data/spec/blocking_spec.rb +0 -64
  52. data/spec/cron_spec.rb +0 -134
  53. data/spec/every_spec.rb +0 -304
  54. data/spec/exception_spec.rb +0 -113
  55. data/spec/in_spec.rb +0 -150
  56. data/spec/mutex_spec.rb +0 -159
  57. data/spec/rtime_spec.rb +0 -137
  58. data/spec/schedulable_spec.rb +0 -97
  59. data/spec/spec_base.rb +0 -87
  60. data/spec/stress_schedule_unschedule_spec.rb +0 -159
  61. data/spec/timeout_spec.rb +0 -148
  62. data/test/kjw.rb +0 -113
  63. data/test/t.rb +0 -20
@@ -1,159 +0,0 @@
1
-
2
- #
3
- # a spec by Klaas Jan Wierenga
4
- #
5
-
6
- require 'spec_base'
7
-
8
-
9
-
10
- JOB_COUNT = 500 # 1000
11
- JOB_IDS = (1..JOB_COUNT).to_a
12
- NUM_RESCHEDULES = 5 # 10
13
- TRIGGER_DELAY = 4 # 15
14
-
15
-
16
- describe SCHEDULER_CLASS do
17
-
18
- # helper methods
19
-
20
- # Wait for a variable to become a certain value.
21
- # This method returns a block which loops waiting for the passed in
22
- # block paramter to have value 'target'.
23
- #
24
- def eventually(timeout = TRIGGER_DELAY * 2, precision = 1)
25
- lambda { |target|
26
- value = nil
27
- (timeout/precision).to_i.times do
28
- value = yield # read variable once
29
- # puts "got #{value}, expected #{target}"
30
- break if target == value
31
- sleep precision
32
- end
33
- target == value
34
- }
35
- end
36
-
37
- def benchmark
38
- now = Time.now
39
- yield
40
- benchmark = Time.now - now
41
- print " (scheduling took #{benchmark}s)"
42
- if benchmark > TRIGGER_DELAY
43
- puts "\nTEST RESULT INVALID/UNRELIABLE"
44
- puts "Scheduling took longer than TRIGGER_DELAY (#{TRIGGER_DELAY}s)."
45
- puts "Increase TRIGGER_DELAY to a value larger than largest scheduling time."
46
- end
47
- end
48
-
49
- def schedule_unschedule_same_ids_spec(mode)
50
- scheduler = SCHEDULER_CLASS.start_new
51
- benchmark { schedule_unschedule(scheduler, mode, NUM_RESCHEDULES) }
52
- JOB_COUNT.should satisfy &eventually { scheduler.all_jobs.size }
53
- JOB_IDS.sort.should == scheduler.find_jobs.map{ |job| job.job_id }.sort
54
- JOB_COUNT.should satisfy &eventually { @trigger_queue.size }
55
- @trigger_queue.size.should == JOB_COUNT
56
- scheduler.stop
57
- end
58
-
59
- def schedule_unschedule_unique_ids_spec(mode)
60
- scheduler = SCHEDULER_CLASS.start_new
61
- job_ids = []
62
- benchmark { job_ids = schedule_unschedule(scheduler, mode, NUM_RESCHEDULES, true) }
63
- JOB_COUNT.should satisfy &eventually { scheduler.all_jobs.size }
64
- job_ids.sort.should == scheduler.find_jobs.map{ |job| job.job_id }.sort
65
- JOB_COUNT.should satisfy &eventually { @trigger_queue.size }
66
- @trigger_queue.size.should == JOB_COUNT
67
- scheduler.stop
68
- end
69
-
70
- def scheduler_counts(scheduler)
71
- "all:%d at:%d cron:%d every:%d pending:%d" % [
72
- scheduler.all_jobs.size,
73
- scheduler.at_job_count,
74
- scheduler.cron_job_count,
75
- scheduler.every_job_count,
76
- scheduler.pending_job_count ]
77
- end
78
-
79
- def schedule_unschedule(scheduler, mode, num_reschedules, generate_ids=false)
80
- job_ids = schedule_jobs(scheduler, mode, generate_ids)
81
- 1.upto(num_reschedules) do
82
- unschedule_jobs(scheduler, job_ids)
83
- job_ids = schedule_jobs(scheduler, mode, generate_ids)
84
- end
85
- job_ids
86
- end
87
-
88
- def schedule_jobs(scheduler, mode, generate_ids=false)
89
- job_ids = []
90
- JOB_IDS.each do |job_id|
91
- case mode
92
- when :cron
93
- job_ids << scheduler.cron(
94
- "%d * * * * *" % @cron_trigger,
95
- { :job_id => (generate_ids ? nil : job_id) },
96
- &@trigger_proc
97
- ).job_id
98
- when :at
99
- job_ids << scheduler.at(
100
- @at_trigger,
101
- { :job_id => (generate_ids ? nil : job_id) },
102
- &@trigger_proc
103
- ).job_id
104
- when :every
105
- job_ids << scheduler.every(
106
- @every_trigger,
107
- { :job_id => (generate_ids ? nil : job_id) },
108
- &@trigger_proc
109
- ).job_id
110
- else
111
- raise ArgumentError
112
- end
113
- end
114
- job_ids
115
- end
116
-
117
- def unschedule_jobs(scheduler, job_ids)
118
- job_ids.each { |job_id| scheduler.unschedule(job_id) }
119
- end
120
-
121
- # the actual tests
122
-
123
- before(:each) do
124
- @trigger_queue = Queue.new
125
- @cron_trigger = ((Time.now.to_i%60) + TRIGGER_DELAY) % 60 # 30 seconds from now
126
- @at_trigger = Time.now + TRIGGER_DELAY
127
- @every_trigger = "#{TRIGGER_DELAY}s"
128
- @trigger_proc = lambda { |job| @trigger_queue << job.job_id }
129
- end
130
-
131
- after(:each) do
132
- @trigger_queue = nil
133
- end
134
-
135
- it "sustains frequent schedule/unschedule 'cron' jobs with same ids" do
136
- schedule_unschedule_same_ids_spec(:cron)
137
- end
138
-
139
- it "sustains frequent schedule/unschedule 'at' jobs with same ids" do
140
- schedule_unschedule_same_ids_spec(:at)
141
- end
142
-
143
- it "sustains frequent schedule/unschedule 'every' jobs same ids" do
144
- schedule_unschedule_same_ids_spec(:every)
145
- end
146
-
147
- it "sustains frequent schedule/unschedule 'cron' jobs with unique ids" do
148
- schedule_unschedule_unique_ids_spec(:cron)
149
- end
150
-
151
- it "sustains frequent schedule/unschedule 'at' jobs with unique ids" do
152
- schedule_unschedule_unique_ids_spec(:at)
153
- end
154
-
155
- it "sustains frequent schedule/unschedule 'every' jobs unique ids" do
156
- schedule_unschedule_unique_ids_spec(:every)
157
- end
158
- end
159
-
data/spec/timeout_spec.rb DELETED
@@ -1,148 +0,0 @@
1
-
2
- #
3
- # Specifying rufus-scheduler
4
- #
5
- # Sun May 3 15:44:28 JST 2009
6
- #
7
-
8
- require 'spec_base'
9
-
10
-
11
- describe "#{SCHEDULER_CLASS} timeouts" do
12
-
13
- before(:each) do
14
- @s = start_scheduler
15
- end
16
- after(:each) do
17
- stop_scheduler(@s)
18
- end
19
-
20
- it 'refuses to schedule a job with :timeout and :blocking' do
21
-
22
- lambda {
23
- @s.in '1s', :timeout => '3s', :blocking => true do
24
- end
25
- }.should raise_error(ArgumentError)
26
- end
27
-
28
- it 'schedules a dedicated job for the timeout' do
29
-
30
- @s.in '1s', :timeout => '3s' do
31
- sleep 5
32
- end
33
-
34
- @s.jobs.size.should == 1
35
-
36
- # the timeout job is left
37
-
38
- sleep 2
39
- @s.jobs.size.should == 1
40
- @s.find_by_tag('timeout').size.should == 1
41
- end
42
-
43
- it 'times out' do
44
-
45
- var = nil
46
- timedout = false
47
-
48
- @s.in '1s', :timeout => '1s' do
49
- begin
50
- sleep 2
51
- var = true
52
- rescue Rufus::Scheduler::TimeOutError => e
53
- timedout = true
54
- end
55
- end
56
-
57
- sleep 4
58
-
59
- var.should == nil
60
- @s.jobs.size.should == 0
61
- timedout.should == true
62
- end
63
-
64
- it 'dies silently if job finished before timeout' do
65
-
66
- var = nil
67
- timedout = false
68
-
69
- @s.in '1s', :timeout => '1s' do
70
- begin
71
- var = true
72
- rescue Rufus::Scheduler::TimeOutError => e
73
- timedout = true
74
- end
75
- end
76
-
77
- sleep 3
78
-
79
- var.should == true
80
- @s.jobs.size.should == 0
81
- timedout.should == false
82
- end
83
-
84
- it 'does not timeout other jobs (in case of every)' do
85
-
86
- timeouts = []
87
-
88
- @s.every '1s', :timeout => '1s500' do
89
- start = Time.now
90
- begin
91
- sleep 2.0
92
- rescue Rufus::Scheduler::TimeOutError => e
93
- timeouts << (Time.now - start)
94
- end
95
- end
96
-
97
- sleep 5.5
98
-
99
- timeouts.size.should == 3
100
- timeouts.each { |to| to.should be_within(0.5).of(1.5) }
101
- end
102
-
103
- it 'points to their "parent" job' do
104
-
105
- @s.in '1s', :timeout => '3s', :job_id => 'nada' do
106
- sleep 4
107
- end
108
-
109
- sleep 2
110
-
111
- @s.jobs.values.first.parent.job_id.should == 'nada'
112
- end
113
-
114
- it 'does not survive their job' do
115
-
116
- @s.in '1s', :timeout => '3s' do
117
- sleep 0.100
118
- end
119
-
120
- sleep 2
121
-
122
- @s.jobs.size.should == 0
123
- end
124
-
125
- it 'times out properly after waiting for a mutex' do
126
-
127
- mutex = Mutex.new
128
- timedout = false
129
-
130
- @s.in '0s', :mutex => mutex do
131
- sleep 1
132
- end
133
-
134
- @s.in '0s', :mutex => mutex, :timeout => 0.1 do
135
- begin
136
- sleep 2
137
- rescue Rufus::Scheduler::TimeOutError => e
138
- timedout = true
139
- end
140
- end
141
-
142
- sleep 2
143
-
144
- @s.jobs.size.should == 0
145
- timedout.should be_true
146
- end
147
- end
148
-
data/test/kjw.rb DELETED
@@ -1,113 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- #
4
- # A test by http://twitter.com/kjw
5
- #
6
-
7
- require 'test/unit'
8
- $LOAD_PATH << 'lib'
9
- require 'rufus/sc/scheduler'
10
-
11
- require 'rubygems'
12
- require 'eventmachine'
13
-
14
- class CronTest < Test::Unit::TestCase
15
-
16
- #
17
- # Stress test program for rufus-scheduler
18
- #
19
-
20
- SECONDS_FROM_NOW = 30
21
- MODE = :cron
22
- JOB_COUNT = 1000
23
- JOB_IDS = (1..JOB_COUNT).to_a
24
- NUM_RESCHEDULES = 20
25
-
26
- def setup
27
- @trigger_queue = Queue.new
28
- end
29
-
30
- def test_stress_schedule_unschedule_plain_cron
31
- stress_schedule_unschedule(:cron, Rufus::Scheduler::PlainScheduler.start_new)
32
- end
33
-
34
- def test_stress_schedule_unschedule_plain_at
35
- stress_schedule_unschedule(:at, Rufus::Scheduler::PlainScheduler.start_new)
36
- end
37
-
38
- def test_stress_schedule_unschedule_plain_every
39
- stress_schedule_unschedule(:every, Rufus::Scheduler::PlainScheduler.start_new)
40
- end
41
-
42
- def test_stress_schedule_unschedule_em_cron
43
- stress_schedule_unschedule(:cron, Rufus::Scheduler::EmScheduler.start_new)
44
- end
45
-
46
- def test_stress_schedule_unschedule_em_at
47
- stress_schedule_unschedule(:at, Rufus::Scheduler::EmScheduler.start_new)
48
- end
49
-
50
- def test_stress_schedule_unschedule_em_every
51
- stress_schedule_unschedule(:every, Rufus::Scheduler::EmScheduler.start_new)
52
- end
53
-
54
- protected
55
-
56
- def stress_schedule_unschedule(mode, scheduler)
57
-
58
- # Schedule all jobs, then unschedule and (re)schedule a number of times
59
- schedule_unschedule(scheduler, mode, NUM_RESCHEDULES)
60
-
61
- # give scheduler thread 10 seconds to process the schedule and unschedule requests
62
- # but don't wait for the jobs to trigger (which is in less than 30 seconds)
63
- sleep 10
64
- # print_scheduler_counts(scheduler, 10)
65
-
66
- # by now the scheduler should have processed everything, check
67
- assert(JOB_IDS.sort == scheduler.find_jobs.map{ |job| job.job_id }.sort)
68
- sleep SECONDS_FROM_NOW # wait for jobs to trigger
69
- assert(JOB_COUNT == @trigger_queue.size)
70
- end
71
-
72
- def schedule_unschedule(scheduler, mode, num_reschedules)
73
- schedule_jobs(scheduler, mode)
74
- 1.upto(num_reschedules) do
75
- sleep 0.01 # cause schedule's to happen before unscheduling
76
- unschedule_jobs(scheduler)
77
- schedule_jobs(scheduler, mode)
78
- end
79
- end
80
-
81
- def print_scheduler_counts(scheduler, seconds)
82
- 1.upto(seconds) do
83
- puts "all:%d at:%d cron:%d every:%d pending:%d" % [
84
- scheduler.all_jobs.size,
85
- scheduler.at_job_count,
86
- scheduler.cron_job_count,
87
- scheduler.every_job_count,
88
- scheduler.pending_job_count]
89
- sleep 1
90
- end
91
- end
92
-
93
- def schedule_jobs(scheduler, mode)
94
- trigger_proc = lambda { |params| @trigger_queue << params[:job_id] }
95
- JOB_IDS.each do |job_id|
96
- case mode
97
- when :at
98
- scheduler.at(Time.now + SECONDS_FROM_NOW, {:job_id => job_id}, &trigger_proc)
99
- when :every
100
- scheduler.every("#{SECONDS_FROM_NOW}s", {:job_id => job_id}, &trigger_proc)
101
- when :cron
102
- scheduler.cron("%d * * * * *" % ((Time.now.to_i%60) + SECONDS_FROM_NOW) % 60,
103
- {:job_id => job_id}, &trigger_proc)
104
- end
105
- end
106
- end
107
-
108
- def unschedule_jobs(scheduler)
109
- JOB_IDS.each { |job_id| scheduler.unschedule(job_id) }
110
- end
111
-
112
- end
113
-
data/test/t.rb DELETED
@@ -1,20 +0,0 @@
1
-
2
- $:.unshift('lib')
3
-
4
- require 'rubygems'
5
- require 'rufus/scheduler/em'
6
-
7
- # scheduler
8
-
9
-
10
- s = Rufus::Scheduler.start_new
11
-
12
- puts Time.now.to_s
13
-
14
- s.in('1s') do
15
- p [ :in, Time.now.to_s ]
16
- exit 0
17
- end
18
-
19
- s.join
20
-