sidekiq-scheduler 4.0.2 → 5.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/README.md +103 -39
- data/lib/sidekiq-scheduler/config.rb +80 -0
- data/lib/sidekiq-scheduler/extensions/web.rb +1 -1
- data/lib/sidekiq-scheduler/manager.rb +15 -24
- data/lib/sidekiq-scheduler/redis_manager.rb +45 -16
- data/lib/sidekiq-scheduler/schedule.rb +1 -3
- data/lib/sidekiq-scheduler/scheduler.rb +30 -16
- data/lib/sidekiq-scheduler/sidekiq_adapter.rb +80 -0
- data/lib/sidekiq-scheduler/utils.rb +5 -3
- data/lib/sidekiq-scheduler/version.rb +1 -1
- data/lib/sidekiq-scheduler/web.rb +6 -1
- data/lib/sidekiq-scheduler.rb +6 -17
- 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 +29 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: adc6f05c8d6f36cedff6c3fb051e7314581cbe1b4e460fe3227ec7c2e11cf842
|
4
|
+
data.tar.gz: d88174e3e2bacf2b4571f9b5a4d758ff5e30e456039dd967fbf1a2ff3440b155
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f41792a0657385179077cda82953df1dfc304af70f80a50355803b5a3b5b33de32e764e043b79874216e2fbbc38997e6fd9dde1ba8a9d3359019ccc86f9ca52e
|
7
|
+
data.tar.gz: 392629ec1306d5ea3d3af1b5a20c23756696d447ee5cee618b5f16b322f0def210c269331248956e43758d6b653257ef123bd73af48de66e49eb019a53b477db
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,23 @@
|
|
1
|
+
# 5.0.0.beta1
|
2
|
+
|
3
|
+
- [**BREAKING CHANGE**] Moves all sidekiq-scheduler config options under the `scheduler` key in the `sidekiq.yml` file [#412](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/412)
|
4
|
+
- If you're migrating from v4 to v5, any `sidekiq-scheduler` config you may have in your `sidekiq.yml` should be moved under the `scheduler` key.
|
5
|
+
- See [#412](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/412) to see which are the config options that you need to move under the `scheduler` key.
|
6
|
+
|
7
|
+
- [**BREAKING CHANGE**] Drop support for EOL Ruby & Sidekiq versions (Ruby: `2.5.x` & `2.6.x`; Sidekiq: `4.x` & `5.x`) [#411](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/411)
|
8
|
+
|
9
|
+
- [**FIX**] Add support for Sidekiq 7 [#410](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/410)
|
10
|
+
|
11
|
+
|
12
|
+
# 4.0.3
|
13
|
+
|
14
|
+
- [**GH Actions**] Add dependabot for GitHub Actions [#390](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/390)
|
15
|
+
- [**ENHANCEMENT**] Add «Enable all» and «Disable all» buttons [#398](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/398)
|
16
|
+
- [**ENHANCEMENT**] Allow for multiple applications to share a Redis DB [#401](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/401)
|
17
|
+
- [**FIX**] Fix metadata for Sidekiq strict_args! [#403](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/403)
|
18
|
+
- [**FIX**] Redis 5.0 compatibility [#404](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/404)
|
19
|
+
- [**FIX**] Fix the constantize method [#408](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/408)
|
20
|
+
|
1
21
|
# 4.0.2
|
2
22
|
|
3
23
|
- [**FIX**] Fix sidekiq deprecation warning when Sidekiq 6.5+ [#385](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/385)
|
data/README.md
CHANGED
@@ -18,7 +18,7 @@
|
|
18
18
|
`sidekiq-scheduler` is an extension to [Sidekiq](http://github.com/mperham/sidekiq) that
|
19
19
|
pushes jobs in a scheduled way, mimicking cron utility.
|
20
20
|
|
21
|
-
__Note:__ Current branch contains work of the
|
21
|
+
__Note:__ Current branch contains work of the upcoming v5 release, if you are looking for version 2.2.\*, 3.\*, or 4.\*, 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) / [v4-stable](https://github.com/sidekiq-scheduler/sidekiq-scheduler/tree/v4-stable).
|
22
22
|
|
23
23
|
## Installation
|
24
24
|
|
@@ -48,10 +48,11 @@ end
|
|
48
48
|
``` yaml
|
49
49
|
# config/sidekiq.yml
|
50
50
|
|
51
|
-
:
|
52
|
-
|
53
|
-
|
54
|
-
|
51
|
+
:scheduler:
|
52
|
+
:schedule:
|
53
|
+
hello_world:
|
54
|
+
cron: '0 * * * * *' # Runs once per minute
|
55
|
+
class: HelloWorld
|
55
56
|
```
|
56
57
|
|
57
58
|
Run sidekiq:
|
@@ -83,40 +84,41 @@ Configuration options are placed inside `sidekiq.yml` config file.
|
|
83
84
|
Available options are:
|
84
85
|
|
85
86
|
``` yaml
|
86
|
-
:dynamic: <if true the schedule can be modified in runtime [false by default]>
|
87
|
-
:dynamic_every: <if dynamic is true, the schedule is reloaded every interval [5s by default]>
|
88
|
-
:enabled: <enables scheduler if true [true by default]>
|
89
87
|
:scheduler:
|
88
|
+
:dynamic: <if true the schedule can be modified in runtime [false by default]>
|
89
|
+
:dynamic_every: <if dynamic is true, the schedule is reloaded every interval [5s by default]>
|
90
|
+
:enabled: <enables scheduler if true [true by default]>
|
90
91
|
: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]>
|
92
|
+
:rufus_scheduler_options: <Set custom options for rufus scheduler, like max_work_threads [{} by default]>
|
92
93
|
```
|
93
94
|
|
94
95
|
## Schedule configuration
|
95
96
|
|
96
|
-
The schedule is configured through the `:schedule` config entry in the sidekiq config file:
|
97
|
+
The schedule is configured through the `:scheduler:` -> `:schedule` config entry in the sidekiq config file:
|
97
98
|
|
98
99
|
``` yaml
|
99
|
-
:
|
100
|
-
|
101
|
-
|
100
|
+
:scheduler:
|
101
|
+
:schedule:
|
102
|
+
CancelAbandonedOrders:
|
103
|
+
cron: '0 */5 * * * *' # Runs when second = 0, every 5 minutes
|
102
104
|
|
103
|
-
|
104
|
-
|
105
|
+
queue_documents_for_indexing:
|
106
|
+
cron: '0 0 * * * *' # Runs every hour
|
105
107
|
|
106
|
-
|
107
|
-
|
108
|
-
|
108
|
+
# By default the job name will be taken as worker class name.
|
109
|
+
# If you want to have a different job name and class name, provide the 'class' option
|
110
|
+
class: QueueDocuments
|
109
111
|
|
110
|
-
|
111
|
-
|
112
|
-
|
112
|
+
queue: slow
|
113
|
+
args: ['*.pdf']
|
114
|
+
description: "This job queues pdf content for indexing in solr"
|
113
115
|
|
114
|
-
|
115
|
-
|
116
|
-
|
116
|
+
# Enable the `metadata` argument which will pass a Hash containing the schedule metadata
|
117
|
+
# as the last argument of the `perform` method. `false` by default.
|
118
|
+
include_metadata: true
|
117
119
|
|
118
|
-
|
119
|
-
|
120
|
+
# Enable / disable a job. All jobs are enabled by default.
|
121
|
+
enabled: true
|
120
122
|
```
|
121
123
|
|
122
124
|
### Schedule metadata
|
@@ -157,9 +159,10 @@ Cron, every, and interval types push jobs into sidekiq in a recurrent manner.
|
|
157
159
|
`cron` follows the same pattern as cron utility, with seconds resolution.
|
158
160
|
|
159
161
|
``` yaml
|
160
|
-
:
|
161
|
-
|
162
|
-
|
162
|
+
:scheduler:
|
163
|
+
:schedule:
|
164
|
+
HelloWorld:
|
165
|
+
cron: '0 * * * * *' # Runs when second = 0
|
163
166
|
```
|
164
167
|
|
165
168
|
`every` triggers following a given frequency:
|
@@ -250,7 +253,8 @@ When `:dynamic` flag is set to `true`, schedule changes are loaded every 5 secon
|
|
250
253
|
|
251
254
|
``` yaml
|
252
255
|
# config/sidekiq.yml
|
253
|
-
:
|
256
|
+
:scheduler:
|
257
|
+
:dynamic: true
|
254
258
|
```
|
255
259
|
|
256
260
|
If `:dynamic` flag is set to `false`, you'll have to reload the schedule manually in sidekiq
|
@@ -299,8 +303,9 @@ You can also override the thread pool size in Rufus Scheduler by setting the fol
|
|
299
303
|
---
|
300
304
|
...
|
301
305
|
|
302
|
-
|
303
|
-
|
306
|
+
:scheduler:
|
307
|
+
rufus_scheduler_options:
|
308
|
+
max_work_threads: 5
|
304
309
|
|
305
310
|
...
|
306
311
|
```
|
@@ -316,6 +321,47 @@ Non-normal conditions that could push a specific job multiple times are:
|
|
316
321
|
|
317
322
|
`every`, `interval` and `in` jobs will be pushed once per host.
|
318
323
|
|
324
|
+
### Suggested setup for Multiple Hosts using Heroku and Rails
|
325
|
+
|
326
|
+
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.
|
327
|
+
|
328
|
+
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.
|
329
|
+
|
330
|
+
Suppose we are using Rails and have the following schedule:
|
331
|
+
|
332
|
+
```yaml
|
333
|
+
# config/scheduler.yml
|
334
|
+
MyRegularJob:
|
335
|
+
description: "We want this job to run very often, but we do not want to run more of them as we scale"
|
336
|
+
interval: ["1m"]
|
337
|
+
queue: default
|
338
|
+
```
|
339
|
+
|
340
|
+
Then we can conditionally load it via an initializer:
|
341
|
+
|
342
|
+
```ruby
|
343
|
+
# config/initializer/sidekiq.rb
|
344
|
+
if ENV.fetch("IS_SCHEDULER", false)
|
345
|
+
Sidekiq.configure_server do |config|
|
346
|
+
config.on(:startup) do
|
347
|
+
Sidekiq.schedule = YAML.load_file(File.expand_path("../scheduler.yml", File.dirname(__FILE__)))
|
348
|
+
Sidekiq::Scheduler.reload_schedule!
|
349
|
+
end
|
350
|
+
end
|
351
|
+
end
|
352
|
+
```
|
353
|
+
|
354
|
+
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:
|
355
|
+
|
356
|
+
```yaml
|
357
|
+
# Procfile
|
358
|
+
web: bin/rails server
|
359
|
+
worker: bundle exec sidekiq -q default
|
360
|
+
scheduler: IS_SCHEDULER=true bundle exec sidekiq -q default
|
361
|
+
```
|
362
|
+
|
363
|
+
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.
|
364
|
+
|
319
365
|
## Notes on when Sidekiq worker is down
|
320
366
|
|
321
367
|
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.
|
@@ -345,12 +391,13 @@ Say you have one process with the schedule:
|
|
345
391
|
|
346
392
|
:queues:
|
347
393
|
- default
|
348
|
-
:
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
394
|
+
:scheduler:
|
395
|
+
:schedule:
|
396
|
+
do_something_every_minute:
|
397
|
+
class: DoSomethingJob
|
398
|
+
args: matey
|
399
|
+
queue: :scheduler
|
400
|
+
cron: '0 * * * * * America/Los_Angeles'
|
354
401
|
```
|
355
402
|
|
356
403
|
And a separate separate configured process without one:
|
@@ -360,7 +407,8 @@ And a separate separate configured process without one:
|
|
360
407
|
- scheduler
|
361
408
|
|
362
409
|
## NOTE Disable the Scheduler
|
363
|
-
:
|
410
|
+
:scheduler:
|
411
|
+
:enabled: false
|
364
412
|
```
|
365
413
|
|
366
414
|
### Details
|
@@ -377,6 +425,22 @@ Redis.
|
|
377
425
|
|
378
426
|
See https://github.com/sidekiq-scheduler/sidekiq-scheduler/issues/361 for a more details.
|
379
427
|
|
428
|
+
## Notes when running multiple applications in the same Redis database
|
429
|
+
|
430
|
+
_NOTE_: **Although we support this option, we recommend having separate redis databases for each application. Choosing this option is at your own risk.**
|
431
|
+
|
432
|
+
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.
|
433
|
+
|
434
|
+
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.
|
435
|
+
|
436
|
+
```ruby
|
437
|
+
Rails.application.reloader.to_prepare do
|
438
|
+
SidekiqScheduler::RedisManager.key_prefix = "my-app"
|
439
|
+
end
|
440
|
+
```
|
441
|
+
|
442
|
+
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.
|
443
|
+
|
380
444
|
## Sidekiq Web Integration
|
381
445
|
|
382
446
|
sidekiq-scheduler provides an extension to the Sidekiq web interface that adds a `Recurring Jobs` page.
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module SidekiqScheduler
|
2
|
+
class Config
|
3
|
+
# We have to set the default as nil because the scheduler could be instantiated without
|
4
|
+
# passing the sidekiq config, and in those scenarios we don't want to fail
|
5
|
+
def initialize(sidekiq_config: nil, without_defaults: false)
|
6
|
+
@sidekiq_config = sidekiq_config
|
7
|
+
@scheduler_config = fetch_scheduler_config(sidekiq_config, without_defaults)
|
8
|
+
end
|
9
|
+
|
10
|
+
def enabled?
|
11
|
+
scheduler_config[:enabled]
|
12
|
+
end
|
13
|
+
|
14
|
+
def enabled=(value)
|
15
|
+
scheduler_config[:enabled] = value
|
16
|
+
end
|
17
|
+
|
18
|
+
def dynamic?
|
19
|
+
scheduler_config[:dynamic]
|
20
|
+
end
|
21
|
+
|
22
|
+
def dynamic=(value)
|
23
|
+
scheduler_config[:dynamic] = value
|
24
|
+
end
|
25
|
+
|
26
|
+
def dynamic_every?
|
27
|
+
scheduler_config[:dynamic_every]
|
28
|
+
end
|
29
|
+
|
30
|
+
def dynamic_every=(value)
|
31
|
+
scheduler_config[:dynamic_every] = value
|
32
|
+
end
|
33
|
+
|
34
|
+
def schedule
|
35
|
+
scheduler_config[:schedule]
|
36
|
+
end
|
37
|
+
|
38
|
+
def schedule=(value)
|
39
|
+
scheduler_config[:schedule] = value
|
40
|
+
end
|
41
|
+
|
42
|
+
def listened_queues_only?
|
43
|
+
scheduler_config[:listened_queues_only]
|
44
|
+
end
|
45
|
+
|
46
|
+
def listened_queues_only=(value)
|
47
|
+
scheduler_config[:listened_queues_only] = value
|
48
|
+
end
|
49
|
+
|
50
|
+
def rufus_scheduler_options
|
51
|
+
scheduler_config[:rufus_scheduler_options]
|
52
|
+
end
|
53
|
+
|
54
|
+
def rufus_scheduler_options=(value)
|
55
|
+
scheduler_config[:rufus_scheduler_options] = value
|
56
|
+
end
|
57
|
+
|
58
|
+
def sidekiq_queues
|
59
|
+
SidekiqScheduler::SidekiqAdapter.sidekiq_queues(sidekiq_config)
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
attr_reader :scheduler_config
|
65
|
+
attr_reader :sidekiq_config
|
66
|
+
|
67
|
+
DEFAULT_OPTIONS = {
|
68
|
+
enabled: true,
|
69
|
+
dynamic: false,
|
70
|
+
dynamic_every: '5s',
|
71
|
+
schedule: {},
|
72
|
+
rufus_scheduler_options: {}
|
73
|
+
}.freeze
|
74
|
+
|
75
|
+
def fetch_scheduler_config(sidekiq_config, without_defaults)
|
76
|
+
conf = SidekiqScheduler::SidekiqAdapter.fetch_scheduler_config_from_sidekiq(sidekiq_config)
|
77
|
+
without_defaults ? conf : DEFAULT_OPTIONS.merge(conf)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -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' }]]
|
@@ -10,19 +10,12 @@ module SidekiqScheduler
|
|
10
10
|
# from Redis onto the work queues
|
11
11
|
#
|
12
12
|
class Manager
|
13
|
-
|
14
|
-
|
15
|
-
dynamic: false,
|
16
|
-
dynamic_every: '5s',
|
17
|
-
schedule: {}
|
18
|
-
}
|
13
|
+
def initialize(config)
|
14
|
+
set_current_scheduler_options(config)
|
19
15
|
|
20
|
-
|
21
|
-
scheduler_options = load_scheduler_options(options)
|
22
|
-
|
23
|
-
@scheduler_instance = SidekiqScheduler::Scheduler.new(scheduler_options)
|
16
|
+
@scheduler_instance = SidekiqScheduler::Scheduler.new(config)
|
24
17
|
SidekiqScheduler::Scheduler.instance = @scheduler_instance
|
25
|
-
Sidekiq.schedule =
|
18
|
+
Sidekiq.schedule = config.schedule if @scheduler_instance.enabled
|
26
19
|
end
|
27
20
|
|
28
21
|
def stop
|
@@ -35,19 +28,17 @@ module SidekiqScheduler
|
|
35
28
|
|
36
29
|
private
|
37
30
|
|
38
|
-
def
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
scheduler_options.merge(current_options)
|
31
|
+
def set_current_scheduler_options(config)
|
32
|
+
enabled = SidekiqScheduler::Scheduler.enabled
|
33
|
+
dynamic = SidekiqScheduler::Scheduler.dynamic
|
34
|
+
dynamic_every = SidekiqScheduler::Scheduler.dynamic_every
|
35
|
+
listened_queues_only = SidekiqScheduler::Scheduler.listened_queues_only
|
36
|
+
|
37
|
+
config.enabled = enabled unless enabled.nil?
|
38
|
+
config.dynamic = dynamic unless dynamic.nil?
|
39
|
+
config.dynamic_every = dynamic_every unless dynamic_every.nil?
|
40
|
+
config.schedule = Sidekiq.schedule if Sidekiq.schedule.present?
|
41
|
+
config.listened_queues_only = listened_queues_only unless listened_queues_only.nil?
|
51
42
|
end
|
52
43
|
end
|
53
44
|
end
|
@@ -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,14 +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
|
-
|
99
|
+
SidekiqScheduler::SidekiqAdapter.redis_key_exists?(schedules_key)
|
100
100
|
end
|
101
101
|
|
102
102
|
# Returns all the schedule changes for a given time range.
|
@@ -106,19 +106,19 @@ module SidekiqScheduler
|
|
106
106
|
#
|
107
107
|
# @return [Array] array with all the changed job names
|
108
108
|
def self.get_schedule_changes(from, to)
|
109
|
-
Sidekiq.redis { |r| r.zrangebyscore(
|
109
|
+
Sidekiq.redis { |r| r.zrangebyscore(schedules_changed_key, from, "(#{to}") }
|
110
110
|
end
|
111
111
|
|
112
112
|
# Register a schedule change for a given job
|
113
113
|
#
|
114
114
|
# @param [String] name The name of the job
|
115
115
|
def self.add_schedule_change(name)
|
116
|
-
Sidekiq.redis { |r| r.zadd(
|
116
|
+
Sidekiq.redis { |r| r.zadd(schedules_changed_key, Time.now.to_f, name) }
|
117
117
|
end
|
118
118
|
|
119
119
|
# Remove all the schedule changes records
|
120
120
|
def self.clean_schedules_changed
|
121
|
-
Sidekiq.redis { |r| r.del(
|
121
|
+
Sidekiq.redis { |r| r.del(schedules_changed_key) unless r.type(schedules_changed_key) == 'zset' }
|
122
122
|
end
|
123
123
|
|
124
124
|
# Removes a queued job instance
|
@@ -136,7 +136,7 @@ module SidekiqScheduler
|
|
136
136
|
end
|
137
137
|
end
|
138
138
|
|
139
|
-
registered
|
139
|
+
registered.instance_of?(Integer) ? (registered > 0) : registered
|
140
140
|
end
|
141
141
|
|
142
142
|
# Removes instances of the job older than 24 hours
|
@@ -156,32 +156,61 @@ module SidekiqScheduler
|
|
156
156
|
#
|
157
157
|
# @return [String] the pushed job key
|
158
158
|
def self.pushed_job_key(job_name)
|
159
|
-
"sidekiq-scheduler:pushed:#{job_name}"
|
159
|
+
"#{key_prefix}sidekiq-scheduler:pushed:#{job_name}"
|
160
160
|
end
|
161
161
|
|
162
162
|
# Returns the key of the Redis hash for job's execution times hash
|
163
163
|
#
|
164
164
|
# @return [String] with the key
|
165
165
|
def self.next_times_key
|
166
|
-
|
166
|
+
"#{key_prefix}sidekiq-scheduler:next_times"
|
167
167
|
end
|
168
168
|
|
169
169
|
# Returns the key of the Redis hash for job's last execution times hash
|
170
170
|
#
|
171
171
|
# @return [String] with the key
|
172
172
|
def self.last_times_key
|
173
|
-
|
173
|
+
"#{key_prefix}sidekiq-scheduler:last_times"
|
174
174
|
end
|
175
175
|
|
176
176
|
# Returns the Redis's key for saving schedule states.
|
177
177
|
#
|
178
178
|
# @return [String] with the key
|
179
179
|
def self.schedules_state_key
|
180
|
-
|
180
|
+
"#{key_prefix}sidekiq-scheduler:states"
|
181
|
+
end
|
182
|
+
|
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
|
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
|
181
210
|
end
|
182
211
|
|
183
212
|
private
|
184
|
-
|
213
|
+
|
185
214
|
# Returns the value of a Redis stored hash field
|
186
215
|
#
|
187
216
|
# @param [String] hash_key The key name of the hash
|
@@ -2,6 +2,7 @@ require 'rufus/scheduler'
|
|
2
2
|
require 'json'
|
3
3
|
require 'sidekiq-scheduler/rufus_utils'
|
4
4
|
require 'sidekiq-scheduler/redis_manager'
|
5
|
+
require 'sidekiq-scheduler/config'
|
5
6
|
|
6
7
|
module SidekiqScheduler
|
7
8
|
class Scheduler
|
@@ -10,6 +11,15 @@ module SidekiqScheduler
|
|
10
11
|
alias_method :params, :opts
|
11
12
|
end
|
12
13
|
|
14
|
+
# TODO: Can we remove those attr_accessor's? If we need to keep them, we should
|
15
|
+
# update those values on the config object instead of just here in the scheduler.
|
16
|
+
# That's why we need to do what we do in the set_current_scheduler_options (not
|
17
|
+
# saying we will have to do it somehow still)
|
18
|
+
#
|
19
|
+
# NOTE: ^ Keeping this TODO here for now, in a future version of this project
|
20
|
+
# we will remove those attr acessors and use only our config object. For now,
|
21
|
+
# let's keep as it is.
|
22
|
+
|
13
23
|
# Set to enable or disable the scheduler.
|
14
24
|
attr_accessor :enabled
|
15
25
|
|
@@ -41,12 +51,14 @@ module SidekiqScheduler
|
|
41
51
|
end
|
42
52
|
end
|
43
53
|
|
44
|
-
def initialize(
|
45
|
-
|
46
|
-
|
47
|
-
self.
|
48
|
-
self.
|
49
|
-
self.
|
54
|
+
def initialize(config = SidekiqScheduler::Config.new(without_defaults: true))
|
55
|
+
@scheduler_config = config
|
56
|
+
|
57
|
+
self.enabled = config.enabled?
|
58
|
+
self.dynamic = config.dynamic?
|
59
|
+
self.dynamic_every = config.dynamic_every?
|
60
|
+
self.listened_queues_only = config.listened_queues_only?
|
61
|
+
self.rufus_scheduler_options = config.rufus_scheduler_options
|
50
62
|
end
|
51
63
|
|
52
64
|
# the Rufus::Scheduler jobs that are scheduled
|
@@ -82,7 +94,7 @@ module SidekiqScheduler
|
|
82
94
|
Sidekiq.logger.info 'Schedule empty! Set Sidekiq.schedule' if Sidekiq.schedule.empty?
|
83
95
|
|
84
96
|
@scheduled_jobs = {}
|
85
|
-
queues = sidekiq_queues
|
97
|
+
queues = scheduler_config.sidekiq_queues
|
86
98
|
|
87
99
|
Sidekiq.schedule.each do |name, config|
|
88
100
|
if !listened_queues_only || enabled_queue?(config['queue'].to_s, queues)
|
@@ -158,7 +170,7 @@ module SidekiqScheduler
|
|
158
170
|
config = prepare_arguments(job_config.dup)
|
159
171
|
|
160
172
|
if config.delete('include_metadata')
|
161
|
-
config['args'] = arguments_with_metadata(config['args'], scheduled_at
|
173
|
+
config['args'] = arguments_with_metadata(config['args'], "scheduled_at" => time.to_f)
|
162
174
|
end
|
163
175
|
|
164
176
|
if SidekiqScheduler::Utils.active_job_enqueue?(config['class'])
|
@@ -228,8 +240,18 @@ module SidekiqScheduler
|
|
228
240
|
set_schedule_state(name, state)
|
229
241
|
end
|
230
242
|
|
243
|
+
def toggle_all_jobs(new_state)
|
244
|
+
Sidekiq.schedule!.keys.each do |name|
|
245
|
+
state = schedule_state(name)
|
246
|
+
state['enabled'] = new_state
|
247
|
+
set_schedule_state(name, state)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
231
251
|
private
|
232
252
|
|
253
|
+
attr_reader :scheduler_config
|
254
|
+
|
233
255
|
def new_job(name, interval_type, config, schedule, options)
|
234
256
|
options = options.merge({ :job => true, :tags => [name] })
|
235
257
|
|
@@ -283,14 +305,6 @@ module SidekiqScheduler
|
|
283
305
|
end
|
284
306
|
end
|
285
307
|
|
286
|
-
def sidekiq_queues
|
287
|
-
if SIDEKIQ_GTE_6_5_0
|
288
|
-
Sidekiq[:queues].map(&:to_s)
|
289
|
-
else
|
290
|
-
Sidekiq.options[:queues].map(&:to_s)
|
291
|
-
end
|
292
|
-
end
|
293
|
-
|
294
308
|
# Returns true if a job's queue is included in the array of queues
|
295
309
|
#
|
296
310
|
# If queues are empty, returns true.
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module SidekiqScheduler
|
2
|
+
class OptionNotSupportedAnymore < StandardError; end
|
3
|
+
|
4
|
+
class SidekiqAdapter
|
5
|
+
SIDEKIQ_GTE_6_5_0 = Gem::Version.new(Sidekiq::VERSION) >= Gem::Version.new('6.5.0')
|
6
|
+
SIDEKIQ_GTE_7_0_0 = Gem::Version.new(Sidekiq::VERSION) >= Gem::Version.new('7.0.0')
|
7
|
+
|
8
|
+
def self.fetch_scheduler_config_from_sidekiq(sidekiq_config)
|
9
|
+
return {} if sidekiq_config.nil?
|
10
|
+
|
11
|
+
check_using_old_sidekiq_scheduler_config!(sidekiq_config)
|
12
|
+
|
13
|
+
if SIDEKIQ_GTE_6_5_0
|
14
|
+
sidekiq_config.fetch(:scheduler, {})
|
15
|
+
else
|
16
|
+
sidekiq_config.options.fetch(:scheduler, {})
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.check_using_old_sidekiq_scheduler_config!(sidekiq_config)
|
21
|
+
%i[enabled dynamic dynamic_every schedule listened_queues_only rufus_scheduler_options].each do |option|
|
22
|
+
if SIDEKIQ_GTE_7_0_0
|
23
|
+
if sidekiq_config.key?(option)
|
24
|
+
raise OptionNotSupportedAnymore, ":#{option} option should be under the :scheduler: key"
|
25
|
+
end
|
26
|
+
elsif SIDEKIQ_GTE_6_5_0
|
27
|
+
unless sidekiq_config[option].nil?
|
28
|
+
raise OptionNotSupportedAnymore, ":#{option} option should be under the :scheduler: key"
|
29
|
+
end
|
30
|
+
else
|
31
|
+
if sidekiq_config.options.key?(option)
|
32
|
+
raise OptionNotSupportedAnymore, ":#{option} option should be under the :scheduler: key"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.start_schedule_manager(sidekiq_config:, schedule_manager:)
|
39
|
+
if SIDEKIQ_GTE_6_5_0
|
40
|
+
sidekiq_config[:schedule_manager] = schedule_manager
|
41
|
+
sidekiq_config[:schedule_manager].start
|
42
|
+
else
|
43
|
+
sidekiq_config.options[:schedule_manager] = schedule_manager
|
44
|
+
sidekiq_config.options[:schedule_manager].start
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.stop_schedule_manager(sidekiq_config:)
|
49
|
+
if SIDEKIQ_GTE_6_5_0
|
50
|
+
sidekiq_config[:schedule_manager].stop
|
51
|
+
else
|
52
|
+
sidekiq_config.options[:schedule_manager].stop
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.sidekiq_queues(sidekiq_config)
|
57
|
+
if SIDEKIQ_GTE_7_0_0
|
58
|
+
if sidekiq_config.present?
|
59
|
+
sidekiq_config.queues.map(&:to_s)
|
60
|
+
else
|
61
|
+
Sidekiq.instance_variable_get(:@config).queues.map(&:to_s)
|
62
|
+
end
|
63
|
+
elsif SIDEKIQ_GTE_6_5_0
|
64
|
+
Sidekiq[:queues].map(&:to_s)
|
65
|
+
else
|
66
|
+
Sidekiq.options[:queues].map(&:to_s)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.redis_key_exists?(key_name)
|
71
|
+
Sidekiq.redis do |r|
|
72
|
+
if SIDEKIQ_GTE_7_0_0
|
73
|
+
r.exists(key_name) > 0
|
74
|
+
else
|
75
|
+
r.exists?(key_name)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -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
|
@@ -3,7 +3,7 @@ require 'sidekiq-scheduler'
|
|
3
3
|
require_relative 'job_presenter'
|
4
4
|
|
5
5
|
module SidekiqScheduler
|
6
|
-
# Hook into *Sidekiq::Web*
|
6
|
+
# Hook into *Sidekiq::Web* app which adds a new '/recurring-jobs' page
|
7
7
|
|
8
8
|
module Web
|
9
9
|
VIEW_PATH = File.expand_path('../../../web/views', __FILE__)
|
@@ -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
@@ -5,9 +5,9 @@ require_relative 'sidekiq/scheduler'
|
|
5
5
|
require_relative 'sidekiq-scheduler/version'
|
6
6
|
require_relative 'sidekiq-scheduler/manager'
|
7
7
|
require_relative 'sidekiq-scheduler/redis_manager'
|
8
|
+
require_relative 'sidekiq-scheduler/config'
|
8
9
|
require_relative 'sidekiq-scheduler/extensions/schedule'
|
9
|
-
|
10
|
-
SIDEKIQ_GTE_6_5_0 = Gem::Version.new(Sidekiq::VERSION) >= Gem::Version.new('6.5.0')
|
10
|
+
require_relative 'sidekiq-scheduler/sidekiq_adapter'
|
11
11
|
|
12
12
|
Sidekiq.configure_server do |config|
|
13
13
|
|
@@ -15,25 +15,14 @@ Sidekiq.configure_server do |config|
|
|
15
15
|
# schedules_changed's type was changed from SET to ZSET, so we remove old versions at startup
|
16
16
|
SidekiqScheduler::RedisManager.clean_schedules_changed
|
17
17
|
|
18
|
-
|
19
|
-
config_options = SIDEKIQ_GTE_6_5_0 ? Sidekiq.instance_variable_get(:@config) : config.options
|
18
|
+
scheduler_config = SidekiqScheduler::Config.new(sidekiq_config: config)
|
20
19
|
|
21
|
-
schedule_manager = SidekiqScheduler::Manager.new(
|
22
|
-
|
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
|
20
|
+
schedule_manager = SidekiqScheduler::Manager.new(scheduler_config)
|
21
|
+
SidekiqScheduler::SidekiqAdapter.start_schedule_manager(sidekiq_config: config, schedule_manager: schedule_manager)
|
29
22
|
end
|
30
23
|
|
31
24
|
config.on(:quiet) do
|
32
|
-
|
33
|
-
config[:schedule_manager].stop
|
34
|
-
else
|
35
|
-
config.options[:schedule_manager].stop
|
36
|
-
end
|
25
|
+
SidekiqScheduler::SidekiqAdapter.stop_schedule_manager(sidekiq_config: config)
|
37
26
|
end
|
38
27
|
|
39
28
|
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,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq-scheduler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 5.0.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Morton Jonuschat
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2022-
|
13
|
+
date: 2022-12-23 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: sidekiq
|
@@ -19,6 +19,9 @@ dependencies:
|
|
19
19
|
- - ">="
|
20
20
|
- !ruby/object:Gem::Version
|
21
21
|
version: '4'
|
22
|
+
- - "<"
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: '8'
|
22
25
|
type: :runtime
|
23
26
|
prerelease: false
|
24
27
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -26,20 +29,9 @@ dependencies:
|
|
26
29
|
- - ">="
|
27
30
|
- !ruby/object:Gem::Version
|
28
31
|
version: '4'
|
29
|
-
-
|
30
|
-
name: redis
|
31
|
-
requirement: !ruby/object:Gem::Requirement
|
32
|
-
requirements:
|
33
|
-
- - ">="
|
34
|
-
- !ruby/object:Gem::Version
|
35
|
-
version: 4.2.0
|
36
|
-
type: :runtime
|
37
|
-
prerelease: false
|
38
|
-
version_requirements: !ruby/object:Gem::Requirement
|
39
|
-
requirements:
|
40
|
-
- - ">="
|
32
|
+
- - "<"
|
41
33
|
- !ruby/object:Gem::Version
|
42
|
-
version:
|
34
|
+
version: '8'
|
43
35
|
- !ruby/object:Gem::Dependency
|
44
36
|
name: rufus-scheduler
|
45
37
|
requirement: !ruby/object:Gem::Requirement
|
@@ -74,14 +66,14 @@ dependencies:
|
|
74
66
|
requirements:
|
75
67
|
- - "~>"
|
76
68
|
- !ruby/object:Gem::Version
|
77
|
-
version: '
|
69
|
+
version: '12.0'
|
78
70
|
type: :development
|
79
71
|
prerelease: false
|
80
72
|
version_requirements: !ruby/object:Gem::Requirement
|
81
73
|
requirements:
|
82
74
|
- - "~>"
|
83
75
|
- !ruby/object:Gem::Version
|
84
|
-
version: '
|
76
|
+
version: '12.0'
|
85
77
|
- !ruby/object:Gem::Dependency
|
86
78
|
name: timecop
|
87
79
|
requirement: !ruby/object:Gem::Requirement
|
@@ -111,33 +103,33 @@ dependencies:
|
|
111
103
|
- !ruby/object:Gem::Version
|
112
104
|
version: '0'
|
113
105
|
- !ruby/object:Gem::Dependency
|
114
|
-
name:
|
106
|
+
name: redis
|
115
107
|
requirement: !ruby/object:Gem::Requirement
|
116
108
|
requirements:
|
117
109
|
- - ">="
|
118
110
|
- !ruby/object:Gem::Version
|
119
|
-
version:
|
111
|
+
version: 4.2.0
|
120
112
|
type: :development
|
121
113
|
prerelease: false
|
122
114
|
version_requirements: !ruby/object:Gem::Requirement
|
123
115
|
requirements:
|
124
116
|
- - ">="
|
125
117
|
- !ruby/object:Gem::Version
|
126
|
-
version:
|
118
|
+
version: 4.2.0
|
127
119
|
- !ruby/object:Gem::Dependency
|
128
|
-
name:
|
120
|
+
name: rspec
|
129
121
|
requirement: !ruby/object:Gem::Requirement
|
130
122
|
requirements:
|
131
|
-
- - "
|
123
|
+
- - ">="
|
132
124
|
- !ruby/object:Gem::Version
|
133
|
-
version: 0
|
125
|
+
version: '0'
|
134
126
|
type: :development
|
135
127
|
prerelease: false
|
136
128
|
version_requirements: !ruby/object:Gem::Requirement
|
137
129
|
requirements:
|
138
|
-
- - "
|
130
|
+
- - ">="
|
139
131
|
- !ruby/object:Gem::Version
|
140
|
-
version: 0
|
132
|
+
version: '0'
|
141
133
|
- !ruby/object:Gem::Dependency
|
142
134
|
name: simplecov
|
143
135
|
requirement: !ruby/object:Gem::Requirement
|
@@ -195,19 +187,19 @@ dependencies:
|
|
195
187
|
- !ruby/object:Gem::Version
|
196
188
|
version: '0'
|
197
189
|
- !ruby/object:Gem::Dependency
|
198
|
-
name:
|
190
|
+
name: rack
|
199
191
|
requirement: !ruby/object:Gem::Requirement
|
200
192
|
requirements:
|
201
|
-
- - "
|
193
|
+
- - "<"
|
202
194
|
- !ruby/object:Gem::Version
|
203
|
-
version: '
|
195
|
+
version: '3'
|
204
196
|
type: :development
|
205
197
|
prerelease: false
|
206
198
|
version_requirements: !ruby/object:Gem::Requirement
|
207
199
|
requirements:
|
208
|
-
- - "
|
200
|
+
- - "<"
|
209
201
|
- !ruby/object:Gem::Version
|
210
|
-
version: '
|
202
|
+
version: '3'
|
211
203
|
description: Light weight job scheduling extension for Sidekiq that adds support for
|
212
204
|
queueing jobs in a recurring way.
|
213
205
|
email:
|
@@ -222,6 +214,7 @@ files:
|
|
222
214
|
- README.md
|
223
215
|
- Rakefile
|
224
216
|
- lib/sidekiq-scheduler.rb
|
217
|
+
- lib/sidekiq-scheduler/config.rb
|
225
218
|
- lib/sidekiq-scheduler/extensions/schedule.rb
|
226
219
|
- lib/sidekiq-scheduler/extensions/web.rb
|
227
220
|
- lib/sidekiq-scheduler/job_presenter.rb
|
@@ -230,11 +223,12 @@ files:
|
|
230
223
|
- lib/sidekiq-scheduler/rufus_utils.rb
|
231
224
|
- lib/sidekiq-scheduler/schedule.rb
|
232
225
|
- lib/sidekiq-scheduler/scheduler.rb
|
226
|
+
- lib/sidekiq-scheduler/sidekiq_adapter.rb
|
233
227
|
- lib/sidekiq-scheduler/utils.rb
|
234
228
|
- lib/sidekiq-scheduler/version.rb
|
235
229
|
- lib/sidekiq-scheduler/web.rb
|
236
230
|
- lib/sidekiq/scheduler.rb
|
237
|
-
- web/assets/stylesheets/recurring_jobs.css
|
231
|
+
- web/assets/stylesheets-scheduler/recurring_jobs.css
|
238
232
|
- web/locales/cs.yml
|
239
233
|
- web/locales/de.yml
|
240
234
|
- web/locales/en.yml
|
@@ -261,14 +255,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
261
255
|
requirements:
|
262
256
|
- - ">="
|
263
257
|
- !ruby/object:Gem::Version
|
264
|
-
version: '2.
|
258
|
+
version: '2.7'
|
265
259
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
266
260
|
requirements:
|
267
|
-
- - "
|
261
|
+
- - ">"
|
268
262
|
- !ruby/object:Gem::Version
|
269
|
-
version:
|
263
|
+
version: 1.3.1
|
270
264
|
requirements: []
|
271
|
-
rubygems_version: 3.2.
|
265
|
+
rubygems_version: 3.2.33
|
272
266
|
signing_key:
|
273
267
|
specification_version: 4
|
274
268
|
summary: Light weight job scheduling extension for Sidekiq
|