rufus-scheduler 3.5.1 → 3.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: f4e266cabe7da6408e8646fbedabd788ad74188f
4
- data.tar.gz: bf8312e05826c8f7aeb150c4f69c874d446f8c55
2
+ SHA256:
3
+ metadata.gz: 86f0ae4ebefa9cf941f66efb56041515eea96cb5105289d9f0f54899841cffc6
4
+ data.tar.gz: 9e6d1422b91536aa56cc2cdb627f3c88e21748c8e8734ba2eb929a46912f303e
5
5
  SHA512:
6
- metadata.gz: 14064eb823dd4efcdf5bcc3cf53de39307184237d1ea95ec826f79fc3398d74ff76edf3206c7bdf113895b9c82d9a27899b4b50dd633fcb56155a36fbec7f8b6
7
- data.tar.gz: dc32167e6b96204a8aa377b8a8c084518ad406eb3b02b8a2ebc7e26698ab3657a4fd6c702093bf7facae54defc0e786a0dd0e69059a653bbfeda2994007309ac
6
+ metadata.gz: 45667cceb3f382ac71b7158d2884fbde21c9ac6f3027889a1dd8b7fd855bd014b35a1a4180b93118552aa7e6e08df061259113b1a5ce86f4e892a4b2f8c0436e
7
+ data.tar.gz: 9ef9d0926f33bacdb0c2b8727b801d861db960ba4b6efac28642ea27e578c1de60a6b1b144217cace6c17de759100b0229c42ba79bb9db4b40527c1e8cdac8e4
data/CHANGELOG.md CHANGED
@@ -2,6 +2,38 @@
2
2
  # CHANGELOG.md
3
3
 
4
4
 
5
+ ### rufus-scheduler 3.8.0 - released 2021-07-14
6
+
7
+ * Add #source_location to Job, gh-322
8
+
9
+
10
+ ### rufus-scheduler 3.7.0 - released 2020-12-31
11
+
12
+ * Implement Job name:/n: #name and #name=, gh-309
13
+ * Add Job #has_key?, #value, and #entries
14
+ * Add #locals access to Job
15
+ * Implement Scheduler#around_trigger, @jjb, gh-310
16
+ * Accept max_worker_threads: for max_work_threads:
17
+ * Clean up Scheduler#shutdwon, thanks @itsaphel and @jjb, gh-304, gh-315
18
+
19
+ * f59df40 Bring in discard_past: for every jobs, gh-290
20
+ * 7613277 Introduce :discard_past = false for cron, gh-305
21
+
22
+
23
+ ### rufus-scheduler 3.6.0 - released 2019-04-22
24
+
25
+ * Let Scheduler#cron fail if the cron string is invalid, gh-289
26
+ * Implement Job#next_times(count) for cron, every, and interval jobs
27
+ * Implement Job#next_times(count) for at and in jobs
28
+ * Stop fooling around and stick to https://semver.org
29
+
30
+
31
+ ### rufus-scheduler 3.5.2 - released 2018-08-01
32
+
33
+ * Use Fugit::Cron#rough_frequency
34
+ * Improve Job#check_frequency performance, gh-276, @drcapulet
35
+
36
+
5
37
  ### rufus-scheduler 3.5.1 - released 2018-07-20
6
38
 
7
39
  * Upgrade fugit to 1.1.4 (with out of DST issue fix)
data/CREDITS.md CHANGED
@@ -4,10 +4,18 @@
4
4
 
5
5
  ## Contributors
6
6
 
