dynamodb-sidekiq-scheduler 0.4 → 0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +58 -5
- data/README.md +36 -10
- data/lib/sidekiq-scheduler/config.rb +11 -0
- data/lib/sidekiq-scheduler/extensions/web.rb +18 -10
- data/lib/sidekiq-scheduler/job_presenter.rb +1 -1
- data/lib/sidekiq-scheduler/manager.rb +10 -1
- data/lib/sidekiq-scheduler/redis_manager.rb +5 -5
- data/lib/sidekiq-scheduler/schedule.rb +1 -1
- data/lib/sidekiq-scheduler/scheduler.rb +27 -11
- data/lib/sidekiq-scheduler/sidekiq_adapter.rb +16 -55
- data/lib/sidekiq-scheduler/utils.rb +41 -3
- data/lib/sidekiq-scheduler/version.rb +1 -1
- data/lib/sidekiq-scheduler/web.rb +24 -4
- data/lib/sidekiq-scheduler.rb +0 -1
- data/web/assets/recurring_jobs/stylesheets-scheduler/recurring_jobs.css +81 -0
- data/web/assets/{stylesheets-scheduler/recurring_jobs.css → recurring_jobs/stylesheets-scheduler/recurring_jobs_73.css} +3 -0
- data/web/locales/fr.yml +4 -1
- data/web/locales/gd.yml +16 -0
- data/web/views/recurring_jobs.erb +51 -88
- data/web/views/sidekiq73/recurring_jobs.erb +61 -0
- metadata +18 -39
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 20ac92a2fa35e6f1e15f3307bbdd862aef92ecaafb1d16760ca9061dbbce334a
|
|
4
|
+
data.tar.gz: 94599cadc83d8afb968649150964f51e4dc846f74a2de81a9570906cb4facc03
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 540ff094b04ca414461214101b441f40d86ded4d1a3304c3ac5a678596adf3fd52455a63a013d81f099a578f13207f2be4bf2233c7a676af72ae69a8f40ed7c5
|
|
7
|
+
data.tar.gz: 5a327f337bbc1ce073a8b8a9cdc4a8b5910cb02e67d39701b61f5e855b7fff729f24a2805028c19bbe14490ffcd995799f25645b1fa0a14e4096bc9216c21a9f
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,56 @@
|
|
|
1
|
+
# 6.0.2
|
|
2
|
+
- [**FIX**] Use parser-safe web locale keys for the recurring jobs tab so the Sidekiq Web UI works with Sidekiq 8.1.3+ [#514](https://github.com/sidekiq-scheduler/sidekiq-scheduler/issues/514)
|
|
3
|
+
- [**FIX**] Stop symbolizing scheduled job `args` hash keys so string keys from YAML/JSON are preserved when enqueuing [ca3d405](https://github.com/sidekiq-scheduler/sidekiq-scheduler/commit/ca3d405e62433e3d889ebba1e3dedd3b0de0c8ef)
|
|
4
|
+
|
|
5
|
+
# 6.0.1
|
|
6
|
+
- [**FIX**] Fix issue with Sidekiq v7.3.0-v7.3.6 [#503](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/503)
|
|
7
|
+
|
|
8
|
+
# 6.0.0
|
|
9
|
+
- Check the changelog for beta1 and beta2 of this version.
|
|
10
|
+
|
|
11
|
+
# 6.0.0.beta2
|
|
12
|
+
- [**FIX**/**BREAKING CHANGE**] Don't clear "schedule" key on boot in `dynamic` schedule mode [#467](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/467)
|
|
13
|
+
- If you use sidekiq-scheduler with the `dynamic` mode, be aware that the schedule key won't be cleared on boot anymore (so maybe patches handling that in your codebase might have to be removed)
|
|
14
|
+
- [**FIX**] SidekiqScheduler::Manager enormous inspect output [17f9c7f](https://github.com/sidekiq-scheduler/sidekiq-scheduler/commit/17f9c7ffc7f7db79a1cb047bed985f2bdf12ac92) / [#462](https://github.com/sidekiq-scheduler/sidekiq-scheduler/issues/462).
|
|
15
|
+
- [**FIX/ENHANCEMENT**] Remove checks that would raise an error if any of the following options was not under the `scheduler` key (`enabled`, `dynamic`, `dynamic_every`, `schedule`, `listened_queues_only`, `rufus_scheduler_options`). [1e64958](https://github.com/sidekiq-scheduler/sidekiq-scheduler/commit/1e6495838aaee91cbf53fbd57c3749f0ed35dc28) / [#469](https://github.com/sidekiq-scheduler/sidekiq-scheduler/issues/469)
|
|
16
|
+
- This was needed for those migrating from v4 to v5, but isn't anymore.
|
|
17
|
+
|
|
18
|
+
# 6.0.0.beta1
|
|
19
|
+
- [**ENHANCEMENT**] Adds compatibility with Sidekiq 8 [#497](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/497)
|
|
20
|
+
- [**BREAKING CHANGE**] Drop support for Sidekiq 7.2 and earlier [#497](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/498)
|
|
21
|
+
|
|
22
|
+
# 5.0.6
|
|
23
|
+
- [**FIX**] Fix typo in `config#to_hash` method [#479](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/479)
|
|
24
|
+
- [**FIX**] Correctly clear scheduled jobs with Scheduler#clear_schedule! [#485](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/485)
|
|
25
|
+
- [**FIX**] Fix scheduling of aperiodic cron jobs [#487](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/487) (see [#484](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/484) for more details as well)
|
|
26
|
+
|
|
27
|
+
# 5.0.5
|
|
28
|
+
- [**FIX**] Use correct folder structure for assets [#476](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/476)
|
|
29
|
+
|
|
30
|
+
# 5.0.4
|
|
31
|
+
- [**FIX**] Ensure rufus-scheduler has a default rufus_scheduler_options value [#434](https://github.com/sidekiq-scheduler/sidekiq-scheduler/issues/426)
|
|
32
|
+
- [**ENHANCEMENT**] Remove code related to sidekiq < 6 [#443](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/443)
|
|
33
|
+
- [**ENHANCEMENT**] Change cache-control to `private` [#446](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/446)
|
|
34
|
+
- [**ENHANCEMENT**] Increase compatibility range with tilt dependency [#458](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/458)
|
|
35
|
+
- [**ENHANCEMENT**] Ensure we support Ruby 3.3 [#461](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/461)
|
|
36
|
+
- [**ENHANCEMENT**] Use Redis MULTI command (https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/464)
|
|
37
|
+
- [**ENHANCEMENT**] Don't attempt to set jon next_time when job is nil [#466](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/466)
|
|
38
|
+
- [**ENHANCEMENT**] Improvements to prevent jobs been enqueued multiple times due to a delay in job execution [#463](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/463)
|
|
39
|
+
- [**FIX**] Prevent stack level too deep error by implementing `to_hash` method [#470](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/470)
|
|
40
|
+
- [**ENHANCEMENT**] Support new Sidekiq model for registering UI plugins [#472](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/472)
|
|
41
|
+
- [**ENHANCEMENT**] Stop testing against Ruby 2.7 and 3.0 [#472](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/472#discussion_r1663197863)
|
|
42
|
+
- [**ENHANCEMENT**] Display `at` and `in` in the dashboard [#291](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/291)
|
|
43
|
+
- [**ENHANCEMENT**] Docs enhancements [#442](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/442), [#449](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/449), [#457](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/457), [#465](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/465), [58e1835](https://github.com/sidekiq-scheduler/sidekiq-scheduler/commit/58e18351054fc3c264b2b5a684173316f674c386)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
# 5.0.3
|
|
47
|
+
|
|
48
|
+
- [**FIX**] Fix "uppercase character in header name: Cache-Control" [#432](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/432)
|
|
49
|
+
- [**ENHANCEMENT**] Add gd translation [#433](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/433)
|
|
50
|
+
- [**ENHANCEMENT**] Add French translation [#435](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/435)
|
|
51
|
+
- [**FIX**] Remove usage of deprecated Redis command `zrangebyscore` [#437](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/437)
|
|
52
|
+
- [**ENHANCEMENT**] Add the ability to force a job args hash to be deconstructed to keyword arguments [#440](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/440)
|
|
53
|
+
|
|
1
54
|
# 5.0.2
|
|
2
55
|
|
|
3
56
|
- [**FIX**] Fix YARD docblocks. [#427](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/427)
|
|
@@ -8,10 +61,10 @@
|
|
|
8
61
|
- [**ENHANCEMENT**] Adds Ruby 3.2 to the CI matrix. [#420](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/420)
|
|
9
62
|
- [**DOCS**] README: refer to v5 as released. [#421](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/421)
|
|
10
63
|
- [**FIX**] Fix dependency on Rails `.present?` method. [#425](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/425)
|
|
11
|
-
|
|
64
|
+
|
|
12
65
|
# 5.0.0
|
|
13
66
|
|
|
14
|
-
- [**FIX**] Ensure generated scheduled time has a precision of 3
|
|
67
|
+
- [**FIX**] Ensure generated scheduled time has a precision of 3 milliseconds. [#418](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/418)
|
|
15
68
|
|
|
16
69
|
*Note 1:* Check [# 5.0.0.beta1](#500beta1) & [# 5.0.0.beta2](#500beta2) releases for breaking changes.
|
|
17
70
|
|
|
@@ -27,7 +80,7 @@
|
|
|
27
80
|
- [**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)
|
|
28
81
|
- 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.
|
|
29
82
|
- 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.
|
|
30
|
-
|
|
83
|
+
|
|
31
84
|
- [**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)
|
|
32
85
|
|
|
33
86
|
- [**FIX**] Add support for Sidekiq 7 [#410](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/410)
|
|
@@ -64,6 +117,6 @@
|
|
|
64
117
|
- [**ENHANCEMENT**] Highlight disabled jobs [#369](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/369)
|
|
65
118
|
- [**BREAKING CHANGE**] Require redis 4.2.0 [#370](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/370)
|
|
66
119
|
- [**FIX**] Fixes redis deprecation warning regarding `exists` [#370](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/370)
|
|
67
|
-
- [**BREAKING CHANGE**] Remove
|
|
120
|
+
- [**BREAKING CHANGE**] Remove dependency on thwait and e2mmap [#371](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/371)
|
|
68
121
|
- Support Ruby 3.1 [#373](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/373)
|
|
69
|
-
- [**BREAKING CHANGE**] Set rufus_scheduler_options via sidekiq.yml file as configuration option [#375](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/375)
|
|
122
|
+
- [**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
|
@@ -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 v6 release, if you are looking for version 2.2.\*, 3.\*, 4.\*, or 5.\*, 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) / [v5-stable](https://github.com/sidekiq-scheduler/sidekiq-scheduler/tree/v5-stable).
|
|
22
22
|
|
|
23
23
|
## Installation
|
|
24
24
|
|
|
@@ -37,7 +37,7 @@ gem install sidekiq-scheduler
|
|
|
37
37
|
require 'sidekiq-scheduler'
|
|
38
38
|
|
|
39
39
|
class HelloWorld
|
|
40
|
-
include Sidekiq::
|
|
40
|
+
include Sidekiq::Job
|
|
41
41
|
|
|
42
42
|
def perform
|
|
43
43
|
puts 'Hello world'
|
|
@@ -45,6 +45,8 @@ class HelloWorld
|
|
|
45
45
|
end
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
+
__Note:__ In Sidekiq v6.3 `Sidekiq::Job` was introduced as an alias for `Sidekiq::Worker`. `Sidekiq::Worker` has been officially deprecated in Sidekiq v7 although it still exists for backwards compatibility. It is therefore recommended to use `include Sidekiq::Job` in the above example unless an older version of Sidekiq is required.
|
|
49
|
+
|
|
48
50
|
``` yaml
|
|
49
51
|
# config/sidekiq.yml
|
|
50
52
|
|
|
@@ -55,6 +57,9 @@ end
|
|
|
55
57
|
class: HelloWorld
|
|
56
58
|
```
|
|
57
59
|
|
|
60
|
+
> [!NOTE]
|
|
61
|
+
> sidekiq-scheduler uses [fugit](https://github.com/floraison/fugit) under the hood, which supports up to six arguments as the cron string, [see](https://github.com/floraison/fugit?tab=readme-ov-file#the-second-extension).
|
|
62
|
+
|
|
58
63
|
Run sidekiq:
|
|
59
64
|
|
|
60
65
|
``` sh
|
|
@@ -119,6 +124,25 @@ The schedule is configured through the `:scheduler:` -> `:schedule` config entry
|
|
|
119
124
|
|
|
120
125
|
# Enable / disable a job. All jobs are enabled by default.
|
|
121
126
|
enabled: true
|
|
127
|
+
|
|
128
|
+
# Deconstructs a hash defined as the `args` to keyword arguments.
|
|
129
|
+
#
|
|
130
|
+
# `false` by default.
|
|
131
|
+
#
|
|
132
|
+
# Example
|
|
133
|
+
#
|
|
134
|
+
# my_job:
|
|
135
|
+
# cron: '0 0 * * * *'
|
|
136
|
+
# class: MyJob
|
|
137
|
+
# args: { foo: 'bar', hello: 'world' }
|
|
138
|
+
# keyword_argument: true
|
|
139
|
+
#
|
|
140
|
+
# class MyJob < ActiveJob::Base
|
|
141
|
+
# def perform(foo:, hello:)
|
|
142
|
+
# # ...
|
|
143
|
+
# end
|
|
144
|
+
# end
|
|
145
|
+
keyword_argument: true
|
|
122
146
|
```
|
|
123
147
|
|
|
124
148
|
### Schedule metadata
|
|
@@ -189,7 +213,7 @@ At, and in types push jobs only once. `at` schedules in a point in time:
|
|
|
189
213
|
at: '3001/01/01'
|
|
190
214
|
```
|
|
191
215
|
|
|
192
|
-
You can specify any string that `DateTime.parse` and `Chronic` understand. To enable Chronic
|
|
216
|
+
You can specify any string that `DateTime.parse` and `Chronic` understand. To enable [Chronic](https://github.com/mojombo/chronic)
|
|
193
217
|
strings, you must add it as a dependency.
|
|
194
218
|
|
|
195
219
|
`in` triggers after a time duration has elapsed:
|
|
@@ -313,7 +337,7 @@ You can also override the thread pool size in Rufus Scheduler by setting the fol
|
|
|
313
337
|
## Notes about running on Multiple Hosts
|
|
314
338
|
|
|
315
339
|
Under normal conditions, `cron` and `at` jobs are pushed once regardless of the number of `sidekiq-scheduler` running instances,
|
|
316
|
-
|
|
340
|
+
assuming that time deltas between hosts is less than 24 hours.
|
|
317
341
|
|
|
318
342
|
Non-normal conditions that could push a specific job multiple times are:
|
|
319
343
|
- high cpu load + a high number of jobs scheduled at the same time, like 100 jobs
|
|
@@ -323,7 +347,7 @@ Non-normal conditions that could push a specific job multiple times are:
|
|
|
323
347
|
|
|
324
348
|
### Suggested setup for Multiple Hosts using Heroku and Rails
|
|
325
349
|
|
|
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.
|
|
350
|
+
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
351
|
|
|
328
352
|
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
353
|
|
|
@@ -340,7 +364,7 @@ MyRegularJob:
|
|
|
340
364
|
Then we can conditionally load it via an initializer:
|
|
341
365
|
|
|
342
366
|
```ruby
|
|
343
|
-
# config/
|
|
367
|
+
# config/initializers/sidekiq.rb
|
|
344
368
|
if ENV.fetch("IS_SCHEDULER", false)
|
|
345
369
|
Sidekiq.configure_server do |config|
|
|
346
370
|
config.on(:startup) do
|
|
@@ -360,7 +384,7 @@ worker: bundle exec sidekiq -q default
|
|
|
360
384
|
scheduler: IS_SCHEDULER=true bundle exec sidekiq -q default
|
|
361
385
|
```
|
|
362
386
|
|
|
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.
|
|
387
|
+
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
388
|
|
|
365
389
|
## Notes on when Sidekiq worker is down
|
|
366
390
|
|
|
@@ -373,7 +397,7 @@ Possible solutions include:
|
|
|
373
397
|
- Zero downtime deploy for sidekiq workers: keep at least one worker up during whole deploy and only restart/shut it down after when new one has started
|
|
374
398
|
- Running scheduler inside your unicorn/rails processes (if you already have zero downtime deploy set up for these)
|
|
375
399
|
|
|
376
|
-
Each option has it's own pros and cons.
|
|
400
|
+
Each option has it's own pros and cons.
|
|
377
401
|
|
|
378
402
|
## Notes when running multiple Sidekiq processors on the same Redis
|
|
379
403
|
|
|
@@ -456,6 +480,8 @@ run Sidekiq::Web
|
|
|
456
480
|
|
|
457
481
|

|
|
458
482
|
|
|
483
|
+

|
|
484
|
+
|
|
459
485
|
## ActiveJob integration
|
|
460
486
|
|
|
461
487
|
When using sidekiq-scheduler with ActiveJob your jobs can just extend `ApplicationJob` as usual, without the `require` and `include` boilerplate. Under the hood Rails will load up the scheduler and include the worker module for you.
|
|
@@ -470,7 +496,7 @@ end
|
|
|
470
496
|
|
|
471
497
|
## The Spring preloader and Testing your initializer via Rails console
|
|
472
498
|
|
|
473
|
-
If you're pulling in your schedule from a YML file via an initializer as shown, be aware that the Spring application preloader included with Rails will
|
|
499
|
+
If you're pulling in your schedule from a YML file via an initializer as shown, be aware that the Spring application preloader included with Rails will interfere with testing via the Rails console.
|
|
474
500
|
|
|
475
501
|
**Spring will not reload initializers** unless the initializer is changed. Therefore, if you're making a change to your YML schedule file and reloading Rails console to see the change, Spring will make it seem like your modified schedule is not being reloaded.
|
|
476
502
|
|
|
@@ -515,7 +541,7 @@ MIT License
|
|
|
515
541
|
|
|
516
542
|
## Copyright
|
|
517
543
|
|
|
518
|
-
- Copyright 2021 -
|
|
544
|
+
- Copyright 2021 - 2024 Marcelo Lauxen.
|
|
519
545
|
- Copyright 2013 - 2022 Moove-IT.
|
|
520
546
|
- Copyright 2012 Morton Jonuschat.
|
|
521
547
|
- Some parts copyright 2010 Ben VandenBos.
|
|
@@ -59,6 +59,17 @@ module SidekiqScheduler
|
|
|
59
59
|
SidekiqScheduler::SidekiqAdapter.sidekiq_queues(sidekiq_config)
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
+
def to_hash
|
|
63
|
+
{
|
|
64
|
+
enabled: enabled?,
|
|
65
|
+
dynamic: dynamic?,
|
|
66
|
+
dynamic_every: dynamic_every?,
|
|
67
|
+
schedule: schedule,
|
|
68
|
+
listened_queues_only: listened_queues_only?,
|
|
69
|
+
rufus_scheduler_options: rufus_scheduler_options
|
|
70
|
+
}
|
|
71
|
+
end
|
|
72
|
+
|
|
62
73
|
private
|
|
63
74
|
|
|
64
75
|
attr_reader :scheduler_config
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
require 'sidekiq/web' unless defined?(Sidekiq::Web)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# Locale and asset cache is configured in `cfg.register`
|
|
4
|
+
args = {
|
|
5
|
+
name: "recurring_jobs",
|
|
6
|
+
tab: ["recurring_jobs"],
|
|
7
|
+
index: ["recurring-jobs"],
|
|
8
|
+
root_dir: File.expand_path("../../../web", File.dirname(__FILE__)),
|
|
9
|
+
asset_paths: ["stylesheets-scheduler"]
|
|
10
|
+
}
|
|
4
11
|
|
|
5
|
-
|
|
6
|
-
Sidekiq::Web.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
if SidekiqScheduler::SidekiqAdapter::SIDEKIQ_GTE_8_0_0
|
|
13
|
+
Sidekiq::Web.configure do |cfg|
|
|
14
|
+
cfg.register(SidekiqScheduler::Web, **args) do |app|
|
|
15
|
+
# add middleware or additional settings here
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
else
|
|
19
|
+
Sidekiq::Web.register(SidekiqScheduler::Web, **args) do |app|
|
|
20
|
+
# add middleware or additional settings here
|
|
21
|
+
end
|
|
14
22
|
end
|
|
@@ -38,7 +38,7 @@ module SidekiqScheduler
|
|
|
38
38
|
#
|
|
39
39
|
# @return [String] with the job's interval
|
|
40
40
|
def interval
|
|
41
|
-
@attributes['cron'] || @attributes['interval'] || @attributes['every']
|
|
41
|
+
@attributes['cron'] || @attributes['interval'] || @attributes['every'] || @attributes['at'] || @attributes['in']
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
# Returns the queue of the job
|
|
@@ -13,7 +13,7 @@ module SidekiqScheduler
|
|
|
13
13
|
|
|
14
14
|
@scheduler_instance = SidekiqScheduler::Scheduler.new(config)
|
|
15
15
|
SidekiqScheduler::Scheduler.instance = @scheduler_instance
|
|
16
|
-
Sidekiq.schedule = config.schedule if @scheduler_instance.enabled
|
|
16
|
+
Sidekiq.schedule = config.schedule if @scheduler_instance.enabled && !@scheduler_instance.dynamic
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def stop
|
|
@@ -24,6 +24,15 @@ module SidekiqScheduler
|
|
|
24
24
|
@scheduler_instance.load_schedule!
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
+
# This method is needed to avoid exposing unnecessary information.
|
|
28
|
+
# Because ActiveSupport's `as_json` traverses instance values to convert the object to a hash
|
|
29
|
+
# unless it responds to `to_hash`.
|
|
30
|
+
def to_hash
|
|
31
|
+
{
|
|
32
|
+
scheduler: @scheduler_instance.to_hash
|
|
33
|
+
}
|
|
34
|
+
end
|
|
35
|
+
|
|
27
36
|
private
|
|
28
37
|
|
|
29
38
|
def set_current_scheduler_options(config)
|
|
@@ -106,7 +106,7 @@ 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
|
-
|
|
109
|
+
SidekiqScheduler::SidekiqAdapter.redis_zrangebyscore(schedules_changed_key, from, "(#{to}")
|
|
110
110
|
end
|
|
111
111
|
|
|
112
112
|
# Register a schedule change for a given job
|
|
@@ -121,7 +121,7 @@ module SidekiqScheduler
|
|
|
121
121
|
Sidekiq.redis { |r| r.del(schedules_changed_key) unless r.type(schedules_changed_key) == 'zset' }
|
|
122
122
|
end
|
|
123
123
|
|
|
124
|
-
#
|
|
124
|
+
# Registers a queued job instance
|
|
125
125
|
#
|
|
126
126
|
# @param [String] job_name The name of the job
|
|
127
127
|
# @param [Time] time The time at which the job was cleared by the scheduler
|
|
@@ -130,9 +130,9 @@ module SidekiqScheduler
|
|
|
130
130
|
def self.register_job_instance(job_name, time)
|
|
131
131
|
job_key = pushed_job_key(job_name)
|
|
132
132
|
registered, _ = Sidekiq.redis do |r|
|
|
133
|
-
r.
|
|
134
|
-
|
|
135
|
-
|
|
133
|
+
r.multi do |m|
|
|
134
|
+
m.zadd(job_key, time.to_i, time.to_i)
|
|
135
|
+
m.expire(job_key, REGISTERED_JOBS_THRESHOLD_IN_SECONDS)
|
|
136
136
|
end
|
|
137
137
|
end
|
|
138
138
|
|
|
@@ -65,7 +65,7 @@ module SidekiqScheduler
|
|
|
65
65
|
end
|
|
66
66
|
alias_method :schedule!, :reload_schedule!
|
|
67
67
|
|
|
68
|
-
#
|
|
68
|
+
# Retrieve the schedule configuration for the given name
|
|
69
69
|
# if the name is nil it returns a hash with all the
|
|
70
70
|
# names end their schedules.
|
|
71
71
|
def get_schedule(name = nil)
|
|
@@ -17,7 +17,7 @@ module SidekiqScheduler
|
|
|
17
17
|
# saying we will have to do it somehow still)
|
|
18
18
|
#
|
|
19
19
|
# NOTE: ^ Keeping this TODO here for now, in a future version of this project
|
|
20
|
-
# we will remove those attr
|
|
20
|
+
# we will remove those attr accessors and use only our config object. For now,
|
|
21
21
|
# let's keep as it is.
|
|
22
22
|
|
|
23
23
|
# Set to enable or disable the scheduler.
|
|
@@ -58,7 +58,7 @@ module SidekiqScheduler
|
|
|
58
58
|
self.dynamic = config.dynamic?
|
|
59
59
|
self.dynamic_every = config.dynamic_every?
|
|
60
60
|
self.listened_queues_only = config.listened_queues_only?
|
|
61
|
-
self.rufus_scheduler_options = config.rufus_scheduler_options
|
|
61
|
+
self.rufus_scheduler_options = config.rufus_scheduler_options || {}
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
# the Rufus::Scheduler jobs that are scheduled
|
|
@@ -128,6 +128,8 @@ module SidekiqScheduler
|
|
|
128
128
|
schedule, options = SidekiqScheduler::RufusUtils.normalize_schedule_options(config_interval_type)
|
|
129
129
|
|
|
130
130
|
rufus_job = new_job(name, interval_type, config, schedule, options)
|
|
131
|
+
return unless rufus_job
|
|
132
|
+
|
|
131
133
|
@scheduled_jobs[name] = rufus_job
|
|
132
134
|
SidekiqScheduler::Utils.update_job_next_time(name, rufus_job.next_time)
|
|
133
135
|
|
|
@@ -194,7 +196,7 @@ module SidekiqScheduler
|
|
|
194
196
|
@rufus_scheduler = nil
|
|
195
197
|
end
|
|
196
198
|
|
|
197
|
-
|
|
199
|
+
@scheduled_jobs = {}
|
|
198
200
|
|
|
199
201
|
rufus_scheduler
|
|
200
202
|
end
|
|
@@ -248,6 +250,16 @@ module SidekiqScheduler
|
|
|
248
250
|
end
|
|
249
251
|
end
|
|
250
252
|
|
|
253
|
+
def to_hash
|
|
254
|
+
{
|
|
255
|
+
scheduler_config: @scheduler_config.to_hash
|
|
256
|
+
}
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def inspect
|
|
260
|
+
"#<SidekiqScheduler::Scheduler enabled=#{enabled} dynamic=#{dynamic} dynamic_every=#{dynamic_every} listened_queues_only=#{listened_queues_only} rufus_scheduler_options=#{rufus_scheduler_options}>"
|
|
261
|
+
end
|
|
262
|
+
|
|
251
263
|
private
|
|
252
264
|
|
|
253
265
|
attr_reader :scheduler_config
|
|
@@ -256,7 +268,15 @@ module SidekiqScheduler
|
|
|
256
268
|
options = options.merge({ :job => true, :tags => [name] })
|
|
257
269
|
|
|
258
270
|
rufus_scheduler.send(interval_type, schedule, options) do |job, time|
|
|
259
|
-
|
|
271
|
+
if job_enabled?(name)
|
|
272
|
+
conf = SidekiqScheduler::Utils.sanitize_job_config(config)
|
|
273
|
+
|
|
274
|
+
if job.is_a?(Rufus::Scheduler::CronJob)
|
|
275
|
+
idempotent_job_enqueue(name, SidekiqScheduler::Utils.calc_cron_run_time(job.cron_line, time.to_t), conf)
|
|
276
|
+
else
|
|
277
|
+
idempotent_job_enqueue(name, time.to_t, conf)
|
|
278
|
+
end
|
|
279
|
+
end
|
|
260
280
|
end
|
|
261
281
|
end
|
|
262
282
|
|
|
@@ -287,12 +307,12 @@ module SidekiqScheduler
|
|
|
287
307
|
end
|
|
288
308
|
|
|
289
309
|
# Adds a Hash with schedule metadata as the last argument to call the worker.
|
|
290
|
-
# It currently returns the schedule time as a Float number representing the
|
|
310
|
+
# It currently returns the schedule time as a Float number representing the milliseconds
|
|
291
311
|
# since epoch.
|
|
292
312
|
#
|
|
293
313
|
# @example with hash argument
|
|
294
314
|
# arguments_with_metadata({value: 1}, scheduled_at: Time.now.round(3))
|
|
295
|
-
# #=> [{value: 1}, {scheduled_at: <
|
|
315
|
+
# #=> [{value: 1}, {scheduled_at: <milliseconds since epoch>}]
|
|
296
316
|
#
|
|
297
317
|
# @param args [Array|Hash]
|
|
298
318
|
# @param metadata [Hash]
|
|
@@ -328,11 +348,7 @@ module SidekiqScheduler
|
|
|
328
348
|
def prepare_arguments(config)
|
|
329
349
|
config['class'] = SidekiqScheduler::Utils.try_to_constantize(config['class'])
|
|
330
350
|
|
|
331
|
-
|
|
332
|
-
config['args'].symbolize_keys! if config['args'].respond_to?(:symbolize_keys!)
|
|
333
|
-
else
|
|
334
|
-
config['args'] = Array(config['args'])
|
|
335
|
-
end
|
|
351
|
+
config['args'] = Array(config['args']) unless config['args'].is_a?(Hash)
|
|
336
352
|
|
|
337
353
|
config
|
|
338
354
|
end
|
|
@@ -1,79 +1,40 @@
|
|
|
1
1
|
module SidekiqScheduler
|
|
2
|
-
class OptionNotSupportedAnymore < StandardError; end
|
|
3
|
-
|
|
4
2
|
class SidekiqAdapter
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
SIDEKIQ_GTE_7_3_0 = Gem::Version.new(Sidekiq::VERSION) >= Gem::Version.new('7.3.0')
|
|
4
|
+
SIDEKIQ_GTE_8_0_0 = Gem::Version.new(Sidekiq::VERSION) >= Gem::Version.new('8.0.0')
|
|
7
5
|
|
|
8
6
|
def self.fetch_scheduler_config_from_sidekiq(sidekiq_config)
|
|
9
7
|
return {} if sidekiq_config.nil?
|
|
10
8
|
|
|
11
|
-
|
|
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
|
|
9
|
+
sidekiq_config.fetch(:scheduler, {})
|
|
36
10
|
end
|
|
37
11
|
|
|
38
12
|
def self.start_schedule_manager(sidekiq_config:, schedule_manager:)
|
|
39
|
-
|
|
40
|
-
|
|
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
|
|
13
|
+
sidekiq_config[:schedule_manager] = schedule_manager
|
|
14
|
+
sidekiq_config[:schedule_manager].start
|
|
46
15
|
end
|
|
47
16
|
|
|
48
17
|
def self.stop_schedule_manager(sidekiq_config:)
|
|
49
|
-
|
|
50
|
-
sidekiq_config[:schedule_manager].stop
|
|
51
|
-
else
|
|
52
|
-
sidekiq_config.options[:schedule_manager].stop
|
|
53
|
-
end
|
|
18
|
+
sidekiq_config[:schedule_manager].stop
|
|
54
19
|
end
|
|
55
20
|
|
|
56
21
|
def self.sidekiq_queues(sidekiq_config)
|
|
57
|
-
if
|
|
58
|
-
|
|
59
|
-
Sidekiq.instance_variable_get(:@config).queues.map(&:to_s)
|
|
60
|
-
else
|
|
61
|
-
sidekiq_config.queues.map(&:to_s)
|
|
62
|
-
end
|
|
63
|
-
elsif SIDEKIQ_GTE_6_5_0
|
|
64
|
-
Sidekiq[:queues].map(&:to_s)
|
|
22
|
+
if sidekiq_config.nil? || (sidekiq_config.respond_to?(:empty?) && sidekiq_config.empty?)
|
|
23
|
+
Sidekiq.instance_variable_get(:@config).queues.map(&:to_s)
|
|
65
24
|
else
|
|
66
|
-
|
|
25
|
+
sidekiq_config.queues.map(&:to_s)
|
|
67
26
|
end
|
|
68
27
|
end
|
|
69
28
|
|
|
70
29
|
def self.redis_key_exists?(key_name)
|
|
71
30
|
Sidekiq.redis do |r|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
31
|
+
r.exists(key_name) > 0
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.redis_zrangebyscore(key, from, to)
|
|
36
|
+
Sidekiq.redis do |r|
|
|
37
|
+
r.zrange(key, from, to, "BYSCORE")
|
|
77
38
|
end
|
|
78
39
|
end
|
|
79
40
|
end
|
|
@@ -60,9 +60,11 @@ module SidekiqScheduler
|
|
|
60
60
|
# @param [Array, Hash] args The parameters passed to the klass initializer
|
|
61
61
|
#
|
|
62
62
|
# @return [Object] instance of the class klass
|
|
63
|
-
def self.initialize_active_job(klass, args)
|
|
63
|
+
def self.initialize_active_job(klass, args, keyword_argument = false)
|
|
64
64
|
if args.is_a?(Array)
|
|
65
65
|
klass.new(*args)
|
|
66
|
+
elsif args.is_a?(Hash) && keyword_argument
|
|
67
|
+
klass.new(**symbolize_keys(args))
|
|
66
68
|
else
|
|
67
69
|
klass.new(args)
|
|
68
70
|
end
|
|
@@ -71,7 +73,7 @@ module SidekiqScheduler
|
|
|
71
73
|
# Returns true if the enqueuing needs to be done for an ActiveJob
|
|
72
74
|
# class false otherwise.
|
|
73
75
|
#
|
|
74
|
-
# @param [Class] klass the class to check is
|
|
76
|
+
# @param [Class] klass the class to check is descendant from ActiveJob
|
|
75
77
|
#
|
|
76
78
|
# @return [Boolean]
|
|
77
79
|
def self.active_job_enqueue?(klass)
|
|
@@ -94,7 +96,7 @@ module SidekiqScheduler
|
|
|
94
96
|
queue: config['queue']
|
|
95
97
|
}.keep_if { |_, v| !v.nil? }
|
|
96
98
|
|
|
97
|
-
initialize_active_job(config['class'], config['args']).enqueue(options)
|
|
99
|
+
initialize_active_job(config['class'], config['args'], config['keyword_argument']).enqueue(options)
|
|
98
100
|
end
|
|
99
101
|
|
|
100
102
|
# Removes the hash values associated to the rufus metadata keys.
|
|
@@ -139,5 +141,41 @@ module SidekiqScheduler
|
|
|
139
141
|
def self.update_job_last_time(name, last_time)
|
|
140
142
|
SidekiqScheduler::RedisManager.set_job_last_time(name, last_time) if last_time
|
|
141
143
|
end
|
|
144
|
+
|
|
145
|
+
# Try to figure out when the cron job was supposed to run.
|
|
146
|
+
#
|
|
147
|
+
# Rufus calls the scheduler block with the current time and not the time the block was scheduled to run.
|
|
148
|
+
# This means under certain conditions you could have a job get scheduled multiple times because `time.to_i` is used
|
|
149
|
+
# to key the job in redis. If one server is under load and Rufus tries to run the jobs 1 seconds after the other
|
|
150
|
+
# server then the job will be queued twice.
|
|
151
|
+
# This method essentially makes a best guess at when this job was supposed to run and return that.
|
|
152
|
+
#
|
|
153
|
+
# @param [Fugit::Cron] cron
|
|
154
|
+
# @param [Time] time
|
|
155
|
+
#
|
|
156
|
+
# @return [Time]
|
|
157
|
+
def self.calc_cron_run_time(cron, time)
|
|
158
|
+
time = time.floor # remove sub seconds to prevent rounding errors.
|
|
159
|
+
return time if cron.match?(time) # If the time is a perfect match then return it.
|
|
160
|
+
|
|
161
|
+
next_t = cron.next_time(time).to_t
|
|
162
|
+
previous_t = cron.previous_time(time).to_t
|
|
163
|
+
# The `time` var is some point between `previous_t` and `next_t`.
|
|
164
|
+
# Figure out how far off we are from each side in seconds.
|
|
165
|
+
next_diff = next_t - time
|
|
166
|
+
previous_diff = time - previous_t
|
|
167
|
+
|
|
168
|
+
if next_diff == previous_diff
|
|
169
|
+
# In the event `time` is exactly between `previous_t` and `next_t` the diff will not be equal to
|
|
170
|
+
# `cron.rough_frequency`. In that case we round down.
|
|
171
|
+
cron.rough_frequency == next_diff ? time : previous_t
|
|
172
|
+
elsif next_diff > previous_diff
|
|
173
|
+
# We are closer to the previous run time so return that.
|
|
174
|
+
previous_t
|
|
175
|
+
else
|
|
176
|
+
# We are closer to the next run time so return that.
|
|
177
|
+
next_t
|
|
178
|
+
end
|
|
179
|
+
end
|
|
142
180
|
end
|
|
143
181
|
end
|
|
@@ -6,9 +6,29 @@ module SidekiqScheduler
|
|
|
6
6
|
# Hook into *Sidekiq::Web* app which adds a new '/recurring-jobs' page
|
|
7
7
|
|
|
8
8
|
module Web
|
|
9
|
-
VIEW_PATH = File.expand_path('../../../web/views', __FILE__)
|
|
9
|
+
VIEW_PATH = File.expand_path(SidekiqAdapter::SIDEKIQ_GTE_8_0_0 ? '../../../web/views' : '../../../web/views/sidekiq73', __FILE__)
|
|
10
|
+
|
|
11
|
+
module Helpers
|
|
12
|
+
def sidekiq_scheduler_fetch_route_param(key)
|
|
13
|
+
if SidekiqAdapter::SIDEKIQ_GTE_8_0_0
|
|
14
|
+
route_params(key)
|
|
15
|
+
else
|
|
16
|
+
route_params[key]
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def sidekiq_scheduler_fetch_url_param(key)
|
|
21
|
+
if SidekiqAdapter::SIDEKIQ_GTE_8_0_0
|
|
22
|
+
url_params(key)
|
|
23
|
+
else
|
|
24
|
+
params[key]
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
10
28
|
|
|
11
29
|
def self.registered(app)
|
|
30
|
+
app.helpers(Helpers)
|
|
31
|
+
|
|
12
32
|
app.get '/recurring-jobs' do
|
|
13
33
|
@presented_jobs = JobPresenter.build_collection(Sidekiq.schedule!)
|
|
14
34
|
|
|
@@ -16,7 +36,7 @@ module SidekiqScheduler
|
|
|
16
36
|
end
|
|
17
37
|
|
|
18
38
|
app.post '/recurring-jobs/:name/enqueue' do
|
|
19
|
-
schedule = Sidekiq.get_schedule(
|
|
39
|
+
schedule = Sidekiq.get_schedule(sidekiq_scheduler_fetch_route_param(:name))
|
|
20
40
|
SidekiqScheduler::Scheduler.instance.enqueue_job(schedule)
|
|
21
41
|
redirect "#{root_path}recurring-jobs"
|
|
22
42
|
end
|
|
@@ -24,7 +44,7 @@ module SidekiqScheduler
|
|
|
24
44
|
app.post '/recurring-jobs/:name/toggle' do
|
|
25
45
|
Sidekiq.reload_schedule!
|
|
26
46
|
|
|
27
|
-
SidekiqScheduler::Scheduler.instance.toggle_job_enabled(
|
|
47
|
+
SidekiqScheduler::Scheduler.instance.toggle_job_enabled(sidekiq_scheduler_fetch_route_param(:name))
|
|
28
48
|
redirect "#{root_path}recurring-jobs"
|
|
29
49
|
end
|
|
30
50
|
|
|
@@ -36,7 +56,7 @@ module SidekiqScheduler
|
|
|
36
56
|
end
|
|
37
57
|
|
|
38
58
|
app.post '/recurring-jobs/toggle-all' do
|
|
39
|
-
SidekiqScheduler::Scheduler.instance.toggle_all_jobs(
|
|
59
|
+
SidekiqScheduler::Scheduler.instance.toggle_all_jobs(sidekiq_scheduler_fetch_url_param(:action) == 'enable')
|
|
40
60
|
redirect "#{root_path}recurring-jobs"
|
|
41
61
|
end
|
|
42
62
|
|
data/lib/sidekiq-scheduler.rb
CHANGED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
.sidekiq-scheduler .job-name {
|
|
2
|
+
color: var(--color-primary);
|
|
3
|
+
display: block;
|
|
4
|
+
font-size: var(--font-size);
|
|
5
|
+
font-weight: 700;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.sidekiq-scheduler .queue {
|
|
9
|
+
text-align: right;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.sidekiq-scheduler .btn-xs {
|
|
13
|
+
padding: 1px 5px;
|
|
14
|
+
font-size: var(--font-size-small);
|
|
15
|
+
line-height: 1.5;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.sidekiq-scheduler .description,
|
|
19
|
+
.sidekiq-scheduler .last-time,
|
|
20
|
+
.sidekiq-scheduler .next-time {
|
|
21
|
+
font-size: var(--font-size-small);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.sidekiq-scheduler .description {
|
|
25
|
+
padding-top: 10px;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.sidekiq-scheduler .inline {
|
|
29
|
+
display: inline;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.sidekiq-scheduler .job-list .job {
|
|
33
|
+
background-color: var(--color-elevated);
|
|
34
|
+
border: 1px solid var(--color-border);
|
|
35
|
+
box-shadow: 0 2px 4px 0 var(--color-shadow);
|
|
36
|
+
padding: 10px;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.sidekiq-scheduler .column-2 {
|
|
40
|
+
float: left;
|
|
41
|
+
width: 50%;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.sidekiq-scheduler .column-3 {
|
|
45
|
+
float: left;
|
|
46
|
+
width: 33.33%;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.sidekiq-scheduler .row:after {
|
|
50
|
+
content: "";
|
|
51
|
+
display: table;
|
|
52
|
+
clear: both;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.sidekiq-scheduler .job.disabled-job {
|
|
56
|
+
background-color: #f3d3d3;
|
|
57
|
+
color: #585454;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@media (prefers-color-scheme: dark) {
|
|
61
|
+
.sidekiq-scheduler .job.disabled-job {
|
|
62
|
+
background-color: #4f0b0b;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.sidekiq-scheduler .disabled-job .next-time {
|
|
67
|
+
text-decoration: line-through;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@media screen and (max-width: 1000px) {
|
|
71
|
+
.sidekiq-scheduler .column-2,
|
|
72
|
+
.sidekiq-scheduler .column-3,
|
|
73
|
+
.sidekiq-scheduler .description {
|
|
74
|
+
width: 100%;
|
|
75
|
+
padding: 5px 10px;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.sidekiq-scheduler .queue {
|
|
79
|
+
text-align: left;
|
|
80
|
+
}
|
|
81
|
+
}
|
data/web/locales/fr.yml
CHANGED
|
@@ -7,7 +7,10 @@ fr:
|
|
|
7
7
|
queue: Queue
|
|
8
8
|
arguments: Arguments
|
|
9
9
|
enqueue_now: Ajouter à la queue
|
|
10
|
-
|
|
10
|
+
last_time: Dernière fois
|
|
11
|
+
next_time: Prochaine fois
|
|
11
12
|
no_next_time: Pas d'exécution prévue pour cette tâche
|
|
12
13
|
disable: Désactiver
|
|
13
14
|
enable: Activer
|
|
15
|
+
disable_all: Tout désactiver
|
|
16
|
+
enable_all: Tout activer
|
data/web/locales/gd.yml
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
gd:
|
|
2
|
+
recurring_jobs: Obraichean ath-chùrsach
|
|
3
|
+
name: Ainm
|
|
4
|
+
description: Tuairisgeul
|
|
5
|
+
interval: Eadaramh
|
|
6
|
+
class: Clas
|
|
7
|
+
queue: Ciudha
|
|
8
|
+
arguments: Argamaidean
|
|
9
|
+
enqueue_now: Cuir sa chiudha an-dràsta
|
|
10
|
+
last_time: An t-àm mu dheireadh
|
|
11
|
+
next_time: An t-ath-àm
|
|
12
|
+
no_next_time: chan eil ath-ghnìomhachadh aig an obair seo
|
|
13
|
+
disable: Cuir à comas
|
|
14
|
+
enable: Cuir an comas
|
|
15
|
+
disable_all: Cuir na h-uile à comas
|
|
16
|
+
enable_all: Cuir na h-uile an comas
|
|
@@ -1,93 +1,55 @@
|
|
|
1
|
-
|
|
2
|
-
<% if Sidekiq::VERSION >= '6.0.0' %>
|
|
3
|
-
<link href="<%= root_path %>stylesheets-scheduler/recurring_jobs.css" media="screen" rel="stylesheet" type="text/css" />
|
|
4
|
-
<% else %>
|
|
5
|
-
<style>
|
|
6
|
-
.recurring-jobs { border-top-left-radius: 4px; border-top-right-radius: 4px; }
|
|
7
|
-
.recurring-jobs .title { margin-bottom: 5px; }
|
|
8
|
-
.recurring-jobs .title .name { font-weight: bold;}
|
|
9
|
-
.recurring-jobs .info,
|
|
10
|
-
.recurring-jobs .description { margin-bottom: 5px; }
|
|
11
|
-
.recurring-jobs .actions { margin-bottom: 5px; }
|
|
12
|
-
.recurring-jobs .status,
|
|
13
|
-
.recurring-jobs .description { font-size: 12px; }
|
|
14
|
-
.recurring-jobs .enqueue { margin-bottom: 0.5rem }
|
|
1
|
+
<% style_tag "recurring_jobs/stylesheets-scheduler/recurring_jobs.css" %>
|
|
15
2
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
@media (max-width: 768px) {
|
|
34
|
-
.toggle-all-buttons {
|
|
35
|
-
margin-top: 0;
|
|
36
|
-
text-align: left;
|
|
37
|
-
line-height: inherit;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
</style>
|
|
41
|
-
<% end %>
|
|
42
|
-
|
|
43
|
-
<div class="row">
|
|
44
|
-
<div class="col-sm-6">
|
|
45
|
-
<h3><%= t('recurring_jobs') %></h3>
|
|
46
|
-
</div>
|
|
47
|
-
<div class="col-sm-6 toggle-all-buttons">
|
|
48
|
-
<form action="<%= root_path %>recurring-jobs/toggle-all" method="post">
|
|
49
|
-
<%= csrf_tag %>
|
|
50
|
-
<button type="submit" class="btn btn-warn btn-xs" name="action" value="enable"><%= t('enable_all') %></button>
|
|
51
|
-
<button type="submit" class="btn btn-warn btn-xs" name="action" value="disable"><%= t('disable_all') %></button>
|
|
52
|
-
</form>
|
|
53
|
-
<form action="<%= root_path %>recurring-jobs/new" method="post">
|
|
54
|
-
<%= csrf_tag %>
|
|
55
|
-
<button type="submit" class="btn btn-warn btn-xs" name="action" value="enable"><%= t('new') %></button>
|
|
56
|
-
</form>
|
|
57
|
-
</div>
|
|
58
|
-
</div>
|
|
3
|
+
<section class="sidekiq-scheduler">
|
|
4
|
+
<header>
|
|
5
|
+
<h2><%= t('recurring_jobs') %></h2>
|
|
6
|
+
<div class="col-sm-6 toggle-all-buttons">
|
|
7
|
+
<form action="<%= root_path %>recurring-jobs/toggle-all" method="POST" class="filter">
|
|
8
|
+
<%= csrf_tag %>
|
|
9
|
+
<div class="btn-group pull-right flip">
|
|
10
|
+
<button type="submit" class="btn btn-xs btn-warn" name="action" value="enable"><%= t('enable_all') %></button>
|
|
11
|
+
<button type="submit" class="btn btn-xs btn-warn" name="action" value="disable"><%= t('disable_all') %></button>
|
|
12
|
+
</div>
|
|
13
|
+
</form>
|
|
14
|
+
<form action="<%= root_path %>recurring-jobs/new" method="post">
|
|
15
|
+
<%= csrf_tag %>
|
|
16
|
+
<button type="submit" class="btn btn-warn btn-xs" name="action" value="enable"><%= t('new') %></button>
|
|
17
|
+
</form>
|
|
18
|
+
</div>
|
|
19
|
+
</header>
|
|
59
20
|
|
|
60
|
-
<
|
|
61
|
-
<ul class="list-group">
|
|
21
|
+
<section class="job-list">
|
|
62
22
|
<% @presented_jobs.each do |job| %>
|
|
63
|
-
<
|
|
64
|
-
<div class="
|
|
65
|
-
<div class="
|
|
66
|
-
<div class="
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
<
|
|
70
|
-
<a href="<%= root_path %>queues/<%= job.queue %>"><%= job.queue %></a>
|
|
71
|
-
</div>
|
|
23
|
+
<section class="job <%= job.enabled? ? "" : "disabled-job" %>">
|
|
24
|
+
<div class="row">
|
|
25
|
+
<div class="column-2">
|
|
26
|
+
<div class="job-name"><%= job.name %></div>
|
|
27
|
+
</div>
|
|
28
|
+
<div class="column-2 queue">
|
|
29
|
+
<a href="<%= root_path %>queues/<%= job.queue %>"><%= job.queue %></a>
|
|
72
30
|
</div>
|
|
73
31
|
</div>
|
|
74
|
-
|
|
75
|
-
<div class="
|
|
76
|
-
<div class="
|
|
77
|
-
<div class="
|
|
78
|
-
|
|
79
|
-
|
|
32
|
+
|
|
33
|
+
<div class="row">
|
|
34
|
+
<div class="column-3">
|
|
35
|
+
<div class="class-name"><%= job['class'] %></div>
|
|
36
|
+
</div>
|
|
37
|
+
<div class="column-3">
|
|
38
|
+
<div><%= t('interval') %>: <%= job.interval %></div>
|
|
39
|
+
</div>
|
|
40
|
+
<div class="column-3">
|
|
41
|
+
<div><%= t('arguments') %>: <%= job['args'] %></div>
|
|
80
42
|
</div>
|
|
81
43
|
</div>
|
|
82
|
-
<div class="
|
|
83
|
-
<div class="
|
|
84
|
-
<form action="<%= root_path %>recurring-jobs/<%= ERB::Util.url_encode(job.name) %>/enqueue" method="
|
|
44
|
+
<div class="row">
|
|
45
|
+
<div class="column-3">
|
|
46
|
+
<form class="inline" action="<%= root_path %>recurring-jobs/<%= ERB::Util.url_encode(job.name) %>/enqueue" method="POST">
|
|
85
47
|
<%= csrf_tag %>
|
|
86
48
|
<input type="submit" class="btn btn-warn btn-xs" value="<%= t('enqueue_now') %>" />
|
|
87
49
|
</form>
|
|
88
|
-
<form action="<%= root_path %>recurring-jobs/<%= ERB::Util.url_encode(job.name) %>/toggle" method="
|
|
50
|
+
<form class="inline" action="<%= root_path %>recurring-jobs/<%= ERB::Util.url_encode(job.name) %>/toggle" method="POST">
|
|
89
51
|
<%= csrf_tag %>
|
|
90
|
-
<input type="submit" class="btn <%= job.enabled? ? "btn-
|
|
52
|
+
<input type="submit" class="btn btn-xs <%= job.enabled? ? "btn-inverse" : "btn-warn"%>" value="<%= job.enabled? ? t('disable') : t('enable') %>" />
|
|
91
53
|
</form>
|
|
92
54
|
<form action="<%= root_path %>recurring-jobs/<%= ERB::Util.url_encode(job.name) %>/destroy" method="post">
|
|
93
55
|
<%= csrf_tag %>
|
|
@@ -98,16 +60,17 @@
|
|
|
98
60
|
<input type="submit" class="btn <%= job.enabled? ? "btn-primary" : "btn-warn"%> btn-xs" value="<%= t('edit') %>" />
|
|
99
61
|
</form>
|
|
100
62
|
</div>
|
|
101
|
-
<div class="
|
|
102
|
-
<
|
|
63
|
+
<div class="column-3">
|
|
64
|
+
<div class="last-time"><%= t('last_time') %>: <%= job.last_time %></div>
|
|
103
65
|
</div>
|
|
104
|
-
<div class="
|
|
105
|
-
<
|
|
106
|
-
<%= t('next_time') %>: <%= job.next_time || t('no_next_time') %>
|
|
107
|
-
</span>
|
|
66
|
+
<div class="column-3">
|
|
67
|
+
<div class="next-time"><%= t('next_time') %>: <%= job.next_time || t('no_next_time') %></div>
|
|
108
68
|
</div>
|
|
69
|
+
|
|
109
70
|
</div>
|
|
110
|
-
|
|
71
|
+
<div class="description"><%= job['description'] %></div>
|
|
72
|
+
|
|
73
|
+
</section>
|
|
111
74
|
<% end %>
|
|
112
|
-
</
|
|
113
|
-
</
|
|
75
|
+
</section>
|
|
76
|
+
</section>
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
<%= style_tag "recurring_jobs/stylesheets-scheduler/recurring_jobs_73.css" %>
|
|
2
|
+
|
|
3
|
+
<div class="row">
|
|
4
|
+
<div class="col-sm-6">
|
|
5
|
+
<h3><%= t('recurring_jobs') %></h3>
|
|
6
|
+
</div>
|
|
7
|
+
<div class="col-sm-6 toggle-all-buttons">
|
|
8
|
+
<form action="<%= root_path %>recurring-jobs/toggle-all" method="post">
|
|
9
|
+
<%= csrf_tag %>
|
|
10
|
+
<button type="submit" class="btn btn-warn btn-xs" name="action" value="enable"><%= t('enable_all') %></button>
|
|
11
|
+
<button type="submit" class="btn btn-warn btn-xs" name="action" value="disable"><%= t('disable_all') %></button>
|
|
12
|
+
</form>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<div class="recurring-jobs">
|
|
17
|
+
<ul class="list-group">
|
|
18
|
+
<% @presented_jobs.each do |job| %>
|
|
19
|
+
<li class="list-group-item <%= !job.enabled? && "list-group-item-disabled" %>">
|
|
20
|
+
<div class="title">
|
|
21
|
+
<div class="row">
|
|
22
|
+
<div class="col-xs-6">
|
|
23
|
+
<span class="name"><%= job.name %></span>
|
|
24
|
+
</div>
|
|
25
|
+
<div class="col-xs-6 text-right">
|
|
26
|
+
<a href="<%= root_path %>queues/<%= job.queue %>"><%= job.queue %></a>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
<div class="description"><%= job['description'] %></div>
|
|
31
|
+
<div class="info">
|
|
32
|
+
<div class="row">
|
|
33
|
+
<div class="col-md-4 class"><%= job['class'] %></div>
|
|
34
|
+
<div class="col-md-4 interval text-left"><%= t('interval') %>: <%= job.interval %></div>
|
|
35
|
+
<div class="col-md-4 args"><%= t('arguments') %>: <%= job['args'] %></div>
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
<div class="status row">
|
|
39
|
+
<div class="col-md-4 actions">
|
|
40
|
+
<form action="<%= root_path %>recurring-jobs/<%= ERB::Util.url_encode(job.name) %>/enqueue" method="post" class="enqueue">
|
|
41
|
+
<%= csrf_tag %>
|
|
42
|
+
<input type="submit" class="btn btn-warn btn-xs" value="<%= t('enqueue_now') %>" />
|
|
43
|
+
</form>
|
|
44
|
+
<form action="<%= root_path %>recurring-jobs/<%= ERB::Util.url_encode(job.name) %>/toggle" method="post">
|
|
45
|
+
<%= csrf_tag %>
|
|
46
|
+
<input type="submit" class="btn <%= job.enabled? ? "btn-primary" : "btn-warn"%> btn-xs" value="<%= job.enabled? ? t('disable') : t('enable') %>" />
|
|
47
|
+
</form>
|
|
48
|
+
</div>
|
|
49
|
+
<div class="col-md-4">
|
|
50
|
+
<span class="last_time"><%= t('last_time') %>: <%= job.last_time %></span>
|
|
51
|
+
</div>
|
|
52
|
+
<div class="col-md-4">
|
|
53
|
+
<span class="next_time text-right" style="<%= 'text-decoration:line-through' unless job.enabled? %>">
|
|
54
|
+
<%= t('next_time') %>: <%= job.next_time || t('no_next_time') %>
|
|
55
|
+
</span>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
</li>
|
|
59
|
+
<% end %>
|
|
60
|
+
</ul>
|
|
61
|
+
</div>
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dynamodb-sidekiq-scheduler
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: '0.
|
|
4
|
+
version: '0.6'
|
|
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:
|
|
13
|
+
date: 2026-05-01 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: sidekiq
|
|
@@ -18,20 +18,20 @@ dependencies:
|
|
|
18
18
|
requirements:
|
|
19
19
|
- - ">="
|
|
20
20
|
- !ruby/object:Gem::Version
|
|
21
|
-
version: '
|
|
21
|
+
version: '7.3'
|
|
22
22
|
- - "<"
|
|
23
23
|
- !ruby/object:Gem::Version
|
|
24
|
-
version: '
|
|
24
|
+
version: '9'
|
|
25
25
|
type: :runtime
|
|
26
26
|
prerelease: false
|
|
27
27
|
version_requirements: !ruby/object:Gem::Requirement
|
|
28
28
|
requirements:
|
|
29
29
|
- - ">="
|
|
30
30
|
- !ruby/object:Gem::Version
|
|
31
|
-
version: '
|
|
31
|
+
version: '7.3'
|
|
32
32
|
- - "<"
|
|
33
33
|
- !ruby/object:Gem::Version
|
|
34
|
-
version: '
|
|
34
|
+
version: '9'
|
|
35
35
|
- !ruby/object:Gem::Dependency
|
|
36
36
|
name: rufus-scheduler
|
|
37
37
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -46,20 +46,6 @@ dependencies:
|
|
|
46
46
|
- - "~>"
|
|
47
47
|
- !ruby/object:Gem::Version
|
|
48
48
|
version: '3.2'
|
|
49
|
-
- !ruby/object:Gem::Dependency
|
|
50
|
-
name: tilt
|
|
51
|
-
requirement: !ruby/object:Gem::Requirement
|
|
52
|
-
requirements:
|
|
53
|
-
- - ">="
|
|
54
|
-
- !ruby/object:Gem::Version
|
|
55
|
-
version: 1.4.0
|
|
56
|
-
type: :runtime
|
|
57
|
-
prerelease: false
|
|
58
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
59
|
-
requirements:
|
|
60
|
-
- - ">="
|
|
61
|
-
- !ruby/object:Gem::Version
|
|
62
|
-
version: 1.4.0
|
|
63
49
|
- !ruby/object:Gem::Dependency
|
|
64
50
|
name: rake
|
|
65
51
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -164,28 +150,14 @@ dependencies:
|
|
|
164
150
|
requirements:
|
|
165
151
|
- - ">="
|
|
166
152
|
- !ruby/object:Gem::Version
|
|
167
|
-
version: '
|
|
153
|
+
version: '1.1'
|
|
168
154
|
type: :development
|
|
169
155
|
prerelease: false
|
|
170
156
|
version_requirements: !ruby/object:Gem::Requirement
|
|
171
157
|
requirements:
|
|
172
158
|
- - ">="
|
|
173
159
|
- !ruby/object:Gem::Version
|
|
174
|
-
version: '
|
|
175
|
-
- !ruby/object:Gem::Dependency
|
|
176
|
-
name: rack
|
|
177
|
-
requirement: !ruby/object:Gem::Requirement
|
|
178
|
-
requirements:
|
|
179
|
-
- - "<"
|
|
180
|
-
- !ruby/object:Gem::Version
|
|
181
|
-
version: '3'
|
|
182
|
-
type: :development
|
|
183
|
-
prerelease: false
|
|
184
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
185
|
-
requirements:
|
|
186
|
-
- - "<"
|
|
187
|
-
- !ruby/object:Gem::Version
|
|
188
|
-
version: '3'
|
|
160
|
+
version: '1.1'
|
|
189
161
|
description: Light weight job scheduling extension for Sidekiq that adds support for
|
|
190
162
|
queueing jobs in a recurring way.
|
|
191
163
|
email:
|
|
@@ -214,12 +186,14 @@ files:
|
|
|
214
186
|
- lib/sidekiq-scheduler/version.rb
|
|
215
187
|
- lib/sidekiq-scheduler/web.rb
|
|
216
188
|
- lib/sidekiq/scheduler.rb
|
|
217
|
-
- web/assets/stylesheets-scheduler/recurring_jobs.css
|
|
189
|
+
- web/assets/recurring_jobs/stylesheets-scheduler/recurring_jobs.css
|
|
190
|
+
- web/assets/recurring_jobs/stylesheets-scheduler/recurring_jobs_73.css
|
|
218
191
|
- web/locales/cs.yml
|
|
219
192
|
- web/locales/de.yml
|
|
220
193
|
- web/locales/en.yml
|
|
221
194
|
- web/locales/es.yml
|
|
222
195
|
- web/locales/fr.yml
|
|
196
|
+
- web/locales/gd.yml
|
|
223
197
|
- web/locales/it.yml
|
|
224
198
|
- web/locales/ja.yml
|
|
225
199
|
- web/locales/nl.yml
|
|
@@ -230,10 +204,15 @@ files:
|
|
|
230
204
|
- web/locales/zh-cn.yml
|
|
231
205
|
- web/views/recurring_job.erb
|
|
232
206
|
- web/views/recurring_jobs.erb
|
|
207
|
+
- web/views/sidekiq73/recurring_jobs.erb
|
|
233
208
|
homepage: https://sidekiq-scheduler.github.io/sidekiq-scheduler/
|
|
234
209
|
licenses:
|
|
235
210
|
- MIT
|
|
236
|
-
metadata:
|
|
211
|
+
metadata:
|
|
212
|
+
rubygems_mfa_required: 'true'
|
|
213
|
+
source_code_uri: https://github.com/sidekiq-scheduler/sidekiq-scheduler
|
|
214
|
+
bug_tracker_uri: https://github.com/sidekiq-scheduler/sidekiq-scheduler/issues
|
|
215
|
+
changelog_uri: https://github.com/sidekiq-scheduler/sidekiq-scheduler/blob/master/CHANGELOG.md
|
|
237
216
|
post_install_message:
|
|
238
217
|
rdoc_options: []
|
|
239
218
|
require_paths:
|
|
@@ -249,7 +228,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
249
228
|
- !ruby/object:Gem::Version
|
|
250
229
|
version: '0'
|
|
251
230
|
requirements: []
|
|
252
|
-
rubygems_version: 3.
|
|
231
|
+
rubygems_version: 3.3.7
|
|
253
232
|
signing_key:
|
|
254
233
|
specification_version: 4
|
|
255
234
|
summary: Light weight job scheduling extension for Sidekiq
|