rufus-scheduler 2.0.24 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/CHANGELOG.txt +6 -0
  2. data/CREDITS.txt +4 -0
  3. data/README.md +1064 -0
  4. data/Rakefile +1 -4
  5. data/TODO.txt +145 -55
  6. data/lib/rufus/scheduler.rb +502 -26
  7. data/lib/rufus/{sc → scheduler}/cronline.rb +46 -17
  8. data/lib/rufus/{sc/version.rb → scheduler/job_array.rb} +56 -4
  9. data/lib/rufus/scheduler/jobs.rb +548 -0
  10. data/lib/rufus/scheduler/util.rb +318 -0
  11. data/rufus-scheduler.gemspec +30 -4
  12. data/spec/cronline_spec.rb +29 -8
  13. data/spec/error_spec.rb +116 -0
  14. data/spec/job_array_spec.rb +39 -0
  15. data/spec/job_at_spec.rb +58 -0
  16. data/spec/job_cron_spec.rb +67 -0
  17. data/spec/job_every_spec.rb +71 -0
  18. data/spec/job_in_spec.rb +20 -0
  19. data/spec/job_interval_spec.rb +68 -0
  20. data/spec/job_repeat_spec.rb +308 -0
  21. data/spec/job_spec.rb +387 -115
  22. data/spec/lockfile_spec.rb +61 -0
  23. data/spec/parse_spec.rb +203 -0
  24. data/spec/schedule_at_spec.rb +129 -0
  25. data/spec/schedule_cron_spec.rb +66 -0
  26. data/spec/schedule_every_spec.rb +109 -0
  27. data/spec/schedule_in_spec.rb +80 -0
  28. data/spec/schedule_interval_spec.rb +128 -0
  29. data/spec/scheduler_spec.rb +831 -124
  30. data/spec/spec_helper.rb +65 -0
  31. data/spec/threads_spec.rb +75 -0
  32. metadata +64 -59
  33. data/README.rdoc +0 -661
  34. data/lib/rufus/otime.rb +0 -3
  35. data/lib/rufus/sc/jobqueues.rb +0 -160
  36. data/lib/rufus/sc/jobs.rb +0 -471
  37. data/lib/rufus/sc/rtime.rb +0 -363
  38. data/lib/rufus/sc/scheduler.rb +0 -636
  39. data/spec/at_in_spec.rb +0 -47
  40. data/spec/at_spec.rb +0 -125
  41. data/spec/blocking_spec.rb +0 -64
  42. data/spec/cron_spec.rb +0 -134
  43. data/spec/every_spec.rb +0 -304
  44. data/spec/exception_spec.rb +0 -113
  45. data/spec/in_spec.rb +0 -150
  46. data/spec/mutex_spec.rb +0 -159
  47. data/spec/rtime_spec.rb +0 -137
  48. data/spec/schedulable_spec.rb +0 -97
  49. data/spec/spec_base.rb +0 -87
  50. data/spec/stress_schedule_unschedule_spec.rb +0 -159
  51. data/spec/timeout_spec.rb +0 -148
  52. data/test/kjw.rb +0 -113
  53. data/test/t.rb +0 -20
