rufus-scheduler 1.0.14 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,87 +2,7 @@
2
2
  = rufus-scheduler CHANGELOG.txt
3
3
 
4
4
 
5
- == rufus-scheduler - 1.0.14 released 2009/05/01
5
+ == rufus-scheduler - 2.0.0 released 2009/05/07
6
6
 
7
- - bug #25746 : at/every/in scheduling stress issue.
8
- Fixed by Klaas Jan Wierenga
9
-
10
-
11
- == rufus-scheduler - 1.0.13 released 2009/02/02
12
-
13
- - todo #23779 : removed lib/openwfe/ and restructured to lib/rufus/scheduler/
14
- - todo #23774 : adapted to Ruby 1.9.1
15
- - todo #23483 : removed gemspec from Rakefile
16
- - bug #23458 : :timeout not working on JRuby (reported by Chris Evans). Fixed.
17
- - patch #23430 : gemspec patch by Ryan Sonnek
18
- - patch #23412 : faster CronLine#next_time patch by TobyH
19
-
20
-
21
- == rufus-scheduler - 1.0.12 released 2008/12/18
22
-
23
- - todo #23257 : added :timeout parameter for cron/in/at/every
24
- - bug #22546 : added note about CronLine#next_time, K Liu
25
- - todo #22489 : find_jobs(tag=nil) patch by Xianhang Zhang
26
-
27
-
28
- == rufus-scheduler - 1.0.11 released 2008/09/03
29
-
30
- - todo #21781 : added lib/rufus-scheduler.rb to make Railsists' lives easier
31
-
32
-
33
- == rufus-scheduler - 1.0.10 released 2008/08/28
34
-
35
- - todo #21357 : added Rufus::Scheduler::VERSION
36
- - bug #21358 : start_new() not accepting parameters. Fixed.
37
-
38
-
39
- == rufus-scheduler - 1.0.9 released 2008/07/18
40
-
41
- - bug #21262 : brought back (proxy) duration_to_f to Rufus::Scheduler
42
- - todo #21251 : added 'at', 'cron', 'in' and 'every' shortcut methods
43
- - todo #21203 : keeping track of At and EveryJob until last trigger is over
44
- - todo #20823 : now raising exception in case of bad 'at' parameter
45
- - todo #21194 : added trigger_thread to Job class
46
- - todo #21193 : spinned CronLine out to rufus/cronline.rb
47
- - bug #20893 : sometimes unschedule(every_job) not working when job was
48
- active (performing). Fixed.
49
-
50
-
51
- == rufus-scheduler - 1.0.7 released 2008/06/16
52
-
53
- - todo #20669 : implemented CronJob.next_time()
54
- - todo #20667 : now passing params to schedule() blocks as well.
55
- - bug #20648 : find_schedulable(tag) broken. Fixed.
56
-
57
-
58
- == rufus-scheduler - 1.0.6 released 2008/05/02
59
-
60
- - bug #20476 : no cron jobs on sundays (wday == 0). Fixed.
61
- (thanks to Manfred Usselmann)
62
- - todo #19619 : added :thread_name options to Scheduler.new
63
- - source moved to http://github.com/jmettraux/rufus-scheduler
64
-
65
-
66
- == rufus-scheduler - 1.0.5 released 2008/03/17
67
-
68
- - bug #18363 : constrained precision to 0.0 < p <= 1.0 - s188
69
- - todo #18821 : best effort drift correction integrated - s187
70
- - bug #18513 : 0 seconds and :drop_seconds => "0m". Fixed - s186
71
-
72
-
73
- == rufus-scheduler - 1.0.4 released 2008/02/29
74
-
75
- - todo #18474 : implemented to_duration_array() - s183
76
- - todo #18472 : added Rufus::to_time_string - s181
77
-
78
-
79
- == rufus-scheduler - 1.0.2 released 2008/01/26
80
-
81
- - patch #17505 : added params :first_at and :first_in for schedule_every()
82
- a patch by John Didion - s115
83
-
84
-
85
- == rufus-scheduler - 1.0 released 2008/01/24
86
-
87
- - initial release after "openwferu-scheduler" - 0.9.16
7
+ - initial release
88
8
 
@@ -1,15 +1,16 @@
1
1
 
2
2
  = CREDITS.txt
3
3
 
4
+
4
5
  == Contributors
5
6
 