7
- * Vais Salikhov (https://github.com/vais) - many document clarifications
8
- * Wes McNamee (https://github.com/ghostsquad) - let #schedule accept a CronLine
9
- * Joe Rafaniello (https://github.com/jrafanie) - Travis Ruby 2.4.1
10
- * Benjamin Fleischer (https://github.com/bf4) - ZoTime#subtract
7
+ * John Bachir https://github.com/jjb gh-310
8
+ * Daniel Berger https://github.com/djberg96 gh-300
9
+ * Ceyhun Onur https://github.com/ceyonur parse_cron no_error: true
10
+ * Darwin Wu https://github.com/dwaxe Rails initializer vs tests change
11
+ * Mike Karolow https://github.com/mike-yesware update Travis target Rubies
12
+ * Jack-Nie https://github.com/jack-nie gh-285 fix broken comment link
13
+ * Yechiel Kalmenson (https://github.com/achasveachas) README link fix
14
+ * Alex Coomans (https://github.com/drcapulet) gh-276 freq check pref improvement
15
+ * Vais Salikhov (https://github.com/vais) many document clarifications
16
+ * Wes McNamee (https://github.com/ghostsquad) let #schedule accept a CronLine
17
+ * Joe Rafaniello (https://github.com/jrafanie) Travis Ruby 2.4.1
18
+ * Benjamin Fleischer (https://github.com/bf4) ZoTime#subtract
11
19
  * Sam Rowe (https://github.com/riddley) gh-240 timezone for Debian
12
20
  * Daniel Rodgers-Pryor (https://github.com/djrodgerspryor), gh-238 fix ZooKeeper example
13
21
  * Cody Cutrer (https://github.com/ccutrer) gh-232 is_a?(Fixnum) replacement
@@ -59,6 +67,8 @@
59
67
 
60
68
  ## Feedback
61
69
 
70
+ * aphel (https://github.com/itsaphel) #shutdown vs current thread, gh-304
71
+ * aesyondu (https://github.com/aesyondu) Rails console 4.2.x, gh-186
62
72
  * Sasha Hoellger (https://github.com/mitnal) parse_cron and readme, gh-270
63
73
  * Gian (https://github.com/snmgian) cron vs :first clarification, gh-266
64
74
  * Vito Laurenza (https://github.com/veetow) help debugging tz issues, gh-240
data/LICENSE.txt CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- Copyright (c) 2005-2017, John Mettraux, jmettraux@gmail.com
2
+ Copyright (c) 2005-2021, John Mettraux, jmettraux@gmail.com
3
3
 
4
4
  Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  of this software and associated documentation files (the "Software"), to deal
data/Makefile CHANGED
@@ -23,5 +23,5 @@ build: gemspec_validate
23
23
  mv $(NAME)-$(VERSION).gem pkg/
24
24
 
25
25
  push: build
26
- gem push pkg/$(NAME)-$(VERSION).gem
26
+ gem push --otp "$(OTP)" pkg/$(NAME)-$(VERSION).gem
27
27
 
data/README.md CHANGED
@@ -1,8 +1,9 @@
1
1
 
2
2
  # rufus-scheduler
3
3
 
4
- [![Build Status](https://secure.travis-ci.org/jmettraux/rufus-scheduler.svg)](http://travis-ci.org/jmettraux/rufus-scheduler)
5
- [![Gem Version](https://badge.fury.io/rb/rufus-scheduler.svg)](http://badge.fury.io/rb/rufus-scheduler)
4
+ [![tests](https://github.com/jmettraux/rufus-scheduler/workflows/test/badge.svg)](https://github.com/jmettraux/rufus-scheduler/actions)
5
+ [![Gem Version](https://badge.fury.io/rb/rufus-scheduler.svg)](https://badge.fury.io/rb/rufus-scheduler)
6
+ [![Join the chat at https://gitter.im/floraison/fugit](https://badges.gitter.im/floraison/fugit.svg)](https://gitter.im/floraison/fugit?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
6
7
 
7
8
  Job scheduler for Ruby (at, cron, in and every jobs).
8
9
 
@@ -23,7 +24,11 @@ scheduler.in '3s' do
23
24
  end
24
25
 
25
26
  scheduler.join
27
+ #
26
28
  # let the current thread join the scheduler thread
29
+ #
30
+ # (please note that this join should be removed when scheduling
31
+ # in a web application (Rails and friends) initializer)
27
32
  ```
28
33
  (run with `ruby quickstart.rb`)
29
34
 
@@ -46,6 +51,9 @@ end
46
51
  scheduler.every '3h' do
47
52
  # do something every 3 hours
48
53
  end
54
+ scheduler.every '3h10m' do
55
+ # do something every 3 hours and 10 minutes
56
+ end
49
57
 
50
58
  scheduler.cron '5 0 * * *' do
51
59
  # do something every day, five minutes after midnight
@@ -55,6 +63,8 @@ end
55
63
  # ...
56
64
  ```
57
65
 
66
+ Rufus-scheduler uses [fugit](https://github.com/floraison/fugit) for parsing time strings, [et-orbi](https://github.com/floraison/et-orbi) for pairing time and [tzinfo](https://github.com/tzinfo/tzinfo) timezones.
67
+
58
68
  ## non-features
59
69
 
60
70
  Rufus-scheduler (out of the box) is an in-process, in-memory scheduler. It uses threads.
@@ -67,9 +77,10 @@ A rufus-scheduler instance will go on scheduling while it is present among the o
67
77
  ## related and similar gems
68
78
 
69
79
  * [Whenever](https://github.com/javan/whenever) - let cron call back your Ruby code, trusted and reliable cron drives your schedule
80
+ * [ruby-clock](https://github.com/jjb/ruby-clock) - a clock process / job scheduler for Ruby
70
81
  * [Clockwork](https://github.com/Rykian/clockwork) - rufus-scheduler inspired gem
71
82
  * [Crono](https://github.com/plashchynski/crono) - an in-Rails cron scheduler
72
- * [PerfectSched](https://github.com/treasure-data/perfectsched) - highly available distributed cron built on [Sequel](http://sequel.jeremyevans.net) and more
83
+ * [PerfectSched](https://github.com/treasure-data/perfectsched) - highly available distributed cron built on [Sequel](https://sequel.jeremyevans.net) and more
73
84
 
74
85
  (please note: rufus-scheduler is not a cron replacement)
75
86
 
@@ -86,7 +97,7 @@ There is no EventMachine-based scheduler anymore.
86
97
  I'll drive you right to the [tracks](#so-rails).
87
98
 
88
99
 
89
- ## Notable changes:
100
+ ## notable changes:
90
101
 
91
102
  * As said, no more EventMachine-based scheduler
92
103
  * ```scheduler.every('100') {``` will schedule every 100 seconds (previously, it would have been 0.1s). This aligns rufus-scheduler with Ruby's ```sleep(100)```
@@ -94,8 +105,8 @@ I'll drive you right to the [tracks](#so-rails).
94
105
  * The error_handler is [#on_error](#rufusscheduleron_errorjob-error) (instead of #on_exception), by default it now prints the details of the error to $stderr (used to be $stdout)
95
106
  * Rufus::Scheduler::TimeOutError renamed to Rufus::Scheduler::TimeoutError
96
107
  * Introduction of "interval" jobs. Whereas "every" jobs are like "every 10 minutes, do this", interval jobs are like "do that, then wait for 10 minutes, then do that again, and so on"
97
- * Introduction of a :lockfile => true/filename mechanism to prevent multiple schedulers from executing
98
- * "discard_past" is on by default. If the scheduler (its host) sleeps for 1 hour and a ```every '10m'``` job is on, it will trigger once at wakeup, not 6 times (discard_past was false by default in rufus-scheduler 2.x). No intention to re-introduce ```:discard_past => false``` in 3.0 for now.
108
+ * Introduction of a lockfile: true/filename mechanism to prevent multiple schedulers from executing
109
+ * "discard_past" is on by default. If the scheduler (its host) sleeps for 1 hour and a `every '10m'` job is on, it will trigger once at wakeup, not 6 times (discard_past was false by default in rufus-scheduler 2.x). No intention to re-introduce `discard_past: false` in 3.0 for now.
99
110
  * Introduction of Scheduler #on_pre_trigger and #on_post_trigger callback points
100
111
 
101
112
 
@@ -105,26 +116,26 @@ So you need help. People can help you, but first help them help you, and don't w
105
116
 
106
117
  "hello", "please" and "thanks" are not swear words.
107
118
 
108
- Go read [how to report bugs effectively](http://www.chiark.greenend.org.uk/~sgtatham/bugs.html), twice.
119
+ Go read [how to report bugs effectively](https://www.chiark.greenend.org.uk/~sgtatham/bugs.html), twice.
109
120
 
110
121
  Update: [help_help.md](https://gist.github.com/jmettraux/310fed75f568fd731814) might help help you.
111
122
 
112
- ### on IRC
123
+ ### on Gitter
113
124
 
114
- I sometimes haunt #ruote on freenode.net. The channel is not dedicated to rufus-scheduler, so if you ask a question, first mention it's about rufus-scheduler.
125
+ You can find help via chat over at [https://gitter.im/floraison/fugit](https://gitter.im/floraison/fugit). It's [fugit](https://github.com/floraison/fugit), [et-orbi](https://github.com/floraison/et-orbi), and rufus-scheduler combined chat room.
115
126
 
116
- Please note that I prefer helping over Stack Overflow because it's more searchable than the ruote IRC archive.
127
+ Please be courteous.
117
128
 
118
129
  ### issues
119
130
 
120
- Yes, issues can be reported in [rufus-scheduler issues](https://github.com/jmettraux/rufus-scheduler/issues), I'd actually prefer bugs in there. If there is nothing wrong with rufus-scheduler, a [Stack Overflow question](http://stackoverflow.com/questions/ask?tags=rufus-scheduler+ruby) is better.
131
+ Yes, issues can be reported in [rufus-scheduler issues](https://github.com/jmettraux/rufus-scheduler/issues), I'd actually prefer bugs in there. If there is nothing wrong with rufus-scheduler, a [Stack Overflow question](https://stackoverflow.com/questions/ask?tags=rufus-scheduler+ruby) is better.
121
132
 
122
133
  ### faq
123
134
 
124
- * [It doesn't work...](http://www.chiark.greenend.org.uk/~sgtatham/bugs.html)
125
- * [I want a refund](http://blog.nodejitsu.com/getting-refunds-on-open-source-projects)
126
- * [Passenger and rufus-scheduler](http://stackoverflow.com/questions/18108719/debugging-rufus-scheduler/18156180#18156180)
127
- * [Passenger and rufus-scheduler (2)](http://stackoverflow.com/questions/21861387/rufus-cron-job-not-working-in-apache-passenger#answer-21868555)
135
+ * [It doesn't work...](https://www.chiark.greenend.org.uk/~sgtatham/bugs.html)
136
+ * [I want a refund](https://blog.nodejitsu.com/getting-refunds-on-open-source-projects)
137
+ * [Passenger and rufus-scheduler](https://stackoverflow.com/questions/18108719/debugging-rufus-scheduler/18156180#18156180)
138
+ * [Passenger and rufus-scheduler (2)](https://stackoverflow.com/questions/21861387/rufus-cron-job-not-working-in-apache-passenger#answer-21868555)
128
139
  * [Passenger in-depth spawn methods](https://www.phusionpassenger.com/library/indepth/ruby/spawn_methods/)
129
140
  * [Passenger in-depth spawn methods (smart spawning)](https://www.phusionpassenger.com/library/indepth/ruby/spawn_methods/#smart-spawning-hooks)
130
141
  * [The scheduler comes up when running the Rails console or a Rake task](https://github.com/jmettraux/rufus-scheduler#avoid-scheduling-when-running-the-ruby-on-rails-console)
@@ -212,7 +223,7 @@ job =
212
223
  # also
213
224
 
214
225
  job =
215
- scheduler.in '10d', :job => true do
226
+ scheduler.in '10d', job: true do
216
227
  # ...
217
228
  end
218
229
  ```
@@ -367,23 +378,40 @@ While paused, the scheduler still accepts schedules, but no schedule will get tr
367
378
 
368
379
  ## job options
369
380
 
370
- ### :blocking => true
381
+ ### name: string
371
382
 
372
- By default, jobs are triggered in their own, new threads. When `:blocking => true`, the job is triggered in the scheduler thread (a new thread is not created). Yes, while a blocking job is running, the scheduler is not scheduling.
383
+ Sets the name of the job.
373
384
 
374
- ### :overlap => false
385
+ ```ruby
386
+ scheduler.cron '*/15 8 * * *', name: 'Robert' do |job|
387
+ puts "A, it's #{Time.now} and my name is #{job.name}"
388
+ end
389
+
390
+ job1 =
391
+ scheduler.schedule_cron '*/30 9 * * *', n: 'temporary' do |job|
392
+ puts "B, it's #{Time.now} and my name is #{job.name}"
393
+ end
394
+ # ...
395
+ job1.name = 'Beowulf'
396
+ ```
397
+
398
+ ### blocking: true
399
+
400
+ By default, jobs are triggered in their own, new threads. When `blocking: true`, the job is triggered in the scheduler thread (a new thread is not created). Yes, while a blocking job is running, the scheduler is not scheduling.
401
+
402
+ ### overlap: false
375
403
 
376
404
  Since, by default, jobs are triggered in their own new threads, job instances might overlap. For example, a job that takes 10 minutes and is scheduled every 7 minutes will have overlaps.
377
405
 
378
- To prevent overlap, one can set `:overlap => false`. Such a job will not trigger if one of its instances is already running.
406
+ To prevent overlap, one can set `overlap: false`. Such a job will not trigger if one of its instances is already running.
379
407
 
380
408
  The `:overlap` option is considered before the `:mutex` option when the scheduler is reviewing jobs for triggering.
381
409
 
382
- ### :mutex => mutex_instance / mutex_name / array of mutexes
410
+ ### mutex: mutex_instance / mutex_name / array of mutexes
383
411
 
384
412
  When a job with a mutex triggers, the job's block is executed with the mutex around it, preventing other jobs with the same mutex from entering (it makes the other jobs wait until it exits the mutex).
385
413
 
386
- This is different from `:overlap => false`, which is, first, limited to instances of the same job, and, second, doesn't make the incoming job instance block/wait but give up.
414
+ This is different from `overlap: false`, which is, first, limited to instances of the same job, and, second, doesn't make the incoming job instance block/wait but give up.
387
415
 
388
416
  `:mutex` accepts a mutex instance or a mutex name (String). It also accept an array of mutex names / mutex instances. It allows for complex relations between jobs.
389
417
 
@@ -393,12 +421,12 @@ Note: creating lots of different mutexes is OK. Rufus-scheduler will place them
393
421
 
394
422
  The `:overlap` option is considered before the `:mutex` option when the scheduler is reviewing jobs for triggering.
395
423
 
396
- ### :timeout => duration or point in time
424
+ ### timeout: duration or point in time
397
425
 
398
426
  It's OK to specify a timeout when scheduling some work. After the time specified, it gets interrupted via a Rufus::Scheduler::TimeoutError.
399
427
 
400
428
  ```ruby
401
- scheduler.in '10d', :timeout => '1d' do
429
+ scheduler.in '10d', timeout: '1d' do
402
430
  begin
403
431
  # ... do something
404
432
  rescue Rufus::Scheduler::TimeoutError
@@ -419,15 +447,15 @@ In the case of an "every" job, this will be the first time (modulo the scheduler
419
447
  For a "cron" job as well, the :first will point to the first time the job has to trigger, the following trigger times are then determined by the cron string.
420
448
 
421
449
  ```ruby
422
- scheduler.every '2d', :first_at => Time.now + 10 * 3600 do
450
+ scheduler.every '2d', first_at: Time.now + 10 * 3600 do
423
451
  # ... every two days, but start in 10 hours
424
452
  end
425
453
 
426
- scheduler.every '2d', :first_in => '10h' do
454
+ scheduler.every '2d', first_in: '10h' do
427
455
  # ... every two days, but start in 10 hours
428
456
  end
429
457
 
430
- scheduler.cron '00 14 * * *', :first_in => '3d' do
458
+ scheduler.cron '00 14 * * *', first_in: '3d' do
431
459
  # ... every day at 14h00, but start after 3 * 24 hours
432
460
  end
433
461
  ```
@@ -449,12 +477,11 @@ s = Rufus::Scheduler.new
449
477
 
450
478
  n = Time.now; p [ :scheduled_at, n, n.to_f ]
451
479
 
452
- s.every '3s', :first => :now do
480
+ s.every '3s', first: :now do
453
481
  n = Time.now; p [ :in, n, n.to_f ]
454
482
  end
455
483
 
456
484
  s.join
457
-
458
485
  ```
459
486
 
460
487
  that'll output something like:
@@ -475,15 +502,15 @@ This option is for repeat jobs (cron / every) only.
475
502
  It indicates the point in time after which the job should unschedule itself.
476
503
 
477
504
  ```ruby
478
- scheduler.cron '5 23 * * *', :last_in => '10d' do
505
+ scheduler.cron '5 23 * * *', last_in: '10d' do
479
506
  # ... do something every evening at 23:05 for 10 days
480
507
  end
481
508
 
482
- scheduler.every '10m', :last_at => Time.now + 10 * 3600 do
509
+ scheduler.every '10m', last_at: Time.now + 10 * 3600 do
483
510
  # ... do something every 10 minutes for 10 hours
484
511
  end
485
512
 
486
- scheduler.every '10m', :last_in => 10 * 3600 do
513
+ scheduler.every '10m', last_in: 10 * 3600 do
487
514
  # ... do something every 10 minutes for 10 hours
488
515
  end
489
516
  ```
@@ -498,16 +525,16 @@ job.last_at = Rufus::Scheduler.parse('2029-12-12')
498
525
  # set the last bound
499
526
  ```
500
527
 
501
- ### :times => nb of times (before auto-unscheduling)
528
+ ### times: nb of times (before auto-unscheduling)
502
529
 
503
530
  One can tell how many times a repeat job (CronJob or EveryJob) is to execute before unscheduling by itself.
504
531
 
505
532
  ```ruby
506
- scheduler.every '2d', :times => 10 do
533
+ scheduler.every '2d', times: 10 do
507
534
  # ... do something every two days, but not more than 10 times
508
535
  end
509
536
 
510
- scheduler.cron '0 23 * * *', :times => 31 do
537
+ scheduler.cron '0 23 * * *', times: 31 do
511
538
  # ... do something every day at 23:00 but do it no more than 31 times
512
539
  end
513
540
  ```
@@ -515,7 +542,7 @@ end
515
542
  It's OK to assign nil to :times to make sure the repeat job is not limited. It's useful when the :times is determined at scheduling time.
516
543
 
517
544
  ```ruby
518
- scheduler.cron '0 23 * * *', :times => nolimit ? nil : 10 do
545
+ scheduler.cron '0 23 * * *', times: (nolimit ? nil : 10) do
519
546
  # ...
520
547
  end
521
548
  ```
@@ -537,7 +564,7 @@ job.times = 10
537
564
 
538
565
  ## Job methods
539
566
 
540
- When calling a schedule method, the id (String) of the job is returned. Longer schedule methods return Job instances directly. Calling the shorter schedule methods with the :job => true also returns Job instances instead of Job ids (Strings).
567
+ When calling a schedule method, the id (String) of the job is returned. Longer schedule methods return Job instances directly. Calling the shorter schedule methods with the `job: true` also returns Job instances instead of Job ids (Strings).
541
568
 
542
569
  ```ruby
543
570
  require 'rufus-scheduler'
@@ -555,7 +582,7 @@ When calling a schedule method, the id (String) of the job is returned. Longer s
555
582
  end
556
583
 
557
584
  job =
558
- scheduler.in '1w', :job => true do
585
+ scheduler.in '1w', job: true do
559
586
  # ...
560
587
  end
561
588
  ```
@@ -581,7 +608,7 @@ Returns the scheduler instance itself.
581
608
  Returns the options passed at the Job creation.
582
609
 
583
610
  ```ruby
584
- job = scheduler.schedule_in('10d', :tag => 'hello') do; end
611
+ job = scheduler.schedule_in('10d', tag: 'hello') do; end
585
612
  job.opts
586
613
  # => { :tag => 'hello' }
587
614
  ```
@@ -591,7 +618,7 @@ job.opts
591
618
  Returns the original schedule.
592
619
 
593
620
  ```ruby
594
- job = scheduler.schedule_in('10d', :tag => 'hello') do; end
621
+ job = scheduler.schedule_in('10d', tag: 'hello') do; end
595
622
  job.original
596
623
  # => '10d'
597
624
  ```
@@ -638,12 +665,30 @@ job.callable
638
665
  # => #<MyHandler:0x0000000163ae88 @counter=0>
639
666
  ```
640
667
 
668
+ ### source_location
669
+
670
+ Added to rufus-scheduler 3.8.0.
671
+
672
+ Returns the array `[ 'path/to/file.rb', 123 ]` like `Proc#source_location` does.
673
+
674
+ ```ruby
675
+ require 'rufus-scheduler'
676
+
677
+ scheduler = Rufus::Scheduler.new
678
+
679
+ job = scheduler.schedule_every('2h') { p Time.now }
680
+
681
+ p job.source_location
682
+ # ==> [ '/home/jmettraux/rufus-scheduler/test.rb', 6 ]
683
+
684
+ ```
685
+
641
686
  ### scheduled_at
642
687
 
643
688
  Returns the Time instance when the job got created.
644
689
 
645
690
  ```ruby
646
- job = scheduler.schedule_in('10d', :tag => 'hello') do; end
691
+ job = scheduler.schedule_in('10d', tag: 'hello') do; end
647
692
  job.scheduled_at
648
693
  # => 2013-07-17 23:48:54 +0900
649
694
  ```
@@ -684,6 +729,12 @@ The job keeps track of how long its work was in the `last_work_time` attribute.
684
729
 
685
730
  The attribute `mean_work_time` contains a computed mean work time. It's recomputed after every run (if it's a repeat job).
686
731
 
732
+ ### next_times(n)
733
+
734
+ Returns an array of `EtOrbi::EoTime` instances (Time instances with a designated time zone), listing the `n` next occurrences for this job.
735
+
736
+ Please note that for "interval" jobs, a mean work time is computed each time and it's used by this `#next_times(n)` method to approximate the next times beyond the immediate next time.
737
+
687
738
  ### unschedule
688
739
 
689
740
  Unschedule the job, preventing it from firing again and removing it from the schedule. This doesn't prevent a running thread for this job to run until its end.
@@ -740,14 +791,14 @@ job = scheduler.schedule_in('10d') do; end
740
791
  job.tags
741
792
  # => []
742
793
 
743
- job = scheduler.schedule_in('10d', :tag => 'hello') do; end
794
+ job = scheduler.schedule_in('10d', tag: 'hello') do; end
744
795
  job.tags
745
796
  # => [ 'hello' ]
746
797
  ```
747
798
 
748
- ### []=, [], key? and keys
799
+ ### []=, [], key?, has_key?, keys, values, and entries
749
800
 
750
- Threads have thread-local variables. Rufus-scheduler jobs have job-local variables.
801
+ Threads have thread-local variables, similarly Rufus-scheduler jobs have job-local variables. Those are more like a dict with thread-safe access.
751
802
 
752
803
  ```ruby
753
804
  job =
@@ -762,13 +813,29 @@ sleep 3.6
762
813
  job[:counter]
763
814
  # => 3
764
815
 
765
- job.key?(:timestamp)
766
- # => true
767
- job.keys
768
- # => [ :timestamp, :counter ]
816
+ job.key?(:timestamp) # => true
817
+ job.has_key?(:timestamp) # => true
818
+ job.keys # => [ :timestamp, :counter ]
769
819
  ```
770
820
 
771
- Job-local variables are thread-safe.
821
+ Locals can be set at schedule time:
822
+ ```ruby
823
+ job0 =
824
+ @scheduler.schedule_cron '*/15 12 * * *', locals: { a: 0 } do
825
+ # ...
826
+ end
827
+ job1 =
828
+ @scheduler.schedule_cron '*/15 13 * * *', l: { a: 1 } do
829
+ # ...
830
+ end
831
+ ```
832
+
833
+ One can fetch the Hash directly with `Job#locals`. Of course, direct manipulation is not thread-safe.
834
+ ```ruby
835
+ job.locals.entries do |k, v|
836
+ p "#{k}: #{v}"
837
+ end
838
+ ```
772
839
 
773
840
  ### call
774
841
 
@@ -909,24 +976,24 @@ Here is an example:
909
976
  scheduler.at_jobs.each(&:unschedule)
910
977
  ```
911
978
 
912
- ### Scheduler#jobs(:tag / :tags => x)
979
+ ### Scheduler#jobs(tag: / tags: x)
913
980
 
914
981
  When scheduling a job, one can specify one or more tags attached to the job. These can be used to look up the job later on.
915
982
 
916
983
  ```ruby
917
- scheduler.in '10d', :tag => 'main_process' do
984
+ scheduler.in '10d', tag: 'main_process' do
918
985
  # ...
919
986
  end
920
- scheduler.in '10d', :tags => [ 'main_process', 'side_dish' ] do
987
+ scheduler.in '10d', tags: [ 'main_process', 'side_dish' ] do
921
988
  # ...
922
989
  end
923
990
 
924
991
  # ...
925
992
 
926
- jobs = scheduler.jobs(:tag => 'main_process')
993
+ jobs = scheduler.jobs(tag: 'main_process')
927
994
  # find all the jobs with the 'main_process' tag
928
995
 
929
- jobs = scheduler.jobs(:tags => [ 'main_process', 'side_dish' ]
996
+ jobs = scheduler.jobs(tags: [ 'main_process', 'side_dish' ]
930
997
  # find all the jobs with the 'main_process' AND 'side_dish' tags
931
998
  ```
932
999
 
@@ -951,6 +1018,10 @@ Shuts down the scheduler, ceases any scheduler/triggering activity.
951
1018
 
952
1019
  Shuts down the scheduler, waits (blocks) until all the jobs cease running.
953
1020
 
1021
+ ### Scheduler#shutdown(wait: n)
1022
+
1023
+ Shuts down the scheduler, waits (blocks) at most n seconds until all the jobs cease running. (Jobs are killed after n seconds have elapsed).
1024
+
954
1025
  ### Scheduler#shutdown(:kill)
955
1026
 
956
1027
  Kills all the job (threads) and then shuts the scheduler down. Radical.
@@ -973,6 +1044,8 @@ Returns since the count of seconds for which the scheduler has been running.
973
1044
 
974
1045
  Lets the current thread join the scheduling thread in rufus-scheduler. The thread comes back when the scheduler gets shut down.
975
1046
 
1047
+ `#join` is mostly used in standalone scheduling script (or tiny one file examples). Calling `#join` from a web application initializer will probably hijack the main thread and prevent the web application from being served. Do not put a `#join` in such a web application initializer file.
1048
+
976
1049
  ### Scheduler#threads
977
1050
 
978
1051
  Returns all the threads associated with the scheduler, including the scheduler thread itself.
@@ -985,7 +1058,7 @@ Lists the work threads associated with the scheduler. The query option defaults
985
1058
  * :active : all the work threads currently running a Job
986
1059
  * :vacant : all the work threads currently not running a Job
987
1060
 
988
- Note that the main schedule thread will be returned if it is currently running a Job (ie one of those :blocking => true jobs).
1061
+ Note that the main schedule thread will be returned if it is currently running a Job (ie one of those `blocking: true` jobs).
989
1062
 
990
1063
  ### Scheduler#scheduled?(job_or_job_id)
991
1064
 
@@ -993,7 +1066,7 @@ Returns true if the arg is a currently scheduled job (see Job#scheduled?).
993
1066
 
994
1067
  ### Scheduler#occurrences(time0, time1)
995
1068
 
996
- Returns a hash ```{ job => [ t0, t1, ... ] }``` mapping jobs to their potential trigger time within the ```[ time0, time1 ]``` span.
1069
+ Returns a hash `{ job => [ t0, t1, ... ] }` mapping jobs to their potential trigger time within the `[ time0, time1 ]` span.
997
1070
 
998
1071
  Please note that, for interval jobs, the ```#mean_work_time``` is used, so the result is only a prediction.
999
1072
 
@@ -1085,7 +1158,9 @@ def scheduler.on_error(job, error)
1085
1158
  end
1086
1159
  ```
1087
1160
 
1088
- ## Rufus::Scheduler #on_pre_trigger and #on_post_trigger callbacks
1161
+ ## Callbacks
1162
+
1163
+ ### Rufus::Scheduler #on_pre_trigger and #on_post_trigger callbacks
1089
1164
 
1090
1165
  One can bind callbacks before and after jobs trigger:
1091
1166
 
@@ -1109,6 +1184,21 @@ The ```trigger_time``` is the time at which the job triggers. It might be a bit
1109
1184
 
1110
1185
  Warning: these two callbacks are executed in the scheduler thread, not in the work threads (the threads where the job execution really happens).
1111
1186
 
1187
+ ### Rufus::Scheduler#around_trigger
1188
+
1189
+ One can create an around callback which will wrap a job:
1190
+
1191
+ ```ruby
1192
+ def s.around_trigger(job)
1193
+ t = Time.now
1194
+ puts "Starting job #{job.id}..."
1195
+ yield
1196
+ puts "job #{job.id} finished in #{Time.now-t} seconds."
1197
+ end
1198
+ ```
1199
+
1200
+ The around callback is executed in the thread.
1201
+
1112
1202
  ### Rufus::Scheduler#on_pre_trigger as a guard
1113
1203
 
1114
1204
  Returning ```false``` in on_pre_trigger will prevent the job from triggering. Returning anything else (nil, -1, true, ...) will let the job trigger.
@@ -1133,23 +1223,23 @@ By default, rufus-scheduler sleeps 0.300 second between every step. At each step
1133
1223
  The :frequency option lets you change that 0.300 second to something else.
1134
1224
 
1135
1225
  ```ruby
1136
- scheduler = Rufus::Scheduler.new(:frequency => 5)
1226
+ scheduler = Rufus::Scheduler.new(frequency: 5)
1137
1227
  ```
1138
1228
 
1139
1229
  It's OK to use a time string to specify the frequency.
1140
1230
 
1141
1231
  ```ruby
1142
- scheduler = Rufus::Scheduler.new(:frequency => '2h10m')
1232
+ scheduler = Rufus::Scheduler.new(frequency: '2h10m')
1143
1233
  # this scheduler will sleep 2 hours and 10 minutes between every "step"
1144
1234
  ```
1145
1235
 
1146
1236
  Use with care.
1147
1237
 
1148
- ### :lockfile => "mylockfile.txt"
1238
+ ### lockfile: "mylockfile.txt"
1149
1239
 
1150
1240
  This feature only works on OSes that support the flock (man 2 flock) call.
1151
1241
 
1152
- Starting the scheduler with ```:lockfile => ".rufus-scheduler.lock"``` will make the scheduler attempt to create and lock the file ```.rufus-scheduler.lock``` in the current working directory. If that fails, the scheduler will not start.
1242
+ Starting the scheduler with ```lockfile: '.rufus-scheduler.lock'``` will make the scheduler attempt to create and lock the file ```.rufus-scheduler.lock``` in the current working directory. If that fails, the scheduler will not start.
1153
1243
 
1154
1244
  The idea is to guarantee only one scheduler (in a group of schedulers sharing the same lockfile) is running.
1155
1245
 
@@ -1178,7 +1268,7 @@ class HostLock
1178
1268
  end
1179
1269
 
1180
1270
  scheduler =
1181
- Rufus::Scheduler.new(:scheduler_lock => HostLock.new('coffee.example.com'))
1271
+ Rufus::Scheduler.new(scheduler_lock: HostLock.new('coffee.example.com'))
1182
1272
  ```
1183
1273
 
1184
1274
  By default, the scheduler_lock is an instance of `Rufus::Scheduler::NullLock`, with a `#lock` that returns true.
@@ -1201,7 +1291,7 @@ class PingLock
1201
1291
  end
1202
1292
 
1203
1293
  scheduler =
1204
- Rufus::Scheduler.new(:trigger_lock => PingLock.new('main.example.com'))
1294
+ Rufus::Scheduler.new(trigger_lock: PingLock.new('main.example.com'))
1205
1295
  ```
1206
1296
 
1207
1297
  By default, the trigger_lock is an instance of `Rufus::Scheduler::NullLock`, with a `#lock` that always returns true.
@@ -1215,7 +1305,7 @@ In rufus-scheduler 2.x, by default, each job triggering received its own, brand
1215
1305
  One can set this maximum value when starting the scheduler.
1216
1306
 
1217
1307
  ```ruby
1218
- scheduler = Rufus::Scheduler.new(:max_work_threads => 77)
1308
+ scheduler = Rufus::Scheduler.new(max_work_threads: 77)
1219
1309
  ```
1220
1310
 
1221
1311
  It's OK to increase the :max_work_threads of a running scheduler.
@@ -1228,7 +1318,7 @@ scheduler.max_work_threads += 10
1228
1318
  ## Rufus::Scheduler.singleton
1229
1319
 
1230
1320
  Do not want to store a reference to your rufus-scheduler instance?
1231
- Then ```Rufus::Scheduler.singleton``` can help, it returns a singleon instance of the scheduler, initialized the first time this class method is called.
1321
+ Then ```Rufus::Scheduler.singleton``` can help, it returns a singleton instance of the scheduler, initialized the first time this class method is called.
1232
1322
 
1233
1323
  ```ruby
1234
1324
  Rufus::Scheduler.singleton.every '10s' { puts "hello, world!" }
@@ -1237,8 +1327,8 @@ Rufus::Scheduler.singleton.every '10s' { puts "hello, world!" }
1237
1327
  It's OK to pass initialization arguments (like :frequency or :max_work_threads) but they will only be taken into account the first time ```.singleton``` is called.
1238
1328
 
1239
1329
  ```ruby
1240
- Rufus::Scheduler.singleton(:max_work_threads => 77)
1241
- Rufus::Scheduler.singleton(:max_work_threads => 277) # no effect
1330
+ Rufus::Scheduler.singleton(max_work_threads: 77)
1331
+ Rufus::Scheduler.singleton(max_work_threads: 277) # no effect
1242
1332
  ```
1243
1333
 
1244
1334
  The ```.s``` is a shortcut for ```.singleton```.
@@ -1287,7 +1377,7 @@ class ZookeptScheduler < Rufus::Scheduler
1287
1377
  end
1288
1378
  ```
1289
1379
 
1290
- This uses a [zookeeper](http://zookeeper.apache.org/) to make sure only one scheduler in a group of distributed schedulers runs.
1380
+ This uses a [zookeeper](https://zookeeper.apache.org/) to make sure only one scheduler in a group of distributed schedulers runs.
1291
1381
 
1292
1382
  The methods #lock and #unlock are overridden and #confirm_lock is provided,
1293
1383
  to make sure that the lock is still valid.
@@ -1311,6 +1401,8 @@ Warning: you may think you're heading towards "high availability" by using a tri
1311
1401
 
1312
1402
  ## parsing cronlines and time strings
1313
1403
 
1404
+ (Please note that [fugit](https://github.com/floraison/fugit) does the heavy-lifting parsing work for rufus-scheduler).
1405
+
1314
1406
  Rufus::Scheduler provides a class method ```.parse``` to parse time durations and cron strings. It's what it's using when receiving schedules. One can use it directly (no need to instantiate a Scheduler).
1315
1407
 
1316
1408
  ```ruby
@@ -1353,7 +1445,7 @@ Rufus::Scheduler.to_duration_hash(60)
1353
1445
  Rufus::Scheduler.to_duration_hash(62.127)
1354
1446
  # => { :m => 1, :s => 2, :ms => 127 }
1355
1447
 
1356
- Rufus::Scheduler.to_duration_hash(62.127, :drop_seconds => true)
1448
+ Rufus::Scheduler.to_duration_hash(62.127, drop_seconds: true)
1357
1449
  # => { :m => 1 }
1358
1450
  ```
1359
1451
 
@@ -1536,7 +1628,7 @@ class ScheController < ApplicationController
1536
1628
  Rails.logger.info "time flies, it's now #{Time.now}"
1537
1629
  end
1538
1630
 
1539
- render :text => "scheduled job #{job_id}"
1631
+ render text: "scheduled job #{job_id}"
1540
1632
  end
1541
1633
  end
1542
1634
  ```
@@ -1547,9 +1639,9 @@ The rufus-scheduler singleton is instantiated in the ```config/initializers/sche
1547
1639
 
1548
1640
  ### avoid scheduling when running the Ruby on Rails console
1549
1641
 
1550
- (Written in reply to https://github.com/jmettraux/rufus-scheduler/issues/186 )
1642
+ (Written in reply to [gh-186](https://github.com/jmettraux/rufus-scheduler/issues/186))
1551
1643
 
1552
- If you don't want rufus-scheduler to kick in when running the Ruby on Rails console or invoking a rake task, you can wrap your initializer in a conditional:
1644
+ If you don't want rufus-scheduler to trigger anything while running the Ruby on Rails console, running for tests/specs, or running from a Rake task, you can insert a conditional return statement before jobs are added to the scheduler instance:
1553
1645
 
1554
1646
  ```ruby
1555
1647
  #
@@ -1559,21 +1651,19 @@ require 'rufus-scheduler'
1559
1651
 
1560
1652
  s = Rufus::Scheduler.singleton
1561
1653
 
1654
+ return if defined?(Rails::Console) || Rails.env.test? || File.split($0).last == 'rake'
1655
+ # return if $PROGRAM_NAME.include?('spring')
1656
+ # see https://github.com/jmettraux/rufus-scheduler/issues/186
1562
1657
 
1563
- unless defined?(Rails::Console) || File.split($0).last == 'rake'
1564
-
1565
- # only schedule when not running from the Ruby on Rails console
1566
- # or from a rake task
1658
+ # do not schedule when Rails is run from its console, for a test/spec, or
1659
+ # from a Rake task
1567
1660
 
1568
- s.every '1m' do
1569
-
1570
- Rails.logger.info "hello, it's #{Time.now}"
1571
- Rails.logger.flush
1572
- end
1661
+ s.every '1m' do
1662
+ Rails.logger.info "hello, it's #{Time.now}"
1663
+ Rails.logger.flush
1573
1664
  end
1574
1665
  ```
1575
1666
 
1576
- It should work for Ruby on Rails 3 and 4.
1577
1667
 
1578
1668
  ### rails server -d
1579
1669
 
@@ -1585,8 +1675,8 @@ I avoid running `-d` in development mode and bother about daemonizing only for p
1585
1675
 
1586
1676
  These are two well crafted articles on process daemonization, please read them:
1587
1677
 
1588
- * http://www.mikeperham.com/2014/09/22/dont-daemonize-your-daemons/
1589
- * http://www.mikeperham.com/2014/07/07/use-runit/
1678
+ * https://www.mikeperham.com/2014/09/22/dont-daemonize-your-daemons/
1679
+ * https://www.mikeperham.com/2014/07/07/use-runit/
1590
1680
 
1591
1681
  If, anyway, you need something like `rails server -d`, why not try `bundle exec unicorn -D` instead? In my (limited) experience, it worked out of the box (well, had to add `gem 'unicorn'` to `Gemfile` first).
1592
1682