sidekiq-scheduler 3.2.2 → 4.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +31 -8
- data/README.md +126 -25
- data/lib/sidekiq-scheduler/extensions/web.rb +1 -1
- data/lib/sidekiq-scheduler/redis_manager.rb +44 -22
- data/lib/sidekiq-scheduler/schedule.rb +1 -3
- data/lib/sidekiq-scheduler/scheduler.rb +19 -12
- data/lib/sidekiq-scheduler/utils.rb +5 -3
- data/lib/sidekiq-scheduler/version.rb +1 -1
- data/lib/sidekiq-scheduler/web.rb +5 -0
- data/lib/sidekiq-scheduler.rb +18 -4
- data/web/assets/{stylesheets → stylesheets-scheduler}/recurring_jobs.css +15 -0
- data/web/locales/de.yml +2 -0
- data/web/locales/en.yml +2 -0
- data/web/locales/ru.yml +2 -0
- data/web/views/recurring_jobs.erb +28 -2
- metadata +24 -78
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c16869144651f4193112eb896e092d382af94340b373f11ba92cefbdcc8fa875
|
4
|
+
data.tar.gz: 00b8efaca9cfcfe0379b633f5ca8aa215fa1f382fcd86fd29910b7ac64e6db7f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5afc74e4fa2a54d2b00e9d1a1343f64f242d217bee9c0ec170a4fd502cc7d7233598123c769034b7ad830c75eecab1f9aa99513bcac0d42bcaef91d771ddf7d0
|
7
|
+
data.tar.gz: 2e096c861063f78ce359807fd6e58477ca3e8489d645dca3a5c188e5713ed07b61392ddc96ec0d0eb6f5c0c6b3da91aec3c9cf3e27dcd9f4094f37b3185352b1
|
data/CHANGELOG.md
CHANGED
@@ -1,11 +1,34 @@
|
|
1
|
-
#
|
1
|
+
# 4.0.3
|
2
2
|
|
3
|
-
- [
|
3
|
+
- [**GH Actions**] Add dependabot for GitHub Actions [#390](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/390)
|
4
|
+
- [**ENHANCEMENT**] Add «Enable all» and «Disable all» buttons [#398](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/398)
|
5
|
+
- [**ENHANCEMENT**] Allow for multiple applications to share a Redis DB [#401](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/401)
|
6
|
+
- [**FIX**] Fix metadata for Sidekiq strict_args! [#403](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/403)
|
7
|
+
- [**FIX**] Redis 5.0 compatibility [#404](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/404)
|
8
|
+
- [**FIX**] Fix the constantize method [#408](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/408)
|
4
9
|
|
5
|
-
#
|
6
|
-
- Fix CSS not loading on Rails app when Sidekiq < 6 https://github.com/moove-it/sidekiq-scheduler/pull/377
|
7
|
-
# 3.2.0
|
10
|
+
# 4.0.2
|
8
11
|
|
9
|
-
- Fix
|
10
|
-
-
|
11
|
-
|
12
|
+
- [**FIX**] Fix sidekiq deprecation warning when Sidekiq 6.5+ [#385](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/385)
|
13
|
+
- [**FIX**] Fix `#print_schedule` calling a method that doesn't exist in rufus scheduler [#388](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/388)
|
14
|
+
|
15
|
+
# 4.0.1
|
16
|
+
|
17
|
+
- [**FIX**] Add support for sidekiq 6.5 [#382](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/382)
|
18
|
+
|
19
|
+
# 4.0.0
|
20
|
+
|
21
|
+
- [**FIX**] Fix CSS not loading on Rails app when Sidekiq < 6 [#377](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/377)
|
22
|
+
- [**BREAKING CHANGE**] Drop support for Sidekiq 3 [f15e7ca1a5f3ab5b6fd3d7664d67723dba1fa1f1](https://github.com/sidekiq-scheduler/sidekiq-scheduler/commit/f15e7ca1a5f3ab5b6fd3d7664d67723dba1fa1f1)
|
23
|
+
|
24
|
+
# 4.0.0.alpha1
|
25
|
+
|
26
|
+
- [**FIX**] Fix deprecated uses of Redis#pipelined [#357](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/357)
|
27
|
+
- [**DOCS**] Add docs for running multi-sidekiq configurations [#362](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/362)
|
28
|
+
- [**FIX**] Prevent sidekiq_options from overriding ActiveJob queue settings [#367](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/367)
|
29
|
+
- [**ENHANCEMENT**] Highlight disabled jobs [#369](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/369)
|
30
|
+
- [**BREAKING CHANGE**] Require redis 4.2.0 [#370](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/370)
|
31
|
+
- [**FIX**] Fixes redis deprecation warning regarding `exists` [#370](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/370)
|
32
|
+
- [**BREAKING CHANGE**] Remove dependecy on thwait and e2mmap [#371](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/371)
|
33
|
+
- Support Ruby 3.1 [#373](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/373)
|
34
|
+
- [**BREAKING CHANGE**] Set rufus_scheduler_options via sidekiq.yml file as configuration option [#375](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/375)
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# sidekiq-scheduler
|
2
2
|
|
3
3
|
<p align="center">
|
4
|
-
<a href="http://
|
5
|
-
<img src="https://
|
4
|
+
<a href="http://sidekiq-scheduler.github.io/sidekiq-scheduler/">
|
5
|
+
<img src="https://sidekiq-scheduler.github.io/sidekiq-scheduler/images/small-logo.svg" width="468px" height="200px" alt="Sidekiq Scheduler" />
|
6
6
|
</a>
|
7
7
|
</p>
|
8
8
|
|
@@ -10,19 +10,7 @@
|
|
10
10
|
<a href="https://badge.fury.io/rb/sidekiq-scheduler">
|
11
11
|
<img src="https://badge.fury.io/rb/sidekiq-scheduler.svg" alt="Gem Version">
|
12
12
|
</a>
|
13
|
-
<a href="
|
14
|
-
<img src="https://codeclimate.com/github/moove-it/sidekiq-scheduler/badges/gpa.svg" alt="Code Climate">
|
15
|
-
</a>
|
16
|
-
<a href="https://travis-ci.org/moove-it/sidekiq-scheduler">
|
17
|
-
<img src="https://api.travis-ci.org/moove-it/sidekiq-scheduler.svg?branch=master" alt="Build Status">
|
18
|
-
</a>
|
19
|
-
<a href="https://coveralls.io/github/moove-it/sidekiq-scheduler?branch=master">
|
20
|
-
<img src="https://coveralls.io/repos/moove-it/sidekiq-scheduler/badge.svg?branch=master&service=github" alt="Coverage Status">
|
21
|
-
</a>
|
22
|
-
<a href="https://inch-ci.org/github/moove-it/sidekiq-scheduler">
|
23
|
-
<img src="https://inch-ci.org/github/moove-it/sidekiq-scheduler.svg?branch=master" alt="Documentation Coverage">
|
24
|
-
</a>
|
25
|
-
<a href="http://www.rubydoc.info/github/moove-it/sidekiq-scheduler">
|
13
|
+
<a href="http://www.rubydoc.info/github/sidekiq-scheduler/sidekiq-scheduler">
|
26
14
|
<img src="https://img.shields.io/badge/yard-docs-blue.svg" alt="Documentation">
|
27
15
|
</a>
|
28
16
|
</p>
|
@@ -30,7 +18,7 @@
|
|
30
18
|
`sidekiq-scheduler` is an extension to [Sidekiq](http://github.com/mperham/sidekiq) that
|
31
19
|
pushes jobs in a scheduled way, mimicking cron utility.
|
32
20
|
|
33
|
-
__Note:__
|
21
|
+
__Note:__ Current branch contains work of the v4 release, if you are looking for version 2.2.* or 3.*, go to [2.2-stable branch](https://github.com/sidekiq-scheduler/sidekiq-scheduler/tree/2.2-stable) / [v3-stable](https://github.com/sidekiq-scheduler/sidekiq-scheduler/tree/v3-stable).
|
34
22
|
|
35
23
|
## Installation
|
36
24
|
|
@@ -100,6 +88,7 @@ Available options are:
|
|
100
88
|
:enabled: <enables scheduler if true [true by default]>
|
101
89
|
:scheduler:
|
102
90
|
:listened_queues_only: <push jobs whose queue is being listened by sidekiq [false by default]>
|
91
|
+
:rufus_scheduler_options: <Set custom options for rufus scheduler, like max_work_threads [{} by default]>
|
103
92
|
```
|
104
93
|
|
105
94
|
## Schedule configuration
|
@@ -304,10 +293,16 @@ If you're configuring your own Redis connection pool, you need to make sure the
|
|
304
293
|
|
305
294
|
That's a minimum of `concurrency` + 5 (per the [Sidekiq wiki](https://github.com/mperham/sidekiq/wiki/Using-Redis#complete-control)) + `Rufus::Scheduler::MAX_WORK_THREADS` (28 as of this writing; per the [Rufus README](https://github.com/jmettraux/rufus-scheduler#max_work_threads)), for a total of 58 with the default `concurrency` of 25.
|
306
295
|
|
307
|
-
You can also override the thread pool size in Rufus Scheduler by setting
|
296
|
+
You can also override the thread pool size in Rufus Scheduler by setting the following in your `sidekiq.yml` config:
|
308
297
|
|
309
|
-
```
|
310
|
-
|
298
|
+
```yaml
|
299
|
+
---
|
300
|
+
...
|
301
|
+
|
302
|
+
rufus_scheduler_options:
|
303
|
+
max_work_threads: 5
|
304
|
+
|
305
|
+
...
|
311
306
|
```
|
312
307
|
|
313
308
|
## Notes about running on Multiple Hosts
|
@@ -321,7 +316,48 @@ Non-normal conditions that could push a specific job multiple times are:
|
|
321
316
|
|
322
317
|
`every`, `interval` and `in` jobs will be pushed once per host.
|
323
318
|
|
324
|
-
|
319
|
+
### Suggested setup for Multiple Hosts using Heroku and Rails
|
320
|
+
|
321
|
+
Configuration options `every`, `interval` and `in` will push once per host. This may be undesirable. One way to achieve single jobs per the schedule would be to manually designate a host as the scheduler. The goal is to have a single scheduler process running across all your hosts.
|
322
|
+
|
323
|
+
This can be achieved by using an environment variable and controlling the number of dynos. In Rails, you can read this variable during initialization and then conditionally load your config file.
|
324
|
+
|
325
|
+
Suppose we are using Rails and have the following schedule:
|
326
|
+
|
327
|
+
```yaml
|
328
|
+
# config/scheduler.yml
|
329
|
+
MyRegularJob:
|
330
|
+
description: "We want this job to run very often, but we do not want to run more of them as we scale"
|
331
|
+
interval: ["1m"]
|
332
|
+
queue: default
|
333
|
+
```
|
334
|
+
|
335
|
+
Then we can conditionally load it via an initializer:
|
336
|
+
|
337
|
+
```ruby
|
338
|
+
# config/initializer/sidekiq.rb
|
339
|
+
if ENV.fetch("IS_SCHEDULER", false)
|
340
|
+
Sidekiq.configure_server do |config|
|
341
|
+
config.on(:startup) do
|
342
|
+
Sidekiq.schedule = YAML.load_file(File.expand_path("../scheduler.yml", File.dirname(__FILE__)))
|
343
|
+
Sidekiq::Scheduler.reload_schedule!
|
344
|
+
end
|
345
|
+
end
|
346
|
+
end
|
347
|
+
```
|
348
|
+
|
349
|
+
Then you would just need to flag the scheduler process when you start it. If you are using a Procfile, it would look like this:
|
350
|
+
|
351
|
+
```yaml
|
352
|
+
# Procfile
|
353
|
+
web: bin/rails server
|
354
|
+
worker: bundle exec sidekiq -q default
|
355
|
+
scheduler: IS_SCHEDULER=true bundle exec sidekiq -q default
|
356
|
+
```
|
357
|
+
|
358
|
+
When running via Heroku, you set your `scheduler` process to have 1 dyno. This will ensure you have at most 1 worker loading the schedule.
|
359
|
+
|
360
|
+
## Notes on when Sidekiq worker is down
|
325
361
|
|
326
362
|
For a `cron`/`at` (and all other) job to be successfully enqueued, you need at least one sidekiq worker with scheduler to be up at that moment. Handling this is up to you and depends on your application.
|
327
363
|
|
@@ -334,6 +370,70 @@ Possible solutions include:
|
|
334
370
|
|
335
371
|
Each option has it's own pros and cons.
|
336
372
|
|
373
|
+
## Notes when running multiple Sidekiq processors on the same Redis
|
374
|
+
|
375
|
+
### TL;DR
|
376
|
+
|
377
|
+
Be **sure** to include the `:enabled: false` top-level key on any additional
|
378
|
+
configurations to avoid any possibility of the `schedules` definition being
|
379
|
+
wiped by the second Sidekiq process.
|
380
|
+
|
381
|
+
To illustrate what we mean:
|
382
|
+
|
383
|
+
Say you have one process with the schedule:
|
384
|
+
```yaml
|
385
|
+
# e.g., config/sidekiq.yml
|
386
|
+
|
387
|
+
:queues:
|
388
|
+
- default
|
389
|
+
:schedule:
|
390
|
+
do_something_every_minute:
|
391
|
+
class: DoSomethingJob
|
392
|
+
args: matey
|
393
|
+
queue: :scheduler
|
394
|
+
cron: '0 * * * * * America/Los_Angeles'
|
395
|
+
```
|
396
|
+
|
397
|
+
And a separate separate configured process without one:
|
398
|
+
```yaml
|
399
|
+
# e.g., config/sidekiq_other.yml
|
400
|
+
:queues:
|
401
|
+
- scheduler
|
402
|
+
|
403
|
+
## NOTE Disable the Scheduler
|
404
|
+
:enabled: false
|
405
|
+
```
|
406
|
+
|
407
|
+
### Details
|
408
|
+
|
409
|
+
This gem stores the configured schedule in Redis on boot. It's used, primarily,
|
410
|
+
to display in the Web Integration, and allow you to interact with that schedule
|
411
|
+
via that integration.
|
412
|
+
|
413
|
+
If you're running multiple Sidekiq processes on the same Redis namespace with
|
414
|
+
different configurations, **you'll want to explicitly _disable_ Sidekiq
|
415
|
+
Scheduler** for the other processes not responsible for the schedule. If you
|
416
|
+
don't, the last booted Sidekiq processes' schedule will be what is stored in
|
417
|
+
Redis.
|
418
|
+
|
419
|
+
See https://github.com/sidekiq-scheduler/sidekiq-scheduler/issues/361 for a more details.
|
420
|
+
|
421
|
+
## Notes when running multiple applications in the same Redis database
|
422
|
+
|
423
|
+
_NOTE_: **Although we support this option, we recommend having separate redis databases for each application. Choosing this option is at your own risk.**
|
424
|
+
|
425
|
+
If you need to run multiple applications with differing schedules, the easiest way is to use a different Redis database per application. Doing that will ensure that each application will have its own schedule, web interface and statistics.
|
426
|
+
|
427
|
+
However, you may want to have a set of related applications share the same Redis database in order to aggregate statistics and manage them all in a single web interface. To do this while maintaining a different schedule for each application, you can configure each application to use a different `key_prefix` in Redis. This prevents the applications overwriting each others' schedules and schedule data.
|
428
|
+
|
429
|
+
```ruby
|
430
|
+
Rails.application.reloader.to_prepare do
|
431
|
+
SidekiqScheduler::RedisManager.key_prefix = "my-app"
|
432
|
+
end
|
433
|
+
```
|
434
|
+
|
435
|
+
Note that this must be set before the schedule is loaded (or it will go into the wrong key). If you are using the web integration, make sure that the prefix is set in the web process so that you see the correct schedule.
|
436
|
+
|
337
437
|
## Sidekiq Web Integration
|
338
438
|
|
339
439
|
sidekiq-scheduler provides an extension to the Sidekiq web interface that adds a `Recurring Jobs` page.
|
@@ -347,7 +447,7 @@ require 'sidekiq-scheduler/web'
|
|
347
447
|
run Sidekiq::Web
|
348
448
|
```
|
349
449
|
|
350
|
-
![Sidekiq Web Integration](https://github.com/
|
450
|
+
![Sidekiq Web Integration](https://github.com/sidekiq-scheduler/sidekiq-scheduler/raw/master/images/recurring-jobs-ui-tab.png)
|
351
451
|
|
352
452
|
## ActiveJob integration
|
353
453
|
|
@@ -371,7 +471,7 @@ To see your updated schedule, be sure to reload Spring by stopping it prior to b
|
|
371
471
|
|
372
472
|
Run `spring stop` to stop Spring.
|
373
473
|
|
374
|
-
For more information, see [this issue](https://github.com/
|
474
|
+
For more information, see [this issue](https://github.com/sidekiq-scheduler/sidekiq-scheduler/issues/35#issuecomment-48067183) and [Spring's README](https://github.com/rails/spring/blob/master/README.md).
|
375
475
|
|
376
476
|
|
377
477
|
## Manage tasks from Unicorn/Rails server
|
@@ -408,6 +508,7 @@ MIT License
|
|
408
508
|
|
409
509
|
## Copyright
|
410
510
|
|
411
|
-
Copyright
|
412
|
-
Copyright
|
413
|
-
|
511
|
+
- Copyright 2021 - 2022 Marcelo Lauxen.
|
512
|
+
- Copyright 2013 - 2022 Moove-IT.
|
513
|
+
- Copyright 2012 Morton Jonuschat.
|
514
|
+
- Some parts copyright 2010 Ben VandenBos.
|
@@ -7,7 +7,7 @@ Sidekiq::Web.tabs['recurring_jobs'] = 'recurring-jobs'
|
|
7
7
|
Sidekiq::Web.locales << File.expand_path("#{File.dirname(__FILE__)}/../../../web/locales")
|
8
8
|
|
9
9
|
if Sidekiq::VERSION >= '6.0.0'
|
10
|
-
Sidekiq::Web.use Rack::Static, urls: ['/stylesheets'],
|
10
|
+
Sidekiq::Web.use Rack::Static, urls: ['/stylesheets-scheduler'],
|
11
11
|
root: ASSETS_PATH,
|
12
12
|
cascade: true,
|
13
13
|
header_rules: [[:all, { 'Cache-Control' => 'public, max-age=86400' }]]
|
@@ -9,7 +9,7 @@ module SidekiqScheduler
|
|
9
9
|
#
|
10
10
|
# @return [String] schedule in JSON format
|
11
11
|
def self.get_job_schedule(name)
|
12
|
-
hget(
|
12
|
+
hget(schedules_key, name)
|
13
13
|
end
|
14
14
|
|
15
15
|
# Returns the state of a given job
|
@@ -44,7 +44,7 @@ module SidekiqScheduler
|
|
44
44
|
# @param [String] name The name of the job
|
45
45
|
# @param [Hash] config The new schedule for the job
|
46
46
|
def self.set_job_schedule(name, config)
|
47
|
-
hset(
|
47
|
+
hset(schedules_key, name, JSON.generate(config))
|
48
48
|
end
|
49
49
|
|
50
50
|
# Sets the state for a given job
|
@@ -60,7 +60,7 @@ module SidekiqScheduler
|
|
60
60
|
# @param [String] name The name of the job
|
61
61
|
# @param [String] next_time The next time the job has to be executed
|
62
62
|
def self.set_job_next_time(name, next_time)
|
63
|
-
hset(next_times_key, name, next_time)
|
63
|
+
hset(next_times_key, name, String(next_time))
|
64
64
|
end
|
65
65
|
|
66
66
|
# Sets the last execution time for a given job
|
@@ -68,14 +68,14 @@ module SidekiqScheduler
|
|
68
68
|
# @param [String] name The name of the job
|
69
69
|
# @param [String] last_time The last time the job was executed
|
70
70
|
def self.set_job_last_time(name, last_time)
|
71
|
-
hset(last_times_key, name, last_time)
|
71
|
+
hset(last_times_key, name, String(last_time))
|
72
72
|
end
|
73
73
|
|
74
74
|
# Removes the schedule for a given job
|
75
75
|
#
|
76
76
|
# @param [String] name The name of the job
|
77
77
|
def self.remove_job_schedule(name)
|
78
|
-
hdel(
|
78
|
+
hdel(schedules_key, name)
|
79
79
|
end
|
80
80
|
|
81
81
|
# Removes the next execution time for a given job
|
@@ -89,21 +89,14 @@ module SidekiqScheduler
|
|
89
89
|
#
|
90
90
|
# @return [Hash] hash with all the job schedules
|
91
91
|
def self.get_all_schedules
|
92
|
-
Sidekiq.redis { |r| r.hgetall(
|
92
|
+
Sidekiq.redis { |r| r.hgetall(schedules_key) }
|
93
93
|
end
|
94
94
|
|
95
95
|
# Returns boolean value that indicates if the schedules value exists
|
96
96
|
#
|
97
97
|
# @return [Boolean] true if the schedules key is set, false otherwise
|
98
98
|
def self.schedule_exist?
|
99
|
-
Sidekiq.redis
|
100
|
-
case r.exists(:schedules)
|
101
|
-
when true, 1
|
102
|
-
true
|
103
|
-
else
|
104
|
-
false
|
105
|
-
end
|
106
|
-
end
|
99
|
+
Sidekiq.redis { |r| r.exists?(schedules_key) }
|
107
100
|
end
|
108
101
|
|
109
102
|
# Returns all the schedule changes for a given time range.
|
@@ -113,19 +106,19 @@ module SidekiqScheduler
|
|
113
106
|
#
|
114
107
|
# @return [Array] array with all the changed job names
|
115
108
|
def self.get_schedule_changes(from, to)
|
116
|
-
Sidekiq.redis { |r| r.zrangebyscore(
|
109
|
+
Sidekiq.redis { |r| r.zrangebyscore(schedules_changed_key, from, "(#{to}") }
|
117
110
|
end
|
118
111
|
|
119
112
|
# Register a schedule change for a given job
|
120
113
|
#
|
121
114
|
# @param [String] name The name of the job
|
122
115
|
def self.add_schedule_change(name)
|
123
|
-
Sidekiq.redis { |r| r.zadd(
|
116
|
+
Sidekiq.redis { |r| r.zadd(schedules_changed_key, Time.now.to_f, name) }
|
124
117
|
end
|
125
118
|
|
126
119
|
# Remove all the schedule changes records
|
127
120
|
def self.clean_schedules_changed
|
128
|
-
Sidekiq.redis { |r| r.del(
|
121
|
+
Sidekiq.redis { |r| r.del(schedules_changed_key) unless r.type(schedules_changed_key) == 'zset' }
|
129
122
|
end
|
130
123
|
|
131
124
|
# Removes a queued job instance
|
@@ -163,32 +156,61 @@ module SidekiqScheduler
|
|
163
156
|
#
|
164
157
|
# @return [String] the pushed job key
|
165
158
|
def self.pushed_job_key(job_name)
|
166
|
-
"sidekiq-scheduler:pushed:#{job_name}"
|
159
|
+
"#{key_prefix}sidekiq-scheduler:pushed:#{job_name}"
|
167
160
|
end
|
168
161
|
|
169
162
|
# Returns the key of the Redis hash for job's execution times hash
|
170
163
|
#
|
171
164
|
# @return [String] with the key
|
172
165
|
def self.next_times_key
|
173
|
-
|
166
|
+
"#{key_prefix}sidekiq-scheduler:next_times"
|
174
167
|
end
|
175
168
|
|
176
169
|
# Returns the key of the Redis hash for job's last execution times hash
|
177
170
|
#
|
178
171
|
# @return [String] with the key
|
179
172
|
def self.last_times_key
|
180
|
-
|
173
|
+
"#{key_prefix}sidekiq-scheduler:last_times"
|
181
174
|
end
|
182
175
|
|
183
176
|
# Returns the Redis's key for saving schedule states.
|
184
177
|
#
|
185
178
|
# @return [String] with the key
|
186
179
|
def self.schedules_state_key
|
187
|
-
|
180
|
+
"#{key_prefix}sidekiq-scheduler:states"
|
188
181
|
end
|
189
182
|
|
190
|
-
|
183
|
+
# Returns the Redis's key for saving schedules.
|
184
|
+
#
|
185
|
+
# @return [String] with the key
|
186
|
+
def self.schedules_key
|
187
|
+
"#{key_prefix}schedules"
|
188
|
+
end
|
189
|
+
|
190
|
+
# Returns the Redis's key for saving schedule changes.
|
191
|
+
#
|
192
|
+
# @return [String] with the key
|
193
|
+
def self.schedules_changed_key
|
194
|
+
"#{key_prefix}schedules_changed"
|
195
|
+
end
|
196
|
+
|
197
|
+
# Returns the key prefix used to generate all scheduler keys
|
198
|
+
#
|
199
|
+
# @return [String] with the key prefix
|
200
|
+
def self.key_prefix
|
201
|
+
@key_prefix
|
202
|
+
end
|
191
203
|
|
204
|
+
# Sets the key prefix used to scope all scheduler keys
|
205
|
+
#
|
206
|
+
# @param [String] value The string to use as the prefix. A ":" will be appended as a delimiter if needed.
|
207
|
+
def self.key_prefix=(value)
|
208
|
+
value = "#{value}:" if value && !%w[. :].include?(value[-1])
|
209
|
+
@key_prefix = value
|
210
|
+
end
|
211
|
+
|
212
|
+
private
|
213
|
+
|
192
214
|
# Returns the value of a Redis stored hash field
|
193
215
|
#
|
194
216
|
# @param [String] hash_key The key name of the hash
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'rufus/scheduler'
|
2
|
-
require 'thwait'
|
3
2
|
require 'json'
|
4
3
|
require 'sidekiq-scheduler/rufus_utils'
|
5
4
|
require 'sidekiq-scheduler/redis_manager'
|
@@ -23,6 +22,9 @@ module SidekiqScheduler
|
|
23
22
|
# Set to schedule jobs only when will be pushed to queues listened by sidekiq
|
24
23
|
attr_accessor :listened_queues_only
|
25
24
|
|
25
|
+
# Set custom options for rufus scheduler, like max_work_threads.
|
26
|
+
attr_accessor :rufus_scheduler_options
|
27
|
+
|
26
28
|
class << self
|
27
29
|
|
28
30
|
def instance
|
@@ -44,6 +46,7 @@ module SidekiqScheduler
|
|
44
46
|
self.dynamic = options[:dynamic]
|
45
47
|
self.dynamic_every = options[:dynamic_every]
|
46
48
|
self.listened_queues_only = options[:listened_queues_only]
|
49
|
+
self.rufus_scheduler_options = options[:rufus_scheduler_options] || {}
|
47
50
|
end
|
48
51
|
|
49
52
|
# the Rufus::Scheduler jobs that are scheduled
|
@@ -54,7 +57,7 @@ module SidekiqScheduler
|
|
54
57
|
def print_schedule
|
55
58
|
if rufus_scheduler
|
56
59
|
Sidekiq.logger.info "Scheduling Info\tLast Run"
|
57
|
-
scheduler_jobs = rufus_scheduler.
|
60
|
+
scheduler_jobs = rufus_scheduler.jobs
|
58
61
|
scheduler_jobs.each_value do |v|
|
59
62
|
Sidekiq.logger.info "#{v.t}\t#{v.last}\t"
|
60
63
|
end
|
@@ -155,7 +158,7 @@ module SidekiqScheduler
|
|
155
158
|
config = prepare_arguments(job_config.dup)
|
156
159
|
|
157
160
|
if config.delete('include_metadata')
|
158
|
-
config['args'] = arguments_with_metadata(config['args'], scheduled_at
|
161
|
+
config['args'] = arguments_with_metadata(config['args'], "scheduled_at" => time.to_f)
|
159
162
|
end
|
160
163
|
|
161
164
|
if SidekiqScheduler::Utils.active_job_enqueue?(config['class'])
|
@@ -165,14 +168,6 @@ module SidekiqScheduler
|
|
165
168
|
end
|
166
169
|
end
|
167
170
|
|
168
|
-
def rufus_scheduler_options
|
169
|
-
@rufus_scheduler_options ||= {}
|
170
|
-
end
|
171
|
-
|
172
|
-
def rufus_scheduler_options=(options)
|
173
|
-
@rufus_scheduler_options = options
|
174
|
-
end
|
175
|
-
|
176
171
|
def rufus_scheduler
|
177
172
|
@rufus_scheduler ||= SidekiqScheduler::Utils.new_rufus_scheduler(rufus_scheduler_options)
|
178
173
|
end
|
@@ -233,6 +228,14 @@ module SidekiqScheduler
|
|
233
228
|
set_schedule_state(name, state)
|
234
229
|
end
|
235
230
|
|
231
|
+
def toggle_all_jobs(new_state)
|
232
|
+
Sidekiq.schedule!.keys.each do |name|
|
233
|
+
state = schedule_state(name)
|
234
|
+
state['enabled'] = new_state
|
235
|
+
set_schedule_state(name, state)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
236
239
|
private
|
237
240
|
|
238
241
|
def new_job(name, interval_type, config, schedule, options)
|
@@ -289,7 +292,11 @@ module SidekiqScheduler
|
|
289
292
|
end
|
290
293
|
|
291
294
|
def sidekiq_queues
|
292
|
-
|
295
|
+
if SIDEKIQ_GTE_6_5_0
|
296
|
+
Sidekiq[:queues].map(&:to_s)
|
297
|
+
else
|
298
|
+
Sidekiq.options[:queues].map(&:to_s)
|
299
|
+
end
|
293
300
|
end
|
294
301
|
|
295
302
|
# Returns true if a job's queue is included in the array of queues
|
@@ -49,7 +49,7 @@ module SidekiqScheduler
|
|
49
49
|
#
|
50
50
|
# @return [Class] the class corresponding to the klass param
|
51
51
|
def self.try_to_constantize(klass)
|
52
|
-
klass.is_a?(String) ? klass
|
52
|
+
klass.is_a?(String) ? Object.const_get(klass) : klass
|
53
53
|
rescue NameError
|
54
54
|
klass
|
55
55
|
end
|
@@ -112,8 +112,10 @@ module SidekiqScheduler
|
|
112
112
|
def self.new_rufus_scheduler(options = {})
|
113
113
|
Rufus::Scheduler.new(options).tap do |scheduler|
|
114
114
|
scheduler.define_singleton_method(:on_post_trigger) do |job, triggered_time|
|
115
|
-
|
116
|
-
|
115
|
+
if (job_name = job.tags[0])
|
116
|
+
SidekiqScheduler::Utils.update_job_last_time(job_name, triggered_time)
|
117
|
+
SidekiqScheduler::Utils.update_job_next_time(job_name, job.next_time)
|
118
|
+
end
|
117
119
|
end
|
118
120
|
end
|
119
121
|
end
|
@@ -27,6 +27,11 @@ module SidekiqScheduler
|
|
27
27
|
SidekiqScheduler::Scheduler.instance.toggle_job_enabled(params[:name])
|
28
28
|
redirect "#{root_path}recurring-jobs"
|
29
29
|
end
|
30
|
+
|
31
|
+
app.post '/recurring-jobs/toggle-all' do
|
32
|
+
SidekiqScheduler::Scheduler.instance.toggle_all_jobs(params[:action] == 'enable')
|
33
|
+
redirect "#{root_path}recurring-jobs"
|
34
|
+
end
|
30
35
|
end
|
31
36
|
end
|
32
37
|
end
|
data/lib/sidekiq-scheduler.rb
CHANGED
@@ -7,19 +7,33 @@ require_relative 'sidekiq-scheduler/manager'
|
|
7
7
|
require_relative 'sidekiq-scheduler/redis_manager'
|
8
8
|
require_relative 'sidekiq-scheduler/extensions/schedule'
|
9
9
|
|
10
|
+
SIDEKIQ_GTE_6_5_0 = Gem::Version.new(Sidekiq::VERSION) >= Gem::Version.new('6.5.0')
|
11
|
+
|
10
12
|
Sidekiq.configure_server do |config|
|
11
13
|
|
12
14
|
config.on(:startup) do
|
13
15
|
# schedules_changed's type was changed from SET to ZSET, so we remove old versions at startup
|
14
16
|
SidekiqScheduler::RedisManager.clean_schedules_changed
|
15
17
|
|
16
|
-
|
17
|
-
config.options
|
18
|
-
|
18
|
+
# Accessing the raw @config hash through .options is deprecated in 6.5 and to be removed in 7.0
|
19
|
+
config_options = SIDEKIQ_GTE_6_5_0 ? Sidekiq.instance_variable_get(:@config) : config.options
|
20
|
+
|
21
|
+
schedule_manager = SidekiqScheduler::Manager.new(config_options)
|
22
|
+
if SIDEKIQ_GTE_6_5_0
|
23
|
+
config[:schedule_manager] = schedule_manager
|
24
|
+
config[:schedule_manager].start
|
25
|
+
else
|
26
|
+
config.options[:schedule_manager] = schedule_manager
|
27
|
+
config.options[:schedule_manager].start
|
28
|
+
end
|
19
29
|
end
|
20
30
|
|
21
31
|
config.on(:quiet) do
|
22
|
-
|
32
|
+
if SIDEKIQ_GTE_6_5_0
|
33
|
+
config[:schedule_manager].stop
|
34
|
+
else
|
35
|
+
config.options[:schedule_manager].stop
|
36
|
+
end
|
23
37
|
end
|
24
38
|
|
25
39
|
end
|
@@ -25,3 +25,18 @@
|
|
25
25
|
border: 1px solid #555;
|
26
26
|
}
|
27
27
|
}
|
28
|
+
|
29
|
+
.toggle-all-buttons {
|
30
|
+
margin-top: 20px;
|
31
|
+
margin-bottom: 10px;
|
32
|
+
line-height: 45px;
|
33
|
+
text-align: right;
|
34
|
+
}
|
35
|
+
|
36
|
+
@media (max-width: 768px) {
|
37
|
+
.toggle-all-buttons {
|
38
|
+
margin-top: 0;
|
39
|
+
text-align: left;
|
40
|
+
line-height: inherit;
|
41
|
+
}
|
42
|
+
}
|
data/web/locales/de.yml
CHANGED
data/web/locales/en.yml
CHANGED
data/web/locales/ru.yml
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
<% if Sidekiq::VERSION >= '6.0.0' %>
|
2
|
-
<link href="<%= root_path %>stylesheets/recurring_jobs.css" media="screen" rel="stylesheet" type="text/css" />
|
2
|
+
<link href="<%= root_path %>stylesheets-scheduler/recurring_jobs.css" media="screen" rel="stylesheet" type="text/css" />
|
3
3
|
<% else %>
|
4
4
|
<style>
|
5
5
|
.recurring-jobs { border-top-left-radius: 4px; border-top-right-radius: 4px; }
|
@@ -21,10 +21,36 @@
|
|
21
21
|
.list-group-item-disabled {
|
22
22
|
background-color: #f3d3d3;
|
23
23
|
}
|
24
|
+
|
25
|
+
.toggle-all-buttons {
|
26
|
+
margin-top: 20px;
|
27
|
+
margin-bottom: 10px;
|
28
|
+
line-height: 45px;
|
29
|
+
text-align: right;
|
30
|
+
}
|
31
|
+
|
32
|
+
@media (max-width: 768px) {
|
33
|
+
.toggle-all-buttons {
|
34
|
+
margin-top: 0;
|
35
|
+
text-align: left;
|
36
|
+
line-height: inherit;
|
37
|
+
}
|
38
|
+
}
|
24
39
|
</style>
|
25
40
|
<% end %>
|
26
41
|
|
27
|
-
<
|
42
|
+
<div class="row">
|
43
|
+
<div class="col-sm-6">
|
44
|
+
<h3><%= t('recurring_jobs') %></h3>
|
45
|
+
</div>
|
46
|
+
<div class="col-sm-6 toggle-all-buttons">
|
47
|
+
<form action="<%= root_path %>recurring-jobs/toggle-all" method="post">
|
48
|
+
<%= csrf_tag %>
|
49
|
+
<button type="submit" class="btn btn-warn btn-xs" name="action" value="enable"><%= t('enable_all') %></button>
|
50
|
+
<button type="submit" class="btn btn-warn btn-xs" name="action" value="disable"><%= t('disable_all') %></button>
|
51
|
+
</form>
|
52
|
+
</div>
|
53
|
+
</div>
|
28
54
|
|
29
55
|
<div class="recurring-jobs">
|
30
56
|
<ul class="list-group">
|
metadata
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq-scheduler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Morton Jonuschat
|
8
8
|
- Moove-it
|
9
|
+
- Marcelo Lauxen
|
9
10
|
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date: 2022-
|
13
|
+
date: 2022-10-05 00:00:00.000000000 Z
|
13
14
|
dependencies:
|
14
15
|
- !ruby/object:Gem::Dependency
|
15
16
|
name: sidekiq
|
@@ -17,34 +18,34 @@ dependencies:
|
|
17
18
|
requirements:
|
18
19
|
- - ">="
|
19
20
|
- !ruby/object:Gem::Version
|
20
|
-
version: '
|
21
|
+
version: '4'
|
22
|
+
- - "<"
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: '7'
|
21
25
|
type: :runtime
|
22
26
|
prerelease: false
|
23
27
|
version_requirements: !ruby/object:Gem::Requirement
|
24
28
|
requirements:
|
25
29
|
- - ">="
|
26
30
|
- !ruby/object:Gem::Version
|
27
|
-
version: '
|
31
|
+
version: '4'
|
32
|
+
- - "<"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '7'
|
28
35
|
- !ruby/object:Gem::Dependency
|
29
36
|
name: redis
|
30
37
|
requirement: !ruby/object:Gem::Requirement
|
31
38
|
requirements:
|
32
39
|
- - ">="
|
33
40
|
- !ruby/object:Gem::Version
|
34
|
-
version:
|
35
|
-
- - "<"
|
36
|
-
- !ruby/object:Gem::Version
|
37
|
-
version: '5'
|
41
|
+
version: 4.2.0
|
38
42
|
type: :runtime
|
39
43
|
prerelease: false
|
40
44
|
version_requirements: !ruby/object:Gem::Requirement
|
41
45
|
requirements:
|
42
46
|
- - ">="
|
43
47
|
- !ruby/object:Gem::Version
|
44
|
-
version:
|
45
|
-
- - "<"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '5'
|
48
|
+
version: 4.2.0
|
48
49
|
- !ruby/object:Gem::Dependency
|
49
50
|
name: rufus-scheduler
|
50
51
|
requirement: !ruby/object:Gem::Requirement
|
@@ -73,34 +74,6 @@ dependencies:
|
|
73
74
|
- - ">="
|
74
75
|
- !ruby/object:Gem::Version
|
75
76
|
version: 1.4.0
|
76
|
-
- !ruby/object:Gem::Dependency
|
77
|
-
name: thwait
|
78
|
-
requirement: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - ">="
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
83
|
-
type: :runtime
|
84
|
-
prerelease: false
|
85
|
-
version_requirements: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - ">="
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '0'
|
90
|
-
- !ruby/object:Gem::Dependency
|
91
|
-
name: e2mmap
|
92
|
-
requirement: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - ">="
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
97
|
-
type: :runtime
|
98
|
-
prerelease: false
|
99
|
-
version_requirements: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - ">="
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
104
77
|
- !ruby/object:Gem::Dependency
|
105
78
|
name: rake
|
106
79
|
requirement: !ruby/object:Gem::Requirement
|
@@ -119,28 +92,28 @@ dependencies:
|
|
119
92
|
name: timecop
|
120
93
|
requirement: !ruby/object:Gem::Requirement
|
121
94
|
requirements:
|
122
|
-
- - "
|
95
|
+
- - ">="
|
123
96
|
- !ruby/object:Gem::Version
|
124
97
|
version: '0'
|
125
98
|
type: :development
|
126
99
|
prerelease: false
|
127
100
|
version_requirements: !ruby/object:Gem::Requirement
|
128
101
|
requirements:
|
129
|
-
- - "
|
102
|
+
- - ">="
|
130
103
|
- !ruby/object:Gem::Version
|
131
104
|
version: '0'
|
132
105
|
- !ruby/object:Gem::Dependency
|
133
106
|
name: mocha
|
134
107
|
requirement: !ruby/object:Gem::Requirement
|
135
108
|
requirements:
|
136
|
-
- - "
|
109
|
+
- - ">="
|
137
110
|
- !ruby/object:Gem::Version
|
138
111
|
version: '0'
|
139
112
|
type: :development
|
140
113
|
prerelease: false
|
141
114
|
version_requirements: !ruby/object:Gem::Requirement
|
142
115
|
requirements:
|
143
|
-
- - "
|
116
|
+
- - ">="
|
144
117
|
- !ruby/object:Gem::Version
|
145
118
|
version: '0'
|
146
119
|
- !ruby/object:Gem::Dependency
|
@@ -157,36 +130,8 @@ dependencies:
|
|
157
130
|
- - ">="
|
158
131
|
- !ruby/object:Gem::Version
|
159
132
|
version: '0'
|
160
|
-
- !ruby/object:Gem::Dependency
|
161
|
-
name: mock_redis
|
162
|
-
requirement: !ruby/object:Gem::Requirement
|
163
|
-
requirements:
|
164
|
-
- - "~>"
|
165
|
-
- !ruby/object:Gem::Version
|
166
|
-
version: 0.19.0
|
167
|
-
type: :development
|
168
|
-
prerelease: false
|
169
|
-
version_requirements: !ruby/object:Gem::Requirement
|
170
|
-
requirements:
|
171
|
-
- - "~>"
|
172
|
-
- !ruby/object:Gem::Version
|
173
|
-
version: 0.19.0
|
174
133
|
- !ruby/object:Gem::Dependency
|
175
134
|
name: simplecov
|
176
|
-
requirement: !ruby/object:Gem::Requirement
|
177
|
-
requirements:
|
178
|
-
- - "~>"
|
179
|
-
- !ruby/object:Gem::Version
|
180
|
-
version: '0'
|
181
|
-
type: :development
|
182
|
-
prerelease: false
|
183
|
-
version_requirements: !ruby/object:Gem::Requirement
|
184
|
-
requirements:
|
185
|
-
- - "~>"
|
186
|
-
- !ruby/object:Gem::Version
|
187
|
-
version: '0'
|
188
|
-
- !ruby/object:Gem::Dependency
|
189
|
-
name: byebug
|
190
135
|
requirement: !ruby/object:Gem::Requirement
|
191
136
|
requirements:
|
192
137
|
- - ">="
|
@@ -200,7 +145,7 @@ dependencies:
|
|
200
145
|
- !ruby/object:Gem::Version
|
201
146
|
version: '0'
|
202
147
|
- !ruby/object:Gem::Dependency
|
203
|
-
name:
|
148
|
+
name: byebug
|
204
149
|
requirement: !ruby/object:Gem::Requirement
|
205
150
|
requirements:
|
206
151
|
- - ">="
|
@@ -214,7 +159,7 @@ dependencies:
|
|
214
159
|
- !ruby/object:Gem::Version
|
215
160
|
version: '0'
|
216
161
|
- !ruby/object:Gem::Dependency
|
217
|
-
name:
|
162
|
+
name: activejob
|
218
163
|
requirement: !ruby/object:Gem::Requirement
|
219
164
|
requirements:
|
220
165
|
- - ">="
|
@@ -259,6 +204,7 @@ description: Light weight job scheduling extension for Sidekiq that adds support
|
|
259
204
|
queueing jobs in a recurring way.
|
260
205
|
email:
|
261
206
|
- sidekiq-scheduler@moove-it.com
|
207
|
+
- marcelolauxen16@gmail.com
|
262
208
|
executables: []
|
263
209
|
extensions: []
|
264
210
|
extra_rdoc_files: []
|
@@ -280,7 +226,7 @@ files:
|
|
280
226
|
- lib/sidekiq-scheduler/version.rb
|
281
227
|
- lib/sidekiq-scheduler/web.rb
|
282
228
|
- lib/sidekiq/scheduler.rb
|
283
|
-
- web/assets/stylesheets/recurring_jobs.css
|
229
|
+
- web/assets/stylesheets-scheduler/recurring_jobs.css
|
284
230
|
- web/locales/cs.yml
|
285
231
|
- web/locales/de.yml
|
286
232
|
- web/locales/en.yml
|
@@ -295,7 +241,7 @@ files:
|
|
295
241
|
- web/locales/sv.yml
|
296
242
|
- web/locales/zh-cn.yml
|
297
243
|
- web/views/recurring_jobs.erb
|
298
|
-
homepage: https://
|
244
|
+
homepage: https://sidekiq-scheduler.github.io/sidekiq-scheduler/
|
299
245
|
licenses:
|
300
246
|
- MIT
|
301
247
|
metadata: {}
|
@@ -307,14 +253,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
307
253
|
requirements:
|
308
254
|
- - ">="
|
309
255
|
- !ruby/object:Gem::Version
|
310
|
-
version: '
|
256
|
+
version: '2.5'
|
311
257
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
312
258
|
requirements:
|
313
259
|
- - ">="
|
314
260
|
- !ruby/object:Gem::Version
|
315
261
|
version: '0'
|
316
262
|
requirements: []
|
317
|
-
rubygems_version: 3.
|
263
|
+
rubygems_version: 3.1.6
|
318
264
|
signing_key:
|
319
265
|
specification_version: 4
|
320
266
|
summary: Light weight job scheduling extension for Sidekiq
|