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,65 @@
1
+
2
+ #
3
+ # Specifying rufus-scheduler
4
+ #
5
+ # Wed Apr 17 06:00:59 JST 2013
6
+ #
7
+
8
+ Thread.abort_on_exception = true
9
+
10
+
11
+ require 'stringio'
12
+ require 'rufus-scheduler'
13
+
14
+
15
+ def local(*args)
16
+
17
+ Time.local(*args)
18
+ end
19
+ alias lo local
20
+
21
+ def utc(*args)
22
+
23
+ Time.utc(*args)
24
+ end
25
+
26
+ def sleep_until_next_minute
27
+
28
+ min = Time.now.min
29
+ while Time.now.min == min; sleep 2; end
30
+ end
31
+
32
+ def sleep_until_next_second
33
+
34
+ sec = Time.now.sec
35
+ while Time.now.sec == sec; sleep 0.2; end
36
+ end
37
+
38
+
39
+ #require 'rspec/expectations'
40
+
41
+ RSpec::Matchers.define :be_within_1s_of do |expected|
42
+
43
+ match do |actual|
44
+
45
+ if actual.respond_to?(:asctime)
46
+ (actual.to_f - expected.to_f).abs <= 1.0
47
+ else
48
+ false
49
+ end
50
+ end
51
+
52
+ failure_message_for_should do |actual|
53
+
54
+ if actual.respond_to?(:asctime)
55
+ "expected #{actual.inspect} to be within 1 second of #{expected}"
56
+ else
57
+ "expected Time instance, got a #{actual.inspect}"
58
+ end
59
+ end
60
+ end
61
+
62
+
63
+ #RSpec.configure do |config|
64
+ #end
65
+
@@ -0,0 +1,75 @@
1
+
2
+ #
3
+ # Specifying rufus-scheduler
4
+ #
5
+ # Thu Jul 25 05:53:51 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
+ context 'thread pool' do
21
+
22
+ it 'starts with an empty thread pool' do
23
+
24
+ @scheduler.work_threads.size.should == 0
25
+ end
26
+
27
+ it 'does not cross the max_work_threads threshold' do
28
+
29
+ #@scheduler.min_work_threads = 2
30
+ @scheduler.max_work_threads = 5
31
+
32
+ 10.times do
33
+ @scheduler.in '0s' do
34
+ sleep 5
35
+ end
36
+ end
37
+
38
+ sleep 0.5
39
+
40
+ #@scheduler.job_threads.each do |t|
41
+ # p t.keys
42
+ # p t[:rufus_scheduler_job].class
43
+ #end
44
+
45
+ @scheduler.work_threads.size.should == 5
46
+ end
47
+
48
+ it 'does not execute unscheduled jobs' do
49
+
50
+ @scheduler.max_work_threads = 1
51
+
52
+ counter = 0
53
+
54
+ job0 =
55
+ @scheduler.schedule_in '0.3s' do
56
+ counter += 1
57
+ sleep 1
58
+ end
59
+ job1 =
60
+ @scheduler.schedule_in '0.35s' do
61
+ counter += 1
62
+ sleep 1
63
+ end
64
+
65
+ sleep(0.1) while counter < 1
66
+ sleep(0.1) while @scheduler.work_queue.size < 1
67
+ job1.unschedule
68
+
69
+ sleep(2)
70
+
71
+ counter.should == 1
72
+ end
73
+ end
74
+ end
75
+
metadata CHANGED
@@ -1,64 +1,64 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rufus-scheduler
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.24
5
- prerelease:
4
+ prerelease:
5
+ version: 3.0.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - John Mettraux
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-09-02 00:00:00.000000000 Z
12
+ date: 2013-10-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: tzinfo
16
- requirement: !ruby/object:Gem::Requirement
17
- none: false
16
+ version_requirements: !ruby/object:Gem::Requirement
18
17
  requirements:
19
- - - ! '>='
18
+ - - '>='
20
19
  - !ruby/object:Gem::Version
21
- version: 0.3.22
22
- type: :runtime
23
- prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
20
+ version: '0'
25
21
  none: false
22
+ requirement: !ruby/object:Gem::Requirement
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
- version: 0.3.22
26
+ version: '0'
27
+ none: false
28
+ prerelease: false
29
+ type: :runtime
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: rake
32
- requirement: !ruby/object:Gem::Requirement
33
- none: false
32
+ version_requirements: !ruby/object:Gem::Requirement
34
33
  requirements:
