resque-scheduler 4.5.0 → 4.6.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of resque-scheduler might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.github/funding.yml +4 -0
- data/.github/workflows/codeql-analysis.yml +59 -0
- data/.github/workflows/rubocop.yml +1 -1
- data/.github/workflows/ruby.yml +26 -8
- data/AUTHORS.md +2 -0
- data/CHANGELOG.md +12 -3
- data/Gemfile +9 -3
- data/README.md +83 -10
- data/Rakefile +1 -0
- data/lib/resque/scheduler/configuration.rb +31 -8
- data/lib/resque/scheduler/delaying_extensions.rb +27 -12
- data/lib/resque/scheduler/env.rb +0 -4
- data/lib/resque/scheduler/locking.rb +1 -1
- data/lib/resque/scheduler/server/views/delayed.erb +4 -4
- data/lib/resque/scheduler/server/views/delayed_timestamp.erb +1 -1
- data/lib/resque/scheduler/server/views/scheduler.erb +2 -2
- data/lib/resque/scheduler/server/views/search.erb +0 -3
- data/lib/resque/scheduler/server/views/search_form.erb +0 -4
- data/lib/resque/scheduler/signal_handling.rb +2 -2
- data/lib/resque/scheduler/util.rb +1 -1
- data/lib/resque/scheduler/version.rb +1 -1
- data/lib/resque/scheduler.rb +1 -2
- data/resque-scheduler.gemspec +7 -5
- metadata +16 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf266ccd935c9464051349f32169248c7fab52aa84304a98f0d05e5e91ccec22
|
4
|
+
data.tar.gz: 517e84a33953fa3bf695ae26f23912d436fc86b7dc0ac9502fb09ca1cc02f1c3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 91b8916a16ad2a6a20860001f137fb558d6dbfa7aca3c67abb022acc298a3f2afac7c1527a043b2d5ed3fa582d0203cc988b101cc45819ae3832145328cdea7d
|
7
|
+
data.tar.gz: 90669eb2a75e71612b1505c87a6ed704e70b80b34aa89023ce84e8a256c1d3e0e4eb2a7931c8e480ff99524ed489bb97ed2d98f512f6646f19d50751613ac97c
|
data/.github/funding.yml
ADDED
@@ -0,0 +1,59 @@
|
|
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@v3
|
31
|
+
|
32
|
+
# Initializes the CodeQL tools for scanning.
|
33
|
+
- name: Initialize CodeQL
|
34
|
+
uses: github/codeql-action/init@v2
|
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@v2
|
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@v2
|
data/.github/workflows/ruby.yml
CHANGED
@@ -8,6 +8,7 @@ on:
|
|
8
8
|
|
9
9
|
jobs:
|
10
10
|
test:
|
11
|
+
continue-on-error: true
|
11
12
|
runs-on: ubuntu-latest
|
12
13
|
services:
|
13
14
|
redis:
|
@@ -24,22 +25,39 @@ jobs:
|
|
24
25
|
- 2.6
|
25
26
|
- 2.7
|
26
27
|
- "3.0"
|
27
|
-
-
|
28
|
-
- jruby-9.1.17.0
|
29
|
-
- jruby-9.2.9.0
|
30
|
-
- jruby-9.2.19.0
|
28
|
+
- 3.1
|
31
29
|
resque-version:
|
32
30
|
- "master"
|
33
|
-
- "~> 2.
|
31
|
+
- "~> 2.2.0"
|
34
32
|
- "~> 1.27"
|
33
|
+
rufus-scheduler:
|
34
|
+
- "3.2"
|
35
|
+
- "3.4"
|
36
|
+
- "3.5"
|
37
|
+
- "3.6"
|
38
|
+
exclude:
|
39
|
+
- ruby-version: head
|
40
|
+
rufus-scheduler: 3.2
|
41
|
+
|
42
|
+
- ruby-version: 2.3
|
43
|
+
resque-version: 1.27
|
44
|
+
rufus-scheduler: 3.4
|
45
|
+
- ruby-version: 2.3
|
46
|
+
resque-version: 1.27
|
47
|
+
rufus-scheduler: 3.5
|
48
|
+
- ruby-version: 2.5
|
49
|
+
resque-version: 2.2.0
|
50
|
+
rufus-scheduler: 3.5
|
51
|
+
- ruby-version: 2.5
|
52
|
+
resque-version: master
|
53
|
+
rufus-scheduler: 3.2
|
35
54
|
env:
|
36
55
|
RESQUE: "${{ matrix.resque-version }}"
|
56
|
+
RUFUS_SCHEDULER: "${{ matrix.rufus-scheduler }}"
|
37
57
|
COVERAGE: 1
|
38
|
-
JRUBY_OPTS: ""
|
39
|
-
RUBYOPT: "-W0"
|
40
58
|
|
41
59
|
steps:
|
42
|
-
- uses: actions/checkout@
|
60
|
+
- uses: actions/checkout@v3
|
43
61
|
- uses: ruby/setup-ruby@v1
|
44
62
|
with:
|
45
63
|
ruby-version: "${{ matrix.ruby-version }}"
|
data/AUTHORS.md
CHANGED
@@ -10,6 +10,7 @@ Resque Scheduler authors
|
|
10
10
|
- Brian Landau
|
11
11
|
- Brian P O'Rourke
|
12
12
|
- Carlos Antonio da Silva
|
13
|
+
- Chris Bisnett
|
13
14
|
- Chris Kampmeier
|
14
15
|
- DJ Hartman
|
15
16
|
- Damon P. Cortesi
|
@@ -42,6 +43,7 @@ Resque Scheduler authors
|
|
42
43
|
- Justin Weiss
|
43
44
|
- Les Hill
|
44
45
|
- Luke Rodgers
|
46
|
+
- Maksymilian Chwałek
|
45
47
|
- Manuel Meurer
|
46
48
|
- Matt Aimonetti
|
47
49
|
- Matt Simpson
|
data/CHANGELOG.md
CHANGED
@@ -2,9 +2,17 @@
|
|
2
2
|
|
3
3
|
**ATTN**: This project uses [semantic versioning](http://semver.org/).
|
4
4
|
|
5
|
-
##
|
5
|
+
## [4.6.0] - 2022-08-04
|
6
|
+
### Changed
|
7
|
+
- Remove support for Ruby < 2.3
|
8
|
+
- Configuration to use a set of truthy values to enable boolean settings instead of simply existence
|
9
|
+
- Add `delay_or_enqueue_at` for delaying existing jobs or creating a new job(#645)
|
10
|
+
- Fix deprecated uses of Redis#pipelined
|
11
|
+
- Fix reading configuration from environment for boolean values (#735)
|
12
|
+
- Unblock rufus-scheduler lock on lower than 3.7 by fixing scheduler shutdown (#736)
|
13
|
+
- Removed testing against jruby (resque doesn't test against jruby)
|
6
14
|
|
7
|
-
## [4.5.0]
|
15
|
+
## [4.5.0] - 2021-09-25
|
8
16
|
### Added
|
9
17
|
- Support Ruby 3
|
10
18
|
- Add optional argument to `remove_schedule` to control reloading of the schedule
|
@@ -443,7 +451,8 @@
|
|
443
451
|
### Added
|
444
452
|
- Initial release
|
445
453
|
|
446
|
-
[Unreleased]: https://github.com/resque/resque-scheduler/compare/v4.
|
454
|
+
[Unreleased]: https://github.com/resque/resque-scheduler/compare/v4.5.0...HEAD
|
455
|
+
[4.5.0]: https://github.com/resque/resque-scheduler/compare/v4.4.0...v4.5.0
|
447
456
|
[4.4.0]: https://github.com/resque/resque-scheduler/compare/v4.3.1...v4.4.0
|
448
457
|
[4.3.1]: https://github.com/resque/resque-scheduler/compare/v4.3.0...v4.3.1
|
449
458
|
[4.3.0]: https://github.com/resque/resque-scheduler/compare/v4.2.1...v4.3.0
|
data/Gemfile
CHANGED
@@ -1,12 +1,18 @@
|
|
1
1
|
# vim:fileencoding=utf-8
|
2
2
|
source 'https://rubygems.org'
|
3
3
|
|
4
|
-
case
|
5
|
-
when nil
|
4
|
+
case resque_version = ENV.fetch('RESQUE', 'master')
|
6
5
|
when 'master'
|
7
6
|
gem 'resque', git: 'https://github.com/resque/resque'
|
8
7
|
else
|
9
|
-
gem 'resque',
|
8
|
+
gem 'resque', resque_version
|
9
|
+
end
|
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
|
10
16
|
end
|
11
17
|
|
12
18
|
gemspec
|
data/README.md
CHANGED
@@ -211,7 +211,7 @@ since the jobs are stored in a redis sorted set (zset). I can't imagine this
|
|
211
211
|
being an issue for someone since redis is stupidly fast even at log(n), but full
|
212
212
|
disclosure is always best.
|
213
213
|
|
214
|
-
#### Removing Delayed
|
214
|
+
#### Removing Delayed Jobs
|
215
215
|
|
216
216
|
If you have the need to cancel a delayed job, you can do like so:
|
217
217
|
|
@@ -255,6 +255,49 @@ Resque.enqueue_delayed_selection { |args| args[0]['account_id'] == current_accou
|
|
255
255
|
Resque.enqueue_delayed_selection { |args| args[0]['user_id'] == current_user.id }
|
256
256
|
```
|
257
257
|
|
258
|
+
#### Updating Delayed Jobs
|
259
|
+
|
260
|
+
Previously delayed jobs may be delayed even further into the future like so:
|
261
|
+
|
262
|
+
```ruby
|
263
|
+
# after you've enqueued a job like:
|
264
|
+
Resque.enqueue_at(1.minute.from_now, SendNotifications, :user_id => current_user.id)
|
265
|
+
# delay running the job until two minutes from now
|
266
|
+
Resque.delay_or_enqueue_at(2.minutes.from_now, SendNotifications, :user_id => current_user.id)
|
267
|
+
```
|
268
|
+
|
269
|
+
You don't need to worry if a matching job has already been queued, because if no matching jobs are found a new job is created and enqueued as if you had called `enqueue_at`. This means you don't need any special conditionals to know if a job has already been queued. You simply create the job like so:
|
270
|
+
|
271
|
+
```ruby
|
272
|
+
Resque.delay_or_enqueue_at(1.minute.from_now, SendNotifications, :user_id => current_user.id)
|
273
|
+
```
|
274
|
+
|
275
|
+
If multiple matching jobs are found, all of the matching jobs will be updated to have the same timestamp even if their original timestamps were not the same.
|
276
|
+
|
277
|
+
```ruby
|
278
|
+
# enqueue multiple jobs with different delay timestamps
|
279
|
+
Resque.enqueue_at(1.minute.from_now, SendNotifications, :user_id => current_user.id)
|
280
|
+
Resque.enqueue_at(2.minutes.from_now, SendNotifications, :user_id => current_user.id)
|
281
|
+
|
282
|
+
# delay running the two jobs until 5 minutes from now
|
283
|
+
Resque.delay_or_enqueue_at(5.minutes.from_now, SendNotifications, :user_id => current_user.id)
|
284
|
+
```
|
285
|
+
|
286
|
+
The most useful case for increasing the delay of an already delayed job is to batch together work based on multiple events. For example, if you wanted to send a notification email to a user when an event triggers but didn't want to send 10 emails if many events happened within a short period, you could use this technique to delay the noficication email until no events have triggered for a period of time. This way you could send 1 email containing the 10 notifications once no events have triggered for 2 minutes. You could implement this like so:
|
287
|
+
|
288
|
+
```ruby
|
289
|
+
# Send a notification when an event is created.
|
290
|
+
# app/models/event.rb
|
291
|
+
after_commit on: :create do
|
292
|
+
Resque.delay_or_enqueue_in(2.minutes, SendNotifications, :user_id => user.id)
|
293
|
+
end
|
294
|
+
```
|
295
|
+
|
296
|
+
When the first event is created a job will be scheduled to send unsent notifications to the associated user. If another event is created within the 2 minute window, the timer will be reset to 2 minutes. This will continue as long as new events are created for the specific user before the 2 minute timer expires. Once the timer expires and the job is scheduled any new events that are created will schedule a new job and start the process over. By adjusting the window you can tweak the trade-off between sending notification emails quickly after an event happens and sending fewer emails.
|
297
|
+
|
298
|
+
Read more in the [original PR](https://github.com/resque/resque-scheduler/pull/645)
|
299
|
+
|
300
|
+
|
258
301
|
### Scheduled Jobs (Recurring Jobs)
|
259
302
|
|
260
303
|
Scheduled (or recurring) jobs are logically no different than a standard cron
|
@@ -304,7 +347,6 @@ If you would like to setup a job that is executed manually you can configure lik
|
|
304
347
|
|
305
348
|
```yaml
|
306
349
|
ImportOrdersManual:
|
307
|
-
description: 'Import Amazon Orders Manual'
|
308
350
|
custom_job_class: 'AmazonMws::ImportOrdersJob'
|
309
351
|
never: "* * * * *"
|
310
352
|
queue: high
|
@@ -344,6 +386,38 @@ seconds past the minute).
|
|
344
386
|
A big shout out to [rufus-scheduler](http://github.com/jmettraux/rufus-scheduler)
|
345
387
|
for handling the heavy lifting of the actual scheduling engine.
|
346
388
|
|
389
|
+
##### Queue with parameters
|
390
|
+
|
391
|
+
It's possible to specify parameters, that must be given by the user when they manually queue the job. To enable this feature add `parameters` key to scheduled job definition.
|
392
|
+
|
393
|
+
```yaml
|
394
|
+
queue_documents_for_indexing:
|
395
|
+
cron: "0 0 * * *"
|
396
|
+
class: "QueueDocuments"
|
397
|
+
queue: high
|
398
|
+
args:
|
399
|
+
foo: "bar"
|
400
|
+
a: "b"
|
401
|
+
parameters:
|
402
|
+
foo:
|
403
|
+
description: "value of foo"
|
404
|
+
default: "baz"
|
405
|
+
|
406
|
+
description: "This job queues all content for indexing in solr"
|
407
|
+
```
|
408
|
+
|
409
|
+
One can use following options for each parameter:
|
410
|
+
* description - tooltip to be shown next to the parameter input
|
411
|
+
* default - prefilled value in the parameter input
|
412
|
+
|
413
|
+
**NOTE**: When sheduling the job, parameters are merged into job args. Assuming the example above and default parametr value, the job will be run with the following args:
|
414
|
+
|
415
|
+
```ruby
|
416
|
+
{"foo"=>"baz", "a"=>"b"}
|
417
|
+
```
|
418
|
+
|
419
|
+
**NOTE**: If user leaves the parameter value empty, it'll be sent as empty string.
|
420
|
+
|
347
421
|
#### Dynamic schedules
|
348
422
|
|
349
423
|
Dynamic schedules are programmatically set on a running `resque-scheduler`.
|
@@ -405,18 +479,17 @@ Resque.set_schedule(name, config)
|
|
405
479
|
|
406
480
|
#### Time zones
|
407
481
|
|
408
|
-
|
409
|
-
rather than the `config.time_zone` specified in Rails.
|
410
|
-
|
482
|
+
If you use the cron syntax, by default it is interpreted in the server time zone.
|
411
483
|
You can explicitly specify the time zone that rufus-scheduler will use:
|
412
|
-
|
413
484
|
```yaml
|
414
485
|
cron: "30 6 * * 1 Europe/Stockholm"
|
415
486
|
```
|
416
487
|
|
417
|
-
|
418
|
-
|
419
|
-
|
488
|
+
##### Rails
|
489
|
+
In Rails, `config.time_zone` will be used to determine the time zone for `resque-scheduler`.
|
490
|
+
|
491
|
+
Note that `config.time_zone` allows for a shorthand (e.g. "Stockholm")
|
492
|
+
that rufus-scheduler does not accept, so make sure it's the right format, e.g. with:
|
420
493
|
|
421
494
|
```ruby
|
422
495
|
ActiveSupport::TimeZone.find_tzinfo(Rails.configuration.time_zone).name
|
@@ -573,7 +646,7 @@ Now make sure you're passing that file to resque-web like so:
|
|
573
646
|
|
574
647
|
### Running in the background
|
575
648
|
|
576
|
-
|
649
|
+
There are scenarios where it's helpful for
|
577
650
|
the resque worker to run itself in the background (usually in combination with
|
578
651
|
PIDFILE). Use the BACKGROUND option so that rake will return as soon as the
|
579
652
|
worker is started.
|
data/Rakefile
CHANGED
@@ -8,13 +8,18 @@ module Resque
|
|
8
8
|
yield self
|
9
9
|
end
|
10
10
|
|
11
|
+
attr_writer :environment
|
12
|
+
def environment
|
13
|
+
@environment ||= ENV
|
14
|
+
end
|
15
|
+
|
11
16
|
# Used in `#load_schedule_job`
|
12
17
|
attr_writer :env
|
13
18
|
|
14
19
|
def env
|
15
20
|
return @env if @env
|
16
21
|
@env ||= Rails.env if defined?(Rails) && Rails.respond_to?(:env)
|
17
|
-
@env ||=
|
22
|
+
@env ||= environment['RAILS_ENV']
|
18
23
|
@env
|
19
24
|
end
|
20
25
|
|
@@ -22,42 +27,42 @@ module Resque
|
|
22
27
|
attr_writer :verbose
|
23
28
|
|
24
29
|
def verbose
|
25
|
-
@verbose ||=
|
30
|
+
@verbose ||= to_bool(environment['VERBOSE'])
|
26
31
|
end
|
27
32
|
|
28
33
|
# If set, produces no output
|
29
34
|
attr_writer :quiet
|
30
35
|
|
31
36
|
def quiet
|
32
|
-
@quiet ||=
|
37
|
+
@quiet ||= to_bool(environment['QUIET'])
|
33
38
|
end
|
34
39
|
|
35
40
|
# If set, will write messages to the file
|
36
41
|
attr_writer :logfile
|
37
42
|
|
38
43
|
def logfile
|
39
|
-
@logfile ||=
|
44
|
+
@logfile ||= environment['LOGFILE']
|
40
45
|
end
|
41
46
|
|
42
47
|
# Sets whether to log in 'text' or 'json'
|
43
48
|
attr_writer :logformat
|
44
49
|
|
45
50
|
def logformat
|
46
|
-
@logformat ||=
|
51
|
+
@logformat ||= environment['LOGFORMAT']
|
47
52
|
end
|
48
53
|
|
49
54
|
# If set, will try to update the schedule in the loop
|
50
55
|
attr_writer :dynamic
|
51
56
|
|
52
57
|
def dynamic
|
53
|
-
@dynamic ||=
|
58
|
+
@dynamic ||= to_bool(environment['DYNAMIC_SCHEDULE'])
|
54
59
|
end
|
55
60
|
|
56
61
|
# If set, will append the app name to procline
|
57
62
|
attr_writer :app_name
|
58
63
|
|
59
64
|
def app_name
|
60
|
-
@app_name ||=
|
65
|
+
@app_name ||= environment['APP_NAME']
|
61
66
|
end
|
62
67
|
|
63
68
|
# Amount of time in seconds to sleep between polls of the delayed
|
@@ -66,7 +71,25 @@ module Resque
|
|
66
71
|
|
67
72
|
def poll_sleep_amount
|
68
73
|
@poll_sleep_amount ||=
|
69
|
-
Float(
|
74
|
+
Float(environment.fetch('RESQUE_SCHEDULER_INTERVAL', '5'))
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
# Copied from https://github.com/rails/rails/blob/main/activemodel/lib/active_model/type/boolean.rb#L17
|
80
|
+
TRUE_VALUES = [
|
81
|
+
true, 1,
|
82
|
+
'1', :'1',
|
83
|
+
't', :t,
|
84
|
+
'T', :T,
|
85
|
+
'true', :true,
|
86
|
+
'TRUE', :TRUE,
|
87
|
+
'on', :on,
|
88
|
+
'ON', :ON
|
89
|
+
].to_set.freeze
|
90
|
+
|
91
|
+
def to_bool(value)
|
92
|
+
TRUE_VALUES.include?(value)
|
70
93
|
end
|
71
94
|
end
|
72
95
|
end
|
@@ -63,6 +63,24 @@ module Resque
|
|
63
63
|
klass, *args)
|
64
64
|
end
|
65
65
|
|
66
|
+
# Update the delayed timestamp of any matching delayed jobs or enqueue a
|
67
|
+
# new job if no matching jobs are found. Returns the number of delayed or
|
68
|
+
# enqueued jobs.
|
69
|
+
def delay_or_enqueue_at(timestamp, klass, *args)
|
70
|
+
count = remove_delayed(klass, *args)
|
71
|
+
count = 1 if count == 0
|
72
|
+
|
73
|
+
count.times do
|
74
|
+
enqueue_at(timestamp, klass, *args)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Identical to +delay_or_enqueue_at+, except it takes
|
79
|
+
# number_of_seconds_from_now instead of a timestamp
|
80
|
+
def delay_or_enqueue_in(number_of_seconds_from_now, klass, *args)
|
81
|
+
delay_or_enqueue_at(Time.now + number_of_seconds_from_now, klass, *args)
|
82
|
+
end
|
83
|
+
|
66
84
|
# Used internally to stuff the item into the schedule sorted list.
|
67
85
|
# +timestamp+ can be either in seconds or a datetime object. The
|
68
86
|
# insertion time complexity is O(log(n)). Returns true if it's
|
@@ -135,10 +153,7 @@ module Resque
|
|
135
153
|
Array(redis.zrange(:delayed_queue_schedule, 0, -1)).each do |item|
|
136
154
|
key = "delayed:#{item}"
|
137
155
|
items = redis.lrange(key, 0, -1)
|
138
|
-
redis.
|
139
|
-
items.each { |ts_item| redis.del("timestamps:#{ts_item}") }
|
140
|
-
end
|
141
|
-
redis.del key
|
156
|
+
redis.del(key, items.map { |ts_item| "timestamps:#{ts_item}" })
|
142
157
|
end
|
143
158
|
|
144
159
|
redis.del :delayed_queue_schedule
|
@@ -217,9 +232,9 @@ module Resque
|
|
217
232
|
|
218
233
|
# Beyond 100 there's almost no improvement in speed
|
219
234
|
found = timestamps.each_slice(100).map do |ts_group|
|
220
|
-
jobs = redis.pipelined do |
|
235
|
+
jobs = redis.pipelined do |pipeline|
|
221
236
|
ts_group.each do |ts|
|
222
|
-
|
237
|
+
pipeline.lrange("delayed:#{ts}", 0, -1)
|
223
238
|
end
|
224
239
|
end
|
225
240
|
|
@@ -299,10 +314,10 @@ module Resque
|
|
299
314
|
|
300
315
|
timestamps = redis.smembers("timestamps:#{encoded_job}")
|
301
316
|
|
302
|
-
replies = redis.pipelined do
|
317
|
+
replies = redis.pipelined do |pipeline|
|
303
318
|
timestamps.each do |key|
|
304
|
-
|
305
|
-
|
319
|
+
pipeline.lrem(key, 0, encoded_job)
|
320
|
+
pipeline.srem("timestamps:#{encoded_job}", key)
|
306
321
|
end
|
307
322
|
end
|
308
323
|
|
@@ -319,9 +334,9 @@ module Resque
|
|
319
334
|
redis.watch(key) do
|
320
335
|
if redis.llen(key).to_i == 0
|
321
336
|
# If the list is empty, remove it.
|
322
|
-
redis.multi do
|
323
|
-
|
324
|
-
|
337
|
+
redis.multi do |transaction|
|
338
|
+
transaction.del(key)
|
339
|
+
transaction.zrem(:delayed_queue_schedule, timestamp.to_i)
|
325
340
|
end
|
326
341
|
else
|
327
342
|
redis.redis.unwatch
|
data/lib/resque/scheduler/env.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
# ### Locking the scheduler process
|
4
4
|
#
|
5
|
-
# There are two places in resque-scheduler that need to be
|
5
|
+
# There are two places in resque-scheduler that need to be synchronized in order
|
6
6
|
# to be able to run redundant scheduler processes while ensuring jobs don't get
|
7
7
|
# queued multiple times when the master process changes.
|
8
8
|
#
|
@@ -1,9 +1,9 @@
|
|
1
1
|
<h1>Delayed Jobs</h1>
|
2
|
-
|
2
|
+
<% size = resque.delayed_queue_schedule_size %>
|
3
3
|
|
4
4
|
<%= scheduler_view :search_form, layout: false %>
|
5
5
|
|
6
|
-
<p style="
|
6
|
+
<p style="color: red; font-weight: bold;">
|
7
7
|
<%= @error_message %>
|
8
8
|
</p>
|
9
9
|
|
@@ -46,7 +46,7 @@
|
|
46
46
|
<td><%= h(show_job_arguments(job['args'])) if job && delayed_timestamp_size == 1 %></td>
|
47
47
|
<td>
|
48
48
|
<% if job %>
|
49
|
-
<a href="<%=u URI("/delayed/jobs/#{CGI.escape(job['class'])}?args=" + CGI.escape(job['args'].to_json)) %>">All schedules</a>
|
49
|
+
<a href="<%= u URI("/delayed/jobs/#{CGI.escape(job['class'])}?args=" + CGI.escape(job['args'].to_json)) %>">All schedules</a>
|
50
50
|
<% end %>
|
51
51
|
</td>
|
52
52
|
</tr>
|
@@ -55,7 +55,7 @@
|
|
55
55
|
|
56
56
|
<% if size > 0 %>
|
57
57
|
<br>
|
58
|
-
<form method="POST" action="<%=u 'delayed/clear'%>" class='clear-delayed'>
|
58
|
+
<form method="POST" action="<%= u 'delayed/clear' %>" class='clear-delayed'>
|
59
59
|
<input type='submit' name='' value='Clear Delayed Jobs' />
|
60
60
|
</form>
|
61
61
|
<% end %>
|
@@ -8,7 +8,7 @@
|
|
8
8
|
<br/> Current master: <%= Resque.redis.get(Resque::Scheduler.master_lock.key) %>
|
9
9
|
</p>
|
10
10
|
<p class='intro'>
|
11
|
-
|
11
|
+
The highlighted jobs are skipped for current environment.
|
12
12
|
</p>
|
13
13
|
<div style="overflow-y: auto; width:100%; padding: 0px 5px;">
|
14
14
|
<table>
|
@@ -29,7 +29,7 @@
|
|
29
29
|
<% Resque.schedule.keys.sort.each_with_index do |name, index| %>
|
30
30
|
<% config = Resque.schedule[name] %>
|
31
31
|
<tr style="<%= scheduled_in_this_env?(name) ? '' : 'color: #9F6000;background: #FEEFB3;' %>">
|
32
|
-
|
32
|
+
<td style="padding-left: 15px;"><%= index + 1 %>.</td>
|
33
33
|
<% if Resque::Scheduler.dynamic %>
|
34
34
|
<td style="padding-top: 12px; padding-bottom: 2px; width: 10px">
|
35
35
|
<form action="<%= u "/schedule" %>" method="post" style="margin-left: 0">
|
@@ -10,13 +10,13 @@ module Resque
|
|
10
10
|
end
|
11
11
|
|
12
12
|
# For all signals, set the shutdown flag and wait for current
|
13
|
-
# poll/
|
13
|
+
# poll/enqueuing to finish (should be almost instant). In the
|
14
14
|
# case of sleeping, exit immediately.
|
15
15
|
def register_signal_handlers
|
16
16
|
(Signal.list.keys & %w(INT TERM USR1 USR2 QUIT)).each do |sig|
|
17
17
|
trap(sig) do
|
18
18
|
signal_queue << sig
|
19
|
-
# break sleep in the primary scheduler thread,
|
19
|
+
# break sleep in the primary scheduler thread, allowing
|
20
20
|
# the signal queue to get processed as soon as possible.
|
21
21
|
@th.wakeup if @th && @th.alive?
|
22
22
|
end
|
@@ -4,7 +4,7 @@ module Resque
|
|
4
4
|
module Scheduler
|
5
5
|
class Util
|
6
6
|
# In order to upgrade to resque(1.25) which has deprecated following
|
7
|
-
# methods, we just added these
|
7
|
+
# methods, we just added these useful helpers back to use in Resque
|
8
8
|
# Scheduler. refer to:
|
9
9
|
# https://github.com/resque/resque-scheduler/pull/273
|
10
10
|
|
data/lib/resque/scheduler.rb
CHANGED
@@ -251,7 +251,7 @@ module Resque
|
|
251
251
|
if job_klass && job_klass != 'Resque::Job'
|
252
252
|
# The custom job class API must offer a static "scheduled" method. If
|
253
253
|
# the custom job class can not be constantized (via a requeue call
|
254
|
-
# from the web perhaps), fall back to
|
254
|
+
# from the web perhaps), fall back to enqueuing normally via
|
255
255
|
# Resque::Job.create.
|
256
256
|
begin
|
257
257
|
Resque::Scheduler::Util.constantize(job_klass).scheduled(
|
@@ -377,7 +377,6 @@ module Resque
|
|
377
377
|
|
378
378
|
def stop_rufus_scheduler
|
379
379
|
rufus_scheduler.shutdown(:wait)
|
380
|
-
rufus_scheduler.join
|
381
380
|
end
|
382
381
|
|
383
382
|
def before_shutdown
|
data/resque-scheduler.gemspec
CHANGED
@@ -26,13 +26,16 @@ Gem::Specification.new do |spec|
|
|
26
26
|
Adds methods enqueue_at/enqueue_in to schedule jobs in the future.
|
27
27
|
Also supports queueing jobs on a fixed, cron-like schedule.
|
28
28
|
DESCRIPTION
|
29
|
-
spec.homepage = '
|
29
|
+
spec.homepage = 'https://github.com/resque/resque-scheduler'
|
30
30
|
spec.license = 'MIT'
|
31
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
32
|
+
|
33
|
+
spec.required_ruby_version = '>= 2.3.0'
|
31
34
|
|
32
35
|
spec.files = `git ls-files -z`.split("\0").reject do |f|
|
33
36
|
f.match(%r{^(test|spec|features|examples|bin|tasks)/}) ||
|
34
37
|
f.match(/^(Vagrantfile|Gemfile\.lock)/) ||
|
35
|
-
f.match(/^\.(rubocop|simplecov|
|
38
|
+
f.match(/^\.(rubocop|simplecov|vagrant|gitignore)/)
|
36
39
|
end
|
37
40
|
spec.bindir = 'exe'
|
38
41
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
@@ -40,7 +43,6 @@ Gem::Specification.new do |spec|
|
|
40
43
|
|
41
44
|
spec.add_development_dependency 'bundler'
|
42
45
|
spec.add_development_dependency 'json'
|
43
|
-
spec.add_development_dependency 'kramdown'
|
44
46
|
spec.add_development_dependency 'minitest'
|
45
47
|
spec.add_development_dependency 'mocha'
|
46
48
|
spec.add_development_dependency 'pry'
|
@@ -49,7 +51,6 @@ Gem::Specification.new do |spec|
|
|
49
51
|
spec.add_development_dependency 'simplecov'
|
50
52
|
spec.add_development_dependency 'test-unit'
|
51
53
|
spec.add_development_dependency 'yard'
|
52
|
-
spec.add_development_dependency 'tzinfo-data'
|
53
54
|
spec.add_development_dependency 'timecop'
|
54
55
|
|
55
56
|
# We pin rubocop because new cops have a tendency to result in false-y
|
@@ -60,5 +61,6 @@ Gem::Specification.new do |spec|
|
|
60
61
|
spec.add_runtime_dependency 'redis', '>= 3.3'
|
61
62
|
spec.add_runtime_dependency 'resque', '>= 1.27'
|
62
63
|
# rufus-scheduler v3.7 causes a failure in test/multi_process_test.rb
|
63
|
-
|
64
|
+
# rufus-scheduler v3.3 is missing a to_local method which fails tests
|
65
|
+
spec.add_runtime_dependency 'rufus-scheduler', '~> 3.2', '!= 3.3'
|
64
66
|
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: 4.
|
4
|
+
version: 4.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben VandenBos
|
@@ -9,10 +9,10 @@ authors:
|
|
9
9
|
- Ryan Biesemeyer
|
10
10
|
- Dan Buch
|
11
11
|
- Michael Bianco
|
12
|
-
autorequire:
|
12
|
+
autorequire:
|
13
13
|
bindir: exe
|
14
14
|
cert_chain: []
|
15
|
-
date:
|
15
|
+
date: 2022-08-20 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: bundler
|
@@ -42,20 +42,6 @@ dependencies:
|
|
42
42
|
- - ">="
|
43
43
|
- !ruby/object:Gem::Version
|
44
44
|
version: '0'
|
45
|
-
- !ruby/object:Gem::Dependency
|
46
|
-
name: kramdown
|
47
|
-
requirement: !ruby/object:Gem::Requirement
|
48
|
-
requirements:
|
49
|
-
- - ">="
|
50
|
-
- !ruby/object:Gem::Version
|
51
|
-
version: '0'
|
52
|
-
type: :development
|
53
|
-
prerelease: false
|
54
|
-
version_requirements: !ruby/object:Gem::Requirement
|
55
|
-
requirements:
|
56
|
-
- - ">="
|
57
|
-
- !ruby/object:Gem::Version
|
58
|
-
version: '0'
|
59
45
|
- !ruby/object:Gem::Dependency
|
60
46
|
name: minitest
|
61
47
|
requirement: !ruby/object:Gem::Requirement
|
@@ -168,20 +154,6 @@ dependencies:
|
|
168
154
|
- - ">="
|
169
155
|
- !ruby/object:Gem::Version
|
170
156
|
version: '0'
|
171
|
-
- !ruby/object:Gem::Dependency
|
172
|
-
name: tzinfo-data
|
173
|
-
requirement: !ruby/object:Gem::Requirement
|
174
|
-
requirements:
|
175
|
-
- - ">="
|
176
|
-
- !ruby/object:Gem::Version
|
177
|
-
version: '0'
|
178
|
-
type: :development
|
179
|
-
prerelease: false
|
180
|
-
version_requirements: !ruby/object:Gem::Requirement
|
181
|
-
requirements:
|
182
|
-
- - ">="
|
183
|
-
- !ruby/object:Gem::Version
|
184
|
-
version: '0'
|
185
157
|
- !ruby/object:Gem::Dependency
|
186
158
|
name: timecop
|
187
159
|
requirement: !ruby/object:Gem::Requirement
|
@@ -259,9 +231,9 @@ dependencies:
|
|
259
231
|
- - "~>"
|
260
232
|
- !ruby/object:Gem::Version
|
261
233
|
version: '3.2'
|
262
|
-
- - "
|
234
|
+
- - "!="
|
263
235
|
- !ruby/object:Gem::Version
|
264
|
-
version: '3.
|
236
|
+
version: '3.3'
|
265
237
|
type: :runtime
|
266
238
|
prerelease: false
|
267
239
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -269,9 +241,9 @@ dependencies:
|
|
269
241
|
- - "~>"
|
270
242
|
- !ruby/object:Gem::Version
|
271
243
|
version: '3.2'
|
272
|
-
- - "
|
244
|
+
- - "!="
|
273
245
|
- !ruby/object:Gem::Version
|
274
|
-
version: '3.
|
246
|
+
version: '3.3'
|
275
247
|
description: |2
|
276
248
|
Light weight job scheduling on top of Resque.
|
277
249
|
Adds methods enqueue_at/enqueue_in to schedule jobs in the future.
|
@@ -288,6 +260,8 @@ extensions: []
|
|
288
260
|
extra_rdoc_files: []
|
289
261
|
files:
|
290
262
|
- ".github/dependabot.yml"
|
263
|
+
- ".github/funding.yml"
|
264
|
+
- ".github/workflows/codeql-analysis.yml"
|
291
265
|
- ".github/workflows/rubocop.yml"
|
292
266
|
- ".github/workflows/ruby.yml"
|
293
267
|
- AUTHORS.md
|
@@ -328,11 +302,12 @@ files:
|
|
328
302
|
- lib/resque/scheduler/util.rb
|
329
303
|
- lib/resque/scheduler/version.rb
|
330
304
|
- resque-scheduler.gemspec
|
331
|
-
homepage:
|
305
|
+
homepage: https://github.com/resque/resque-scheduler
|
332
306
|
licenses:
|
333
307
|
- MIT
|
334
|
-
metadata:
|
335
|
-
|
308
|
+
metadata:
|
309
|
+
rubygems_mfa_required: 'true'
|
310
|
+
post_install_message:
|
336
311
|
rdoc_options: []
|
337
312
|
require_paths:
|
338
313
|
- lib
|
@@ -340,15 +315,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
340
315
|
requirements:
|
341
316
|
- - ">="
|
342
317
|
- !ruby/object:Gem::Version
|
343
|
-
version:
|
318
|
+
version: 2.3.0
|
344
319
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
345
320
|
requirements:
|
346
321
|
- - ">="
|
347
322
|
- !ruby/object:Gem::Version
|
348
323
|
version: '0'
|
349
324
|
requirements: []
|
350
|
-
rubygems_version: 3.
|
351
|
-
signing_key:
|
325
|
+
rubygems_version: 3.3.5
|
326
|
+
signing_key:
|
352
327
|
specification_version: 4
|
353
328
|
summary: Light weight job scheduling on top of Resque
|
354
329
|
test_files: []
|