rufus-scheduler 3.6.0 → 3.8.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +30 -0
- data/CREDITS.md +10 -0
- data/LICENSE.txt +1 -1
- data/Makefile +1 -1
- data/README.md +153 -62
- data/lib/rufus/scheduler/job_array.rb +37 -47
- data/lib/rufus/scheduler/jobs_core.rb +369 -0
- data/lib/rufus/scheduler/jobs_one_time.rb +53 -0
- data/lib/rufus/scheduler/jobs_repeat.rb +335 -0
- data/lib/rufus/scheduler/locks.rb +41 -44
- data/lib/rufus/scheduler/util.rb +166 -150
- data/lib/rufus/scheduler.rb +537 -431
- data/rufus-scheduler.gemspec +1 -2
- metadata +11 -10
- data/lib/rufus/scheduler/jobs.rb +0 -701
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9fbe0f73068129b96196031b141f480f830e3110e35d3c5eaa2206530b1ae536
|
4
|
+
data.tar.gz: bec310a43820928b8d342b5b3602edf8cb27aaca8995e0a18073d70dfd3839f8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3e8edfd4df2ddbb0f8026ffa13fff69f9f4bd045da1638fe5ac38610992e0f7d173b20a27ad1833760d6fee62d41b5b160978e107dbc55a1b9d07dfaa62444ad
|
7
|
+
data.tar.gz: 412bb7e80546c5cd13bf8875f928ce6920a9e62774d296db83935adbfee56069cbb2729bb4640962351297cd55b8b5cfb92facfec38e7cb92b3ef9f7446c7283
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,36 @@
|
|
2
2
|
# CHANGELOG.md
|
3
3
|
|
4
4
|
|
5
|
+
### rufus-scheduler 3.8.2 - released 2022-07-12
|
6
|
+
|
7
|
+
* Prevent error in shutdown when @thread is current Thread, gh-337
|
8
|
+
* Rescue errors on the scheduling thread, gh-335
|
9
|
+
|
10
|
+
|
11
|
+
### rufus-scheduler 3.8.1 - released 2022-01-11
|
12
|
+
|
13
|
+
* Suppress warning about @resume_discard_past
|
14
|
+
* Suppress warning about unused variable, solackerman gh-332
|
15
|
+
|
16
|
+
|
17
|
+
### rufus-scheduler 3.8.0 - released 2021-07-14
|
18
|
+
|
19
|
+
* Add #source_location to Job, gh-322
|
20
|
+
|
21
|
+
|
22
|
+
### rufus-scheduler 3.7.0 - released 2020-12-31
|
23
|
+
|
24
|
+
* Implement Job name:/n: #name and #name=, gh-309
|
25
|
+
* Add Job #has_key?, #value, and #entries
|
26
|
+
* Add #locals access to Job
|
27
|
+
* Implement Scheduler#around_trigger, @jjb, gh-310
|
28
|
+
* Accept max_worker_threads: for max_work_threads:
|
29
|
+
* Clean up Scheduler#shutdwon, thanks @itsaphel and @jjb, gh-304, gh-315
|
30
|
+
|
31
|
+
* f59df40 Bring in discard_past: for every jobs, gh-290
|
32
|
+
* 7613277 Introduce :discard_past = false for cron, gh-305
|
33
|
+
|
34
|
+
|
5
35
|
### rufus-scheduler 3.6.0 - released 2019-04-22
|
6
36
|
|
7
37
|
* Let Scheduler#cron fail if the cron string is invalid, gh-289
|
data/CREDITS.md
CHANGED
@@ -4,6 +4,14 @@
|
|
4
4
|
|
5
5
|
## Contributors
|
6
6
|
|
7
|
+
* Bence Monus https://github.com/cromega gh-337 on_error and friends
|
8
|
+
* Talia Wong https://github.com/blowfishpro gh-335 on_error and friends
|
9
|
+
* Konstantin https://github.com/fa11enangel gh-334 nodejitsu link
|
10
|
+
* Olle Jonsson https://github.com/olleolleolle gh-333
|
11
|
+
* Sol Ackerman https://github.com/solarckerman gh-332
|
12
|
+
* John Bachir https://github.com/jjb gh-310 gh-327
|
13
|
+
* Daniel Berger https://github.com/djberg96 gh-300
|
14
|
+
* Ceyhun Onur https://github.com/ceyonur parse_cron no_error: true
|
7
15
|
* Darwin Wu https://github.com/dwaxe Rails initializer vs tests change
|
8
16
|
* Mike Karolow https://github.com/mike-yesware update Travis target Rubies
|
9
17
|
* Jack-Nie https://github.com/jack-nie gh-285 fix broken comment link
|
@@ -64,6 +72,8 @@
|
|
64
72
|
|
65
73
|
## Feedback
|
66
74
|
|
75
|
+
* aphel (https://github.com/itsaphel) #shutdown vs current thread, gh-304
|
76
|
+
* aesyondu (https://github.com/aesyondu) Rails console 4.2.x, gh-186
|
67
77
|
* Sasha Hoellger (https://github.com/mitnal) parse_cron and readme, gh-270
|
68
78
|
* Gian (https://github.com/snmgian) cron vs :first clarification, gh-266
|
69
79
|
* 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-
|
2
|
+
Copyright (c) 2005-2022, 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
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
# rufus-scheduler
|
3
3
|
|
4
|
-
[![
|
4
|
+
[![tests](https://github.com/jmettraux/rufus-scheduler/workflows/test/badge.svg)](https://github.com/jmettraux/rufus-scheduler/actions)
|
5
5
|
[![Gem Version](https://badge.fury.io/rb/rufus-scheduler.svg)](https://badge.fury.io/rb/rufus-scheduler)
|
6
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)
|
7
7
|
|
@@ -24,7 +24,11 @@ scheduler.in '3s' do
|
|
24
24
|
end
|
25
25
|
|
26
26
|
scheduler.join
|
27
|
+
#
|
27
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)
|
28
32
|
```
|
29
33
|
(run with `ruby quickstart.rb`)
|
30
34
|
|
@@ -73,6 +77,7 @@ A rufus-scheduler instance will go on scheduling while it is present among the o
|
|
73
77
|
## related and similar gems
|
74
78
|
|
75
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
|
76
81
|
* [Clockwork](https://github.com/Rykian/clockwork) - rufus-scheduler inspired gem
|
77
82
|
* [Crono](https://github.com/plashchynski/crono) - an in-Rails cron scheduler
|
78
83
|
* [PerfectSched](https://github.com/treasure-data/perfectsched) - highly available distributed cron built on [Sequel](https://sequel.jeremyevans.net) and more
|
@@ -100,8 +105,8 @@ I'll drive you right to the [tracks](#so-rails).
|
|
100
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)
|
101
106
|
* Rufus::Scheduler::TimeOutError renamed to Rufus::Scheduler::TimeoutError
|
102
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"
|
103
|
-
* Introduction of a :
|
104
|
-
* "discard_past" is on by default. If the scheduler (its host) sleeps for 1 hour and a
|
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.
|
105
110
|
* Introduction of Scheduler #on_pre_trigger and #on_post_trigger callback points
|
106
111
|
|
107
112
|
|
@@ -128,7 +133,7 @@ Yes, issues can be reported in [rufus-scheduler issues](https://github.com/jmett
|
|
128
133
|
### faq
|
129
134
|
|
130
135
|
* [It doesn't work...](https://www.chiark.greenend.org.uk/~sgtatham/bugs.html)
|
131
|
-
* [I want a refund](https://blog.nodejitsu.com/getting-refunds-on-open-source-projects)
|
136
|
+
* [I want a refund](https://web.archive.org/web/20160425034214/http://blog.nodejitsu.com/getting-refunds-on-open-source-projects/)
|
132
137
|
* [Passenger and rufus-scheduler](https://stackoverflow.com/questions/18108719/debugging-rufus-scheduler/18156180#18156180)
|
133
138
|
* [Passenger and rufus-scheduler (2)](https://stackoverflow.com/questions/21861387/rufus-cron-job-not-working-in-apache-passenger#answer-21868555)
|
134
139
|
* [Passenger in-depth spawn methods](https://www.phusionpassenger.com/library/indepth/ruby/spawn_methods/)
|
@@ -218,7 +223,7 @@ job =
|
|
218
223
|
# also
|
219
224
|
|
220
225
|
job =
|
221
|
-
scheduler.in '10d', :
|
226
|
+
scheduler.in '10d', job: true do
|
222
227
|
# ...
|
223
228
|
end
|
224
229
|
```
|
@@ -373,23 +378,40 @@ While paused, the scheduler still accepts schedules, but no schedule will get tr
|
|
373
378
|
|
374
379
|
## job options
|
375
380
|
|
376
|
-
### :
|
381
|
+
### name: string
|
382
|
+
|
383
|
+
Sets the name of the job.
|
384
|
+
|
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
|
377
399
|
|
378
|
-
By default, jobs are triggered in their own, new threads. When
|
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.
|
379
401
|
|
380
|
-
### :
|
402
|
+
### overlap: false
|
381
403
|
|
382
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.
|
383
405
|
|
384
|
-
To prevent overlap, one can set
|
406
|
+
To prevent overlap, one can set `overlap: false`. Such a job will not trigger if one of its instances is already running.
|
385
407
|
|
386
408
|
The `:overlap` option is considered before the `:mutex` option when the scheduler is reviewing jobs for triggering.
|
387
409
|
|
388
|
-
### :
|
410
|
+
### mutex: mutex_instance / mutex_name / array of mutexes
|
389
411
|
|
390
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).
|
391
413
|
|
392
|
-
This is different from
|
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.
|
393
415
|
|
394
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.
|
395
417
|
|
@@ -399,12 +421,12 @@ Note: creating lots of different mutexes is OK. Rufus-scheduler will place them
|
|
399
421
|
|
400
422
|
The `:overlap` option is considered before the `:mutex` option when the scheduler is reviewing jobs for triggering.
|
401
423
|
|
402
|
-
### :
|
424
|
+
### timeout: duration or point in time
|
403
425
|
|
404
426
|
It's OK to specify a timeout when scheduling some work. After the time specified, it gets interrupted via a Rufus::Scheduler::TimeoutError.
|
405
427
|
|
406
428
|
```ruby
|
407
|
-
scheduler.in '10d', :
|
429
|
+
scheduler.in '10d', timeout: '1d' do
|
408
430
|
begin
|
409
431
|
# ... do something
|
410
432
|
rescue Rufus::Scheduler::TimeoutError
|
@@ -425,15 +447,15 @@ In the case of an "every" job, this will be the first time (modulo the scheduler
|
|
425
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.
|
426
448
|
|
427
449
|
```ruby
|
428
|
-
scheduler.every '2d', :
|
450
|
+
scheduler.every '2d', first_at: Time.now + 10 * 3600 do
|
429
451
|
# ... every two days, but start in 10 hours
|
430
452
|
end
|
431
453
|
|
432
|
-
scheduler.every '2d', :
|
454
|
+
scheduler.every '2d', first_in: '10h' do
|
433
455
|
# ... every two days, but start in 10 hours
|
434
456
|
end
|
435
457
|
|
436
|
-
scheduler.cron '00 14 * * *', :
|
458
|
+
scheduler.cron '00 14 * * *', first_in: '3d' do
|
437
459
|
# ... every day at 14h00, but start after 3 * 24 hours
|
438
460
|
end
|
439
461
|
```
|
@@ -455,12 +477,11 @@ s = Rufus::Scheduler.new
|
|
455
477
|
|
456
478
|
n = Time.now; p [ :scheduled_at, n, n.to_f ]
|
457
479
|
|
458
|
-
s.every '3s', :
|
480
|
+
s.every '3s', first: :now do
|
459
481
|
n = Time.now; p [ :in, n, n.to_f ]
|
460
482
|
end
|
461
483
|
|
462
484
|
s.join
|
463
|
-
|
464
485
|
```
|
465
486
|
|
466
487
|
that'll output something like:
|
@@ -481,15 +502,15 @@ This option is for repeat jobs (cron / every) only.
|
|
481
502
|
It indicates the point in time after which the job should unschedule itself.
|
482
503
|
|
483
504
|
```ruby
|
484
|
-
scheduler.cron '5 23 * * *', :
|
505
|
+
scheduler.cron '5 23 * * *', last_in: '10d' do
|
485
506
|
# ... do something every evening at 23:05 for 10 days
|
486
507
|
end
|
487
508
|
|
488
|
-
scheduler.every '10m', :
|
509
|
+
scheduler.every '10m', last_at: Time.now + 10 * 3600 do
|
489
510
|
# ... do something every 10 minutes for 10 hours
|
490
511
|
end
|
491
512
|
|
492
|
-
scheduler.every '10m', :
|
513
|
+
scheduler.every '10m', last_in: 10 * 3600 do
|
493
514
|
# ... do something every 10 minutes for 10 hours
|
494
515
|
end
|
495
516
|
```
|
@@ -504,16 +525,16 @@ job.last_at = Rufus::Scheduler.parse('2029-12-12')
|
|
504
525
|
# set the last bound
|
505
526
|
```
|
506
527
|
|
507
|
-
### :
|
528
|
+
### times: nb of times (before auto-unscheduling)
|
508
529
|
|
509
530
|
One can tell how many times a repeat job (CronJob or EveryJob) is to execute before unscheduling by itself.
|
510
531
|
|
511
532
|
```ruby
|
512
|
-
scheduler.every '2d', :
|
533
|
+
scheduler.every '2d', times: 10 do
|
513
534
|
# ... do something every two days, but not more than 10 times
|
514
535
|
end
|
515
536
|
|
516
|
-
scheduler.cron '0 23 * * *', :
|
537
|
+
scheduler.cron '0 23 * * *', times: 31 do
|
517
538
|
# ... do something every day at 23:00 but do it no more than 31 times
|
518
539
|
end
|
519
540
|
```
|
@@ -521,7 +542,7 @@ end
|
|
521
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.
|
522
543
|
|
523
544
|
```ruby
|
524
|
-
scheduler.cron '0 23 * * *', :
|
545
|
+
scheduler.cron '0 23 * * *', times: (nolimit ? nil : 10) do
|
525
546
|
# ...
|
526
547
|
end
|
527
548
|
```
|
@@ -543,7 +564,7 @@ job.times = 10
|
|
543
564
|
|
544
565
|
## Job methods
|
545
566
|
|
546
|
-
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 :
|
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).
|
547
568
|
|
548
569
|
```ruby
|
549
570
|
require 'rufus-scheduler'
|
@@ -561,7 +582,7 @@ When calling a schedule method, the id (String) of the job is returned. Longer s
|
|
561
582
|
end
|
562
583
|
|
563
584
|
job =
|
564
|
-
scheduler.in '1w', :
|
585
|
+
scheduler.in '1w', job: true do
|
565
586
|
# ...
|
566
587
|
end
|
567
588
|
```
|
@@ -587,7 +608,7 @@ Returns the scheduler instance itself.
|
|
587
608
|
Returns the options passed at the Job creation.
|
588
609
|
|
589
610
|
```ruby
|
590
|
-
job = scheduler.schedule_in('10d', :
|
611
|
+
job = scheduler.schedule_in('10d', tag: 'hello') do; end
|
591
612
|
job.opts
|
592
613
|
# => { :tag => 'hello' }
|
593
614
|
```
|
@@ -597,7 +618,7 @@ job.opts
|
|
597
618
|
Returns the original schedule.
|
598
619
|
|
599
620
|
```ruby
|
600
|
-
job = scheduler.schedule_in('10d', :
|
621
|
+
job = scheduler.schedule_in('10d', tag: 'hello') do; end
|
601
622
|
job.original
|
602
623
|
# => '10d'
|
603
624
|
```
|
@@ -644,12 +665,30 @@ job.callable
|
|
644
665
|
# => #<MyHandler:0x0000000163ae88 @counter=0>
|
645
666
|
```
|
646
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
|
+
|
647
686
|
### scheduled_at
|
648
687
|
|
649
688
|
Returns the Time instance when the job got created.
|
650
689
|
|
651
690
|
```ruby
|
652
|
-
job = scheduler.schedule_in('10d', :
|
691
|
+
job = scheduler.schedule_in('10d', tag: 'hello') do; end
|
653
692
|
job.scheduled_at
|
654
693
|
# => 2013-07-17 23:48:54 +0900
|
655
694
|
```
|
@@ -752,14 +791,14 @@ job = scheduler.schedule_in('10d') do; end
|
|
752
791
|
job.tags
|
753
792
|
# => []
|
754
793
|
|
755
|
-
job = scheduler.schedule_in('10d', :
|
794
|
+
job = scheduler.schedule_in('10d', tag: 'hello') do; end
|
756
795
|
job.tags
|
757
796
|
# => [ 'hello' ]
|
758
797
|
```
|
759
798
|
|
760
|
-
### []=, [], key
|
799
|
+
### []=, [], key?, has_key?, keys, values, and entries
|
761
800
|
|
762
|
-
Threads have thread-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.
|
763
802
|
|
764
803
|
```ruby
|
765
804
|
job =
|
@@ -774,13 +813,29 @@ sleep 3.6
|
|
774
813
|
job[:counter]
|
775
814
|
# => 3
|
776
815
|
|
777
|
-
job.key?(:timestamp)
|
778
|
-
|
779
|
-
job.keys
|
780
|
-
# => [ :timestamp, :counter ]
|
816
|
+
job.key?(:timestamp) # => true
|
817
|
+
job.has_key?(:timestamp) # => true
|
818
|
+
job.keys # => [ :timestamp, :counter ]
|
781
819
|
```
|
782
820
|
|
783
|
-
|
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
|
+
```
|
784
839
|
|
785
840
|
### call
|
786
841
|
|
@@ -805,7 +860,11 @@ require 'rufus-scheduler'
|
|
805
860
|
s = Rufus::Scheduler.new
|
806
861
|
|
807
862
|
def s.on_error(job, err)
|
808
|
-
|
863
|
+
if job
|
864
|
+
p [ 'error in scheduled job', job.class, job.original, err.message ]
|
865
|
+
else
|
866
|
+
p [ 'error while scheduling', err.message ]
|
867
|
+
end
|
809
868
|
rescue
|
810
869
|
p $!
|
811
870
|
end
|
@@ -921,24 +980,24 @@ Here is an example:
|
|
921
980
|
scheduler.at_jobs.each(&:unschedule)
|
922
981
|
```
|
923
982
|
|
924
|
-
### Scheduler#jobs(:
|
983
|
+
### Scheduler#jobs(tag: / tags: x)
|
925
984
|
|
926
985
|
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.
|
927
986
|
|
928
987
|
```ruby
|
929
|
-
scheduler.in '10d', :
|
988
|
+
scheduler.in '10d', tag: 'main_process' do
|
930
989
|
# ...
|
931
990
|
end
|
932
|
-
scheduler.in '10d', :
|
991
|
+
scheduler.in '10d', tags: [ 'main_process', 'side_dish' ] do
|
933
992
|
# ...
|
934
993
|
end
|
935
994
|
|
936
995
|
# ...
|
937
996
|
|
938
|
-
jobs = scheduler.jobs(:
|
997
|
+
jobs = scheduler.jobs(tag: 'main_process')
|
939
998
|
# find all the jobs with the 'main_process' tag
|
940
999
|
|
941
|
-
jobs = scheduler.jobs(:
|
1000
|
+
jobs = scheduler.jobs(tags: [ 'main_process', 'side_dish' ]
|
942
1001
|
# find all the jobs with the 'main_process' AND 'side_dish' tags
|
943
1002
|
```
|
944
1003
|
|
@@ -963,6 +1022,10 @@ Shuts down the scheduler, ceases any scheduler/triggering activity.
|
|
963
1022
|
|
964
1023
|
Shuts down the scheduler, waits (blocks) until all the jobs cease running.
|
965
1024
|
|
1025
|
+
### Scheduler#shutdown(wait: n)
|
1026
|
+
|
1027
|
+
Shuts down the scheduler, waits (blocks) at most n seconds until all the jobs cease running. (Jobs are killed after n seconds have elapsed).
|
1028
|
+
|
966
1029
|
### Scheduler#shutdown(:kill)
|
967
1030
|
|
968
1031
|
Kills all the job (threads) and then shuts the scheduler down. Radical.
|
@@ -985,6 +1048,8 @@ Returns since the count of seconds for which the scheduler has been running.
|
|
985
1048
|
|
986
1049
|
Lets the current thread join the scheduling thread in rufus-scheduler. The thread comes back when the scheduler gets shut down.
|
987
1050
|
|
1051
|
+
`#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.
|
1052
|
+
|
988
1053
|
### Scheduler#threads
|
989
1054
|
|
990
1055
|
Returns all the threads associated with the scheduler, including the scheduler thread itself.
|
@@ -997,7 +1062,7 @@ Lists the work threads associated with the scheduler. The query option defaults
|
|
997
1062
|
* :active : all the work threads currently running a Job
|
998
1063
|
* :vacant : all the work threads currently not running a Job
|
999
1064
|
|
1000
|
-
Note that the main schedule thread will be returned if it is currently running a Job (ie one of those :
|
1065
|
+
Note that the main schedule thread will be returned if it is currently running a Job (ie one of those `blocking: true` jobs).
|
1001
1066
|
|
1002
1067
|
### Scheduler#scheduled?(job_or_job_id)
|
1003
1068
|
|
@@ -1005,7 +1070,7 @@ Returns true if the arg is a currently scheduled job (see Job#scheduled?).
|
|
1005
1070
|
|
1006
1071
|
### Scheduler#occurrences(time0, time1)
|
1007
1072
|
|
1008
|
-
Returns a hash
|
1073
|
+
Returns a hash `{ job => [ t0, t1, ... ] }` mapping jobs to their potential trigger time within the `[ time0, time1 ]` span.
|
1009
1074
|
|
1010
1075
|
Please note that, for interval jobs, the ```#mean_work_time``` is used, so the result is only a prediction.
|
1011
1076
|
|
@@ -1097,7 +1162,9 @@ def scheduler.on_error(job, error)
|
|
1097
1162
|
end
|
1098
1163
|
```
|
1099
1164
|
|
1100
|
-
##
|
1165
|
+
## Callbacks
|
1166
|
+
|
1167
|
+
### Rufus::Scheduler #on_pre_trigger and #on_post_trigger callbacks
|
1101
1168
|
|
1102
1169
|
One can bind callbacks before and after jobs trigger:
|
1103
1170
|
|
@@ -1121,6 +1188,21 @@ The ```trigger_time``` is the time at which the job triggers. It might be a bit
|
|
1121
1188
|
|
1122
1189
|
Warning: these two callbacks are executed in the scheduler thread, not in the work threads (the threads where the job execution really happens).
|
1123
1190
|
|
1191
|
+
### Rufus::Scheduler#around_trigger
|
1192
|
+
|
1193
|
+
One can create an around callback which will wrap a job:
|
1194
|
+
|
1195
|
+
```ruby
|
1196
|
+
def s.around_trigger(job)
|
1197
|
+
t = Time.now
|
1198
|
+
puts "Starting job #{job.id}..."
|
1199
|
+
yield
|
1200
|
+
puts "job #{job.id} finished in #{Time.now-t} seconds."
|
1201
|
+
end
|
1202
|
+
```
|
1203
|
+
|
1204
|
+
The around callback is executed in the thread.
|
1205
|
+
|
1124
1206
|
### Rufus::Scheduler#on_pre_trigger as a guard
|
1125
1207
|
|
1126
1208
|
Returning ```false``` in on_pre_trigger will prevent the job from triggering. Returning anything else (nil, -1, true, ...) will let the job trigger.
|
@@ -1145,23 +1227,23 @@ By default, rufus-scheduler sleeps 0.300 second between every step. At each step
|
|
1145
1227
|
The :frequency option lets you change that 0.300 second to something else.
|
1146
1228
|
|
1147
1229
|
```ruby
|
1148
|
-
scheduler = Rufus::Scheduler.new(:
|
1230
|
+
scheduler = Rufus::Scheduler.new(frequency: 5)
|
1149
1231
|
```
|
1150
1232
|
|
1151
1233
|
It's OK to use a time string to specify the frequency.
|
1152
1234
|
|
1153
1235
|
```ruby
|
1154
|
-
scheduler = Rufus::Scheduler.new(:
|
1236
|
+
scheduler = Rufus::Scheduler.new(frequency: '2h10m')
|
1155
1237
|
# this scheduler will sleep 2 hours and 10 minutes between every "step"
|
1156
1238
|
```
|
1157
1239
|
|
1158
1240
|
Use with care.
|
1159
1241
|
|
1160
|
-
### :
|
1242
|
+
### lockfile: "mylockfile.txt"
|
1161
1243
|
|
1162
1244
|
This feature only works on OSes that support the flock (man 2 flock) call.
|
1163
1245
|
|
1164
|
-
Starting the scheduler with
|
1246
|
+
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.
|
1165
1247
|
|
1166
1248
|
The idea is to guarantee only one scheduler (in a group of schedulers sharing the same lockfile) is running.
|
1167
1249
|
|
@@ -1190,7 +1272,7 @@ class HostLock
|
|
1190
1272
|
end
|
1191
1273
|
|
1192
1274
|
scheduler =
|
1193
|
-
Rufus::Scheduler.new(:
|
1275
|
+
Rufus::Scheduler.new(scheduler_lock: HostLock.new('coffee.example.com'))
|
1194
1276
|
```
|
1195
1277
|
|
1196
1278
|
By default, the scheduler_lock is an instance of `Rufus::Scheduler::NullLock`, with a `#lock` that returns true.
|
@@ -1213,7 +1295,7 @@ class PingLock
|
|
1213
1295
|
end
|
1214
1296
|
|
1215
1297
|
scheduler =
|
1216
|
-
Rufus::Scheduler.new(:
|
1298
|
+
Rufus::Scheduler.new(trigger_lock: PingLock.new('main.example.com'))
|
1217
1299
|
```
|
1218
1300
|
|
1219
1301
|
By default, the trigger_lock is an instance of `Rufus::Scheduler::NullLock`, with a `#lock` that always returns true.
|
@@ -1227,7 +1309,7 @@ In rufus-scheduler 2.x, by default, each job triggering received its own, brand
|
|
1227
1309
|
One can set this maximum value when starting the scheduler.
|
1228
1310
|
|
1229
1311
|
```ruby
|
1230
|
-
scheduler = Rufus::Scheduler.new(:
|
1312
|
+
scheduler = Rufus::Scheduler.new(max_work_threads: 77)
|
1231
1313
|
```
|
1232
1314
|
|
1233
1315
|
It's OK to increase the :max_work_threads of a running scheduler.
|
@@ -1249,8 +1331,8 @@ Rufus::Scheduler.singleton.every '10s' { puts "hello, world!" }
|
|
1249
1331
|
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.
|
1250
1332
|
|
1251
1333
|
```ruby
|
1252
|
-
Rufus::Scheduler.singleton(:
|
1253
|
-
Rufus::Scheduler.singleton(:
|
1334
|
+
Rufus::Scheduler.singleton(max_work_threads: 77)
|
1335
|
+
Rufus::Scheduler.singleton(max_work_threads: 277) # no effect
|
1254
1336
|
```
|
1255
1337
|
|
1256
1338
|
The ```.s``` is a shortcut for ```.singleton```.
|
@@ -1367,7 +1449,7 @@ Rufus::Scheduler.to_duration_hash(60)
|
|
1367
1449
|
Rufus::Scheduler.to_duration_hash(62.127)
|
1368
1450
|
# => { :m => 1, :s => 2, :ms => 127 }
|
1369
1451
|
|
1370
|
-
Rufus::Scheduler.to_duration_hash(62.127, :
|
1452
|
+
Rufus::Scheduler.to_duration_hash(62.127, drop_seconds: true)
|
1371
1453
|
# => { :m => 1 }
|
1372
1454
|
```
|
1373
1455
|
|
@@ -1550,7 +1632,7 @@ class ScheController < ApplicationController
|
|
1550
1632
|
Rails.logger.info "time flies, it's now #{Time.now}"
|
1551
1633
|
end
|
1552
1634
|
|
1553
|
-
render :
|
1635
|
+
render text: "scheduled job #{job_id}"
|
1554
1636
|
end
|
1555
1637
|
end
|
1556
1638
|
```
|
@@ -1571,12 +1653,16 @@ If you don't want rufus-scheduler to trigger anything while running the Ruby on
|
|
1571
1653
|
|
1572
1654
|
require 'rufus-scheduler'
|
1573
1655
|
|
1574
|
-
|
1656
|
+
return if defined?(Rails::Console) || Rails.env.test? || File.split($PROGRAM_NAME).last == 'rake'
|
1657
|
+
#
|
1658
|
+
# do not schedule when Rails is run from its console, for a test/spec, or
|
1659
|
+
# from a Rake task
|
1575
1660
|
|
1576
|
-
return if
|
1661
|
+
# return if $PROGRAM_NAME.include?('spring')
|
1662
|
+
#
|
1663
|
+
# see https://github.com/jmettraux/rufus-scheduler/issues/186
|
1577
1664
|
|
1578
|
-
|
1579
|
-
# from a Rake task
|
1665
|
+
s = Rufus::Scheduler.singleton
|
1580
1666
|
|
1581
1667
|
s.every '1m' do
|
1582
1668
|
Rails.logger.info "hello, it's #{Time.now}"
|
@@ -1584,6 +1670,8 @@ s.every '1m' do
|
|
1584
1670
|
end
|
1585
1671
|
```
|
1586
1672
|
|
1673
|
+
(Beware later version of Rails where Spring takes care pre-running the initializers. Running `spring stop` or disabling Spring might be necessary in some cases to see changes to initializers being taken into account.)
|
1674
|
+
|
1587
1675
|
|
1588
1676
|
### rails server -d
|
1589
1677
|
|
@@ -1600,6 +1688,9 @@ These are two well crafted articles on process daemonization, please read them:
|
|
1600
1688
|
|
1601
1689
|
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).
|
1602
1690
|
|
1691
|
+
### executor / reloader
|
1692
|
+
|
1693
|
+
You might benefit from wraping your scheduled code in the executor or reloader. Read more here: https://guides.rubyonrails.org/threading_and_code_execution.html
|
1603
1694
|
|
1604
1695
|
## support
|
1605
1696
|
|