35
- - - ! '>='
34
+ - - '>='
36
35
  - !ruby/object:Gem::Version
37
36
  version: '0'
38
- type: :development
39
- prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
41
37
  none: false
38
+ requirement: !ruby/object:Gem::Requirement
42
39
  requirements:
43
- - - ! '>='
40
+ - - '>='
44
41
  - !ruby/object:Gem::Version
45
42
  version: '0'
43
+ none: false
44
+ prerelease: false
45
+ type: :development
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: rspec
48
- requirement: !ruby/object:Gem::Requirement
49
- none: false
48
+ version_requirements: !ruby/object:Gem::Requirement
50
49
  requirements:
51
- - - ! '>='
50
+ - - '>='
52
51
  - !ruby/object:Gem::Version
53
- version: 2.7.0
54
- type: :development
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
52
+ version: 2.13.0
57
53
  none: false
54
+ requirement: !ruby/object:Gem::Requirement
58
55
  requirements:
59
- - - ! '>='
56
+ - - '>='
60
57
  - !ruby/object:Gem::Version
61
- version: 2.7.0
58
+ version: 2.13.0
59
+ none: false
60
+ prerelease: false
61
+ type: :development
62
62
  description: job scheduler for Ruby (at, cron, in and every jobs).
63
63
  email:
64
64
  - jmettraux@gmail.com
@@ -69,60 +69,65 @@ files:
69
69
  - Rakefile
70
70
  - lib/rufus-scheduler.rb
71
71
  - lib/rufus/scheduler.rb
72
- - lib/rufus/sc/scheduler.rb
73
- - lib/rufus/sc/rtime.rb
74
- - lib/rufus/sc/version.rb
75
- - lib/rufus/sc/cronline.rb
76
- - lib/rufus/sc/jobs.rb
77
- - lib/rufus/sc/jobqueues.rb
78
- - lib/rufus/otime.rb
72
+ - lib/rufus/scheduler/cronline.rb
73
+ - lib/rufus/scheduler/util.rb
74
+ - lib/rufus/scheduler/jobs.rb
75
+ - lib/rufus/scheduler/job_array.rb
79
76
  - spec/job_spec.rb
80
- - spec/stress_schedule_unschedule_spec.rb
81
- - spec/schedulable_spec.rb
82
- - spec/exception_spec.rb
83
- - spec/in_spec.rb
84
- - spec/timeout_spec.rb
85
- - spec/at_spec.rb
86
- - spec/at_in_spec.rb
87
- - spec/spec_base.rb
77
+ - spec/schedule_in_spec.rb
78
+ - spec/spec_helper.rb
79
+ - spec/job_array_spec.rb
80
+ - spec/schedule_interval_spec.rb
81
+ - spec/job_at_spec.rb
82
+ - spec/schedule_at_spec.rb
83
+ - spec/error_spec.rb
84
+ - spec/schedule_cron_spec.rb
85
+ - spec/job_interval_spec.rb
86
+ - spec/job_repeat_spec.rb
87
+ - spec/lockfile_spec.rb
88
+ - spec/schedule_every_spec.rb
89
+ - spec/threads_spec.rb
88
90
  - spec/cronline_spec.rb
89
- - spec/rtime_spec.rb
90
- - spec/mutex_spec.rb
91
+ - spec/job_in_spec.rb
92
+ - spec/parse_spec.rb
91
93
  - spec/scheduler_spec.rb
92
- - spec/blocking_spec.rb
93
- - spec/every_spec.rb
94
- - spec/cron_spec.rb
95
- - test/t.rb
96
- - test/kjw.rb
94
+ - spec/job_cron_spec.rb
95
+ - spec/job_every_spec.rb
97
96
  - rufus-scheduler.gemspec
98
97
  - CHANGELOG.txt
99
98
  - TODO.txt
100
99
  - LICENSE.txt
101
100
  - CREDITS.txt
102
- - README.rdoc
101
+ - README.md
103
102
  homepage: http://github.com/jmettraux/rufus-scheduler
104
103
  licenses:
105
104
  - MIT
