resque 2.1.0 → 2.3.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 might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/HISTORY.md +31 -5
- data/README.markdown +59 -56
- data/bin/resque-web +10 -26
- data/lib/resque/data_store.rb +29 -28
- data/lib/resque/failure.rb +6 -0
- data/lib/resque/server/helpers.rb +3 -1
- data/lib/resque/server/views/error.erb +1 -1
- data/lib/resque/server/views/failed.erb +9 -3
- data/lib/resque/server/views/job_class.erb +3 -1
- data/lib/resque/server/views/key_string.erb +1 -1
- data/lib/resque/server/views/layout.erb +1 -1
- data/lib/resque/server/views/next_more.erb +2 -2
- data/lib/resque/server/views/queues.erb +1 -1
- data/lib/resque/server.rb +6 -1
- data/lib/resque/stat.rb +4 -4
- data/lib/resque/tasks.rb +1 -1
- data/lib/resque/version.rb +1 -1
- data/lib/resque/web_runner.rb +372 -0
- data/lib/resque/worker.rb +24 -15
- data/lib/resque.rb +8 -8
- metadata +40 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 26c77950669242c68e75f64480a798486a84ac3aa2c4bd22c5ae212caa6bf57c
|
4
|
+
data.tar.gz: bea29587e61e5b2a41c675ff26afb69cca7891613212e0d052a41a43ce5404b4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 81f58c37a382d84e6f168ad9ada384ac160c223fa5cc1070c251ad01c8840389af78736af263aa3cd594dcd77970a2539a7f44082dca07a25f236c6d147625b4
|
7
|
+
data.tar.gz: f28ffa6efb6e8037cf3ec7d233f824b7190f97d91c4d3d6ba00399e6533f2958581e98422a31068a9145dd789f63d1caff58ca8744905a1cf747b02eaeed9d02
|
data/HISTORY.md
CHANGED
@@ -1,14 +1,40 @@
|
|
1
|
-
##
|
1
|
+
## 2.3.0
|
2
|
+
|
3
|
+
### Fixed
|
4
|
+
|
5
|
+
* Fix NoMethodError: undefined method 'application' for Rails:Module when Rails module is defined but not a full Rails app (#1799)
|
6
|
+
* Fix deprecation warnings in Redis#pipelined for redis 4.6 (#1806)
|
7
|
+
* Add Ruby syntax highlighting to remaining markdown docs (#1802)
|
8
|
+
* Fix pagination section (#1809)
|
9
|
+
* Fix `before_run` undefined local variable or method `runner` (#1811)
|
10
|
+
|
11
|
+
### Added
|
12
|
+
|
13
|
+
* Added support for pausing all workers by setting the Redis key `pause-all-workers` to string value "true" (#1803)
|
14
|
+
|
15
|
+
## 2.2.1
|
16
|
+
|
17
|
+
### Fixed
|
18
|
+
|
19
|
+
* Escape HTML from the params to avoid XSS (#1790)
|
20
|
+
* Remove vegas as a dependency (#1780)
|
21
|
+
|
22
|
+
### Added
|
23
|
+
|
24
|
+
* Add support for specifying queues that workers should ignore when using globs
|
25
|
+
* Allow plugins to have spaces in their name (#1718)
|
26
|
+
|
27
|
+
## 2.2.0
|
2
28
|
|
3
29
|
### Added
|
4
30
|
|
5
|
-
*
|
6
|
-
*
|
31
|
+
* Add 'Retry Failed Jobs' button to Failed page
|
7
32
|
|
8
33
|
### Fixed
|
9
34
|
|
10
|
-
*
|
11
|
-
*
|
35
|
+
* Loading railtie when it did not exist #1765
|
36
|
+
* Fix closing parent Redis connection in child process after fork
|
37
|
+
* Fix the failed queues list on /queues UI when the RedisMultiQueue backend is used #1638
|
12
38
|
|
13
39
|
## 2.1.0
|
14
40
|
|
data/README.markdown
CHANGED
@@ -4,19 +4,15 @@ Resque
|
|
4
4
|
[![Gem Version](https://badge.fury.io/rb/resque.svg)](https://rubygems.org/gems/resque)
|
5
5
|
[![Build Status](https://github.com/resque/resque/actions/workflows/ci.yml/badge.svg)](https://github.com/resque/resque/actions/workflows/ci.yml)
|
6
6
|
|
7
|
+
Introduction
|
8
|
+
------------
|
9
|
+
|
7
10
|
Resque (pronounced like "rescue") is a Redis-backed library for creating
|
8
11
|
background jobs, placing those jobs on multiple queues, and processing
|
9
12
|
them later.
|
10
13
|
|
11
|
-
|
12
|
-
### Note on the future of this repo
|
13
|
-
|
14
|
-
Would you like to be involved in Resque? Do you have thoughts about what
|
15
|
-
Resque should be and do going forward? There's currently an [open discussion here](https://github.com/resque/resque/issues/1759)
|
16
|
-
on just that topic, so please feel free to join in. We'd love to hear your thoughts
|
17
|
-
and/or have people volunteer to be a part of the project!
|
14
|
+
For the backstory, philosophy, and history of Resque's beginnings, please see [the blog post](http://github.com/blog/542-introducing-resque) (2009).
|
18
15
|
|
19
|
-
---------
|
20
16
|
Background jobs can be any Ruby class or module that responds to
|
21
17
|
`perform`. Your existing classes can easily be converted to background
|
22
18
|
jobs or you can create new classes specifically to do work. Or, you
|
@@ -29,10 +25,11 @@ three parts:
|
|
29
25
|
2. A Rake task for starting a worker which processes jobs
|
30
26
|
3. A Sinatra app for monitoring queues, jobs, and workers.
|
31
27
|
|
32
|
-
Resque workers can be
|
33
|
-
|
34
|
-
|
35
|
-
|
28
|
+
Resque workers can be given multiple queues (a "queue list"),
|
29
|
+
distributed between multiple machines,
|
30
|
+
run anywhere with network access to the Redis server,
|
31
|
+
support priorities, are resilient to memory bloat / "leaks,"
|
32
|
+
tell you what they're doing, and expect failure.
|
36
33
|
|
37
34
|
Resque queues are persistent; support constant time, atomic push and
|
38
35
|
pop (thanks to Redis); provide visibility into their contents; and
|
@@ -45,42 +42,15 @@ general usage stats, and helps you track failures.
|
|
45
42
|
Resque now supports Ruby 2.3.0 and above.
|
46
43
|
We will also only be supporting Redis 3.0 and above going forward.
|
47
44
|
|
45
|
+
### Note on the future of Resque
|
48
46
|
|
49
|
-
|
50
|
-
|
47
|
+
Would you like to be involved in Resque? Do you have thoughts about what
|
48
|
+
Resque should be and do going forward? There's currently an [open discussion here](https://github.com/resque/resque/issues/1759)
|
49
|
+
on just that topic, so please feel free to join in. We'd love to hear your thoughts
|
50
|
+
and/or have people volunteer to be a part of the project!
|
51
51
|
|
52
|
-
|
53
|
-
|
54
|
-
* [Running Workers](#running-workers)
|
55
|
-
* [The Front End](#the-front-end)
|
56
|
-
* [Jobs](#jobs)
|
57
|
-
* [Configuration](#configuration)
|
58
|
-
* * [Redis](#redis)
|
59
|
-
* * [Logging](#logging)
|
60
|
-
* * [Namespaces](#namespaces)
|
61
|
-
* * [Storing Statistics](#storing-statistics)
|
62
|
-
* [Plugins and Hooks](#plugins-and-hooks)
|
63
|
-
* [Additional Information](#additional-information)
|
64
|
-
* * [Resque vs DelayedJob](#resque-vs-delayedjob)
|
65
|
-
* * [Forking](#forking)
|
66
|
-
* * [Signals](#signals)
|
67
|
-
* * [Heroku](#heroku)
|
68
|
-
* * [Monitoring](#monitoring)
|
69
|
-
* * [Mysql::Error](#mysqlerror-mysql-server-has-gone-away)
|
70
|
-
* [Development](#development)
|
71
|
-
* * [Demo](#demo)
|
72
|
-
* * [Contributing](#contributing)
|
73
|
-
* [Questions](#questions)
|
74
|
-
* [Meta](#meta)
|
75
|
-
* [Author](#author)
|
76
|
-
|
77
|
-
Overview
|
78
|
-
--------
|
79
|
-
|
80
|
-
For the backstory, philosophy, and history of Resque's beginnings, please see [the blog post](http://github.com/blog/542-introducing-resque).
|
81
|
-
|
82
|
-
Resque allows you to create jobs and place them on a queue, then,
|
83
|
-
later, pull those jobs off the queue and process them.
|
52
|
+
Example
|
53
|
+
-------
|
84
54
|
|
85
55
|
Resque jobs are Ruby classes (or modules) which respond to the
|
86
56
|
`perform` method. Here's an example:
|
@@ -140,10 +110,6 @@ This starts one Resque worker and tells it to work off the
|
|
140
110
|
find any more, at which point it will sleep for a small period and
|
141
111
|
repeatedly poll the queue for more jobs.
|
142
112
|
|
143
|
-
Workers can be given multiple queues (a "queue list") and run on
|
144
|
-
multiple machines. In fact they can be run anywhere with network
|
145
|
-
access to the Redis server.
|
146
|
-
|
147
113
|
Installation
|
148
114
|
------------
|
149
115
|
|
@@ -165,7 +131,7 @@ require 'resque/tasks'
|
|
165
131
|
require 'your/app' # Include this line if you want your workers to have access to your application
|
166
132
|
```
|
167
133
|
|
168
|
-
#### Rails
|
134
|
+
#### Rails
|
169
135
|
|
170
136
|
To make resque specific changes, you can override the `resque:setup` job in `lib/tasks` (ex: `lib/tasks/resque.rake`). GitHub's setup task looks like this:
|
171
137
|
|
@@ -253,6 +219,22 @@ Or, prioritize some queues above `*`:
|
|
253
219
|
|
254
220
|
# QUEUE=critical,* rake resque:work
|
255
221
|
|
222
|
+
#### Running All Queues Except for Some
|
223
|
+
|
224
|
+
If you want your workers to work off of all queues except for some,
|
225
|
+
you can use negation:
|
226
|
+
|
227
|
+
$ QUEUE=*,!low rake resque:work
|
228
|
+
|
229
|
+
Negated globs also work. The following will instruct workers to work
|
230
|
+
off of all queues except those beginning with `file_`:
|
231
|
+
|
232
|
+
$ QUEUE=*,!file_* rake resque:work
|
233
|
+
|
234
|
+
Note that the order in which negated queues are specified does not
|
235
|
+
matter, so `QUEUE=*,!file_*` and `QUEUE=!file_*,*` will have the same
|
236
|
+
effect.
|
237
|
+
|
256
238
|
#### Process IDs (PIDs)
|
257
239
|
|
258
240
|
There are scenarios where it's helpful to record the PID of a resque
|
@@ -331,9 +313,9 @@ run Rack::URLMap.new \
|
|
331
313
|
Check `examples/demo/config.ru` for a functional example (including
|
332
314
|
HTTP basic auth).
|
333
315
|
|
334
|
-
#### Rails
|
316
|
+
#### Rails
|
335
317
|
|
336
|
-
You can also mount Resque on a subpath in your existing Rails
|
318
|
+
You can also mount Resque on a subpath in your existing Rails app by adding `require 'resque/server'` to the top of your routes file or in an initializer then adding this to `routes.rb`:
|
337
319
|
|
338
320
|
``` ruby
|
339
321
|
mount Resque::Server.new, :at => "/resque"
|
@@ -687,6 +669,12 @@ complicated.
|
|
687
669
|
|
688
670
|
Workers instead handle their own state.
|
689
671
|
|
672
|
+
#### `at_exit` Callbacks
|
673
|
+
|
674
|
+
Resque uses `Kernel#exit!` for exiting its workers' child processes. So any `at_exit` callback defined in your application won't be executed when the job is finished and the child process exits.
|
675
|
+
|
676
|
+
You can alter this behavior by setting the `RUN_AT_EXIT_HOOKS` environment variable.
|
677
|
+
|
690
678
|
#### Parents and Children
|
691
679
|
|
692
680
|
Here's a parent / child pair doing some work:
|
@@ -728,7 +716,7 @@ If you want to kill a stale or stuck child and shutdown, use `TERM`
|
|
728
716
|
|
729
717
|
If you want to stop processing jobs, but want to leave the worker running
|
730
718
|
(for example, to temporarily alleviate load), use `USR2` to stop processing,
|
731
|
-
then `CONT` to start it again.
|
719
|
+
then `CONT` to start it again. It's also possible to [pause all workers](#pausing-all-workers).
|
732
720
|
|
733
721
|
#### Heroku
|
734
722
|
|
@@ -752,6 +740,22 @@ time to complete before being forced to die.
|
|
752
740
|
|
753
741
|
* `RESQUE_TERM_TIMEOUT` - By default you have a few seconds to handle `Resque::TermException` in your job. `RESQUE_TERM_TIMEOUT` and `RESQUE_PRE_SHUTDOWN_TIMEOUT` must be lower than the [heroku dyno timeout](https://devcenter.heroku.com/articles/limits#exit-timeout).
|
754
742
|
|
743
|
+
#### Pausing all workers
|
744
|
+
|
745
|
+
Workers will not process pending jobs if the Redis key `pause-all-workers` is set with the string value "true".
|
746
|
+
|
747
|
+
``` ruby
|
748
|
+
Resque.redis.set('pause-all-workers', 'true')
|
749
|
+
```
|
750
|
+
|
751
|
+
Nothing happens to jobs that are already being processed by workers.
|
752
|
+
|
753
|
+
Unpause by removing the Redis key `pause-all-workers`.
|
754
|
+
|
755
|
+
``` ruby
|
756
|
+
Resque.redis.del('pause-all-workers')
|
757
|
+
```
|
758
|
+
|
755
759
|
#### Monitoring
|
756
760
|
|
757
761
|
##### god
|
@@ -770,7 +774,7 @@ send patches for any tweaks or improvements you can make to it.
|
|
770
774
|
|
771
775
|
If your workers remain idle for too long they may lose their MySQL connection. Depending on your version of Rails, we recommend the following:
|
772
776
|
|
773
|
-
##### Rails
|
777
|
+
##### Rails
|
774
778
|
In your `perform` method, add the following line:
|
775
779
|
|
776
780
|
``` ruby
|
@@ -861,7 +865,6 @@ Meta
|
|
861
865
|
* Home: <http://github.com/resque/resque>
|
862
866
|
* Docs: <http://rubydoc.info/gems/resque>
|
863
867
|
* Bugs: <http://github.com/resque/resque/issues>
|
864
|
-
* Chat: <irc://irc.freenode.net/resque>
|
865
868
|
* Gems: <https://rubygems.org/gems/resque>
|
866
869
|
|
867
870
|
This project uses [Semantic Versioning](http://semver.org/)
|
data/bin/resque-web
CHANGED
@@ -1,31 +1,15 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
4
|
-
begin
|
5
|
-
require 'vegas'
|
6
|
-
rescue LoadError
|
7
|
-
require 'rubygems'
|
8
|
-
require 'vegas'
|
9
|
-
end
|
10
|
-
require 'resque/server'
|
11
|
-
|
12
4
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
runner.logger.info "Using Redis namespace '#{namespace}'"
|
21
|
-
Resque.redis.namespace = namespace
|
22
|
-
}
|
23
|
-
opts.on('-r redis-connection', "--redis redis-connection", "set the Redis connection string") {|redis_conf|
|
24
|
-
runner.logger.info "Using Redis connection '#{redis_conf}'"
|
25
|
-
Resque.redis = redis_conf
|
26
|
-
}
|
27
|
-
opts.on('-a url-prefix', "--append url-prefix", "set reverse_proxy friendly prefix to links") {|url_prefix|
|
28
|
-
runner.logger.info "Using URL Prefix '#{url_prefix}'"
|
29
|
-
Resque::Server.url_prefix = url_prefix
|
30
|
-
}
|
5
|
+
if !!(RUBY_PLATFORM =~ /(mingw|bccwin|wince|mswin32)/i)
|
6
|
+
begin
|
7
|
+
require 'win32/process'
|
8
|
+
rescue
|
9
|
+
puts "Sorry, in order to use resque-web on Windows you need the win32-process gem:",
|
10
|
+
"gem install win32-process"
|
11
|
+
end
|
31
12
|
end
|
13
|
+
require 'resque/web_runner'
|
14
|
+
|
15
|
+
Resque::WebRunner.new(*ARGV)
|
data/lib/resque/data_store.rb
CHANGED
@@ -76,9 +76,10 @@ module Resque
|
|
76
76
|
@redis.inspect
|
77
77
|
end
|
78
78
|
|
79
|
-
# Force a reconnect to Redis
|
79
|
+
# Force a reconnect to Redis without closing the connection in the parent
|
80
|
+
# process after a fork.
|
80
81
|
def reconnect
|
81
|
-
@redis._client.
|
82
|
+
@redis._client.connect
|
82
83
|
end
|
83
84
|
|
84
85
|
# Returns an array of all known Resque keys in Redis. Redis' KEYS operation
|
@@ -99,9 +100,9 @@ module Resque
|
|
99
100
|
@redis = redis
|
100
101
|
end
|
101
102
|
def push_to_queue(queue,encoded_item)
|
102
|
-
@redis.pipelined do
|
103
|
-
watch_queue(queue)
|
104
|
-
|
103
|
+
@redis.pipelined do |piped|
|
104
|
+
watch_queue(queue, redis: piped)
|
105
|
+
piped.rpush redis_key_for_queue(queue), encoded_item
|
105
106
|
end
|
106
107
|
end
|
107
108
|
|
@@ -128,9 +129,9 @@ module Resque
|
|
128
129
|
end
|
129
130
|
|
130
131
|
def remove_queue(queue)
|
131
|
-
@redis.pipelined do
|
132
|
-
|
133
|
-
|
132
|
+
@redis.pipelined do |piped|
|
133
|
+
piped.srem(:queues, queue.to_s)
|
134
|
+
piped.del(redis_key_for_queue(queue))
|
134
135
|
end
|
135
136
|
end
|
136
137
|
|
@@ -144,8 +145,8 @@ module Resque
|
|
144
145
|
end
|
145
146
|
|
146
147
|
# Private: do not call
|
147
|
-
def watch_queue(queue)
|
148
|
-
|
148
|
+
def watch_queue(queue, redis: @redis)
|
149
|
+
redis.sadd(:queues, queue.to_s)
|
149
150
|
end
|
150
151
|
|
151
152
|
# Private: do not call
|
@@ -236,24 +237,24 @@ module Resque
|
|
236
237
|
end
|
237
238
|
|
238
239
|
def register_worker(worker)
|
239
|
-
@redis.pipelined do
|
240
|
-
|
241
|
-
worker_started(worker)
|
240
|
+
@redis.pipelined do |piped|
|
241
|
+
piped.sadd(:workers, worker)
|
242
|
+
worker_started(worker, redis: piped)
|
242
243
|
end
|
243
244
|
end
|
244
245
|
|
245
|
-
def worker_started(worker)
|
246
|
-
|
246
|
+
def worker_started(worker, redis: @redis)
|
247
|
+
redis.set(redis_key_for_worker_start_time(worker), Time.now.to_s)
|
247
248
|
end
|
248
249
|
|
249
250
|
def unregister_worker(worker, &block)
|
250
|
-
@redis.pipelined do
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
251
|
+
@redis.pipelined do |piped|
|
252
|
+
piped.srem(:workers, worker)
|
253
|
+
piped.del(redis_key_for_worker(worker))
|
254
|
+
piped.del(redis_key_for_worker_start_time(worker))
|
255
|
+
piped.hdel(HEARTBEAT_KEY, worker.to_s)
|
255
256
|
|
256
|
-
block.call
|
257
|
+
block.call redis: piped
|
257
258
|
end
|
258
259
|
end
|
259
260
|
|
@@ -287,9 +288,9 @@ module Resque
|
|
287
288
|
end
|
288
289
|
|
289
290
|
def worker_done_working(worker, &block)
|
290
|
-
@redis.pipelined do
|
291
|
-
|
292
|
-
block.call
|
291
|
+
@redis.pipelined do |piped|
|
292
|
+
piped.del(redis_key_for_worker(worker))
|
293
|
+
block.call redis: piped
|
293
294
|
end
|
294
295
|
end
|
295
296
|
|
@@ -316,16 +317,16 @@ module Resque
|
|
316
317
|
@redis.get("stat:#{stat}").to_i
|
317
318
|
end
|
318
319
|
|
319
|
-
def increment_stat(stat, by = 1)
|
320
|
-
|
320
|
+
def increment_stat(stat, by = 1, redis: @redis)
|
321
|
+
redis.incrby("stat:#{stat}", by)
|
321
322
|
end
|
322
323
|
|
323
324
|
def decremet_stat(stat, by = 1)
|
324
325
|
@redis.decrby("stat:#{stat}", by)
|
325
326
|
end
|
326
327
|
|
327
|
-
def clear_stat(stat)
|
328
|
-
|
328
|
+
def clear_stat(stat, redis: @redis)
|
329
|
+
redis.del("stat:#{stat}")
|
329
330
|
end
|
330
331
|
end
|
331
332
|
end
|
data/lib/resque/failure.rb
CHANGED
@@ -9,7 +9,9 @@ Resque::Server.helpers do
|
|
9
9
|
|
10
10
|
def failed_multiple_queues?
|
11
11
|
return @multiple_failed_queues if defined?(@multiple_failed_queues)
|
12
|
-
|
12
|
+
|
13
|
+
@multiple_failed_queues = Resque::Failure.queues.size > 1 ||
|
14
|
+
(defined?(Resque::Failure::RedisMultiQueue) && Resque::Failure.backend == Resque::Failure::RedisMultiQueue)
|
13
15
|
end
|
14
16
|
|
15
17
|
def failed_size
|
@@ -1 +1 @@
|
|
1
|
-
<h1 style="font-size:110%;font-family:Arial, sans-serif;"><%= error %></h1>
|
1
|
+
<h1 style="font-size:110%;font-family:Arial, sans-serif;"><%= escape_html(error) %></h1>
|
@@ -1,15 +1,21 @@
|
|
1
1
|
<% if failed_multiple_queues? && !params[:queue] %>
|
2
2
|
<h1>All Failed Queues: <%= Resque::Failure.queues.size %> total</h1>
|
3
3
|
<% else %>
|
4
|
-
<h1>Failed Jobs <%= "on '#{params[:queue]}'" if params[:queue] %> <%= "with class '#{params[:class]}'" if params[:class] %></h1>
|
4
|
+
<h1>Failed Jobs <%= "on '#{escape_html(params[:queue])}'" if params[:queue] %> <%= "with class '#{escape_html(params[:class])}'" if params[:class] %></h1>
|
5
5
|
<% end %>
|
6
6
|
|
7
7
|
<% unless failed_size.zero? %>
|
8
8
|
<form method="POST" action="<%= u "failed#{'/' + params[:queue] if params[:queue]}/clear" %>">
|
9
|
-
<input type="submit" name="" value="Clear <%= params[:queue] ? "'#{params[:queue]}'" : 'Failed' %> Jobs" class="confirmSubmission" />
|
9
|
+
<input type="submit" name="" value="Clear <%= params[:queue] ? "'#{escape_html(params[:queue])}'" : 'Failed' %> Jobs" class="confirmSubmission" />
|
10
10
|
</form>
|
11
|
+
|
12
|
+
<% unless params[:queue] %>
|
13
|
+
<form method="POST" action="<%= u "failed/clear_retried" %>">
|
14
|
+
<input type="submit" name="" value="Clear Retried Jobs" onclick='return confirm("Are you absolutely sure? This cannot be undone.");' />
|
15
|
+
</form>
|
16
|
+
<% end %>
|
11
17
|
<form method="POST" action="<%= u "failed#{'/' + params[:queue] if params[:queue]}/requeue/all" %>">
|
12
|
-
<input type="submit" name="" value="Retry <%= params[:queue] ? "'#{params[:queue]}'" : 'Failed' %> Jobs" class="confirmSubmission" />
|
18
|
+
<input type="submit" name="" value="Retry <%= params[:queue] ? "'#{escape_html(params[:queue])}'" : 'Failed' %> Jobs" class="confirmSubmission" />
|
13
19
|
</form>
|
14
20
|
<% end %>
|
15
21
|
|
@@ -1,6 +1,8 @@
|
|
1
1
|
<% if job['class'] == 'ActiveJob::QueueAdapters::ResqueAdapter::JobWrapper' %>
|
2
2
|
<code><%= job['args'].first['job_class'] %></code>
|
3
|
-
<small
|
3
|
+
<small>
|
4
|
+
<a href="http://edgeguides.rubyonrails.org/active_job_basics.html" rel="noopener noreferrer" target="_blank">(via ActiveJob)</a>
|
5
|
+
</small>
|
4
6
|
<% else %>
|
5
7
|
<code><%= job['class'] %></code>
|
6
8
|
<% end %>
|
@@ -37,7 +37,7 @@
|
|
37
37
|
</div>
|
38
38
|
|
39
39
|
<div id="footer">
|
40
|
-
<p>Powered by <a href="http://github.com/resque/resque">Resque</a> v<%=Resque::
|
40
|
+
<p>Powered by <a href="http://github.com/resque/resque">Resque</a> v<%=Resque::VERSION%></p>
|
41
41
|
<p>Connected to Redis namespace <%= Resque.redis.namespace %> on <%=Resque.redis_id%></p>
|
42
42
|
</div>
|
43
43
|
|
@@ -7,7 +7,7 @@
|
|
7
7
|
<a href="<%= current_page %>?start=<%= start - per_page %>" class='less'>« Previous</a>
|
8
8
|
<% end %>
|
9
9
|
|
10
|
-
<% (size / per_page.to_f
|
10
|
+
<% (size / per_page.to_f).ceil.times do |page_num| %>
|
11
11
|
<% if start == page_num * per_page %>
|
12
12
|
<span><%= page_num + 1 %></span>
|
13
13
|
<% else %>
|
@@ -15,7 +15,7 @@
|
|
15
15
|
<% end %>
|
16
16
|
<% end %>
|
17
17
|
|
18
|
-
<% if start + per_page
|
18
|
+
<% if start + per_page < size %>
|
19
19
|
<a href="<%= current_page %>?start=<%= start + per_page %>" class='more'>Next »</a>
|
20
20
|
<% end %>
|
21
21
|
</div>
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
<% if current_queue = params[:id] %>
|
4
4
|
|
5
|
-
<h1>Pending jobs on <span class='hl'><%= h current_queue %></span></h1>
|
5
|
+
<h1>Pending jobs on <span class='hl'><%= h escape_html(current_queue) %></span></h1>
|
6
6
|
<form method="POST" action="<%=u "/queues/#{current_queue}/remove" %>" class='remove-queue'>
|
7
7
|
<input type='submit' name='' value='Remove Queue' class="confirmSubmission" />
|
8
8
|
</form>
|
data/lib/resque/server.rb
CHANGED
@@ -53,7 +53,7 @@ module Resque
|
|
53
53
|
def tab(name)
|
54
54
|
dname = name.to_s.downcase
|
55
55
|
path = url_path(dname)
|
56
|
-
"<li #{class_if_current(path)}><a href='#{path}'>#{name}</a></li>"
|
56
|
+
"<li #{class_if_current(path)}><a href='#{path.gsub(" ", "_")}'>#{name}</a></li>"
|
57
57
|
end
|
58
58
|
|
59
59
|
def tabs
|
@@ -205,6 +205,11 @@ module Resque
|
|
205
205
|
redirect u('failed')
|
206
206
|
end
|
207
207
|
|
208
|
+
post "/failed/clear_retried" do
|
209
|
+
Resque::Failure.clear_retried
|
210
|
+
redirect u('failed')
|
211
|
+
end
|
212
|
+
|
208
213
|
post "/failed/:queue/clear" do
|
209
214
|
Resque::Failure.clear params[:queue]
|
210
215
|
redirect u('failed')
|
data/lib/resque/stat.rb
CHANGED
@@ -35,8 +35,8 @@ module Resque
|
|
35
35
|
#
|
36
36
|
# Can optionally accept a second int parameter. The stat is then
|
37
37
|
# incremented by that amount.
|
38
|
-
def incr(stat, by = 1)
|
39
|
-
data_store.increment_stat(stat,by)
|
38
|
+
def incr(stat, by = 1, **opts)
|
39
|
+
data_store.increment_stat(stat, by, **opts)
|
40
40
|
end
|
41
41
|
|
42
42
|
# Increments a stat by one.
|
@@ -58,8 +58,8 @@ module Resque
|
|
58
58
|
end
|
59
59
|
|
60
60
|
# Removes a stat from Redis, effectively setting it to 0.
|
61
|
-
def clear(stat)
|
62
|
-
data_store.clear_stat(stat)
|
61
|
+
def clear(stat, **opts)
|
62
|
+
data_store.clear_stat(stat, **opts)
|
63
63
|
end
|
64
64
|
end
|
65
65
|
end
|
data/lib/resque/tasks.rb
CHANGED
@@ -39,7 +39,7 @@ namespace :resque do
|
|
39
39
|
|
40
40
|
# Preload app files if this is Rails
|
41
41
|
task :preload => :setup do
|
42
|
-
if defined?(Rails)
|
42
|
+
if defined?(Rails) && Rails.respond_to?(:application)
|
43
43
|
if Rails.application.config.eager_load
|
44
44
|
ActiveSupport.run_load_hooks(:before_eager_load, Rails.application)
|
45
45
|
Rails.application.config.eager_load_namespaces.each(&:eager_load!)
|
data/lib/resque/version.rb
CHANGED
@@ -0,0 +1,372 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'logger'
|
3
|
+
require 'optparse'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'rack'
|
6
|
+
require 'resque/server'
|
7
|
+
|
8
|
+
# only used with `bin/resque-web`
|
9
|
+
# https://github.com/resque/resque/pull/1780
|
10
|
+
|
11
|
+
module Resque
|
12
|
+
WINDOWS = !!(RUBY_PLATFORM =~ /(mingw|bccwin|wince|mswin32)/i)
|
13
|
+
JRUBY = !!(RbConfig::CONFIG["RUBY_INSTALL_NAME"] =~ /^jruby/i)
|
14
|
+
|
15
|
+
class WebRunner
|
16
|
+
attr_reader :app, :app_name, :filesystem_friendly_app_name,
|
17
|
+
:rack_handler, :port, :options, :args
|
18
|
+
|
19
|
+
PORT = 5678
|
20
|
+
HOST = WINDOWS ? 'localhost' : '0.0.0.0'
|
21
|
+
|
22
|
+
def initialize(*runtime_args)
|
23
|
+
@options = runtime_args.last.is_a?(Hash) ? runtime_args.pop : {}
|
24
|
+
|
25
|
+
self.class.logger.level = options[:debug] ? Logger::DEBUG : Logger::INFO
|
26
|
+
|
27
|
+
@app = Resque::Server
|
28
|
+
@app_name = 'resque-web'
|
29
|
+
@filesystem_friendly_app_name = @app_name.gsub(/\W+/, "_")
|
30
|
+
|
31
|
+
@args = load_options(runtime_args)
|
32
|
+
|
33
|
+
@rack_handler = (s = options[:rack_handler]) ? Rack::Handler.get(s) : setup_rack_handler
|
34
|
+
|
35
|
+
case option_parser.command
|
36
|
+
when :help
|
37
|
+
puts option_parser
|
38
|
+
when :kill
|
39
|
+
kill!
|
40
|
+
when :status
|
41
|
+
status
|
42
|
+
when :version
|
43
|
+
puts "resque #{Resque::VERSION}"
|
44
|
+
puts "rack #{Rack::VERSION.join('.')}"
|
45
|
+
puts "sinatra #{Sinatra::VERSION}" if defined?(Sinatra)
|
46
|
+
else
|
47
|
+
before_run
|
48
|
+
start unless options[:start] == false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def launch_path
|
53
|
+
if options[:launch_path].respond_to?(:call)
|
54
|
+
options[:launch_path].call(self)
|
55
|
+
else
|
56
|
+
options[:launch_path]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def app_dir
|
61
|
+
if !options[:app_dir] && !ENV['HOME']
|
62
|
+
raise ArgumentError.new("nor --app-dir neither ENV['HOME'] defined")
|
63
|
+
end
|
64
|
+
options[:app_dir] || File.join(ENV['HOME'], filesystem_friendly_app_name)
|
65
|
+
end
|
66
|
+
|
67
|
+
def pid_file
|
68
|
+
options[:pid_file] || File.join(app_dir, "#{filesystem_friendly_app_name}.pid")
|
69
|
+
end
|
70
|
+
|
71
|
+
def url_file
|
72
|
+
options[:url_file] || File.join(app_dir, "#{filesystem_friendly_app_name}.url")
|
73
|
+
end
|
74
|
+
|
75
|
+
def log_file
|
76
|
+
options[:log_file] || File.join(app_dir, "#{filesystem_friendly_app_name}.log")
|
77
|
+
end
|
78
|
+
|
79
|
+
def host
|
80
|
+
options.fetch(:host) { HOST }
|
81
|
+
end
|
82
|
+
|
83
|
+
def url
|
84
|
+
"http://#{host}:#{port}"
|
85
|
+
end
|
86
|
+
|
87
|
+
def before_run
|
88
|
+
if (redis_conf = options[:redis_conf])
|
89
|
+
logger.info "Using Redis connection '#{redis_conf}'"
|
90
|
+
Resque.redis = redis_conf
|
91
|
+
end
|
92
|
+
if (namespace = options[:redis_namespace])
|
93
|
+
logger.info "Using Redis namespace '#{namespace}'"
|
94
|
+
Resque.redis.namespace = namespace
|
95
|
+
end
|
96
|
+
if (url_prefix = options[:url_prefix])
|
97
|
+
logger.info "Using URL Prefix '#{url_prefix}'"
|
98
|
+
Resque::Server.url_prefix = url_prefix
|
99
|
+
end
|
100
|
+
app.set(options.merge web_runner: self)
|
101
|
+
path = (ENV['RESQUECONFIG'] || args.first)
|
102
|
+
load_config_file(path.to_s.strip) if path
|
103
|
+
end
|
104
|
+
|
105
|
+
def start(path = launch_path)
|
106
|
+
logger.info "Running with Windows Settings" if WINDOWS
|
107
|
+
logger.info "Running with JRuby" if JRUBY
|
108
|
+
logger.info "Starting '#{app_name}'..."
|
109
|
+
|
110
|
+
check_for_running(path)
|
111
|
+
find_port
|
112
|
+
write_url
|
113
|
+
launch!(url, path)
|
114
|
+
daemonize! unless options[:foreground]
|
115
|
+
run!
|
116
|
+
rescue RuntimeError => e
|
117
|
+
logger.warn "There was an error starting '#{app_name}': #{e}"
|
118
|
+
exit
|
119
|
+
end
|
120
|
+
|
121
|
+
def find_port
|
122
|
+
if @port = options[:port]
|
123
|
+
announce_port_attempted
|
124
|
+
|
125
|
+
unless port_open?
|
126
|
+
logger.warn "Port #{port} is already in use. Please try another. " +
|
127
|
+
"You can also omit the port flag, and we'll find one for you."
|
128
|
+
end
|
129
|
+
else
|
130
|
+
@port = PORT
|
131
|
+
announce_port_attempted
|
132
|
+
|
133
|
+
until port_open?
|
134
|
+
@port += 1
|
135
|
+
announce_port_attempted
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def announce_port_attempted
|
141
|
+
logger.info "trying port #{port}..."
|
142
|
+
end
|
143
|
+
|
144
|
+
def port_open?(check_url = nil)
|
145
|
+
begin
|
146
|
+
check_url ||= url
|
147
|
+
options[:no_proxy] ? uri_open(check_url, :proxy => nil) : uri_open(check_url)
|
148
|
+
false
|
149
|
+
rescue Errno::ECONNREFUSED, Errno::EPERM, Errno::ETIMEDOUT
|
150
|
+
true
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def uri_open(*args)
|
155
|
+
(RbConfig::CONFIG['ruby_version'] < '2.7') ? open(*args) : URI.open(*args)
|
156
|
+
end
|
157
|
+
|
158
|
+
def write_url
|
159
|
+
# Make sure app dir is setup
|
160
|
+
FileUtils.mkdir_p(app_dir)
|
161
|
+
File.open(url_file, 'w') {|f| f << url }
|
162
|
+
end
|
163
|
+
|
164
|
+
def check_for_running(path = nil)
|
165
|
+
if File.exist?(pid_file) && File.exist?(url_file)
|
166
|
+
running_url = File.read(url_file)
|
167
|
+
if !port_open?(running_url)
|
168
|
+
logger.warn "'#{app_name}' is already running at #{running_url}"
|
169
|
+
launch!(running_url, path)
|
170
|
+
exit!(1)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def run!
|
176
|
+
logger.info "Running with Rack handler: #{@rack_handler.inspect}"
|
177
|
+
|
178
|
+
rack_handler.run app, :Host => host, :Port => port do |server|
|
179
|
+
kill_commands.each do |command|
|
180
|
+
trap(command) do
|
181
|
+
## Use thins' hard #stop! if available, otherwise just #stop
|
182
|
+
server.respond_to?(:stop!) ? server.stop! : server.stop
|
183
|
+
logger.info "'#{app_name}' received INT ... stopping"
|
184
|
+
delete_pid!
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
# Adapted from Rackup
|
191
|
+
def daemonize!
|
192
|
+
if JRUBY
|
193
|
+
# It's not a true daemon but when executed with & works like one
|
194
|
+
thread = Thread.new {daemon_execute}
|
195
|
+
thread.join
|
196
|
+
|
197
|
+
elsif RUBY_VERSION < "1.9"
|
198
|
+
logger.debug "Parent Process: #{Process.pid}"
|
199
|
+
exit!(0) if fork
|
200
|
+
logger.debug "Child Process: #{Process.pid}"
|
201
|
+
daemon_execute
|
202
|
+
|
203
|
+
else
|
204
|
+
Process.daemon(true, true)
|
205
|
+
daemon_execute
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def daemon_execute
|
210
|
+
File.umask 0000
|
211
|
+
FileUtils.touch log_file
|
212
|
+
STDIN.reopen log_file
|
213
|
+
STDOUT.reopen log_file, "a"
|
214
|
+
STDERR.reopen log_file, "a"
|
215
|
+
|
216
|
+
logger.debug "Child Process: #{Process.pid}"
|
217
|
+
|
218
|
+
File.open(pid_file, 'w') {|f| f.write("#{Process.pid}") }
|
219
|
+
at_exit { delete_pid! }
|
220
|
+
end
|
221
|
+
|
222
|
+
def launch!(specific_url = nil, path = nil)
|
223
|
+
return if options[:skip_launch]
|
224
|
+
cmd = WINDOWS ? "start" : "open"
|
225
|
+
system "#{cmd} #{specific_url || url}#{path}"
|
226
|
+
end
|
227
|
+
|
228
|
+
def kill!
|
229
|
+
pid = File.read(pid_file)
|
230
|
+
logger.warn "Sending #{kill_command} to #{pid.to_i}"
|
231
|
+
Process.kill(kill_command, pid.to_i)
|
232
|
+
rescue => e
|
233
|
+
logger.warn "pid not found at #{pid_file} : #{e}"
|
234
|
+
end
|
235
|
+
|
236
|
+
def status
|
237
|
+
if File.exists?(pid_file)
|
238
|
+
logger.info "'#{app_name}' running"
|
239
|
+
logger.info "PID #{File.read(pid_file)}"
|
240
|
+
logger.info "URL #{File.read(url_file)}" if File.exists?(url_file)
|
241
|
+
else
|
242
|
+
logger.info "'#{app_name}' not running!"
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
# Loads a config file at config_path and evals it in the context of the @app.
|
247
|
+
def load_config_file(config_path)
|
248
|
+
abort "Can not find config file at #{config_path}" if !File.readable?(config_path)
|
249
|
+
config = File.read(config_path)
|
250
|
+
# trim off anything after __END__
|
251
|
+
config.sub!(/^__END__\n.*/, '')
|
252
|
+
@app.module_eval(config)
|
253
|
+
end
|
254
|
+
|
255
|
+
def self.logger=(logger)
|
256
|
+
@logger = logger
|
257
|
+
end
|
258
|
+
|
259
|
+
def self.logger
|
260
|
+
@logger ||= LOGGER if defined?(LOGGER)
|
261
|
+
if !@logger
|
262
|
+
@logger = Logger.new(STDOUT)
|
263
|
+
@logger.formatter = Proc.new {|s, t, n, msg| "[#{t}] #{msg}\n"}
|
264
|
+
@logger
|
265
|
+
end
|
266
|
+
@logger
|
267
|
+
end
|
268
|
+
|
269
|
+
def logger
|
270
|
+
self.class.logger
|
271
|
+
end
|
272
|
+
|
273
|
+
private
|
274
|
+
def setup_rack_handler
|
275
|
+
# First try to set Rack handler via a special hook we honor
|
276
|
+
@rack_handler = if @app.respond_to?(:detect_rack_handler)
|
277
|
+
@app.detect_rack_handler
|
278
|
+
|
279
|
+
# If they aren't using our hook, try to use their @app.server settings
|
280
|
+
elsif @app.respond_to?(:server) and @app.server
|
281
|
+
# If :server isn't set, it returns an array of possibilities,
|
282
|
+
# sorted from most to least preferable.
|
283
|
+
if @app.server.is_a?(Array)
|
284
|
+
handler = nil
|
285
|
+
@app.server.each do |server|
|
286
|
+
begin
|
287
|
+
handler = Rack::Handler.get(server)
|
288
|
+
break
|
289
|
+
rescue LoadError, NameError => e
|
290
|
+
next
|
291
|
+
end
|
292
|
+
end
|
293
|
+
handler
|
294
|
+
|
295
|
+
# :server might be set explicitly to a single option like "mongrel"
|
296
|
+
else
|
297
|
+
Rack::Handler.get(@app.server)
|
298
|
+
end
|
299
|
+
|
300
|
+
# If all else fails, we'll use Thin
|
301
|
+
else
|
302
|
+
JRUBY ? Rack::Handler::WEBrick : Rack::Handler::Thin
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
def load_options(runtime_args)
|
307
|
+
@args = option_parser.parse!(runtime_args)
|
308
|
+
options.merge!(option_parser.options)
|
309
|
+
args
|
310
|
+
rescue OptionParser::MissingArgument => e
|
311
|
+
logger.warn "#{e}, run -h for options"
|
312
|
+
exit
|
313
|
+
end
|
314
|
+
|
315
|
+
def option_parser
|
316
|
+
@option_parser ||= Parser.new(app_name)
|
317
|
+
end
|
318
|
+
|
319
|
+
class Parser < OptionParser
|
320
|
+
attr_reader :command, :options
|
321
|
+
|
322
|
+
def initialize(app_name)
|
323
|
+
super("", 24, ' ')
|
324
|
+
self.banner = "Usage: #{app_name} [options]"
|
325
|
+
|
326
|
+
@options = {}
|
327
|
+
basename = app_name.gsub(/\W+/, "_")
|
328
|
+
on('-K', "--kill", "kill the running process and exit") { @command = :kill }
|
329
|
+
on('-S', "--status", "display the current running PID and URL then quit") { @command = :status }
|
330
|
+
string_option("-s", "--server SERVER", "serve using SERVER (thin/mongrel/webrick)", :rack_handler)
|
331
|
+
string_option("-o", "--host HOST", "listen on HOST (default: #{HOST})", :host)
|
332
|
+
string_option("-p", "--port PORT", "use PORT (default: #{PORT})", :port)
|
333
|
+
on("-x", "--no-proxy", "ignore env proxy settings (e.g. http_proxy)") { opts[:no_proxy] = true }
|
334
|
+
boolean_option("-F", "--foreground", "don't daemonize, run in the foreground", :foreground)
|
335
|
+
boolean_option("-L", "--no-launch", "don't launch the browser", :skip_launch)
|
336
|
+
boolean_option('-d', "--debug", "raise the log level to :debug (default: :info)", :debug)
|
337
|
+
string_option("--app-dir APP_DIR", "set the app dir where files are stored (default: ~/#{basename}/)", :app_dir)
|
338
|
+
string_option("-P", "--pid-file PID_FILE", "set the path to the pid file (default: app_dir/#{basename}.pid)", :pid_file)
|
339
|
+
string_option("--log-file LOG_FILE", "set the path to the log file (default: app_dir/#{basename}.log)", :log_file)
|
340
|
+
string_option("--url-file URL_FILE", "set the path to the URL file (default: app_dir/#{basename}.url)", :url_file)
|
341
|
+
string_option('-N NAMESPACE', "--namespace NAMESPACE", "set the Redis namespace", :redis_namespace)
|
342
|
+
string_option('-r redis-connection', "--redis redis-connection", "set the Redis connection string", :redis_conf)
|
343
|
+
string_option('-a url-prefix', "--append url-prefix", "set reverse_proxy friendly prefix to links", :url_prefix)
|
344
|
+
separator ""
|
345
|
+
separator "Common options:"
|
346
|
+
on_tail("-h", "--help", "Show this message") { @command = :help }
|
347
|
+
on_tail("--version", "Show version") { @command = :version }
|
348
|
+
end
|
349
|
+
|
350
|
+
def boolean_option(*argv)
|
351
|
+
k = argv.pop; on(*argv) { options[k] = true }
|
352
|
+
end
|
353
|
+
|
354
|
+
def string_option(*argv)
|
355
|
+
k = argv.pop; on(*argv) { |value| options[k] = value }
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
def kill_commands
|
360
|
+
WINDOWS ? [1] : [:INT, :TERM]
|
361
|
+
end
|
362
|
+
|
363
|
+
def kill_command
|
364
|
+
kill_commands[0]
|
365
|
+
end
|
366
|
+
|
367
|
+
def delete_pid!
|
368
|
+
File.delete(pid_file) if File.exist?(pid_file)
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
end
|
data/lib/resque/worker.rb
CHANGED
@@ -180,9 +180,17 @@ module Resque
|
|
180
180
|
WILDCARDS = ['*', '?', '{', '}', '[', ']'].freeze
|
181
181
|
|
182
182
|
def queues=(queues)
|
183
|
-
queues =
|
184
|
-
|
185
|
-
|
183
|
+
queues = (ENV["QUEUES"] || ENV['QUEUE']).to_s.split(',') if queues.empty?
|
184
|
+
queues = queues.map { |queue| queue.to_s.strip }
|
185
|
+
|
186
|
+
@skip_queues, @queues = queues.partition { |queue| queue.start_with?('!') }
|
187
|
+
@skip_queues.map! { |queue| queue[1..-1] }
|
188
|
+
|
189
|
+
# The behavior of `queues` is dependent on the value of `@has_dynamic_queues: if it's true, the method returns the result of filtering @queues with `glob_match`
|
190
|
+
# if it's false, the method returns @queues directly. Since `glob_match` will cause skipped queues to be filtered out, we want to make sure it's called if we have @skip_queues.any?
|
191
|
+
@has_dynamic_queues =
|
192
|
+
@skip_queues.any? || WILDCARDS.any? { |char| @queues.join.include?(char) }
|
193
|
+
|
186
194
|
validate_queues
|
187
195
|
end
|
188
196
|
|
@@ -210,7 +218,8 @@ module Resque
|
|
210
218
|
|
211
219
|
def glob_match(list, pattern)
|
212
220
|
list.select do |queue|
|
213
|
-
File.fnmatch?(pattern, queue)
|
221
|
+
File.fnmatch?(pattern, queue) &&
|
222
|
+
@skip_queues.none? { |skip_pattern| File.fnmatch?(skip_pattern, queue) }
|
214
223
|
end.sort
|
215
224
|
end
|
216
225
|
|
@@ -570,7 +579,7 @@ module Resque
|
|
570
579
|
|
571
580
|
# are we paused?
|
572
581
|
def paused?
|
573
|
-
@paused
|
582
|
+
@paused || redis.get('pause-all-workers').to_s.strip.downcase == 'true'
|
574
583
|
end
|
575
584
|
|
576
585
|
# Stop processing jobs after the current one has completed (if we're
|
@@ -688,9 +697,9 @@ module Resque
|
|
688
697
|
|
689
698
|
kill_background_threads
|
690
699
|
|
691
|
-
data_store.unregister_worker(self) do
|
692
|
-
Stat.clear("processed:#{self}")
|
693
|
-
Stat.clear("failed:#{self}")
|
700
|
+
data_store.unregister_worker(self) do |**opts|
|
701
|
+
Stat.clear("processed:#{self}", **opts)
|
702
|
+
Stat.clear("failed:#{self}", **opts)
|
694
703
|
end
|
695
704
|
rescue Exception => exception_while_unregistering
|
696
705
|
message = exception_while_unregistering.message
|
@@ -717,8 +726,8 @@ module Resque
|
|
717
726
|
# Called when we are done working - clears our `working_on` state
|
718
727
|
# and tells Redis we processed a job.
|
719
728
|
def done_working
|
720
|
-
data_store.worker_done_working(self) do
|
721
|
-
processed!
|
729
|
+
data_store.worker_done_working(self) do |**opts|
|
730
|
+
processed!(**opts)
|
722
731
|
end
|
723
732
|
end
|
724
733
|
|
@@ -736,9 +745,9 @@ module Resque
|
|
736
745
|
end
|
737
746
|
|
738
747
|
# Tell Redis we've processed a job.
|
739
|
-
def processed!
|
740
|
-
Stat
|
741
|
-
Stat
|
748
|
+
def processed!(**opts)
|
749
|
+
Stat.incr("processed", 1, **opts)
|
750
|
+
Stat.incr("processed:#{self}", 1, **opts)
|
742
751
|
end
|
743
752
|
|
744
753
|
# How many failed jobs has this worker seen? Returns an int.
|
@@ -852,7 +861,7 @@ module Resque
|
|
852
861
|
`ps -A -o pid,comm | grep "[r]uby" | grep -v "resque-web"`.split("\n").map do |line|
|
853
862
|
real_pid = line.split(' ')[0]
|
854
863
|
pargs_command = `pargs -a #{real_pid} 2>/dev/null | grep [r]esque | grep -v "resque-web"`
|
855
|
-
if pargs_command.split(':')[1] == " resque-#{Resque::
|
864
|
+
if pargs_command.split(':')[1] == " resque-#{Resque::VERSION}"
|
856
865
|
real_pid
|
857
866
|
end
|
858
867
|
end.compact
|
@@ -862,7 +871,7 @@ module Resque
|
|
862
871
|
# Procline is always in the format of:
|
863
872
|
# RESQUE_PROCLINE_PREFIXresque-VERSION: STRING
|
864
873
|
def procline(string)
|
865
|
-
$0 = "#{ENV['RESQUE_PROCLINE_PREFIX']}resque-#{Resque::
|
874
|
+
$0 = "#{ENV['RESQUE_PROCLINE_PREFIX']}resque-#{Resque::VERSION}: #{string}"
|
866
875
|
log_with_severity :debug, $0
|
867
876
|
end
|
868
877
|
|
data/lib/resque.rb
CHANGED
@@ -23,7 +23,7 @@ require 'resque/thread_signal'
|
|
23
23
|
|
24
24
|
require 'resque/vendor/utf8_util'
|
25
25
|
|
26
|
-
require 'resque/railtie' if defined?(Rails)
|
26
|
+
require 'resque/railtie' if defined?(Rails::Railtie)
|
27
27
|
|
28
28
|
module Resque
|
29
29
|
include Helpers
|
@@ -364,8 +364,8 @@ module Resque
|
|
364
364
|
data_store.queue_size(queue)
|
365
365
|
end
|
366
366
|
|
367
|
-
# Returns an array of items currently queued
|
368
|
-
# a string.
|
367
|
+
# Returns an array of items currently queued, or the item itself
|
368
|
+
# if count = 1. Queue name should be a string.
|
369
369
|
#
|
370
370
|
# start and count should be integer and can be used for pagination.
|
371
371
|
# start is the item to begin, count is how many items to return.
|
@@ -584,9 +584,9 @@ module Resque
|
|
584
584
|
def queue_sizes
|
585
585
|
queue_names = queues
|
586
586
|
|
587
|
-
sizes = redis.pipelined do
|
587
|
+
sizes = redis.pipelined do |piped|
|
588
588
|
queue_names.each do |name|
|
589
|
-
|
589
|
+
piped.llen("queue:#{name}")
|
590
590
|
end
|
591
591
|
end
|
592
592
|
|
@@ -597,11 +597,11 @@ module Resque
|
|
597
597
|
def sample_queues(sample_size = 1000)
|
598
598
|
queue_names = queues
|
599
599
|
|
600
|
-
samples = redis.pipelined do
|
600
|
+
samples = redis.pipelined do |piped|
|
601
601
|
queue_names.each do |name|
|
602
602
|
key = "queue:#{name}"
|
603
|
-
|
604
|
-
|
603
|
+
piped.llen(key)
|
604
|
+
piped.lrange(key, 0, sample_size - 1)
|
605
605
|
end
|
606
606
|
end
|
607
607
|
|
metadata
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: resque
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Wanstrath
|
8
8
|
- Steve Klabnik
|
9
9
|
- Terence Lee
|
10
|
-
|
10
|
+
- Michael Bianco
|
11
|
+
autorequire:
|
11
12
|
bindir: bin
|
12
13
|
cert_chain: []
|
13
|
-
date:
|
14
|
+
date: 2022-08-20 00:00:00.000000000 Z
|
14
15
|
dependencies:
|
15
16
|
- !ruby/object:Gem::Dependency
|
16
17
|
name: redis-namespace
|
@@ -26,20 +27,6 @@ dependencies:
|
|
26
27
|
- - "~>"
|
27
28
|
- !ruby/object:Gem::Version
|
28
29
|
version: '1.6'
|
29
|
-
- !ruby/object:Gem::Dependency
|
30
|
-
name: vegas
|
31
|
-
requirement: !ruby/object:Gem::Requirement
|
32
|
-
requirements:
|
33
|
-
- - "~>"
|
34
|
-
- !ruby/object:Gem::Version
|
35
|
-
version: 0.1.2
|
36
|
-
type: :runtime
|
37
|
-
prerelease: false
|
38
|
-
version_requirements: !ruby/object:Gem::Requirement
|
39
|
-
requirements:
|
40
|
-
- - "~>"
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
version: 0.1.2
|
43
30
|
- !ruby/object:Gem::Dependency
|
44
31
|
name: sinatra
|
45
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -82,6 +69,34 @@ dependencies:
|
|
82
69
|
- - "~>"
|
83
70
|
- !ruby/object:Gem::Version
|
84
71
|
version: '1.0'
|
72
|
+
- !ruby/object:Gem::Dependency
|
73
|
+
name: thin
|
74
|
+
requirement: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
type: :development
|
80
|
+
prerelease: false
|
81
|
+
version_requirements: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
- !ruby/object:Gem::Dependency
|
87
|
+
name: webrick
|
88
|
+
requirement: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
type: :development
|
94
|
+
prerelease: false
|
95
|
+
version_requirements: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
85
100
|
description: |2
|
86
101
|
Resque is a Redis-backed Ruby library for creating background jobs,
|
87
102
|
placing those jobs on multiple queues, and processing them later.
|
@@ -162,14 +177,17 @@ files:
|
|
162
177
|
- lib/resque/thread_signal.rb
|
163
178
|
- lib/resque/vendor/utf8_util.rb
|
164
179
|
- lib/resque/version.rb
|
180
|
+
- lib/resque/web_runner.rb
|
165
181
|
- lib/resque/worker.rb
|
166
182
|
- lib/tasks/redis.rake
|
167
183
|
- lib/tasks/resque.rake
|
168
|
-
homepage:
|
184
|
+
homepage: https://github.com/resque/resque
|
169
185
|
licenses:
|
170
186
|
- MIT
|
171
|
-
metadata:
|
172
|
-
|
187
|
+
metadata:
|
188
|
+
changelog_uri: https://github.com/resque/resque/blob/master/HISTORY.md
|
189
|
+
rubygems_mfa_required: 'true'
|
190
|
+
post_install_message:
|
173
191
|
rdoc_options:
|
174
192
|
- "--charset=UTF-8"
|
175
193
|
require_paths:
|
@@ -185,8 +203,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
185
203
|
- !ruby/object:Gem::Version
|
186
204
|
version: '0'
|
187
205
|
requirements: []
|
188
|
-
rubygems_version: 3.
|
189
|
-
signing_key:
|
206
|
+
rubygems_version: 3.3.5
|
207
|
+
signing_key:
|
190
208
|
specification_version: 4
|
191
209
|
summary: Resque is a Redis-backed queueing system.
|
192
210
|
test_files: []
|