@@ -0,0 +1,61 @@
1
+
2
+ #
3
+ # Specifying rufus-scheduler
4
+ #
5
+ # Tue Aug 13 05:58:48 JST 2013
6
+ #
7
+
8
+ require 'spec_helper'
9
+
10
+
11
+ describe Rufus::Scheduler do
12
+
13
+ after :each do
14
+
15
+ FileUtils.rm_f('.rufus-scheduler.lock')
16
+ FileUtils.rm_f('lock.txt')
17
+ end
18
+
19
+ context ':lockfile => ".rufus-scheduler.lock"' do
20
+
21
+ it 'writes down a .rufus-scheduler.lock file' do
22
+
23
+ s = Rufus::Scheduler.new :lockfile => '.rufus-scheduler.lock'
24
+
25
+ line = File.read('.rufus-scheduler.lock')
26
+
27
+ #p line
28
+ line.should match(/pid: #{$$}/)
29
+ end
30
+
31
+ it '"flocks" the lock file' do
32
+
33
+ s = Rufus::Scheduler.new :lockfile => '.rufus-scheduler.lock'
34
+
35
+ f = File.new('.rufus-scheduler.lock', 'a')
36
+
37
+ f.flock(File::LOCK_NB | File::LOCK_EX).should == false
38
+ end
39
+
40
+ it 'prevents newer schedulers from starting' do
41
+
42
+ s0 = Rufus::Scheduler.new :lockfile => '.rufus-scheduler.lock'
43
+ s1 = Rufus::Scheduler.new :lockfile => '.rufus-scheduler.lock'
44
+
45
+ s0.started_at.should_not == nil
46
+ s1.started_at.should == nil
47
+ end
48
+
49
+ it 'releases the lockfile when shutting down' do
50
+
51
+ s = Rufus::Scheduler.new :lockfile => '.rufus-scheduler.lock'
52
+
53
+ s.shutdown(:kill)
54
+
55
+ f = File.new('.rufus-scheduler.lock', 'a')
56
+
57
+ f.flock(File::LOCK_NB | File::LOCK_EX).should == 0
58
+ end
59
+ end
60
+ end
61
+
@@ -0,0 +1,203 @@
1
+
2
+ #
3
+ # Specifying rufus-scheduler
4
+ #
5
+ # Wed Apr 17 06:00:59 JST 2013
6
+ #
7
+
8
+ require 'spec_helper'
9
+
10
+
11
+ describe Rufus::Scheduler do
12
+
13
+ describe '.parse' do
14
+
15
+ def parse(s)
16
+ Rufus::Scheduler.parse(s)
17
+ end
18
+
19
+ it 'parses duration strings' do
20
+
21
+ parse('1.0d1.0w1.0d').should == 777600.0
22
+ end
23
+
24
+ it 'parses datetimes' do
25
+
26
+ # local
27
+
28
+ parse('Sun Nov 18 16:01:00 2012').strftime('%c').should ==
29
+ 'Sun Nov 18 16:01:00 2012'
30
+ end
31
+
32
+ it 'parses datetimes with timezones' do
33
+
34
+ parse('Sun Nov 18 16:01:00 2012 Japan').getutc.strftime('%c').should ==
35
+ 'Sun Nov 18 07:01:00 2012'
36
+
37
+ parse('Sun Nov 18 16:01:00 2012 Zulu').getutc.strftime('%c').should ==
38
+ 'Sun Nov 18 16:01:00 2012'
39
+
40
+ parse('Sun Nov 18 16:01:00 Japan 2012').getutc.strftime('%c').should ==
41
+ 'Sun Nov 18 07:01:00 2012'
42
+
43
+ parse('Japan Sun Nov 18 16:01:00 2012').getutc.strftime('%c').should ==
44
+ 'Sun Nov 18 07:01:00 2012'
45
+ end
46
+
47
+ it 'parses datetimes with named timezones' do
48
+
49
+ parse(
50
+ 'Sun Nov 18 16:01:00 2012 Europe/Berlin'
51
+ ).strftime('%c %z').should ==
52
+ 'Sun Nov 18 15:01:00 2012 +0000'
53
+ end
54
+
55
+ it 'parses datetimes (with the local timezone implicitely)' do
56
+
57
+ localzone = Time.now.strftime('%z')
58
+
59
+ parse('Sun Nov 18 16:01:00 2012').strftime('%c %z').should ==
60
+ "Sun Nov 18 16:01:00 2012 #{localzone}"
61
+ end
62
+
63
+ it 'parses cronlines' do
64
+
65
+ out = parse('* * * * *')
66
+
67
+ out.class.should == Rufus::Scheduler::CronLine
68
+ out.original.should == '* * * * *'
69
+
70
+ parse('10 23 * * *').class.should == Rufus::Scheduler::CronLine
71
+ parse('* 23 * * *').class.should == Rufus::Scheduler::CronLine
72
+ end
73
+
74
+ it 'raises on unparseable input' do
75
+
76
+ lambda {
77
+ parse('nada')
78
+ }.should raise_error(ArgumentError, 'couldn\'t parse "nada"')
79
+ end
80
+ end
81
+
82
+ describe '.parse_duration' do
83
+
84
+ def pd(s)
85
+ Rufus::Scheduler.parse_duration(s)
86
+ end
87
+
88
+ it 'parses duration strings' do
89
+
90
+ pd('-1.0d1.0w1.0d').should == -777600.0
91
+ pd('-1d1w1d').should == -777600.0
92
+ pd('-1w2d').should == -777600.0
93
+ pd('-1h10s').should == -3610.0
94
+ pd('-1h').should == -3600.0
95
+ pd('-5.').should == -5.0
96
+ pd('-2.5s').should == -2.5
97
+ pd('-1s').should == -1.0
98
+ pd('-500').should == -500
99
+ pd('').should == 0.0
100
+ pd('5.0').should == 5.0
101
+ pd('0.5').should == 0.5
102
+ pd('.5').should == 0.5
103
+ pd('5.').should == 5.0
104
+ pd('500').should == 500
105
+ pd('1000').should == 1000
106
+ pd('1').should == 1.0
107
+ pd('1s').should == 1.0
108
+ pd('2.5s').should == 2.5
109
+ pd('1h').should == 3600.0
110
+ pd('1h10s').should == 3610.0
111
+ pd('1w2d').should == 777600.0
112
+ pd('1d1w1d').should == 777600.0
113
+ pd('1.0d1.0w1.0d').should == 777600.0
114
+
115
+ pd('.5m').should == 30.0
116
+ pd('5.m').should == 300.0
117
+ pd('1m.5s').should == 60.5
118
+ pd('-.5m').should == -30.0
119
+
120
+ pd('1').should == 1
121
+ pd('0.1').should == 0.1
122
+ pd('1s').should == 1
123
+ end
124
+
125
+ it 'calls #to_s on its input' do
126
+
127
+ pd(0.1).should == 0.1
128
+ end
129
+
130
+ it 'raises on wrong duration strings' do
131
+
132
+ lambda { pd('-') }.should raise_error(ArgumentError)
133
+ lambda { pd('h') }.should raise_error(ArgumentError)
134
+ lambda { pd('whatever') }.should raise_error(ArgumentError)
135
+ lambda { pd('hms') }.should raise_error(ArgumentError)
136
+
137
+ lambda { pd(' 1h ') }.should raise_error(ArgumentError)
138
+ end
139
+ end
140
+
141
+ describe '.to_duration' do
142
+
143
+ def td(o, opts={})
144
+ Rufus::Scheduler.to_duration(o, opts)
145
+ end
146
+
147
+ it 'turns integers into duration strings' do
148
+
149
+ td(0).should == '0s'
150
+ td(60).should == '1m'
151
+ td(61).should == '1m1s'
152
+ td(3661).should == '1h1m1s'
153
+ td(24 * 3600).should == '1d'
154
+ td(7 * 24 * 3600 + 1).should == '1w1s'
155
+ td(30 * 24 * 3600 + 1).should == '4w2d1s'
156
+ end
157
+
158
+ it 'ignores seconds and milliseconds if :drop_seconds => true' do
159
+
160
+ td(0, :drop_seconds => true).should == '0m'
161
+ td(5, :drop_seconds => true).should == '0m'
162
+ td(61, :drop_seconds => true).should == '1m'
163
+ end
164
+
165
+ it 'displays months if :months => true' do
166
+
167
+ td(1, :months => true).should == '1s'
168
+ td(30 * 24 * 3600 + 1, :months => true).should == '1M1s'
169
+ end
170
+
171
+ it 'turns floats into duration strings' do
172
+
173
+ td(0.1).should == '100'
174
+ td(1.1).should == '1s100'
175
+ end
176
+ end
177
+
178
+ describe '.to_duration_hash' do
179
+
180
+ def tdh(o, opts={})
181
+ Rufus::Scheduler.to_duration_hash(o, opts)
182
+ end
183
+
184
+ it 'turns integers duration hashes' do
185
+
186
+ tdh(0).should == {}
187
+ tdh(60).should == { :m => 1 }
188
+ end
189
+
190
+ it 'turns floats duration hashes' do
191
+
192
+ tdh(0.128).should == { :ms => 128 }
193
+ tdh(60.127).should == { :m => 1, :ms => 127 }
194
+ end
195
+
196
+ it 'drops seconds and milliseconds if :drop_seconds => true' do
197
+
198
+ tdh(61.127).should == { :m => 1, :s => 1, :ms => 127 }
199
+ tdh(61.127, :drop_seconds => true).should == { :m => 1 }
200
+ end
201
+ end
202
+ end
203
+
@@ -0,0 +1,129 @@
1
+
2
+ #
3
+ # Specifying rufus-scheduler
4
+ #
5
+ # Wed Apr 17 06:00:59 JST 2013
6
+ #
7
+
8
+ require 'spec_helper'
9
+
10
+
11
+ describe Rufus::Scheduler do
12
+
13
+ before :each do
14
+ @scheduler = Rufus::Scheduler.new
15
+ end
16
+ after :each do
17
+ @scheduler.shutdown
18
+ end
19
+
20
+ describe '#at' do
21
+
22
+ it 'raises if the block to schedule is missing' do
23
+
24
+ lambda {
25
+ @scheduler.at(Time.now + 3600)
26
+ }.should raise_error(ArgumentError)
27
+ end
28
+
29
+ it 'returns a job id' do
30
+
31
+ job_id =
32
+ @scheduler.at(Time.now + 3600) do
33
+ end
34
+
35
+ job_id.class.should == String
36
+ job_id.should match(/^at_/)
37
+ end
38
+
39
+ it 'returns a job if :job => true' do
40
+
41
+ job =
42
+ @scheduler.at(Time.now + 3600, :job => true) do
43
+ end
44
+
45
+ job.class.should == Rufus::Scheduler::AtJob
46
+ end
47
+
48
+ it 'adds a job' do
49
+
50
+ t = Time.now + 3600
51
+
52
+ @scheduler.at(t) do
53
+ end
54
+
55
+ @scheduler.jobs.size.should == 1
56
+ @scheduler.jobs.first.class.should == Rufus::Scheduler::AtJob
57
+ @scheduler.jobs.first.time.should == t
58
+ end
59
+
60
+ it 'triggers a job' do
61
+
62
+ a = false
63
+
64
+ @scheduler.at(Time.now + 0.100) do
65
+ a = true
66
+ end
67
+
68
+ sleep 0.4
69
+
70
+ a.should == true
71
+ end
72
+
73
+ it 'removes the job after execution' do
74
+
75
+ @scheduler.at(Time.now + 0.100) do
76
+ end
77
+
78
+ sleep 0.4
79
+
80
+ @scheduler.jobs.size.should == 0
81
+ end
82
+
83
+ it 'accepts a Time instance' do
84
+
85
+ t = Time.now + 3600
86
+
87
+ job = @scheduler.at(t, :job => true) {}
88
+
89
+ job.time.should == t
90
+ end
91
+
92
+ it 'accepts a time string' do
93
+
94
+ job = @scheduler.at('2100-12-12 20:30', :job => true) {}
95
+
96
+ job.time.should == Time.parse('2100-12-12 20:30')
97
+ end
98
+
99
+ it 'accepts a time string with a delta timezone' do
100
+
101
+ job = @scheduler.at('2100-12-12 20:30 -0200', :job => true) {}
102
+
103
+ job.time.should == Time.parse('2100-12-12 20:30 -0200')
104
+ end
105
+
106
+ it 'accepts a time string with a named timezone' do
107
+
108
+ job = @scheduler.at('2050-12-12 20:30 Europe/Berlin', :job => true) {}
109
+
110
+ job.time.strftime('%c %z').should == 'Mon Dec 12 19:30:00 2050 +0000'
111
+ end
112
+
113
+ it 'accepts a Chronic time string (if Chronic is present)'
114
+ it 'accepts an ActiveSupport time thinggy'
115
+ end
116
+
117
+ describe '#schedule_at' do
118
+
119
+ it 'returns a job' do
120
+
121
+ job = @scheduler.schedule_at(Time.now + 3600) do
122
+ end
123
+
124
+ job.class.should == Rufus::Scheduler::AtJob
125
+ job.id.should match(/^at_/)
126
+ end
127
+ end
128
+ end
129
+
@@ -0,0 +1,66 @@
1
+
2
+ #
3
+ # Specifying rufus-scheduler
4
+ #
5
+ # Sat Jul 13 04:52:08 JST 2013
6
+ #
7
+ # In the train between Bern and Fribourg, riding back
8
+ # from the @ruvetia drinkup
9
+ #
10
+
11
+ require 'spec_helper'
12
+
13
+
14
+ describe Rufus::Scheduler do
15
+
16
+ before :each do
17
+ @scheduler = Rufus::Scheduler.new
18
+ end
19
+ after :each do
20
+ @scheduler.shutdown
21
+ end
22
+
23
+ describe '#cron' do
24
+
25
+ it 'schedules' do
26
+
27
+ counter = 0
28
+
29
+ sleep_until_next_second
30
+ sleep 0.3 # make sure to schedule right after a scheduler 'tick'
31
+
32
+ job =
33
+ @scheduler.cron '* * * * * *', :job => true do
34
+ counter = counter + 1
35
+ end
36
+
37
+ sleep_until_next_second
38
+ sleep_until_next_second
39
+ sleep 0.3 # be sure to be well into the second
40
+
41
+ counter.should == 2
42
+ end
43
+
44
+ it 'raises if the job frequency is higher than the scheduler frequency' do
45
+
46
+ @scheduler.frequency = 10
47
+
48
+ lambda {
49
+ @scheduler.cron '* * * * * *' do; end
50
+ }.should raise_error(ArgumentError)
51
+ end
52
+ end
53
+
54
+ describe '#schedule_cron' do
55
+
56
+ it 'returns a CronJob instance' do
57
+
58
+ job = @scheduler.schedule_cron '* * * * *' do; end
59
+
60
+ job.class.should == Rufus::Scheduler::CronJob
61
+ job.original.should == '* * * * *'
62
+ job.job_id.should match(/^cron_/)
63
+ end
64
+ end
65
+ end
66
+