106
- post_install_message:
105
+ post_install_message: "\n***\n\nThanks for installing rufus-scheduler 3.0.0\n\nIt\
106
+ \ might not be 100% compatible with rufus-scheduler 2.x.\n\nIf you encounter issues\
107
+ \ with this new rufus-scheduler, especially\nif your app worked fine with previous\
108
+ \ versions of it, you can\n\nA) Forget it and peg your Gemfile to rufus-scheduler\
109
+ \ 2.0.24\n\nand / or\n\nB) Take some time to carefully report the issue at\n https://github.com/jmettraux/rufus-scheduler/issue\n\
110
+ \nFor general help about rufus-scheduler, ask via:\nhttp://stackoverflow.com/questions/ask?tags=rufus-scheduler+ruby\n\
111
+ \nCheers.\n\n***\n "
107
112
  rdoc_options: []
108
113
  require_paths:
109
114
  - lib
110
115
  required_ruby_version: !ruby/object:Gem::Requirement
111
- none: false
112
116
  requirements:
113
- - - ! '>='
117
+ - - '>='
114
118
  - !ruby/object:Gem::Version
115
119
  version: '0'
116
- required_rubygems_version: !ruby/object:Gem::Requirement
117
120
  none: false
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
122
  requirements:
119
- - - ! '>='
123
+ - - '>='
120
124
  - !ruby/object:Gem::Version
121
125
  version: '0'
126
+ none: false
122
127
  requirements: []
123
128
  rubyforge_project: rufus
124
- rubygems_version: 1.8.23
125
- signing_key:
129
+ rubygems_version: 1.8.24
130
+ signing_key:
126
131
  specification_version: 3
127
132
  summary: job scheduler for Ruby (at, cron, in and every jobs)
128
133
  test_files: []
