resque-scheduler 5.0.1 → 5.1.1
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/.github/workflows/ruby.yml +16 -9
- data/CHANGELOG.md +30 -0
- data/Gemfile +0 -7
- data/README.md +32 -4
- data/lib/resque/scheduler/cli.rb +17 -1
- data/lib/resque/scheduler/configuration.rb +15 -2
- data/lib/resque/scheduler/delaying_extensions.rb +28 -14
- data/lib/resque/scheduler/env.rb +8 -0
- data/lib/resque/scheduler/plugin.rb +36 -0
- data/lib/resque/scheduler/railtie.rb +13 -0
- data/lib/resque/scheduler/server/views/search_form.erb +2 -0
- data/lib/resque/scheduler/server.rb +15 -15
- data/lib/resque/scheduler/util.rb +5 -0
- data/lib/resque/scheduler/version.rb +1 -1
- data/lib/resque/scheduler.rb +62 -55
- data/resque-scheduler.gemspec +5 -5
- metadata +35 -14
- data/.github/workflows/codeql-analysis.yml +0 -59
- data/.github/workflows/rubocop.yml +0 -27
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7a49c095f83e23c0bb20e1dffe6038c64a50376d89a0123436eae4233a74e390
|
|
4
|
+
data.tar.gz: 80bd2fb3055d7904d0d62f47f3683c5c6a6f5c4d7236d7311b29ee7c6d2f1174
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c206ceb2414921369b7fd89800f95a8e3583226d709fd6d92effbfa69c1284711081cd46189b05aee1d14fdc3161f3d8fee0d7588c4e81a0a2cff6a791c0e415
|
|
7
|
+
data.tar.gz: f99d4d481f7ec3de91bef5a3b5ead66474e0f1df72a68bb705058de727ed448cd60cae39b901fd0b3edd4d02004fb87147e08a7b265517ca2b5109e194d7fb54
|
data/.github/workflows/ruby.yml
CHANGED
|
@@ -6,9 +6,11 @@ on:
|
|
|
6
6
|
pull_request:
|
|
7
7
|
branches: [master]
|
|
8
8
|
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
9
12
|
jobs:
|
|
10
13
|
test:
|
|
11
|
-
continue-on-error: true
|
|
12
14
|
runs-on: ubuntu-latest
|
|
13
15
|
services:
|
|
14
16
|
redis:
|
|
@@ -19,20 +21,16 @@ jobs:
|
|
|
19
21
|
fail-fast: false
|
|
20
22
|
matrix:
|
|
21
23
|
ruby-version:
|
|
22
|
-
- "3.0"
|
|
23
|
-
- 3.1
|
|
24
24
|
- 3.2
|
|
25
25
|
- 3.3
|
|
26
26
|
- 3.4
|
|
27
|
+
- "4.0"
|
|
27
28
|
- head
|
|
28
29
|
resque-version:
|
|
29
30
|
- "master"
|
|
30
|
-
rufus-scheduler:
|
|
31
|
-
- "3.4"
|
|
32
|
-
- "3.5"
|
|
33
|
-
- "3.6"
|
|
34
31
|
redis-version:
|
|
35
32
|
- "4.8"
|
|
33
|
+
- "5.4"
|
|
36
34
|
- "latest"
|
|
37
35
|
rack-version:
|
|
38
36
|
- 2
|
|
@@ -40,15 +38,24 @@ jobs:
|
|
|
40
38
|
env:
|
|
41
39
|
REDIS_VERSION: "${{ matrix.redis-version }}"
|
|
42
40
|
RESQUE: "${{ matrix.resque-version }}"
|
|
43
|
-
RUFUS_SCHEDULER: "${{ matrix.rufus-scheduler }}"
|
|
44
41
|
RACK_VERSION: "${{ matrix.rack-version }}"
|
|
45
42
|
COVERAGE: 1
|
|
46
43
|
|
|
47
44
|
steps:
|
|
48
|
-
- uses: actions/checkout@
|
|
45
|
+
- uses: actions/checkout@v7
|
|
49
46
|
- uses: ruby/setup-ruby@v1
|
|
50
47
|
with:
|
|
51
48
|
ruby-version: "${{ matrix.ruby-version }}"
|
|
52
49
|
bundler-cache: true
|
|
53
50
|
- run: bundle exec rake
|
|
54
51
|
- run: bin/bundle_console_test.sh
|
|
52
|
+
|
|
53
|
+
rubocop:
|
|
54
|
+
runs-on: ubuntu-latest
|
|
55
|
+
steps:
|
|
56
|
+
- uses: actions/checkout@v7
|
|
57
|
+
- uses: ruby/setup-ruby@v1
|
|
58
|
+
with:
|
|
59
|
+
ruby-version: 3.4
|
|
60
|
+
bundler-cache: true
|
|
61
|
+
- run: bundle exec rubocop
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
**ATTN**: This project uses [semantic versioning](http://semver.org/).
|
|
4
4
|
|
|
5
|
+
## [5.1.1] - 2026-11-02
|
|
6
|
+
### Fixed
|
|
7
|
+
* Enqueue batched delayed jobs outside the Redis transaction so a conflicted batch is no longer enqueued twice and enqueue hooks can use Redis by @neuromanskie in #850
|
|
8
|
+
* Skip due delayed items when not master instead of spinning on them by @neuromanskie in #852
|
|
9
|
+
* Load the web UI after Rails initialization to avoid a circular require warning by @neuromanskie in #854
|
|
10
|
+
|
|
11
|
+
## [5.1.0] - 2026-10-28
|
|
12
|
+
### Breaking Changes
|
|
13
|
+
* Ruby requirement: `>= 3.0.0` → `>= 3.2.0` by @neuromanskie in #837
|
|
14
|
+
* rufus-scheduler dependency: `~> 3.2, != 3.3` → `~> 3.9` by @neuromanskie in #837
|
|
15
|
+
* Schedule entries (`cron`/`every`) no longer run `before_schedule`, `after_schedule` or `before_delayed_enqueue`. Move that code to `before_recurring`/`after_recurring` by @top-sigrid in #844
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
* `before_recurring` and `after_recurring` hooks for jobs enqueued from the schedule by @top-sigrid in #844
|
|
19
|
+
* `DISABLE_DELAYED_REQUEUE_BATCHES` to opt out of batched delayed job enqueues by @onyxraven in #796
|
|
20
|
+
* Search delayed jobs by args in the web UI by @bmo in #839 (originally #714)
|
|
21
|
+
* Allow a number of seconds for `every` by @carsonreinke in #838 (originally #607)
|
|
22
|
+
* Railtie to load resque-scheduler automatically in Rails apps by @josh-m-sharpe in #694
|
|
23
|
+
* Add Ruby 4.0 and redis-rb 5.4 to the CI matrix by @neuromanskie in #837
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
* Upgrade RuboCop to 1.91 and run it as a CI job by @neuromanskie in #837
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
* Delayed jobs no longer run `before_schedule`/`after_schedule` a second time when they become due by @top-sigrid in #844
|
|
30
|
+
* Skip schedule hooks when `enqueue_at` is given a timestamp that is not in the future by @top-sigrid in #817
|
|
31
|
+
* Schedule Active Job classes through `perform_later` by @neuromanskie and @josh-m-sharpe in #842 (originally #696)
|
|
32
|
+
* Schedule delayed test jobs far enough out to not race the clock by @neuromanskie in #843
|
|
33
|
+
* Fail CI when tests fail by @neuromanskie in #837
|
|
34
|
+
|
|
5
35
|
## [5.0.1] - 2026-10-11
|
|
6
36
|
### Changed
|
|
7
37
|
* Pipeline `count_all_scheduled_jobs` for significantly faster execution by @top-sigrid in #822
|
data/Gemfile
CHANGED
|
@@ -8,13 +8,6 @@ else
|
|
|
8
8
|
gem 'resque', resque_version
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
case rufus_scheduler_version = ENV.fetch('RUFUS_SCHEDULER', '3.6')
|
|
12
|
-
when 'master'
|
|
13
|
-
gem 'rufus-scheduler', git: 'https://github.com/jmettraux/rufus-scheduler'
|
|
14
|
-
else
|
|
15
|
-
gem 'rufus-scheduler', rufus_scheduler_version
|
|
16
|
-
end
|
|
17
|
-
|
|
18
11
|
case redis_version = ENV.fetch('REDIS_VERSION', 'latest')
|
|
19
12
|
when 'master'
|
|
20
13
|
gem 'redis', git: 'https://github.com/redis/redis-rb'
|
data/README.md
CHANGED
|
@@ -48,6 +48,9 @@ Adding the resque:scheduler rake task:
|
|
|
48
48
|
require 'resque/scheduler/tasks'
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
+
In a Rails app, you can skip this step. A Railtie loads the
|
|
52
|
+
`resque:scheduler` rake task and the Resque web UI tabs automatically.
|
|
53
|
+
|
|
51
54
|
### Rake integration
|
|
52
55
|
|
|
53
56
|
By default, `resque-scheduler` depends on the "resque:setup" rake task.
|
|
@@ -131,6 +134,8 @@ environment variables:
|
|
|
131
134
|
* `APP_NAME` - Application name used in procline (`$0`) (default empty)
|
|
132
135
|
* `BACKGROUND` - [Run in the background](#running-in-the-background) if
|
|
133
136
|
non-empty (via `Process.daemon`, if supported) (default `false`)
|
|
137
|
+
* `DELAYED_REQUEUE_BATCH_SIZE` - Set the delayed job batch size if enabled (default `100`). If `<= 1`, this disables batching.
|
|
138
|
+
* `DISABLE_DELAYED_REQUEUE_BATCHES` - Disable batched delayed job queuing (default `false`)
|
|
134
139
|
* `DYNAMIC_SCHEDULE` - Enables [dynamic scheduling](#dynamic-schedules)
|
|
135
140
|
if non-empty (default `false`)
|
|
136
141
|
* `RAILS_ENV` - Environment to use in procline (`$0`) (default empty)
|
|
@@ -199,6 +204,19 @@ Resque.enqueue_at_with_queue(
|
|
|
199
204
|
)
|
|
200
205
|
```
|
|
201
206
|
|
|
207
|
+
#### Active Job
|
|
208
|
+
|
|
209
|
+
`ActiveJob::Base` subclasses can be passed to `enqueue_at`, `enqueue_in` and
|
|
210
|
+
their `_with_queue` variants, and used as the `class` of a scheduled job. They
|
|
211
|
+
are handed to `perform_later` (with `set(wait_until:)` for delayed jobs), so
|
|
212
|
+
Active Job must be using the `:resque` adapter. The job's `queue_as` applies
|
|
213
|
+
unless a queue is given.
|
|
214
|
+
|
|
215
|
+
Since the stored class is the adapter's `JobWrapper`, `delayed?`,
|
|
216
|
+
`remove_delayed` and `find_delayed_selection` won't match Active Job classes,
|
|
217
|
+
and [hooks](#hooks) defined on them aren't called. Use Active Job's callbacks
|
|
218
|
+
instead.
|
|
219
|
+
|
|
202
220
|
The delayed queue is stored in redis and is persisted in the same way the
|
|
203
221
|
standard resque jobs are persisted (redis writing to disk). Delayed jobs differ
|
|
204
222
|
from scheduled jobs in that if your scheduler process is down or workers are
|
|
@@ -457,6 +475,8 @@ config[:persist] = true
|
|
|
457
475
|
Resque.set_schedule(name, config)
|
|
458
476
|
```
|
|
459
477
|
|
|
478
|
+
`every` also accepts a number of seconds, so `config[:every] = 1.hour` works too.
|
|
479
|
+
|
|
460
480
|
Schedules can later be removed by passing their name to the `remove_schedule` method:
|
|
461
481
|
|
|
462
482
|
```ruby
|
|
@@ -506,13 +526,18 @@ Similar to the `before_enqueue`- and `after_enqueue`-hooks provided in Resque
|
|
|
506
526
|
the delayed queue. If the hook returns `false`, the job will not be placed on
|
|
507
527
|
the queue.
|
|
508
528
|
* `after_schedule`: Called with the job args after a job is placed on the
|
|
509
|
-
delayed queue. Any exception raised propagates up to the code
|
|
529
|
+
delayed queue. Any exception raised propagates up to the code that queued the
|
|
510
530
|
job.
|
|
511
531
|
* `before_delayed_enqueue`: Called with the job args after the job has been
|
|
512
|
-
removed from the delayed queue, but not yet put on
|
|
532
|
+
removed from the delayed queue, but not yet put on its work queue. It is
|
|
513
533
|
called before `before_enqueue`-hooks, and on the same job instance as the
|
|
514
534
|
`before_enqueue`-hooks will be invoked on. Return values are ignored.
|
|
515
|
-
* `
|
|
535
|
+
* `before_recurring`: Called with the job args before a job from the schedule
|
|
536
|
+
(`cron`, `every` or "Queue now" in resque-web) is put on its work queue. If
|
|
537
|
+
the hook returns `false`, the job will not be enqueued.
|
|
538
|
+
* `after_recurring`: Called with the job args after a job from the schedule has
|
|
539
|
+
been put on its work queue, after the `after_enqueue`-hooks.
|
|
540
|
+
* `on_enqueue_failure`: Called with the job config and the exception that was raised
|
|
516
541
|
while enqueueing a job to resque or external application fails. Return
|
|
517
542
|
values are ignored. For example:
|
|
518
543
|
|
|
@@ -610,6 +635,9 @@ The Delayed tab:
|
|
|
610
635
|
|
|
611
636
|

|
|
612
637
|
|
|
638
|
+
The Delayed tab's search matches job class names, or job arguments when
|
|
639
|
+
"Search Args?" is checked.
|
|
640
|
+
|
|
613
641
|
#### How do I get the schedule tabs to show up???
|
|
614
642
|
|
|
615
643
|
To get these to show up you need to pass a file to `resque-web` to tell it to
|
|
@@ -752,10 +780,10 @@ This table explains the version requirements for rufus-scheduler
|
|
|
752
780
|
|
|
753
781
|
| resque-scheduler | rufus-scheduler |
|
|
754
782
|
|:-----------------|----------------:|
|
|
783
|
+
| `>= 5.1` | `~> 3.9` |
|
|
755
784
|
| `~> 4.0` | `~> 3.0` |
|
|
756
785
|
| `< 4.0` | `~> 2.0` |
|
|
757
786
|
|
|
758
|
-
|
|
759
787
|
### Contributing
|
|
760
788
|
|
|
761
789
|
See [CONTRIBUTING.md](CONTRIBUTING.md)
|
data/lib/resque/scheduler/cli.rb
CHANGED
|
@@ -16,7 +16,9 @@ module Resque
|
|
|
16
16
|
pidfile: 'PIDFILE',
|
|
17
17
|
poll_sleep_amount: 'RESQUE_SCHEDULER_INTERVAL',
|
|
18
18
|
verbose: 'VERBOSE',
|
|
19
|
-
lock_timeout: 'LOCK_TIMEOUT'
|
|
19
|
+
lock_timeout: 'LOCK_TIMEOUT',
|
|
20
|
+
delayed_requeue_batch_size: 'DELAYED_REQUEUE_BATCH_SIZE',
|
|
21
|
+
disable_delayed_requeue_batches: 'DISABLE_DELAYED_REQUEUE_BATCHES'
|
|
20
22
|
}.freeze
|
|
21
23
|
|
|
22
24
|
class Cli
|
|
@@ -74,6 +76,20 @@ module Resque
|
|
|
74
76
|
{
|
|
75
77
|
args: ['-v', '--verbose', 'Run with verbose output [VERBOSE]'],
|
|
76
78
|
callback: ->(options) { ->(v) { options[:verbose] = v } }
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
args: [
|
|
82
|
+
'--delayed-requeue-batch-size [DELAYED_REQUEUE_BATCH_SIZE]',
|
|
83
|
+
'Delayed requeue batch size'
|
|
84
|
+
],
|
|
85
|
+
callback: ->(options) { ->(d) { options[:delayed_requeue_batch_size] = d } }
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
args: [
|
|
89
|
+
'--disable-delayed-requeue-batches',
|
|
90
|
+
'Disable delayed requeue batches [DISABLE_DELAYED_REQUEUE_BATCHES]'
|
|
91
|
+
],
|
|
92
|
+
callback: ->(options) { ->(d) { options[:disable_delayed_requeue_batches] = d } }
|
|
77
93
|
}
|
|
78
94
|
].freeze
|
|
79
95
|
|
|
@@ -65,10 +65,23 @@ module Resque
|
|
|
65
65
|
@app_name ||= environment['APP_NAME']
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
+
# Batch size for requeueing delayed jobs. If <= 1, this disables batching.
|
|
69
|
+
# Defaults to 100.
|
|
70
|
+
attr_writer :delayed_requeue_batch_size
|
|
71
|
+
|
|
68
72
|
def delayed_requeue_batch_size
|
|
69
73
|
@delayed_requeue_batch_size ||= \
|
|
70
|
-
|
|
71
|
-
|
|
74
|
+
Integer(environment.fetch('DELAYED_REQUEUE_BATCH_SIZE', '100'))
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
attr_writer :disable_delayed_requeue_batches
|
|
78
|
+
|
|
79
|
+
def disable_delayed_requeue_batches
|
|
80
|
+
if @disable_delayed_requeue_batches.nil?
|
|
81
|
+
to_bool(environment['DISABLE_DELAYED_REQUEUE_BATCHES'])
|
|
82
|
+
else
|
|
83
|
+
@disable_delayed_requeue_batches
|
|
84
|
+
end
|
|
72
85
|
end
|
|
73
86
|
|
|
74
87
|
# Amount of time in seconds to sleep between polls of the delayed
|
|
@@ -10,6 +10,10 @@ module Resque
|
|
|
10
10
|
# for queueing. Until timestamp is in the past, the job will
|
|
11
11
|
# sit in the schedule list.
|
|
12
12
|
def enqueue_at(timestamp, klass, *args)
|
|
13
|
+
if Resque::Scheduler::Util.active_job_class?(klass)
|
|
14
|
+
return enqueue_at_with_queue(nil, timestamp, klass, *args)
|
|
15
|
+
end
|
|
16
|
+
|
|
13
17
|
validate(klass)
|
|
14
18
|
enqueue_at_with_queue(
|
|
15
19
|
queue_from_class(klass), timestamp, klass, *args
|
|
@@ -21,19 +25,29 @@ module Resque
|
|
|
21
25
|
# timestamp has passed. It respects Resque.inline option, by
|
|
22
26
|
# creating the job right away instead of adding to the queue.
|
|
23
27
|
def enqueue_at_with_queue(queue, timestamp, klass, *args)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
28
|
+
if Resque::Scheduler::Util.active_job_class?(klass)
|
|
29
|
+
return klass.set(**{ wait_until: timestamp, queue: queue }.compact)
|
|
30
|
+
.perform_later(*args)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
if Resque.inline? || timestamp.to_i <= Time.now.to_i
|
|
34
|
+
# Just create the job and let resque perform it right away with
|
|
35
|
+
# inline. If the class is a custom job class, call self#scheduled
|
|
36
|
+
# on it. This allows you to do things like
|
|
37
|
+
# Resque.enqueue_at(timestamp, CustomJobClass, :opt1 => val1).
|
|
38
|
+
# Otherwise, pass off to Resque.
|
|
39
|
+
#
|
|
40
|
+
# Note: schedule hooks are NOT called here because the job is not
|
|
41
|
+
# actually being added to the delayed queue.
|
|
42
|
+
if klass.respond_to?(:scheduled)
|
|
43
|
+
klass.scheduled(queue, klass.to_s, *args)
|
|
36
44
|
else
|
|
45
|
+
Resque.enqueue_to(queue, klass, *args)
|
|
46
|
+
end
|
|
47
|
+
else
|
|
48
|
+
# Job is being added to the delayed queue, so we call the
|
|
49
|
+
# before_schedule and after_schedule hooks.
|
|
50
|
+
plugin.process_schedule_hooks(klass, *args) do
|
|
37
51
|
delayed_push(timestamp, job_to_hash_with_queue(queue, klass, args))
|
|
38
52
|
end
|
|
39
53
|
end
|
|
@@ -173,14 +187,14 @@ module Resque
|
|
|
173
187
|
def enqueue_delayed(klass, *args)
|
|
174
188
|
hash = job_to_hash(klass, args)
|
|
175
189
|
remove_delayed(klass, *args).times do
|
|
176
|
-
Resque::Scheduler.enqueue_from_config(hash)
|
|
190
|
+
Resque::Scheduler.enqueue_from_config(hash, :delayed)
|
|
177
191
|
end
|
|
178
192
|
end
|
|
179
193
|
|
|
180
194
|
def enqueue_delayed_with_queue(klass, queue, *args)
|
|
181
195
|
hash = job_to_hash_with_queue(queue, klass, args)
|
|
182
196
|
remove_delayed_in_queue(klass, queue, *args).times do
|
|
183
|
-
Resque::Scheduler.enqueue_from_config(hash)
|
|
197
|
+
Resque::Scheduler.enqueue_from_config(hash, :delayed)
|
|
184
198
|
end
|
|
185
199
|
end
|
|
186
200
|
|
data/lib/resque/scheduler/env.rb
CHANGED
|
@@ -74,6 +74,14 @@ module Resque
|
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
c.verbose = !!options[:verbose] if options.key?(:verbose)
|
|
77
|
+
|
|
78
|
+
if options.key?(:delayed_requeue_batch_size)
|
|
79
|
+
c.delayed_requeue_batch_size = Integer(options[:delayed_requeue_batch_size])
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
if options.key?(:disable_delayed_requeue_batches)
|
|
83
|
+
c.disable_delayed_requeue_batches = !!options[:disable_delayed_requeue_batches]
|
|
84
|
+
end
|
|
77
85
|
end
|
|
78
86
|
end
|
|
79
87
|
# rubocop:enable Metrics/AbcSize
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
module Resque
|
|
4
4
|
module Scheduler
|
|
5
5
|
module Plugin
|
|
6
|
+
ENQUEUE_HOOKS = %i[delayed recurring].freeze
|
|
7
|
+
|
|
6
8
|
def self.process_schedule_hooks(klass, *args)
|
|
7
9
|
# the documentation states that if any before_schedule hook returns
|
|
8
10
|
# false, the process should not be enqueued
|
|
@@ -12,6 +14,32 @@ module Resque
|
|
|
12
14
|
run_after_schedule_hooks(klass, *args)
|
|
13
15
|
end
|
|
14
16
|
|
|
17
|
+
def self.process_recurring_hooks(klass, *args)
|
|
18
|
+
return unless run_before_recurring_hooks(klass, *args)
|
|
19
|
+
|
|
20
|
+
enqueued = yield
|
|
21
|
+
run_after_recurring_hooks(klass, *args) if enqueued
|
|
22
|
+
enqueued
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.validate_enqueue_hooks(hooks)
|
|
26
|
+
return if hooks.nil? || ENQUEUE_HOOKS.include?(hooks)
|
|
27
|
+
|
|
28
|
+
raise ArgumentError, "unknown hooks: #{hooks.inspect}"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.process_enqueue_hooks(hooks, klass, *args, &block)
|
|
32
|
+
case hooks
|
|
33
|
+
when :delayed
|
|
34
|
+
run_before_delayed_enqueue_hooks(klass, *args)
|
|
35
|
+
yield
|
|
36
|
+
when :recurring
|
|
37
|
+
process_recurring_hooks(klass, *args, &block)
|
|
38
|
+
else
|
|
39
|
+
yield
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
15
43
|
def self.hooks(job, pattern)
|
|
16
44
|
job.methods.grep(/^#{pattern}/).sort
|
|
17
45
|
end
|
|
@@ -35,6 +63,14 @@ module Resque
|
|
|
35
63
|
def self.run_after_schedule_hooks(klass, *args)
|
|
36
64
|
run_hooks(klass, 'after_schedule', *args)
|
|
37
65
|
end
|
|
66
|
+
|
|
67
|
+
def self.run_before_recurring_hooks(klass, *args)
|
|
68
|
+
run_hooks(klass, 'before_recurring', *args)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def self.run_after_recurring_hooks(klass, *args)
|
|
72
|
+
run_hooks(klass, 'after_recurring', *args)
|
|
73
|
+
end
|
|
38
74
|
end
|
|
39
75
|
end
|
|
40
76
|
end
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<form method="POST" action="<%= u 'delayed/search' %>">
|
|
2
|
+
<input type='checkbox' id='search_args' name='search_args' value="checked" <%= 'checked' if params[:search_args] == 'checked' %>/>
|
|
3
|
+
<label for="search_args"> Search Args?</label><br>
|
|
2
4
|
<input type='input' name='search' value="<%= h params[:search] %>"/>
|
|
3
5
|
<input type='submit' value='Search'/>
|
|
4
6
|
</form>
|
|
@@ -48,7 +48,7 @@ module Resque
|
|
|
48
48
|
if @parameters
|
|
49
49
|
erb scheduler_template('requeue-params')
|
|
50
50
|
else
|
|
51
|
-
Resque::Scheduler.enqueue_from_config(config)
|
|
51
|
+
Resque::Scheduler.enqueue_from_config(config, :recurring)
|
|
52
52
|
redirect u('/overview')
|
|
53
53
|
end
|
|
54
54
|
end
|
|
@@ -68,7 +68,7 @@ module Resque
|
|
|
68
68
|
|
|
69
69
|
# Insert the args hash into config and queue the resque job
|
|
70
70
|
config = config.merge('args' => config_args)
|
|
71
|
-
Resque::Scheduler.enqueue_from_config(config)
|
|
71
|
+
Resque::Scheduler.enqueue_from_config(config, :recurring)
|
|
72
72
|
redirect u('/overview')
|
|
73
73
|
end
|
|
74
74
|
|
|
@@ -99,7 +99,8 @@ module Resque
|
|
|
99
99
|
end
|
|
100
100
|
|
|
101
101
|
def delayed_search
|
|
102
|
-
|
|
102
|
+
field = params[:search_args] == 'checked' ? 'args' : 'class'
|
|
103
|
+
@jobs = find_job(params[:search], field)
|
|
103
104
|
erb scheduler_template('search')
|
|
104
105
|
end
|
|
105
106
|
|
|
@@ -153,21 +154,21 @@ module Resque
|
|
|
153
154
|
)
|
|
154
155
|
end
|
|
155
156
|
|
|
156
|
-
def find_job(
|
|
157
|
-
|
|
158
|
-
|
|
157
|
+
def find_job(term, field = 'class')
|
|
158
|
+
term = term.downcase
|
|
159
|
+
matches = ->(job) { job[field].to_s.downcase.include?(term) }
|
|
160
|
+
results = working_jobs_matching(matches)
|
|
159
161
|
|
|
160
|
-
dels = delayed_jobs_for_worker(
|
|
162
|
+
dels = delayed_jobs_for_worker(term)
|
|
161
163
|
results += dels.select do |j|
|
|
162
|
-
|
|
163
|
-
j.merge!('where_at' => 'delayed')
|
|
164
|
+
matches.call(j) && j.merge!('where_at' => 'delayed')
|
|
164
165
|
end
|
|
165
166
|
|
|
166
167
|
Resque.queues.each do |queue|
|
|
167
168
|
queued = Resque.peek(queue, 0, Resque.size(queue))
|
|
168
169
|
queued = [queued] unless queued.is_a?(Array)
|
|
169
170
|
results += queued.select do |j|
|
|
170
|
-
|
|
171
|
+
matches.call(j) &&
|
|
171
172
|
j.merge!('queue' => queue, 'where_at' => 'queued')
|
|
172
173
|
end
|
|
173
174
|
end
|
|
@@ -187,13 +188,13 @@ module Resque
|
|
|
187
188
|
|
|
188
189
|
def schedule_interval_every(every)
|
|
189
190
|
every = [*every]
|
|
190
|
-
s = 'every: ' << every.first
|
|
191
|
+
s = 'every: ' << "#{every.first}#{'s' if every.first.is_a?(Numeric)}"
|
|
191
192
|
|
|
192
193
|
return s unless every.length > 1
|
|
193
194
|
|
|
194
195
|
s << ' ('
|
|
195
196
|
meta = every.last.map do |key, value|
|
|
196
|
-
"#{key.to_s.tr('_', ' ')} #{value}"
|
|
197
|
+
"#{key.to_s.tr('_', ' ')} #{value}#{'s' if value.is_a?(Numeric)}"
|
|
197
198
|
end
|
|
198
199
|
s << meta.join(', ') << ')'
|
|
199
200
|
end
|
|
@@ -228,12 +229,11 @@ module Resque
|
|
|
228
229
|
|
|
229
230
|
private
|
|
230
231
|
|
|
231
|
-
def
|
|
232
|
+
def working_jobs_matching(matches)
|
|
232
233
|
[].tap do |results|
|
|
233
234
|
working = [*Resque.working]
|
|
234
235
|
work = working.select do |w|
|
|
235
|
-
w.job && w.job['payload'] &&
|
|
236
|
-
w.job['payload']['class'].downcase.include?(worker)
|
|
236
|
+
w.job && w.job['payload'] && matches.call(w.job['payload'])
|
|
237
237
|
end
|
|
238
238
|
work.each do |w|
|
|
239
239
|
results += [
|
|
@@ -34,6 +34,11 @@ module Resque
|
|
|
34
34
|
def self.classify(dashed_word)
|
|
35
35
|
dashed_word.split('-').map(&:capitalize).join
|
|
36
36
|
end
|
|
37
|
+
|
|
38
|
+
def self.active_job_class?(klass)
|
|
39
|
+
defined?(::ActiveJob::Base) && klass.is_a?(Class) &&
|
|
40
|
+
klass < ::ActiveJob::Base
|
|
41
|
+
end
|
|
37
42
|
end
|
|
38
43
|
end
|
|
39
44
|
end
|
data/lib/resque/scheduler.rb
CHANGED
|
@@ -8,6 +8,8 @@ require_relative 'scheduler/logger_builder'
|
|
|
8
8
|
require_relative 'scheduler/signal_handling'
|
|
9
9
|
require_relative 'scheduler/failure_handler'
|
|
10
10
|
|
|
11
|
+
require 'resque/scheduler/railtie' if defined?(Rails::Railtie)
|
|
12
|
+
|
|
11
13
|
module Resque
|
|
12
14
|
module Scheduler
|
|
13
15
|
autoload :Cli, 'resque/scheduler/cli'
|
|
@@ -151,7 +153,7 @@ module Resque
|
|
|
151
153
|
interval_defined = false
|
|
152
154
|
interval_types = %w(cron every)
|
|
153
155
|
interval_types.each do |interval_type|
|
|
154
|
-
next unless !config[interval_type].nil? && !config[interval_type].empty?
|
|
156
|
+
next unless !config[interval_type].nil? && !config[interval_type].to_s.empty?
|
|
155
157
|
args = optionizate_interval_value(config[interval_type])
|
|
156
158
|
args = [args, nil, job: true] if args.is_a?(::String)
|
|
157
159
|
|
|
@@ -196,7 +198,7 @@ module Resque
|
|
|
196
198
|
# at_time - Time to start scheduling items (default: now).
|
|
197
199
|
def handle_delayed_items(at_time = nil)
|
|
198
200
|
timestamp = Resque.next_delayed_timestamp(at_time)
|
|
199
|
-
if timestamp
|
|
201
|
+
if timestamp && am_master
|
|
200
202
|
procline 'Processing Delayed Items'
|
|
201
203
|
until timestamp.nil?
|
|
202
204
|
enqueue_delayed_items_for_timestamp(timestamp)
|
|
@@ -210,40 +212,48 @@ module Resque
|
|
|
210
212
|
|
|
211
213
|
if item
|
|
212
214
|
log "queuing #{item['class']} [delayed]"
|
|
213
|
-
enqueue(item)
|
|
215
|
+
enqueue(item, :delayed)
|
|
214
216
|
end
|
|
215
217
|
|
|
216
218
|
item
|
|
217
219
|
end
|
|
218
220
|
|
|
221
|
+
def batch_delayed_items?
|
|
222
|
+
!disable_delayed_requeue_batches && delayed_requeue_batch_size > 1
|
|
223
|
+
end
|
|
224
|
+
|
|
219
225
|
# Enqueues all delayed jobs for a timestamp
|
|
220
226
|
def enqueue_delayed_items_for_timestamp(timestamp)
|
|
221
227
|
count = 0
|
|
222
|
-
batch_size = delayed_requeue_batch_size
|
|
223
|
-
actual_batch_size = nil
|
|
228
|
+
batch_size = batch_delayed_items? ? delayed_requeue_batch_size : 1
|
|
224
229
|
|
|
225
|
-
|
|
230
|
+
message = "Processing delayed items for timestamp #{timestamp}"
|
|
231
|
+
message += ", in batches of #{batch_size}" if batch_delayed_items?
|
|
232
|
+
log message
|
|
226
233
|
|
|
227
234
|
loop do
|
|
235
|
+
actual_batch_size = 0
|
|
236
|
+
|
|
228
237
|
handle_shutdown do
|
|
229
|
-
# Continually check that it is still the master
|
|
230
238
|
if am_master
|
|
231
|
-
|
|
232
|
-
|
|
239
|
+
if batch_delayed_items?
|
|
240
|
+
actual_batch_size = enqueue_items_in_batch_for_timestamp(timestamp, batch_size)
|
|
241
|
+
log "queued batch of #{actual_batch_size} jobs"
|
|
242
|
+
else
|
|
243
|
+
item = enqueue_next_item(timestamp)
|
|
244
|
+
actual_batch_size = item.nil? ? 0 : 1
|
|
245
|
+
end
|
|
233
246
|
end
|
|
234
247
|
end
|
|
235
248
|
|
|
236
249
|
count += actual_batch_size
|
|
237
|
-
log "queued #{count} jobs" if actual_batch_size != -1
|
|
238
250
|
|
|
239
251
|
# continue processing until there are no more items in this
|
|
240
252
|
# timestamp. If we don't have a full batch, this is the last one.
|
|
241
|
-
# This also breaks us in the event of a redis transaction failure
|
|
242
|
-
# i.e. enqueue_items_in_batch_for_timestamp returned -1
|
|
243
253
|
break if actual_batch_size < batch_size
|
|
244
254
|
end
|
|
245
255
|
|
|
246
|
-
log "finished queueing #{count} total jobs for timestamp #{timestamp}" if count
|
|
256
|
+
log "finished queueing #{count} total jobs for timestamp #{timestamp}" if count > 0
|
|
247
257
|
end
|
|
248
258
|
|
|
249
259
|
def timestamp_key(timestamp)
|
|
@@ -253,49 +263,40 @@ module Resque
|
|
|
253
263
|
def enqueue_items_in_batch_for_timestamp(timestamp, batch_size)
|
|
254
264
|
timestamp_bucket_key = timestamp_key(timestamp)
|
|
255
265
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
# Watch is used to ensure that the timestamp bucket we are operating on
|
|
259
|
-
# is not altered by any other clients between the watch call and when we call exec
|
|
260
|
-
# (to execute the multi block). We should error catch on the redis.exec return value
|
|
261
|
-
# as that will indicate if the entire transaction was aborted or not. Though we should
|
|
262
|
-
# be safe as our ltrim is inside the multi block and therefore also would have been
|
|
263
|
-
# aborted. So nothing would have been queued, but also nothing lost from the bucket.
|
|
264
|
-
watch_result = Resque.redis.watch(timestamp_bucket_key) do
|
|
265
|
-
Resque.redis.multi do |pipeline|
|
|
266
|
-
encoded_jobs_to_requeue.each do |encoded_job|
|
|
267
|
-
pipeline.srem("timestamps:#{encoded_job}", timestamp_bucket_key)
|
|
268
|
-
|
|
269
|
-
decoded_job = Resque.decode(encoded_job)
|
|
270
|
-
enqueue(decoded_job)
|
|
271
|
-
end
|
|
266
|
+
return 0 unless (encoded_jobs = take_delayed_batch(timestamp_bucket_key, batch_size))
|
|
272
267
|
|
|
273
|
-
|
|
274
|
-
|
|
268
|
+
encoded_jobs.each do |encoded_job|
|
|
269
|
+
enqueue(Resque.decode(encoded_job), :delayed)
|
|
275
270
|
end
|
|
276
271
|
|
|
277
|
-
|
|
278
|
-
success = !watch_result.nil?
|
|
279
|
-
|
|
280
|
-
# If this was the last batch in this timestamp bucket, clean up
|
|
281
|
-
if success && encoded_jobs_to_requeue.count < batch_size
|
|
272
|
+
if encoded_jobs.count < batch_size
|
|
282
273
|
Resque.clean_up_timestamp(timestamp_bucket_key, timestamp)
|
|
283
274
|
end
|
|
284
275
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
276
|
+
encoded_jobs.count
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# Returns nil if the timestamp bucket changed before the batch was taken.
|
|
280
|
+
def take_delayed_batch(timestamp_bucket_key, batch_size)
|
|
281
|
+
Resque.redis.watch(timestamp_bucket_key) do
|
|
282
|
+
encoded_jobs = Resque.redis.lrange(timestamp_bucket_key, 0, batch_size - 1)
|
|
283
|
+
taken = Resque.redis.multi do |transaction|
|
|
284
|
+
encoded_jobs.each do |encoded_job|
|
|
285
|
+
transaction.srem("timestamps:#{encoded_job}", [timestamp_bucket_key])
|
|
286
|
+
end
|
|
287
|
+
transaction.ltrim(timestamp_bucket_key, batch_size, -1)
|
|
288
|
+
end
|
|
292
289
|
|
|
293
|
-
|
|
294
|
-
|
|
290
|
+
encoded_jobs if taken
|
|
291
|
+
end
|
|
295
292
|
end
|
|
296
293
|
|
|
297
|
-
|
|
298
|
-
|
|
294
|
+
# Enqueues a job like enqueue_from_config, but hands errors to the failure
|
|
295
|
+
# handler instead of raising them. Pass :delayed as hooks for a job that
|
|
296
|
+
# left the delayed queue or :recurring for a schedule entry to run the
|
|
297
|
+
# matching hooks.
|
|
298
|
+
def enqueue(config, hooks = nil)
|
|
299
|
+
enqueue_from_config(config, hooks)
|
|
299
300
|
rescue => e
|
|
300
301
|
Resque::Scheduler.failure_handler.on_enqueue_failure(config, e)
|
|
301
302
|
end
|
|
@@ -306,8 +307,11 @@ module Resque
|
|
|
306
307
|
exit if @shutdown
|
|
307
308
|
end
|
|
308
309
|
|
|
309
|
-
# Enqueues a job based on a config hash
|
|
310
|
-
|
|
310
|
+
# Enqueues a job based on a config hash. Pass :delayed as hooks for a job
|
|
311
|
+
# that left the delayed queue or :recurring for a schedule entry to run
|
|
312
|
+
# the matching hooks.
|
|
313
|
+
def enqueue_from_config(job_config, hooks = nil)
|
|
314
|
+
Resque::Scheduler::Plugin.validate_enqueue_hooks(hooks)
|
|
311
315
|
args = job_config['args'] || job_config[:args]
|
|
312
316
|
|
|
313
317
|
klass_name = job_config['class'] || job_config[:class]
|
|
@@ -318,9 +322,13 @@ module Resque
|
|
|
318
322
|
end
|
|
319
323
|
|
|
320
324
|
params = args.is_a?(Hash) ? [args] : Array(args)
|
|
321
|
-
queue = job_config['queue'] ||
|
|
322
|
-
|
|
323
|
-
|
|
325
|
+
queue = job_config['queue'] || job_config[:queue]
|
|
326
|
+
|
|
327
|
+
if Resque::Scheduler::Util.active_job_class?(klass)
|
|
328
|
+
return klass.set(**{ queue: queue }.compact).perform_later(*params)
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
queue ||= Resque.queue_from_class(klass)
|
|
324
332
|
# Support custom job classes like those that inherit from
|
|
325
333
|
# Resque::JobWithStatus (resque-status)
|
|
326
334
|
job_klass = job_config['custom_job_class']
|
|
@@ -343,8 +351,7 @@ module Resque
|
|
|
343
351
|
# for non-existent classes (for example: running scheduler in
|
|
344
352
|
# one app that schedules for another.
|
|
345
353
|
if Class === klass
|
|
346
|
-
Resque::Scheduler::Plugin.
|
|
347
|
-
Resque::Scheduler::Plugin.run_before_delayed_enqueue_hooks(klass, *params)
|
|
354
|
+
Resque::Scheduler::Plugin.process_enqueue_hooks(hooks, klass, *params) do
|
|
348
355
|
# If the class is a custom job class, call self#scheduled on it.
|
|
349
356
|
# This allows you to do things like Resque.enqueue_at(timestamp,
|
|
350
357
|
# CustomJobClass). Otherwise, pass off to Resque.
|
|
@@ -504,7 +511,7 @@ module Resque
|
|
|
504
511
|
def enqueue_recurring(name, config)
|
|
505
512
|
if am_master
|
|
506
513
|
log! "queueing #{config['class']} (#{name})"
|
|
507
|
-
enqueue(config)
|
|
514
|
+
enqueue(config, :recurring)
|
|
508
515
|
Resque.last_enqueued_at(name, Time.now.to_s)
|
|
509
516
|
end
|
|
510
517
|
end
|
data/resque-scheduler.gemspec
CHANGED
|
@@ -32,7 +32,7 @@ Gem::Specification.new do |spec|
|
|
|
32
32
|
spec.license = 'MIT'
|
|
33
33
|
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
34
34
|
|
|
35
|
-
spec.required_ruby_version = '>= 3.
|
|
35
|
+
spec.required_ruby_version = '>= 3.2.0'
|
|
36
36
|
|
|
37
37
|
spec.files = `git ls-files -z`.split("\0").reject do |f|
|
|
38
38
|
f.match(%r{^(test|spec|features|examples|bin|tasks)/}) ||
|
|
@@ -43,6 +43,7 @@ Gem::Specification.new do |spec|
|
|
|
43
43
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
44
44
|
spec.require_paths = %w(lib)
|
|
45
45
|
|
|
46
|
+
spec.add_development_dependency 'activejob'
|
|
46
47
|
spec.add_development_dependency 'bundler'
|
|
47
48
|
spec.add_development_dependency 'json'
|
|
48
49
|
spec.add_development_dependency 'irb'
|
|
@@ -51,6 +52,7 @@ Gem::Specification.new do |spec|
|
|
|
51
52
|
spec.add_development_dependency 'ostruct'
|
|
52
53
|
spec.add_development_dependency 'pry'
|
|
53
54
|
spec.add_development_dependency 'rack-test'
|
|
55
|
+
spec.add_development_dependency 'railties'
|
|
54
56
|
spec.add_development_dependency 'rake'
|
|
55
57
|
spec.add_development_dependency 'simplecov'
|
|
56
58
|
spec.add_development_dependency 'test-unit'
|
|
@@ -59,14 +61,12 @@ Gem::Specification.new do |spec|
|
|
|
59
61
|
|
|
60
62
|
# We pin rubocop because new cops have a tendency to result in false-y
|
|
61
63
|
# positives for new contributors, which is not a nice experience.
|
|
62
|
-
spec.add_development_dependency 'rubocop', '~>
|
|
64
|
+
spec.add_development_dependency 'rubocop', '~> 1.91'
|
|
63
65
|
|
|
64
66
|
spec.add_runtime_dependency 'base64', '~> 0.1'
|
|
65
67
|
spec.add_runtime_dependency 'logger'
|
|
66
68
|
spec.add_runtime_dependency 'mono_logger', '~> 1.0'
|
|
67
69
|
spec.add_runtime_dependency 'redis', '>= 4.0'
|
|
68
70
|
spec.add_runtime_dependency 'resque', '>= 3.0'
|
|
69
|
-
|
|
70
|
-
# rufus-scheduler v3.3 is missing a to_local method which fails tests
|
|
71
|
-
spec.add_runtime_dependency 'rufus-scheduler', '~> 3.2', '!= 3.3'
|
|
71
|
+
spec.add_runtime_dependency 'rufus-scheduler', '~> 3.9'
|
|
72
72
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: resque-scheduler
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.
|
|
4
|
+
version: 5.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ben VandenBos
|
|
@@ -14,6 +14,20 @@ bindir: exe
|
|
|
14
14
|
cert_chain: []
|
|
15
15
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
16
16
|
dependencies:
|
|
17
|
+
- !ruby/object:Gem::Dependency
|
|
18
|
+
name: activejob
|
|
19
|
+
requirement: !ruby/object:Gem::Requirement
|
|
20
|
+
requirements:
|
|
21
|
+
- - ">="
|
|
22
|
+
- !ruby/object:Gem::Version
|
|
23
|
+
version: '0'
|
|
24
|
+
type: :development
|
|
25
|
+
prerelease: false
|
|
26
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
27
|
+
requirements:
|
|
28
|
+
- - ">="
|
|
29
|
+
- !ruby/object:Gem::Version
|
|
30
|
+
version: '0'
|
|
17
31
|
- !ruby/object:Gem::Dependency
|
|
18
32
|
name: bundler
|
|
19
33
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -126,6 +140,20 @@ dependencies:
|
|
|
126
140
|
- - ">="
|
|
127
141
|
- !ruby/object:Gem::Version
|
|
128
142
|
version: '0'
|
|
143
|
+
- !ruby/object:Gem::Dependency
|
|
144
|
+
name: railties
|
|
145
|
+
requirement: !ruby/object:Gem::Requirement
|
|
146
|
+
requirements:
|
|
147
|
+
- - ">="
|
|
148
|
+
- !ruby/object:Gem::Version
|
|
149
|
+
version: '0'
|
|
150
|
+
type: :development
|
|
151
|
+
prerelease: false
|
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
153
|
+
requirements:
|
|
154
|
+
- - ">="
|
|
155
|
+
- !ruby/object:Gem::Version
|
|
156
|
+
version: '0'
|
|
129
157
|
- !ruby/object:Gem::Dependency
|
|
130
158
|
name: rake
|
|
131
159
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -202,14 +230,14 @@ dependencies:
|
|
|
202
230
|
requirements:
|
|
203
231
|
- - "~>"
|
|
204
232
|
- !ruby/object:Gem::Version
|
|
205
|
-
version: '
|
|
233
|
+
version: '1.91'
|
|
206
234
|
type: :development
|
|
207
235
|
prerelease: false
|
|
208
236
|
version_requirements: !ruby/object:Gem::Requirement
|
|
209
237
|
requirements:
|
|
210
238
|
- - "~>"
|
|
211
239
|
- !ruby/object:Gem::Version
|
|
212
|
-
version: '
|
|
240
|
+
version: '1.91'
|
|
213
241
|
- !ruby/object:Gem::Dependency
|
|
214
242
|
name: base64
|
|
215
243
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -286,20 +314,14 @@ dependencies:
|
|
|
286
314
|
requirements:
|
|
287
315
|
- - "~>"
|
|
288
316
|
- !ruby/object:Gem::Version
|
|
289
|
-
version: '3.
|
|
290
|
-
- - "!="
|
|
291
|
-
- !ruby/object:Gem::Version
|
|
292
|
-
version: '3.3'
|
|
317
|
+
version: '3.9'
|
|
293
318
|
type: :runtime
|
|
294
319
|
prerelease: false
|
|
295
320
|
version_requirements: !ruby/object:Gem::Requirement
|
|
296
321
|
requirements:
|
|
297
322
|
- - "~>"
|
|
298
323
|
- !ruby/object:Gem::Version
|
|
299
|
-
version: '3.
|
|
300
|
-
- - "!="
|
|
301
|
-
- !ruby/object:Gem::Version
|
|
302
|
-
version: '3.3'
|
|
324
|
+
version: '3.9'
|
|
303
325
|
description: |2
|
|
304
326
|
Light weight job scheduling on top of Resque.
|
|
305
327
|
Adds methods enqueue_at/enqueue_in to schedule jobs in the future.
|
|
@@ -321,8 +343,6 @@ files:
|
|
|
321
343
|
- ".devcontainer/devcontainer.json"
|
|
322
344
|
- ".devcontainer/docker-compose.yml"
|
|
323
345
|
- ".github/dependabot.yml"
|
|
324
|
-
- ".github/workflows/codeql-analysis.yml"
|
|
325
|
-
- ".github/workflows/rubocop.yml"
|
|
326
346
|
- ".github/workflows/ruby.yml"
|
|
327
347
|
- AUTHORS.md
|
|
328
348
|
- CHANGELOG.md
|
|
@@ -348,6 +368,7 @@ files:
|
|
|
348
368
|
- lib/resque/scheduler/locking.rb
|
|
349
369
|
- lib/resque/scheduler/logger_builder.rb
|
|
350
370
|
- lib/resque/scheduler/plugin.rb
|
|
371
|
+
- lib/resque/scheduler/railtie.rb
|
|
351
372
|
- lib/resque/scheduler/scheduling_extensions.rb
|
|
352
373
|
- lib/resque/scheduler/server.rb
|
|
353
374
|
- lib/resque/scheduler/server/views/delayed.erb
|
|
@@ -374,7 +395,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
374
395
|
requirements:
|
|
375
396
|
- - ">="
|
|
376
397
|
- !ruby/object:Gem::Version
|
|
377
|
-
version: 3.
|
|
398
|
+
version: 3.2.0
|
|
378
399
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
379
400
|
requirements:
|
|
380
401
|
- - ">="
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
name: "CodeQL"
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [ master, '*-stable' ]
|
|
6
|
-
pull_request:
|
|
7
|
-
# The branches below must be a subset of the branches above
|
|
8
|
-
branches: [ master ]
|
|
9
|
-
schedule:
|
|
10
|
-
- cron: '44 16 * * 6'
|
|
11
|
-
|
|
12
|
-
jobs:
|
|
13
|
-
analyze:
|
|
14
|
-
name: Analyze
|
|
15
|
-
runs-on: ubuntu-latest
|
|
16
|
-
permissions:
|
|
17
|
-
actions: read
|
|
18
|
-
contents: read
|
|
19
|
-
security-events: write
|
|
20
|
-
|
|
21
|
-
strategy:
|
|
22
|
-
fail-fast: false
|
|
23
|
-
matrix:
|
|
24
|
-
language: [ 'ruby' ]
|
|
25
|
-
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
|
26
|
-
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
|
27
|
-
|
|
28
|
-
steps:
|
|
29
|
-
- name: Checkout repository
|
|
30
|
-
uses: actions/checkout@v4
|
|
31
|
-
|
|
32
|
-
# Initializes the CodeQL tools for scanning.
|
|
33
|
-
- name: Initialize CodeQL
|
|
34
|
-
uses: github/codeql-action/init@v3
|
|
35
|
-
with:
|
|
36
|
-
languages: ${{ matrix.language }}
|
|
37
|
-
# If you wish to specify custom queries, you can do so here or in a config file.
|
|
38
|
-
# By default, queries listed here will override any specified in a config file.
|
|
39
|
-
# Prefix the list here with "+" to use these queries and those in the config file.
|
|
40
|
-
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
|
41
|
-
|
|
42
|
-
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
|
43
|
-
# If this step fails, then you should remove it and run the build manually (see below)
|
|
44
|
-
- name: Autobuild
|
|
45
|
-
uses: github/codeql-action/autobuild@v3
|
|
46
|
-
|
|
47
|
-
# ℹ️ Command-line programs to run using the OS shell.
|
|
48
|
-
# 📚 https://git.io/JvXDl
|
|
49
|
-
|
|
50
|
-
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
|
51
|
-
# and modify them (or add more) to build your code if your project
|
|
52
|
-
# uses a compiled language
|
|
53
|
-
|
|
54
|
-
#- run: |
|
|
55
|
-
# make bootstrap
|
|
56
|
-
# make release
|
|
57
|
-
|
|
58
|
-
- name: Perform CodeQL Analysis
|
|
59
|
-
uses: github/codeql-action/analyze@v3
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
name: Rubocop
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [master]
|
|
6
|
-
pull_request:
|
|
7
|
-
branches: [master]
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
rubocop:
|
|
11
|
-
name: Rubocop
|
|
12
|
-
runs-on: ${{ matrix.os }}
|
|
13
|
-
strategy:
|
|
14
|
-
matrix:
|
|
15
|
-
os: [ubuntu-latest]
|
|
16
|
-
ruby: [
|
|
17
|
-
3.4
|
|
18
|
-
]
|
|
19
|
-
|
|
20
|
-
steps:
|
|
21
|
-
- uses: actions/checkout@v4
|
|
22
|
-
- uses: ruby/setup-ruby@v1
|
|
23
|
-
with:
|
|
24
|
-
ruby-version: ${{ matrix.ruby }}
|
|
25
|
-
bundler-cache: true
|
|
26
|
-
- name: Ruby linter
|
|
27
|
-
run: bundle exec rubocop
|