resque-scheduler 4.11.0 → 5.0.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/.devcontainer/Dockerfile +42 -0
- data/.devcontainer/README.md +111 -0
- data/.devcontainer/devcontainer.json +41 -0
- data/.devcontainer/docker-compose.yml +31 -0
- data/.github/workflows/rubocop.yml +1 -1
- data/.github/workflows/ruby.yml +8 -36
- data/CHANGELOG.md +48 -1
- data/Gemfile +7 -0
- data/lib/resque/scheduler/delaying_extensions.rb +14 -7
- data/lib/resque/scheduler/env.rb +7 -7
- data/lib/resque/scheduler/server/views/delayed_schedules.erb +1 -1
- data/lib/resque/scheduler/server/views/delayed_timestamp.erb +1 -1
- data/lib/resque/scheduler/server/views/requeue-params.erb +5 -5
- data/lib/resque/scheduler/server/views/scheduler.erb +2 -2
- data/lib/resque/scheduler/server/views/search.erb +6 -6
- data/lib/resque/scheduler/server.rb +3 -1
- data/lib/resque/scheduler/version.rb +1 -1
- data/lib/resque/scheduler.rb +19 -7
- data/resque-scheduler.gemspec +8 -4
- metadata +70 -14
- data/.github/funding.yml +0 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 046040c8fa18b0cb7aabc7fdc46ff008f7b0c30f9aa0500137f5c6c987bdbabc
|
|
4
|
+
data.tar.gz: b3e243c3c9ccefa0c1282b492b70a9b26677fa2b4be6ead096e339c721d9f86a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8b6c3caa8b47c24aee900d2c348cabb20d1a32a5fce88e02a974649ca6c711b1703562393902c7638e14c1a11180b1901b126480e905c7cca8b2dbd47d27daa3
|
|
7
|
+
data.tar.gz: 7b2665804103943b3bf9a98b84134ba71a0ac00ace8e0c2ed7c765873445c801bea14c8ae9082fec4133e6f3be0314bdf1485ecd47c7bab8aba6d8d85ef36ec8
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Use Ruby 3.3 as specified in the test matrix
|
|
2
|
+
FROM ruby:3.3
|
|
3
|
+
|
|
4
|
+
# Install dependencies
|
|
5
|
+
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
|
6
|
+
&& apt-get -y install --no-install-recommends \
|
|
7
|
+
git \
|
|
8
|
+
build-essential \
|
|
9
|
+
libssl-dev \
|
|
10
|
+
libreadline-dev \
|
|
11
|
+
zlib1g-dev \
|
|
12
|
+
redis-tools \
|
|
13
|
+
&& apt-get clean \
|
|
14
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
15
|
+
|
|
16
|
+
# Create a non-root user
|
|
17
|
+
ARG USERNAME=vscode
|
|
18
|
+
ARG USER_UID=1000
|
|
19
|
+
ARG USER_GID=$USER_UID
|
|
20
|
+
|
|
21
|
+
RUN groupadd --gid $USER_GID $USERNAME \
|
|
22
|
+
&& useradd --uid $USER_UID --gid $USER_GID -m $USERNAME \
|
|
23
|
+
&& apt-get update \
|
|
24
|
+
&& apt-get install -y sudo \
|
|
25
|
+
&& echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
|
|
26
|
+
&& chmod 0440 /etc/sudoers.d/$USERNAME
|
|
27
|
+
|
|
28
|
+
# Set the default user
|
|
29
|
+
USER $USERNAME
|
|
30
|
+
|
|
31
|
+
# Set working directory
|
|
32
|
+
WORKDIR /workspaces/resque-scheduler
|
|
33
|
+
|
|
34
|
+
# Install bundler
|
|
35
|
+
RUN gem install bundler
|
|
36
|
+
|
|
37
|
+
# Set environment variables for the test matrix configuration
|
|
38
|
+
ENV REDIS_VERSION=latest
|
|
39
|
+
ENV RESQUE=master
|
|
40
|
+
ENV RUFUS_SCHEDULER=3.6
|
|
41
|
+
ENV RACK_VERSION=3
|
|
42
|
+
ENV COVERAGE=1
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Dev Container for Resque Scheduler
|
|
2
|
+
|
|
3
|
+
This dev container is configured to match the GitHub Actions test matrix with the following configuration:
|
|
4
|
+
|
|
5
|
+
- **Ruby version**: 3.3
|
|
6
|
+
- **Resque version**: master (from git)
|
|
7
|
+
- **Rufus-scheduler**: 3.6
|
|
8
|
+
- **Redis version**: latest
|
|
9
|
+
- **Rack version**: 3
|
|
10
|
+
|
|
11
|
+
## Getting Started
|
|
12
|
+
|
|
13
|
+
1. Open this repository in VS Code
|
|
14
|
+
2. When prompted, click "Reopen in Container" (or run the command "Dev Containers: Reopen in Container")
|
|
15
|
+
3. Wait for the container to build and start
|
|
16
|
+
4. Once inside the container, dependencies will be automatically installed via `bundle install`
|
|
17
|
+
|
|
18
|
+
## Running Tests
|
|
19
|
+
|
|
20
|
+
To run the full test suite:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
bundle exec rake
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
To run a specific test file:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
bundle exec ruby test/scheduler_test.rb
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
To run tests with verbose output:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
VERBOSE=1 bundle exec rake
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
To run tests matching a specific pattern:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
PATTERN='test/scheduler_*_test.rb' bundle exec rake
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Testing with Different Configurations
|
|
45
|
+
|
|
46
|
+
If you want to test with different versions, you can modify the environment variables and reinstall dependencies:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# Example: Test with rufus-scheduler 3.4
|
|
50
|
+
export RUFUS_SCHEDULER=3.4
|
|
51
|
+
bundle install
|
|
52
|
+
|
|
53
|
+
# Run tests
|
|
54
|
+
bundle exec rake
|
|
55
|
+
|
|
56
|
+
# Reset to original configuration
|
|
57
|
+
export RUFUS_SCHEDULER=3.6
|
|
58
|
+
bundle install
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Available Environment Variables
|
|
62
|
+
|
|
63
|
+
The following environment variables are set to match the test matrix:
|
|
64
|
+
|
|
65
|
+
- `REDIS_VERSION`: latest
|
|
66
|
+
- `RESQUE`: master
|
|
67
|
+
- `RUFUS_SCHEDULER`: 3.6
|
|
68
|
+
- `RACK_VERSION`: 3
|
|
69
|
+
- `COVERAGE`: 1
|
|
70
|
+
|
|
71
|
+
## Services
|
|
72
|
+
|
|
73
|
+
### Redis
|
|
74
|
+
Redis is available at `redis://redis:6379` or via `localhost:6379` from within the container.
|
|
75
|
+
|
|
76
|
+
To connect to Redis CLI:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
redis-cli -h redis
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Troubleshooting
|
|
83
|
+
|
|
84
|
+
### Bundle Install Issues
|
|
85
|
+
|
|
86
|
+
If you encounter issues with bundle install, try:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
bundle config set --local build.redis --with-cflags="-Wno-error=implicit-function-declaration"
|
|
90
|
+
bundle install
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Redis Connection Issues
|
|
94
|
+
|
|
95
|
+
Make sure Redis is running:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
redis-cli -h redis ping
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Should return `PONG`.
|
|
102
|
+
|
|
103
|
+
### Rebuilding the Container
|
|
104
|
+
|
|
105
|
+
If you need to rebuild the container from scratch:
|
|
106
|
+
|
|
107
|
+
1. Run "Dev Containers: Rebuild Container" from the command palette
|
|
108
|
+
2. Or delete the container and volume manually:
|
|
109
|
+
```bash
|
|
110
|
+
docker-compose -f .devcontainer/docker-compose.yml down -v
|
|
111
|
+
```
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Resque Scheduler Dev Container",
|
|
3
|
+
"dockerComposeFile": "docker-compose.yml",
|
|
4
|
+
"service": "app",
|
|
5
|
+
"workspaceFolder": "/workspaces/resque-scheduler",
|
|
6
|
+
|
|
7
|
+
// Features to add to the dev container
|
|
8
|
+
"features": {
|
|
9
|
+
"ghcr.io/devcontainers/features/git:1": {}
|
|
10
|
+
},
|
|
11
|
+
|
|
12
|
+
// Configure tool-specific properties
|
|
13
|
+
"customizations": {
|
|
14
|
+
"vscode": {
|
|
15
|
+
"extensions": [
|
|
16
|
+
"rebornix.ruby"
|
|
17
|
+
],
|
|
18
|
+
"settings": {
|
|
19
|
+
"terminal.integrated.defaultProfile.linux": "bash"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
// Use 'forwardPorts' to make a list of ports inside the container available locally
|
|
25
|
+
"forwardPorts": [6379],
|
|
26
|
+
|
|
27
|
+
// Use 'postCreateCommand' to run commands after the container is created
|
|
28
|
+
"postCreateCommand": "bundle install",
|
|
29
|
+
|
|
30
|
+
// Set environment variables for the test matrix
|
|
31
|
+
"containerEnv": {
|
|
32
|
+
"REDIS_VERSION": "latest",
|
|
33
|
+
"RESQUE": "master",
|
|
34
|
+
"RUFUS_SCHEDULER": "3.6",
|
|
35
|
+
"RACK_VERSION": "3",
|
|
36
|
+
"COVERAGE": "1"
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root
|
|
40
|
+
"remoteUser": "vscode"
|
|
41
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
services:
|
|
2
|
+
app:
|
|
3
|
+
build:
|
|
4
|
+
context: .
|
|
5
|
+
dockerfile: Dockerfile
|
|
6
|
+
volumes:
|
|
7
|
+
- ../..:/workspaces:cached
|
|
8
|
+
working_dir: /workspaces/resque-scheduler
|
|
9
|
+
command: sleep infinity
|
|
10
|
+
environment:
|
|
11
|
+
REDIS_VERSION: "latest"
|
|
12
|
+
RESQUE: "master"
|
|
13
|
+
RUFUS_SCHEDULER: "3.6"
|
|
14
|
+
RACK_VERSION: "3"
|
|
15
|
+
COVERAGE: "1"
|
|
16
|
+
REDIS_URL: "redis://redis:6379"
|
|
17
|
+
depends_on:
|
|
18
|
+
- redis
|
|
19
|
+
# Runs app on the same network as the redis container, allows "forwardPorts" in devcontainer.json function
|
|
20
|
+
network_mode: service:redis
|
|
21
|
+
|
|
22
|
+
redis:
|
|
23
|
+
image: redis:latest
|
|
24
|
+
restart: unless-stopped
|
|
25
|
+
ports:
|
|
26
|
+
- "6379:6379"
|
|
27
|
+
volumes:
|
|
28
|
+
- redis-data:/data
|
|
29
|
+
|
|
30
|
+
volumes:
|
|
31
|
+
redis-data:
|
data/.github/workflows/ruby.yml
CHANGED
|
@@ -19,57 +19,29 @@ jobs:
|
|
|
19
19
|
fail-fast: false
|
|
20
20
|
matrix:
|
|
21
21
|
ruby-version:
|
|
22
|
-
- 2.3
|
|
23
|
-
- 2.4
|
|
24
|
-
- 2.5
|
|
25
|
-
- 2.6
|
|
26
|
-
- 2.7
|
|
27
22
|
- "3.0"
|
|
28
23
|
- 3.1
|
|
29
24
|
- 3.2
|
|
30
25
|
- 3.3
|
|
26
|
+
- 3.4
|
|
27
|
+
- head
|
|
31
28
|
resque-version:
|
|
32
29
|
- "master"
|
|
33
|
-
- "~> 2.4.0"
|
|
34
|
-
- "~> 1.27"
|
|
35
30
|
rufus-scheduler:
|
|
36
|
-
- "3.2"
|
|
37
31
|
- "3.4"
|
|
38
32
|
- "3.5"
|
|
39
33
|
- "3.6"
|
|
40
34
|
redis-version:
|
|
41
|
-
- "
|
|
42
|
-
- "
|
|
43
|
-
|
|
44
|
-
-
|
|
45
|
-
|
|
46
|
-
- ruby-version: 3.2
|
|
47
|
-
rufus-scheduler: 3.2
|
|
48
|
-
|
|
49
|
-
- ruby-version: 2.3
|
|
50
|
-
resque-version: "~> 1.27"
|
|
51
|
-
rufus-scheduler: 3.4
|
|
52
|
-
- ruby-version: 2.3
|
|
53
|
-
resque-version: "~> 1.27"
|
|
54
|
-
rufus-scheduler: 3.5
|
|
55
|
-
- ruby-version: 2.5
|
|
56
|
-
resque-version: "~> 2.4.0"
|
|
57
|
-
rufus-scheduler: 3.5
|
|
58
|
-
- ruby-version: 2.5
|
|
59
|
-
resque-version: master
|
|
60
|
-
rufus-scheduler: 3.2
|
|
61
|
-
|
|
62
|
-
- ruby-version: 2.3
|
|
63
|
-
redis-version: "~> 5.x"
|
|
64
|
-
- ruby-version: 2.4
|
|
65
|
-
redis-version: "~> 5.x"
|
|
66
|
-
|
|
67
|
-
- resque-version: "~> 1.27"
|
|
68
|
-
redis-version: "~> 5.x"
|
|
35
|
+
- "4.8"
|
|
36
|
+
- "latest"
|
|
37
|
+
rack-version:
|
|
38
|
+
- 2
|
|
39
|
+
- 3
|
|
69
40
|
env:
|
|
70
41
|
REDIS_VERSION: "${{ matrix.redis-version }}"
|
|
71
42
|
RESQUE: "${{ matrix.resque-version }}"
|
|
72
43
|
RUFUS_SCHEDULER: "${{ matrix.rufus-scheduler }}"
|
|
44
|
+
RACK_VERSION: "${{ matrix.rack-version }}"
|
|
73
45
|
COVERAGE: 1
|
|
74
46
|
|
|
75
47
|
steps:
|
data/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,54 @@
|
|
|
2
2
|
|
|
3
3
|
**ATTN**: This project uses [semantic versioning](http://semver.org/).
|
|
4
4
|
|
|
5
|
-
## [
|
|
5
|
+
## [5.0.1] - 2026-10-11
|
|
6
|
+
### Changed
|
|
7
|
+
* Pipeline `count_all_scheduled_jobs` for significantly faster execution by @top-sigrid in #822
|
|
8
|
+
* Avoid unnecessary reloads in static mode by @ekmartin in #823
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
* Skip invalid schedules without interrupting scheduler loading by @taf2 in #543
|
|
12
|
+
* Encode a delayed job once so its timestamps key can be cleaned up by @kamaljoshi in #827 (originally #599)
|
|
13
|
+
* Log to the logfile when backgrounded by @meatballhat in #828 (originally #568)
|
|
14
|
+
* Require redis before using its error classes by @neuromanskie in #829
|
|
15
|
+
* Fix flaky test by using strings instead of symbols for JSON-serialized args by @top-sigrid in #813
|
|
16
|
+
|
|
17
|
+
### Security
|
|
18
|
+
* Escape job class and queue names in the scheduler web UI by @PatrickTulskie in #830
|
|
19
|
+
* Escape schedule names and parameters on the requeue params page by @PatrickTulskie in #831
|
|
20
|
+
* Escape the scheduler environment and master lock holder on the schedule page by @PatrickTulskie in #832
|
|
21
|
+
|
|
22
|
+
## [5.0.0] - 2026-01-15
|
|
23
|
+
### Breaking Changes
|
|
24
|
+
* Ruby requirement: `>= 2.3.0` → `>= 3.0.0`
|
|
25
|
+
* Resque dependency: `>= 1.27` → `>= 3.0`
|
|
26
|
+
* Redis dependency: `>= 3.3` → `>= 4.0`
|
|
27
|
+
* Removed `rack < 3` constraint
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
* Add Ruby 3.4 to the CI matrix by @and9000 in #804
|
|
31
|
+
* Added `base64 ~> 0.1` runtime dependency (Ruby 3.4+ compatibility) by @PatrickTulskie in #809
|
|
32
|
+
* Added `irb` dev dependency (Ruby 4+ compatibility) by @PatrickTulskie in #809
|
|
33
|
+
* Added Rack 2/3 matrix testing by @PatrickTulskie in #809
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
* Prepare for resque 3.0 compatibility by @PatrickTulskie in #809
|
|
37
|
+
* CI now tests Ruby 3.0-3.4 + head only (removed Ruby 2.x)
|
|
38
|
+
* Simplified to test against resque master only
|
|
39
|
+
* Modernized `.rubocop.yml` to `DisabledByDefault: true` approach
|
|
40
|
+
* Set `TargetRubyVersion: 3.0`
|
|
41
|
+
* Updated rubocop: `~> 0.40.0` → `~> 0.80`
|
|
42
|
+
* Use `JSON.parse` instead of `JSON.load` (security improvement) by @PatrickTulskie in #809
|
|
43
|
+
* Use `URI.decode_www_form_component` instead of `CGI.unescape` by @PatrickTulskie in #809
|
|
44
|
+
* Consistent time formatting in views by @PatrickTulskie in #809
|
|
45
|
+
|
|
46
|
+
### Fixed
|
|
47
|
+
* Fix `Resque::Scheduler.print_schedule` by @codealchemy in #794
|
|
48
|
+
* Remove circular require for resque from resque-scheduler by @zzak in #795
|
|
49
|
+
* Fixed test compatibility with Rack 3 by @PatrickTulskie in #809
|
|
50
|
+
* Fixed race condition in scheduler task tests by @PatrickTulskie in #809
|
|
51
|
+
|
|
52
|
+
## [4.11.0] - 2024-12-30
|
|
6
53
|
### Added
|
|
7
54
|
* Expose timeout for lock via environment variable configuration by @pmm4654 in #786
|
|
8
55
|
* Add Ruby 3.3 to the CI matrix by @santiagorodriguez96 in #797
|
data/Gemfile
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
# vim:fileencoding=utf-8
|
|
2
|
-
require 'resque'
|
|
3
2
|
require_relative 'plugin'
|
|
4
3
|
require_relative '../scheduler'
|
|
5
4
|
|
|
@@ -84,11 +83,13 @@ module Resque
|
|
|
84
83
|
# insertion time complexity is O(log(n)). Returns true if it's
|
|
85
84
|
# the first job to be scheduled at that time, else false.
|
|
86
85
|
def delayed_push(timestamp, item)
|
|
86
|
+
encoded_job = encode(item)
|
|
87
|
+
|
|
87
88
|
# First add this item to the list for this timestamp
|
|
88
|
-
redis.rpush("delayed:#{timestamp.to_i}",
|
|
89
|
+
redis.rpush("delayed:#{timestamp.to_i}", encoded_job)
|
|
89
90
|
|
|
90
91
|
# Store the timestamps at with this item occurs
|
|
91
|
-
redis.sadd("timestamps:#{
|
|
92
|
+
redis.sadd("timestamps:#{encoded_job}", ["delayed:#{timestamp.to_i}"])
|
|
92
93
|
|
|
93
94
|
# Now, add this timestamp to the zsets. The score and the value are
|
|
94
95
|
# the same since we'll be querying by timestamp, and we don't have
|
|
@@ -262,12 +263,18 @@ module Resque
|
|
|
262
263
|
count
|
|
263
264
|
end
|
|
264
265
|
|
|
266
|
+
# Counts all jobs across all delayed timestamps.
|
|
267
|
+
# Uses pipelined LLEN calls in batches to avoid blocking the Redis thread
|
|
268
|
+
# for too long while being significantly faster than sequential calls.
|
|
265
269
|
def count_all_scheduled_jobs
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
270
|
+
timestamps = Array(redis.zrange(:delayed_queue_schedule, 0, -1))
|
|
271
|
+
return 0 if timestamps.empty?
|
|
272
|
+
|
|
273
|
+
timestamps.each_slice(10_000).sum do |batch|
|
|
274
|
+
redis.pipelined do |pipeline|
|
|
275
|
+
batch.each { |ts| pipeline.llen("delayed:#{ts}") }
|
|
276
|
+
end.sum
|
|
269
277
|
end
|
|
270
|
-
total_jobs
|
|
271
278
|
end
|
|
272
279
|
|
|
273
280
|
# Discover if a job has been delayed.
|
data/lib/resque/scheduler/env.rb
CHANGED
|
@@ -30,18 +30,18 @@ module Resque
|
|
|
30
30
|
def setup_backgrounding
|
|
31
31
|
return unless options[:background]
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
# stderr/stdout to /dev/null
|
|
35
|
-
Resque::Scheduler.quiet = if options.key?(:quiet)
|
|
36
|
-
!!options[:quiet]
|
|
37
|
-
else
|
|
38
|
-
true
|
|
39
|
-
end
|
|
33
|
+
Resque::Scheduler.quiet = background_quiet?
|
|
40
34
|
|
|
41
35
|
Process.daemon(true, !Resque::Scheduler.quiet)
|
|
42
36
|
Resque.redis.reconnect
|
|
43
37
|
end
|
|
44
38
|
|
|
39
|
+
def background_quiet?
|
|
40
|
+
return !!options[:quiet] if options.key?(:quiet)
|
|
41
|
+
return false if options.key?(:logfile)
|
|
42
|
+
!!options[:background]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
45
|
def setup_pid_file
|
|
46
46
|
return unless options[:pidfile]
|
|
47
47
|
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
<% jobs = resque.delayed_timestamp_peek(timestamp, start, 20) %>
|
|
13
13
|
<% jobs.each do |job| %>
|
|
14
14
|
<tr>
|
|
15
|
-
<td class='class'><%= job['class'] %></td>
|
|
15
|
+
<td class='class'><%= h job['class'] %></td>
|
|
16
16
|
<td class='args'><%= h show_job_arguments(job['args']) %></td>
|
|
17
17
|
</tr>
|
|
18
18
|
<% end %>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<h1><%= @job_name %></h1>
|
|
1
|
+
<h1><%= h @job_name %></h1>
|
|
2
2
|
|
|
3
3
|
<p class='intro'>
|
|
4
4
|
This job requires parameters:
|
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
<% value ||= {} %>
|
|
11
11
|
<tr>
|
|
12
12
|
<td>
|
|
13
|
-
<%= key %>
|
|
13
|
+
<%= h key %>
|
|
14
14
|
<% if value['description'] || value[:description] %>
|
|
15
|
-
<span style="border-bottom:1px dotted;" title="<%=value
|
|
15
|
+
<span style="border-bottom:1px dotted;" title="<%= h(value['description'] || value[:description]) %>">(?)</span>
|
|
16
16
|
<% end %>:
|
|
17
17
|
</td>
|
|
18
|
-
<td><input type="text" name="<%= key %>" value="<%= value['default'] || value[:default] %>"></td>
|
|
18
|
+
<td><input type="text" name="<%= h key %>" value="<%= h(value['default'] || value[:default]) %>"></td>
|
|
19
19
|
<% end %>
|
|
20
20
|
</table>
|
|
21
|
-
<input type="hidden" name="job_name" value="<%= @job_name %>">
|
|
21
|
+
<input type="hidden" name="job_name" value="<%= h @job_name %>">
|
|
22
22
|
<input type="submit" value="Queue now">
|
|
23
23
|
</form>
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
The list below contains all scheduled jobs. Click "Queue now" to queue
|
|
5
5
|
a job immediately.
|
|
6
6
|
<br/> Server local time: <%= Time.now %>
|
|
7
|
-
<br/> Server Environment: <%= Resque::Scheduler.env %>
|
|
8
|
-
<br/> Current master: <%= Resque.redis.get(Resque::Scheduler.master_lock.key) %>
|
|
7
|
+
<br/> Server Environment: <%= h Resque::Scheduler.env %>
|
|
8
|
+
<br/> Current master: <%= h 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.
|
|
@@ -22,13 +22,13 @@
|
|
|
22
22
|
<td style="padding-top: 12px; padding-bottom: 2px; width: 10px">
|
|
23
23
|
<form action="<%= u "/delayed/cancel_now" %>" method="post">
|
|
24
24
|
<input type="hidden" name="timestamp" value="<%= job['timestamp'].to_i %>">
|
|
25
|
-
<input type="hidden" name="klass" value="<%= job['class'] %>">
|
|
25
|
+
<input type="hidden" name="klass" value="<%= h job['class'] %>">
|
|
26
26
|
<input type="hidden" name="args" value="<%= h(Resque.encode job['args']) %>">
|
|
27
27
|
<input type="submit" value="Cancel Job">
|
|
28
28
|
</form>
|
|
29
29
|
</td>
|
|
30
30
|
<td class='args'><%= format_time(Time.at(job['timestamp'])) %></td>
|
|
31
|
-
<td class='class'><%= job['class'] %></td>
|
|
31
|
+
<td class='class'><%= h job['class'] %></td>
|
|
32
32
|
<td class='args'><%= h job['args'].inspect %></td>
|
|
33
33
|
</tr>
|
|
34
34
|
<% end %>
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
</tr>
|
|
45
45
|
<% queued.each do |job| %>
|
|
46
46
|
<tr>
|
|
47
|
-
<td class='class'><%= job['queue'] %></td>
|
|
48
|
-
<td class='class'><%= job['class'] %></td>
|
|
47
|
+
<td class='class'><%= h job['queue'] %></td>
|
|
48
|
+
<td class='class'><%= h job['class'] %></td>
|
|
49
49
|
<td class='args'><%= h job['args'].inspect %></td>
|
|
50
50
|
</tr>
|
|
51
51
|
<% end %>
|
|
@@ -61,8 +61,8 @@
|
|
|
61
61
|
</tr>
|
|
62
62
|
<% working.each do |job| %>
|
|
63
63
|
<tr>
|
|
64
|
-
<td class='class'><%= job['queue'] %></td>
|
|
65
|
-
<td class='class'><%= job['class'] %></td>
|
|
64
|
+
<td class='class'><%= h job['queue'] %></td>
|
|
65
|
+
<td class='class'><%= h job['class'] %></td>
|
|
66
66
|
<td class='args'><%= h job['args'].inspect %></td>
|
|
67
67
|
</tr>
|
|
68
68
|
<% end %>
|
|
@@ -87,9 +87,11 @@ module Resque
|
|
|
87
87
|
def delayed_jobs_klass
|
|
88
88
|
begin
|
|
89
89
|
klass = Resque::Scheduler::Util.constantize(params[:klass])
|
|
90
|
-
|
|
90
|
+
args_param = params[:args] || params['args']
|
|
91
|
+
@args = args_param ? JSON.parse(URI.decode_www_form_component(args_param)) : []
|
|
91
92
|
@timestamps = Resque.scheduled_at(klass, *@args)
|
|
92
93
|
rescue
|
|
94
|
+
@args = []
|
|
93
95
|
@timestamps = []
|
|
94
96
|
end
|
|
95
97
|
|
data/lib/resque/scheduler.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# vim:fileencoding=utf-8
|
|
2
2
|
|
|
3
|
-
require 'redis
|
|
3
|
+
require 'redis'
|
|
4
4
|
require 'rufus/scheduler'
|
|
5
5
|
require_relative 'scheduler/configuration'
|
|
6
6
|
require_relative 'scheduler/locking'
|
|
@@ -49,6 +49,7 @@ module Resque
|
|
|
49
49
|
$stderr.sync = true
|
|
50
50
|
|
|
51
51
|
was_master = nil
|
|
52
|
+
schedule_loaded = false
|
|
52
53
|
|
|
53
54
|
begin
|
|
54
55
|
@th = Thread.current
|
|
@@ -61,8 +62,14 @@ module Resque
|
|
|
61
62
|
if am_master != was_master
|
|
62
63
|
procline am_master ? 'Master scheduler' : 'Child scheduler'
|
|
63
64
|
|
|
64
|
-
#
|
|
65
|
-
|
|
65
|
+
# The first pass always loads the schedule - load_schedule!
|
|
66
|
+
# reads am_master, so it cannot run before the check above.
|
|
67
|
+
# After that, only a dynamic schedule can have changed while
|
|
68
|
+
# we were not master.
|
|
69
|
+
if dynamic || !schedule_loaded
|
|
70
|
+
reload_schedule!
|
|
71
|
+
schedule_loaded = true
|
|
72
|
+
end
|
|
66
73
|
end
|
|
67
74
|
|
|
68
75
|
if am_master
|
|
@@ -86,8 +93,8 @@ module Resque
|
|
|
86
93
|
if rufus_scheduler
|
|
87
94
|
log! "Scheduling Info\tLast Run"
|
|
88
95
|
scheduler_jobs = rufus_scheduler.jobs
|
|
89
|
-
scheduler_jobs.each do |
|
|
90
|
-
log! "#{
|
|
96
|
+
scheduler_jobs.each do |job|
|
|
97
|
+
log! "#{job.opts}\t#{job.last_time}\t"
|
|
91
98
|
end
|
|
92
99
|
end
|
|
93
100
|
end
|
|
@@ -148,8 +155,13 @@ module Resque
|
|
|
148
155
|
args = optionizate_interval_value(config[interval_type])
|
|
149
156
|
args = [args, nil, job: true] if args.is_a?(::String)
|
|
150
157
|
|
|
151
|
-
|
|
152
|
-
|
|
158
|
+
begin
|
|
159
|
+
job = rufus_scheduler.send(interval_type, *args) do
|
|
160
|
+
enqueue_recurring(name, config)
|
|
161
|
+
end
|
|
162
|
+
rescue ArgumentError => e
|
|
163
|
+
log_error "Invalid #{interval_type} schedule for #{name}: #{e.message} - skipping"
|
|
164
|
+
return
|
|
153
165
|
end
|
|
154
166
|
@scheduled_jobs[name] = job
|
|
155
167
|
interval_defined = true
|
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 = '>=
|
|
35
|
+
spec.required_ruby_version = '>= 3.0.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)/}) ||
|
|
@@ -45,8 +45,10 @@ Gem::Specification.new do |spec|
|
|
|
45
45
|
|
|
46
46
|
spec.add_development_dependency 'bundler'
|
|
47
47
|
spec.add_development_dependency 'json'
|
|
48
|
+
spec.add_development_dependency 'irb'
|
|
48
49
|
spec.add_development_dependency 'minitest'
|
|
49
50
|
spec.add_development_dependency 'mocha'
|
|
51
|
+
spec.add_development_dependency 'ostruct'
|
|
50
52
|
spec.add_development_dependency 'pry'
|
|
51
53
|
spec.add_development_dependency 'rack-test'
|
|
52
54
|
spec.add_development_dependency 'rake'
|
|
@@ -57,11 +59,13 @@ Gem::Specification.new do |spec|
|
|
|
57
59
|
|
|
58
60
|
# We pin rubocop because new cops have a tendency to result in false-y
|
|
59
61
|
# positives for new contributors, which is not a nice experience.
|
|
60
|
-
spec.add_development_dependency 'rubocop', '~> 0.
|
|
62
|
+
spec.add_development_dependency 'rubocop', '~> 0.80'
|
|
61
63
|
|
|
64
|
+
spec.add_runtime_dependency 'base64', '~> 0.1'
|
|
65
|
+
spec.add_runtime_dependency 'logger'
|
|
62
66
|
spec.add_runtime_dependency 'mono_logger', '~> 1.0'
|
|
63
|
-
spec.add_runtime_dependency 'redis', '>=
|
|
64
|
-
spec.add_runtime_dependency 'resque', '>=
|
|
67
|
+
spec.add_runtime_dependency 'redis', '>= 4.0'
|
|
68
|
+
spec.add_runtime_dependency 'resque', '>= 3.0'
|
|
65
69
|
# rufus-scheduler v3.7 causes a failure in test/multi_process_test.rb
|
|
66
70
|
# rufus-scheduler v3.3 is missing a to_local method which fails tests
|
|
67
71
|
spec.add_runtime_dependency 'rufus-scheduler', '~> 3.2', '!= 3.3'
|
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
|
+
version: 5.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ben VandenBos
|
|
@@ -10,10 +10,9 @@ authors:
|
|
|
10
10
|
- Dan Buch
|
|
11
11
|
- Michael Bianco
|
|
12
12
|
- Patrick Tulskie
|
|
13
|
-
autorequire:
|
|
14
13
|
bindir: exe
|
|
15
14
|
cert_chain: []
|
|
16
|
-
date:
|
|
15
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
17
16
|
dependencies:
|
|
18
17
|
- !ruby/object:Gem::Dependency
|
|
19
18
|
name: bundler
|
|
@@ -43,6 +42,20 @@ dependencies:
|
|
|
43
42
|
- - ">="
|
|
44
43
|
- !ruby/object:Gem::Version
|
|
45
44
|
version: '0'
|
|
45
|
+
- !ruby/object:Gem::Dependency
|
|
46
|
+
name: irb
|
|
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'
|
|
46
59
|
- !ruby/object:Gem::Dependency
|
|
47
60
|
name: minitest
|
|
48
61
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -71,6 +84,20 @@ dependencies:
|
|
|
71
84
|
- - ">="
|
|
72
85
|
- !ruby/object:Gem::Version
|
|
73
86
|
version: '0'
|
|
87
|
+
- !ruby/object:Gem::Dependency
|
|
88
|
+
name: ostruct
|
|
89
|
+
requirement: !ruby/object:Gem::Requirement
|
|
90
|
+
requirements:
|
|
91
|
+
- - ">="
|
|
92
|
+
- !ruby/object:Gem::Version
|
|
93
|
+
version: '0'
|
|
94
|
+
type: :development
|
|
95
|
+
prerelease: false
|
|
96
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
97
|
+
requirements:
|
|
98
|
+
- - ">="
|
|
99
|
+
- !ruby/object:Gem::Version
|
|
100
|
+
version: '0'
|
|
74
101
|
- !ruby/object:Gem::Dependency
|
|
75
102
|
name: pry
|
|
76
103
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -175,14 +202,42 @@ dependencies:
|
|
|
175
202
|
requirements:
|
|
176
203
|
- - "~>"
|
|
177
204
|
- !ruby/object:Gem::Version
|
|
178
|
-
version: 0.
|
|
205
|
+
version: '0.80'
|
|
179
206
|
type: :development
|
|
180
207
|
prerelease: false
|
|
181
208
|
version_requirements: !ruby/object:Gem::Requirement
|
|
182
209
|
requirements:
|
|
183
210
|
- - "~>"
|
|
184
211
|
- !ruby/object:Gem::Version
|
|
185
|
-
version: 0.
|
|
212
|
+
version: '0.80'
|
|
213
|
+
- !ruby/object:Gem::Dependency
|
|
214
|
+
name: base64
|
|
215
|
+
requirement: !ruby/object:Gem::Requirement
|
|
216
|
+
requirements:
|
|
217
|
+
- - "~>"
|
|
218
|
+
- !ruby/object:Gem::Version
|
|
219
|
+
version: '0.1'
|
|
220
|
+
type: :runtime
|
|
221
|
+
prerelease: false
|
|
222
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
223
|
+
requirements:
|
|
224
|
+
- - "~>"
|
|
225
|
+
- !ruby/object:Gem::Version
|
|
226
|
+
version: '0.1'
|
|
227
|
+
- !ruby/object:Gem::Dependency
|
|
228
|
+
name: logger
|
|
229
|
+
requirement: !ruby/object:Gem::Requirement
|
|
230
|
+
requirements:
|
|
231
|
+
- - ">="
|
|
232
|
+
- !ruby/object:Gem::Version
|
|
233
|
+
version: '0'
|
|
234
|
+
type: :runtime
|
|
235
|
+
prerelease: false
|
|
236
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
237
|
+
requirements:
|
|
238
|
+
- - ">="
|
|
239
|
+
- !ruby/object:Gem::Version
|
|
240
|
+
version: '0'
|
|
186
241
|
- !ruby/object:Gem::Dependency
|
|
187
242
|
name: mono_logger
|
|
188
243
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -203,28 +258,28 @@ dependencies:
|
|
|
203
258
|
requirements:
|
|
204
259
|
- - ">="
|
|
205
260
|
- !ruby/object:Gem::Version
|
|
206
|
-
version: '
|
|
261
|
+
version: '4.0'
|
|
207
262
|
type: :runtime
|
|
208
263
|
prerelease: false
|
|
209
264
|
version_requirements: !ruby/object:Gem::Requirement
|
|
210
265
|
requirements:
|
|
211
266
|
- - ">="
|
|
212
267
|
- !ruby/object:Gem::Version
|
|
213
|
-
version: '
|
|
268
|
+
version: '4.0'
|
|
214
269
|
- !ruby/object:Gem::Dependency
|
|
215
270
|
name: resque
|
|
216
271
|
requirement: !ruby/object:Gem::Requirement
|
|
217
272
|
requirements:
|
|
218
273
|
- - ">="
|
|
219
274
|
- !ruby/object:Gem::Version
|
|
220
|
-
version: '
|
|
275
|
+
version: '3.0'
|
|
221
276
|
type: :runtime
|
|
222
277
|
prerelease: false
|
|
223
278
|
version_requirements: !ruby/object:Gem::Requirement
|
|
224
279
|
requirements:
|
|
225
280
|
- - ">="
|
|
226
281
|
- !ruby/object:Gem::Version
|
|
227
|
-
version: '
|
|
282
|
+
version: '3.0'
|
|
228
283
|
- !ruby/object:Gem::Dependency
|
|
229
284
|
name: rufus-scheduler
|
|
230
285
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -261,8 +316,11 @@ executables:
|
|
|
261
316
|
extensions: []
|
|
262
317
|
extra_rdoc_files: []
|
|
263
318
|
files:
|
|
319
|
+
- ".devcontainer/Dockerfile"
|
|
320
|
+
- ".devcontainer/README.md"
|
|
321
|
+
- ".devcontainer/devcontainer.json"
|
|
322
|
+
- ".devcontainer/docker-compose.yml"
|
|
264
323
|
- ".github/dependabot.yml"
|
|
265
|
-
- ".github/funding.yml"
|
|
266
324
|
- ".github/workflows/codeql-analysis.yml"
|
|
267
325
|
- ".github/workflows/rubocop.yml"
|
|
268
326
|
- ".github/workflows/ruby.yml"
|
|
@@ -309,7 +367,6 @@ licenses:
|
|
|
309
367
|
- MIT
|
|
310
368
|
metadata:
|
|
311
369
|
rubygems_mfa_required: 'true'
|
|
312
|
-
post_install_message:
|
|
313
370
|
rdoc_options: []
|
|
314
371
|
require_paths:
|
|
315
372
|
- lib
|
|
@@ -317,15 +374,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
317
374
|
requirements:
|
|
318
375
|
- - ">="
|
|
319
376
|
- !ruby/object:Gem::Version
|
|
320
|
-
version:
|
|
377
|
+
version: 3.0.0
|
|
321
378
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
322
379
|
requirements:
|
|
323
380
|
- - ">="
|
|
324
381
|
- !ruby/object:Gem::Version
|
|
325
382
|
version: '0'
|
|
326
383
|
requirements: []
|
|
327
|
-
rubygems_version:
|
|
328
|
-
signing_key:
|
|
384
|
+
rubygems_version: 4.0.16
|
|
329
385
|
specification_version: 4
|
|
330
386
|
summary: Light weight job scheduling on top of Resque
|
|
331
387
|
test_files: []
|
data/.github/funding.yml
DELETED