data/README.rdoc DELETED
@@ -1,661 +0,0 @@
1
- = rufus-scheduler
2
-
3
- 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.
4
-
5
- rufus-scheduler is no replacement for cron/at since it runs inside of Ruby.
6
-
7
-
8
- == alternatives / complements
9
-
10
- A list of related Ruby projects :
11
-
12
- * http://github.com/javan/whenever
13
- * http://github.com/yakischloba/em-timers
14
- * http://github.com/adamwiggins/clockwork
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
- 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 22:00 (10pm)
46
- puts 'activate security system'
47
- end
48
-
49
- scheduler.every '5m' do
50
- puts 'check blood pressure'
51
- end
52
-
53
-
54
- This code summons a plain version of the scheduler, this can be made more explicit via :
55
-
56
- scheduler = Rufus::Scheduler::PlainScheduler.start_new
57
-
58
- This PlainScheduler accepts a :thread_name option :
59
-
60
- scheduler = Rufus::Scheduler::PlainScheduler.start_new(:thread_name => 'my scheduler')
61
-
62
- which might be helpful when tracking threads.
63
-
64
-
65
- Note that if there is an EventMachine present and running,
66
-
67
- scheduler = Rufus::Scheduler.start_new
68
-
69
- will return an instance of Rufus::Scheduler::EmScheduler (leveraging EventMachine).
70
-
71
-
72
- == a note about cron jobs
73
-
74
- This is a classical cron :
75
-
76
- scheduler.cron '0 22 * * 1-5' do
77
- # every day of the week at 22:00 (10pm)
78
- end
79
-
80
- Rufus-scheduler supports three variants to that notation : seconds, last day of month and timezones.
81
-
82
- scheduler.cron '13 0 22 * * 1-5' do
83
- # every day of the week at 22:00:13
84
- end
85
-
86
- scheduler.cron '0 22 L * *' do
87
- # every month on the last day at 22:00
88
- end
89
-
90
- scheduler.cron '0 22 * * 1-5 Europe/Paris' do
91
- # every day of the week when it's 22:00 in Paris
92
- end
93
- scheduler.cron '0 22 * * 1-5 Etc/GMT+2' do
94
- # every day of the week when it's 22:00 in GMT+2
95
- end
96
-
97
- The timezones are the ones supported by the 'tzinfo' rubygem (http://tzinfo.rubyforge.org/).
98
-
99
- The timezone support was contributed by Tanzeeb Khalili.
100
-
101
- "monthdays" are supported
102
-
103
- scheduler.cron '0 22 * * sun#1,sun#2' do
104
- # every first and second sunday of the month, at 22:00
105
- end
106
-
107
- It's also OK (since 2.0.19) to use L (for last monthday) or negative numbers.
108
-
109
- scheduler.cron '0 22 * * sun#-1' do
110
- # every last sunday of the month, at 22:00
111
- end
112
-
113
-
114
- == scheduler.join
115
-
116
- Note that if you have a tiny script like this one :
117
-
118
- require 'rubygems'; require 'rufus-scheduler'
119
-
120
- scheduler = Rufus::Scheduler.start_new
121
-
122
- scheduler.at 'Thu Mar 26 07:31:43 +0900 2009' do
123
- puts 'order pizza'
124
- end
125
-
126
- And you run it, it will exit immediately.
127
-
128
- If you place
129
-
130
- scheduler.join
131
-
132
- at the end, it will make the current (main) thread join the scheduler and prevent the Ruby runtime from exiting.
133
-
134
- You shouldn't be exposed to this issue when using EventMachine, since while running EM, your runtime won't exit.
135
-
136
- === important note about #join
137
-
138
- DO NOT CALL this #join method if you're running rufus-scheduler from Rails or Sinatra or any application that's already some kind of 'daemon'. It's not necessary! #join is meant for small standalone scripts.
139
-
140
-
141
- == schedule.stop
142
-
143
- scheduler.stop
144
-
145
- This call stops the scheduler. It doesn't unschedule jobs. If there are running jobs, they're left running.
146
-
147
- If you need to stop the scheduler and wait for all the jobs currently running to finish (without killing them), rufus-scheduler 2.0.20 brings a new :terminate => true option.
148
-
149
- scheduler.stop(:terminate => true)
150
- # returns once all the jobs have been unscheduled and no jobs is running
151
-
152
-
153
- == block parameters
154
-
155
- Scheduled blocks accept 0 or 1 parameter (this unique parameter is the job
156
- instance itself).
157
-
158
- scheduler.every '5m' do
159
- puts 'check blood pressure'
160
- end
161
- scheduler.every '1y' do |job|
162
- puts "check cholesterol levels (#{job.job_id})"
163
- end
164
-
165
- See the class Job for more details :
166
-
167
- http://rufus.rubyforge.org/rufus-scheduler/classes/Rufus/Scheduler/Job.html
168
-
169
-
170
- == the time strings understood by rufus-scheduler
171
-
172
- require 'rubygems'
173
- require 'rufus/scheduler'
174
-
175
- p Rufus.parse_time_string '500' # => 0.5
176
- p Rufus.parse_time_string '1000' # => 1.0
177
- p Rufus.parse_time_string '1h' # => 3600.0
178
- p Rufus.parse_time_string '1h10s' # => 3610.0
179
- p Rufus.parse_time_string '1w2d' # => 777600.0
180
-
181
- p Rufus.to_time_string 60 # => "1m"
182
- p Rufus.to_time_string 3661 # => "1h1m1s"
183
- p Rufus.to_time_string 7 * 24 * 3600 # => "1w"
184
-
185
-
186
- == :blocking => true
187
-
188
- 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.
189
-
190
- Jobs scheduled with the :blocking parameter will run in the thread of the scheduler, blocking it.
191
-
192
- scheduler.in '20m', :blocking => true do
193
- puts "order ristretto"
194
- sleep 2 * 60
195
- end
196
- scheduler.in '21m' do
197
- puts "order espresso"
198
- end
199
-
200
- Hence, our espresso will come in 22 minutes instead of 21.
201
-
202
- 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).
203
-
204
- scheduler.cron '0 16 * * * *' do
205
- puts "four o'clock tea"
206
- end
207
-
208
- If at 4pm the scheduler is in a blocking task, there will be no four o'clock tea.
209
-
210
-
211
- == :mutex => 'that_mutex'
212
-
213
- :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 ?
214
-
215
- scheduler.in '20m', :mutex => 'that_mutex' do
216
- puts "order ristretto"
217
- sleep 2 * 60
218
- puts "ah, that was delicious"
219
- end
220
- scheduler.in '21m' :mutex => 'that_mutex' do
221
- puts "order espresso"
222
- end
223
-
224
- 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).
225
-
226
- It's OK to use a mutex directly:
227
-
228
- m = Mutex.new
229
- # ...
230
- scheduler.cron '0 18 * * *', :mutex => m do
231
- # ...
232
- end
233
- scheduler.in '21m' :mutex => m do
234
- # ...
235
- end
236
-
237
- It can be handy for even more fine-grained control:
238
-
239
- m = Mutex.new
240
- # ...
241
- scheduler.cron '0 18 * * *', :mutex => m do
242
- # ...
243
- end
244
- scheduler.in '21m' do
245
- # non-critical
246
- m.synchronize do
247
- # critical
248
- end
249
- # non-critical
250
- end
251
-
252
- Please note that a mutex can also be used to prevent overlapping executions of the same job:
253
-
254
- scheduler.every '5m', :mutex => 'the_mutex' do
255
- puts "order ristretto"
256
- # do something that might take more that 5 minutes...
257
- puts "ah, that was delicious"
258
- end
259
-
260
- But beware the cascades...
261
-
262
-
263
- == :mutex => ['mutex_a', 'mutex_b', ...]
264
-
265
- Multiple mutexes can be used to ensure exlusivity:
266
-
267
- scheduler.in '20m', :mutex => 'mutex_r' do
268
- puts "order ristretto"
269
- sleep 2 * 60
270
- end
271
-
272
- scheduler.in '20m' :mutex => 'mutex_e' do
273
- puts "order espresso"
274
- sleep 3 * 60
275
- end
276
-
277
- scheduler.in '1h' :mutex => ['mutex_r', 'mutex_e'] do
278
- puts "code for fun"
279
- end
280
-
281
- This allow you order ristretto and espresso at same time, but when you coding it ensure you can't order any thing, and when you ordering anything it ensure you can't code.
282
-
283
- Sure you can also use array of Mutex object directly:
284
-
285
- mutex_r = Mutex.new
286
- mutex_e = Mutex.new
287
- # ...
288
- scheduler.in '1h' :mutex => [mutex_r, mutex_e] do
289
- puts "code for fun"
290
- end
291
-
292
-
293
- == :allow_overlapping => false
294
-
295
- By default, every and cron jobs will "overlap":
296
-
297
- scheduler.every '3s' do
298
- 4.times do |i|
299
- puts "hello #{i}"
300
- sleep 1
301
- end
302
- end
303
-
304
- You might end up with something that looks like
305
-
306
- hello 0
307
- hello 1
308
- hello 2
309
- hello 3
310
- hello 3
311
- hello 4
312
- ...
313
-
314
- This every job will have overlaps. To prevent that:
315
-
316
- scheduler.every '3s', :allow_overlapping => false do
317
- # ...
318
- end
319
-
320
-
321
- == 'every' jobs and :first_at / :first_in
322
-
323
- This job will execute every 3 days, but first time will be in 5 days from now :
324
-
325
- scheduler.every '3d', :first_in => '5d' do
326
- # do something
327
- end
328
-
329
- This job will execute every 3 days, starting from Christmas Eve at noon :
330
-
331
- scheduler.every '3d', :first_at => '2009/12/24 12:00' do
332
- # do something
333
- end
334
-
335
- The chronic gem may help (http://chronic.rubyforge.org/) :
336
-
337
- require 'chronic' # sudo gem install chronic
338
-
339
- scheduler.every '3h', :first_at => Chronic.parse('this tuesday 5:00') do
340
- # do something starting this tuesday
341
- end
342
-
343
- Note : setting a :first_at/:first_in in the past will get rufus-scheduler to trigger for all the past schedules until now. Adding :discard_past => true will prevent this.
344
-
345
-
346
- == self unschedule for 'cron' and 'every' jobs
347
-
348
- 'at' and 'in' jobs fire once only. 'cron' and 'every' jobs do fire repeatedly, so it might be useful to stop them.
349
-
350
- scheduler.every '3d' do |job|
351
- l = determine_crop_maturity_level()
352
- if l >= 7
353
- puts "crop is ready."
354
- job.unschedule
355
- else
356
- puts "crop not yet ready..."
357
- end
358
- end
359
-
360
- In this example, the 'every' job will unschedule itself when the crop is ready.
361
-
362
-
363
- == #running?
364
-
365
- job = scheduler.every '3d' do
366
- # ...
367
- end
368
-
369
- # ...
370
-
371
- p job.running?
372
-
373
- Job#running? will return true when the job got triggered and is actually performing.
374
-
375
- Please note, that #running? is not related to the #paused? which is detailed in the next section.
376
-
377
-
378
- == #pause, #resume and #paused?
379
-
380
- Jobs, as well as the scheduler itself have a pair of #pause and #resume methods.
381
-
382
- job = scheduler.every '2h' do
383
- # ...
384
- end
385
-
386
- # ...
387
-
388
- job.pause # the job will be scheduled but won't trigger
389
-
390
- # ...
391
-
392
- puts job.paused?
393
-
394
- Pausing / resuming a job doesn't affect the scheduling of a job, it merely "silences" it, its block won't get executed. Calling resume will not reset the schedule of the job. If you schedule a job to trigger every 10 minutes at 10am and pause it from 1020 to 1025, it's next triggering time will be 1030 approximately.
395
-
396
- One can pause an "at" or "in" job. If it's still paused at trigger time, it will simply become a dud.
397
-
398
- As said, the scheduler has a #pause(job_or_job_id) and a #resume(job_or_job_id) pair of methods:
399
-
400
- scheduler.pause(job)
401
- scheduler.pause(job_id)
402
- scheduler.resume(job)
403
- scheduler.resume(job_id)
404
-
405
-
406
- == Scheduler#running_jobs
407
-
408
- One can get a list of the jobs just triggered (actually running) by doing
409
-
410
- jobs = scheduler.running_jobs
411
-
412
-
413
- == schedulables
414
-
415
- Sometimes passing a block isn't that convenient :
416
-
417
- class JobThing
418
- def initialize(relevant_info)
419
- @ri = relevant_info
420
- end
421
- def call(job)
422
- do_something_about_it
423
- end
424
- end
425
-
426
- # ...
427
-
428
- scheduler.in '3d', JobThing.new('http://news.example.com/data_xyz')
429
- scheduler.in '1w', JobThing.new('http://news.example.com/data_abc'), :timeout => '1d'
430
-
431
- rufus-scheduler accepts anything that responds to a call method with a unique parameter (it will pass the job) as a 'schedulable'.
432
-
433
- For compatibility with older (1.x) versions, schedulables with a trigger methods are accepted :
434
-
435
- class JobThing
436
- def trigger(params)
437
- job = params[:job]
438
- end
439
- end
440
-
441
- The 'params' correspond to the scheduler job params, and the key :job points to the rufus-scheduler job for the schedulable that is passed to a 'call schedulable'.
442
-
443
-
444
- == looking up jobs
445
-
446
- scheduler.jobs
447
- # returns a map job_id => job of at/in/every jobs
448
-
449
- scheduler.cron_jobs
450
- # idem for cron jobs
451
-
452
- scheduler.all_jobs
453
- # idem but for every/at/in/cron jobs (all of them)
454
-
455
- scheduler.find_by_tag(t)
456
- # returns all the jobs with a given tag (passed at schedule time with :tags)
457
-
458
-
459
- == unscheduling jobs
460
-
461
- The 'scheduling' methods always return an instance of Rufus::Scheduler::Job. This object can be used for unscheduling :
462
-
463
- job = scheduler.in '2d', :tags => 'admin' do
464
- run_backlog_cleaning()
465
- end
466
-
467
- # later ...
468
-
469
- job.unschedule
470
- # or
471
- scheduler.unschedule(job.job_id)
472
-
473
-
474
- == tags
475
-
476
- You can specify tags at schedule time :
477
-
478
- scheduler.in '2d', :tags => 'admin' do
479
- run_backlog_cleaning()
480
- end
481
- scheduler.every '3m', :tags => 'production' do
482
- check_order_log()
483
- end
484
-
485
- And later query the scheduler for those jobs :
486
-
487
- admin_jobs = scheduler.find_by_tag('admin')
488
- production_jobs = scheduler.find_by_tag('production')
489
-
490
-
491
- == timeout
492
-
493
- One can specify a timeout for the triggering of a job.
494
-
495
- scheduler.every '2d', :timeout => '40m' do
496
- begin
497
- run_backlog_cleaning()
498
- rescue Rufus::Scheduler::TimeOutError => toe
499
- # timeout occurred
500
- end
501
- end
502
-
503
- This job will run every two days. If a run takes more than 40 minutes it will timeout (its thread will receive a TimeOutError).
504
-
505
- This timeout feature relies on an 'in' job scheduled at the moment the main job gets triggered, hence the '40m' time string format.
506
-
507
-
508
- == exceptions in jobs
509
-
510
- By default, when exceptions occur when a job performs, the error messages will be output to the STDOUT.
511
-
512
- It's easy to customize that behaviour :
513
-
514
- scheduler = Rufus::Scheduler::PlainScheduler.start_new
515
- # or
516
- #scheduler = Rufus::Scheduler::EmScheduler.start_new
517
-
518
- def scheduler.handle_exception(job, exception)
519
- puts "job #{job.job_id} caught exception '#{exception}'"
520
- end
521
-
522
- These are OK too:
523
-
524
- def scheduler.on_exception(job, exception)
525
- puts "job #{job.job_id} caught exception '#{exception}'"
526
- end
527
-
528
- # or
529
-
530
- def scheduler.on_exception(exception)
531
- puts "caught exception '#{exception}'"
532
-
533
- For backward compatibility, overriding #log_exception is still OK :
534
-
535
- def scheduler.log_exception(exception)
536
- puts "caught exception '#{exception}'"
537
- end
538
-
539
- Note that an every job or a cron job will stay scheduled even if it experiences an exception.
540
-
541
- By default, all exceptions are rescued. It's easy to customize that behaviour :
542
-
543
- scheduler = Rufus::Scheduler::PlainScheduler.start_new(:exception => StandardError)
544
- # or
545
- #scheduler = Rufus::Scheduler::EmScheduler.start_new(:exception => StandardError)
546
-
547
- scheduler.in "3s" do
548
- exit
549
- end
550
-
551
- == frequency
552
-
553
- 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).
554
-
555
- You can set a different frequency when starting / initializing the scheduler :
556
-
557
- require 'rubygems'
558
- require 'rufus/scheduler'
559
-
560
- scheduler = Rufus::Scheduler.start_new(:frequency => 60.0)
561
- # for a lazy scheduler that only wakes up every 60 seconds
562
-
563
-
564
- == usage with EventMachine
565
-
566
- rufus-scheduler 2.0 can be used in conjunction with EventMachine (http://github.com/eventmachine/eventmachine/).
567
-
568
- 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.
569
-
570
- require 'rubygems'
571
- require 'eventmachine'
572
-
573
- EM.run {
574
-
575
- scheduler = Rufus::Scheduler::EmScheduler.start_new
576
-
577
- scheduler.in '20m' do
578
- puts "order ristretto"
579
- end
580
- }
581
-
582
-
583
- == with Passenger
584
-
585
- "it terminates for no apparent reason!"
586
-
587
- https://github.com/jmettraux/rufus-scheduler/issues/issue/10
588
-
589
-
590
- == tested with
591
-
592
- * 1.8.7-p249
593
- * 1.9.2-p290
594
- * jruby-1.5.1
595
-
596
- on Mac OS X (Snow Leopard).
597
-
598
-
599
- == dependencies
600
-
601
- The 'tzinfo' rubygem.
602
-
603
- The ruby gem 'eventmachine' if you use Rufus::Scheduler::EmScheduler, else no other dependencies.
604
-
605
-
606
- == support
607
-
608
- If you identify and pinpoint a bug, please use the issue tracker. If you are unsure whether the fault lies in rufus-scheduler or in your software, use the mailing list. The mailing list is Google-powered, so, yes, you can search it.
609
-
610
- Please read carefully: http://www.chiark.greenend.org.uk/~sgtatham/bugs.html (then re-read it).
611
-
612
-
613
- === mailing list
614
-
615
- On the rufus-ruby list :
616
-
617
- http://groups.google.com/group/rufus-ruby
618
-
619
- Newcomers' first message is held for moderation in order to prevent spam. Further messages are not held.
620
-
621
-
622
- === issue tracker
623
-
624
- https://github.com/jmettraux/rufus-scheduler/issues
625
-
626
-
627
- === irc
628
-
629
- If you come over to #ruote to ask for rufus-scheduler help, please make sure to 1) say hello 2) be polite 3) state that you're looking for rufus-scheduler help 4) remember that we cannot read your mind and guess whatever lies in your deployment.
630
-
631
- irc.freenode.net #ruote
632
-
633
- If there is no answer on IRC, use the mailing list.
634
-
635
-
636
- == source
637
-
638
- http://github.com/jmettraux/rufus-scheduler
639
-
640
- git clone git://github.com/jmettraux/rufus-scheduler.git
641
-
642
-
643
- == credits
644
-
645
- http://github.com/jmettraux/rufus-scheduler/blob/master/CREDITS.txt
646
-
647
-
648
- == authors
649
-
650
- John Mettraux, jmettraux@gmail.com, http://jmettraux.github.com
651
-
652
-
653
- == the rest of Rufus
654
-
655
- http://rufus.rubyforge.org
656
-
657
-
658
- == license
659
-
660
- MIT
661
-