6
- - Klaas Jan Wierenga, at/every/in stress tests, stress patch
7
+ - Klaas Jan Wierenga, at/every/in stress tests (1.0 and 2.0)
7
8
  - TobyH (http://github.com/tobyh), faster and cleaner CronLine#next_time
8
- - Ryan Sonnek (http://github.com/wireframe), gemspec
9
9
 
10
10
 
11
11
  == Feedback
12
12
 
13
+ - Kenneth Kalmer (daemon-kit)
13
14
  - Chris Evans, :timeout tests on JRuby
14
15
  - Tim Uckun, :timeout concept
15
16
  - K Liu, for the note about CronLine#next_time
@@ -23,3 +24,8 @@
23
24
  * many people gave feedback previously, see
24
25
  http://openwferu.rubyforge.org/svn/trunk/openwfe-ruby/CREDITS.txt
25
26
 
27
+
28
+ == and finally
29
+
30
+ - many thanks to the EventMachine team (especially Aman Gupta)
31
+
@@ -0,0 +1,359 @@
1
+
2
+ = rufus-scheduler
3
+
4
+ rufus-scheduler is a Ruby gem for scheduling pieces of code (jobs). It understands running a job AT a certain time, IN a certain time, EVERY x time or simply via a CRON statement.
5
+
6
+ rufus-scheduler is no replacement for cron/at since it runs inside of Ruby.
7
+
8
+
9
+ == alternatives / complements
10
+
11
+ A list of related Ruby projects :
12
+
13
+ http://github.com/javan/whenever
14
+ http://github.com/yakischloba/em-timers/
15
+
16
+ More like complements :
17
+
18
+ http://github.com/mojombo/chronic/
19
+ http://github.com/hpoydar/chronic_duration
20
+
21
+
22
+ == installation
23
+
24
+ sudo gem install rufus-scheduler
25
+
26
+
27
+ == usage
28
+
29
+ The usage is similar to the one of the old rufus-scheduler. There are a few differences though.
30
+
31
+ require 'rubygems'
32
+ require 'rufus/scheduler'
33
+
34
+ scheduler = Rufus::Scheduler.start_new
35
+
36
+ scheduler.in '20m' do
37
+ puts "order ristretto"
38
+ end
39
+
40
+ scheduler.at 'Thu Mar 26 07:31:43 +0900 2009' do
41
+ puts 'order pizza'
42
+ end
43
+
44
+ scheduler.cron '0 22 * * 1-5' do
45
+ # every day of the week at 00:22
46
+ puts 'activate security system'
47
+ end
48
+
49
+ scheduler.every '5m' do
50
+ puts 'check blood pressure'
51
+ end
52
+
53
+ # ...
54
+
55
+ scheduler.stop
56
+
57
+
58
+ This code summons a plain version of the scheduler, this can be made more explicit via :
59
+
60
+ scheduler = Rufus::Scheduler::PlainScheduler.start_new
61
+
62
+ This PlainScheduler accepts a :thread_name option :
63
+
64
+ scheduler = Rufus::Scheduler::PlainScheduler.start_new(:thread_name => 'my scheduler')
65
+
66
+ might be helpful when tracking threads.
67
+
68
+
69
+ Note that is there is EventMachine present and running,
70
+
71
+ scheduler = Rufus::Scheduler.start_new
72
+
73
+ will return an instance of Rufus::Scheduler::EmScheduler (leveraging EventMachine).
74
+
75
+
76
+ == block parameters
77
+
78
+ Scheduled blocks accept 0 or 1 parameter (this unique parameter is the job
79
+ instance itself).
80
+
81
+ scheduler.every '5m' do
82
+ puts 'check blood pressure'
83
+ end
84
+ scheduler.every '1y' do |job|
85
+ puts "check cholesterol levels (#{job.job_id})"
86
+ end
87
+
88
+ See the class Job for more details :
89
+
90
+ http://rufus.rubyforge.org/rufus-scheduler/classes/Rufus/Scheduler/Job.html
91
+
92
+
93
+ == the time strings understood by rufus-scheduler
94
+
95
+ require 'rubygems'
96
+ require 'rufus/scheduler'
97
+
98
+ p Rufus.parse_time_string '500' # => 0.5
99
+ p Rufus.parse_time_string '1000' # => 1.0
100
+ p Rufus.parse_time_string '1h' # => 3600.0
101
+ p Rufus.parse_time_string '1h10s' # => 3610.0
102
+ p Rufus.parse_time_string '1w2d' # => 777600.0
103
+
104
+ p Rufus.to_time_string 60 # => "1m"
105
+ p Rufus.to_time_string 3661 # => "1h1m1s"
106
+ p Rufus.to_time_string 7 * 24 * 3600 # => "1w"
107
+
108
+
109
+ == :blocking
110
+
111
+ Jobs will, by default, trigger in their own thread. This is usually desirable since one expects the scheduler to continue scheduling even if a job is currently running.
112
+
113
+ Jobs scheduled with the :blocking parameter will run in the thread of the scheduler, blocking it.
114
+
115
+ scheduler.in '20m', :blocking => true do
116
+ puts "order ristretto"
117
+ sleep 2 * 60
118
+ end
119
+ scheduler.in '21m' do
120
+ puts "order espresso"
121
+ end
122
+
123
+ Hence, our espresso wil come in 22 minutes instead of 21.
124
+
125
+
126
+ == 'every' jobs and :first_at / :first_in
127
+
128
+ This job will execute every 3 days, but first time will be in 5 days from now :
129
+
130
+ scheduler.every '3d', :first_in => '5d' do
131
+ # do something
132
+ end
133
+
134
+ This job will execute every 3 days, starting from Christmas Eve at noon :
135
+
136
+ scheduler.every '3d', :first_at => '2009/12/24 12:00' do
137
+ # do something
138
+ end
139
+
140
+ The chronic gem may help (http://chronic.rubyforge.org/) :
141
+
142
+ require 'chronic' # sudo gem install chronic
143
+
144
+ scheduler.every '3h', :first_at => Chronic.parse('this tuesday 5:00') do
145
+ # do something starting this tueday
146
+ end
147
+
148
+
149
+ == self unschedule for 'cron' and 'every' jobs
150
+
151
+ 'at' and 'in' jobs fire once only. 'cron' and 'every' jobs do fire repeatedly, so it might be useful to stop them.
152
+
153
+ scheduler.every '3d' do |job|
154
+ l = determine_crop_maturity_level()
155
+ if l >= 7
156
+ puts "crop is ready."
157
+ job.unschedule
158
+ else
159
+ puts "crop not yet ready..."
160
+ end
161
+ end
162
+
163
+ In this example, the 'every' job will unschedule itself when the crop is ready.
164
+
165
+
166
+ == schedulables
167
+
168
+ Sometimes passing a block isn't that convenient :
169
+
170
+ class JobThing
171
+ def initialize (relevant_info)
172
+ @ri = relevant_info
173
+ end
174
+ def call (job)
175
+ do_something_about_it
176
+ end
177
+ end
178
+
179
+ # ...
180
+
181
+ scheduler.in '3d', JobThing.new('http://news.example.com/data_xyz')
182
+ scheduler.in '1w', JobThing.new('http://news.example.com/data_abc'), :timeout => '1d'
183
+
184
+ rufus-scheduler accepts anything that responds to a call method with a unique parameter (it will pass the job) as a 'schedulable'.
185
+
186
+
187
+ == looking up jobs
188
+
189
+ scheduler.jobs
190
+ # returns a map job_id => job of at/in/every jobs
191
+
192
+ scheduler.cron_jobs
193
+ # idem for cron jobs
194
+
195
+ scheduler.all_jobs
196
+ # idem but for every/at/in/cron jobs (all of them)
197
+
198
+ scheduler.find_by_tag(t)
199
+ # returns all the jobs with a given tag (passed at schedule time with :tags)
200
+
201
+
202
+ == unscheduling jobs
203
+
204
+ The 'scheduling' methods always return an instance of Rufus::Scheduler::Job. This object can be used for unscheduling :
205
+
206
+ job = scheduler.in '2d', :tags => 'admin' do
207
+ run_backlog_cleaning()
208
+ end
209
+
210
+ # later ...
211
+
212
+ job.unschedule
213
+ # or
214
+ scheduler.unschedule(job.job_id)
215
+
216
+
217
+ == tags
218
+
219
+ You can specify tags at schedule time :
220
+
221
+ scheduler.in '2d', :tags => 'admin' do
222
+ run_backlog_cleaning()
223
+ end
224
+ scheduler.every '3m', :tags => 'production' do
225
+ check_order_log()
226
+ end
227
+
228
+ And later query the scheduler for those jobs :
229
+
230
+ admin_jobs = scheduler.find_by_tag('admin')
231
+ production_jobs = scheduler.find_by_tag('production')
232
+
233
+
234
+ == timeout
235
+
236
+ One can specify a timeout for the triggering of a job.
237
+
238
+ scheduler.every '2d', :timeout => '40m' do
239
+ begin
240
+ run_backlog_cleaning()
241
+ rescue Rufus::Scheduler::TimeOutError => toe
242
+ # timeout occurred
243
+ end
244
+ end
245
+
246
+ This job will run every two days. If a run takes more than 40 minutes it will timeout (its thread will receive a TimeOutError).
247
+
248
+ This timeout feature relies on an 'in' job scheduled at the moment the main job gets triggered, hence the '40m' time string format.
249
+
250
+
251
+ == exceptions in jobs
252
+
253
+ By default, when exception occur when a job performs, the error message will be output to the STDOUT.
254
+
255
+ It's easy to customize that behaviour :
256
+
257
+ scheduler = Rufus::Scheduler::PlainScheduler.start_new
258
+ # or
259
+ #scheduler = Rufus::Scheduler::EmScheduler.start_new
260
+
261
+ def scheduler.handle_exception (job, exception)
262
+ puts "job #{job.job_id} caught exception '#{exception}'"
263
+ end
264
+
265
+ For backward compatibility, overriding #log_exception is still OK :
266
+
267
+ def scheduler.log_exception (exception)
268
+ puts "caught exception '#{exception}'"
269
+ end
270
+
271
+ Note that an every job or a cron job will stay scheduled even if it experiences an exception.
272
+
273
+
274
+ == frequency
275
+
276
+ The default frequency for the scheduler is 0.330 seconds. This means that the usual scheduler implementation will wake up, trigger jobs that are to be triggered and then go back to sleep for 0.330 seconds. Note that this doesn't mean that the scheduler will wake up very 0.330 seconds (checking and triggering do take time).
277
+
278
+ You can set a different frequency when starting / initializing the scheduler :
279
+
280
+ require 'rubygems'
281
+ require 'rufus/scheduler'
282
+
283
+ scheduler = Rufus::Scheduler.start_new(:frequency => 60.0)
284
+ # for a lazy scheduler that only wakes up every 60 seconds
285
+
286
+
287
+ == usage with EventMachine
288
+
289
+ rufus-scheduler 2.0 can be used in conjunction with EventMachine (http://github.com/eventmachine/eventmachine/).
290
+
291
+ More and more ruby applications are using EventMachine. This flavour of the scheduler relies on EventMachine, thus it doesn't require a separate thread like the PlainScheduler does.
292
+
293
+ require 'rubygems'
294
+ require 'eventmachine'
295
+
296
+ EM.run {
297
+
298
+ scheduler = Rufus::Scheduler::EmScheduler.start_new
299
+
300
+ scheduler.in '20m' do
301
+ puts "order ristretto"
302
+ end
303
+ }
304
+
305
+
306
+ == tested with
307
+
308
+ ruby 1.8.6, ruby 1.9.1p0
309
+ on jruby 1.2.0 it has some tiny issues (spec/blocking_spec.rb)
310
+
311
+
312
+ == dependencies
313
+
314
+ the ruby gem 'eventmachine' if you use Rufus::Scheduler::EmScheduler, else no other dependencies.
315
+
316
+
317
+ == mailing list
318
+
319
+ On the rufus-ruby list :
320
+
321
+ http://groups.google.com/group/rufus-ruby
322
+
323
+
324
+ == issue tracker
325
+
326
+ http://rubyforge.org/tracker/?atid=18584&group_id=4812&func=browse
327
+
328
+
329
+ == irc
330
+
331
+ irc.freenode.net #ruote
332
+
333
+
334
+ == source
335
+
336
+ http://github.com/jmettraux/rufus-scheduler
337
+
338
+ git clone git://github.com/jmettraux/rufus-scheduler.git
339
+
340
+
341
+ == credits
342
+
343
+ http://github.com/jmettraux/rufus-scheduler/blob/master/CREDITS.txt
344
+
345
+
346
+ == authors
347
+
348
+ John Mettraux, jmettraux@gmail.com, http://jmettraux.wordpress.com
349
+
350
+
351
+ == the rest of Rufus
352
+
353
+ http://rufus.rubyforge.org
354
+
355
+
356
+ == license
357
+
358
+ MIT
359
+