rufus-scheduler 2.0.24 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+