resque 2.2.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 +19 -5
- data/README.markdown +59 -56
- data/bin/resque-web +10 -26
- data/lib/resque/data_store.rb +26 -26
- data/lib/resque/server/views/error.erb +1 -1
- data/lib/resque/server/views/failed.erb +3 -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/next_more.erb +2 -2
- data/lib/resque/server/views/queues.erb +1 -1
- data/lib/resque/server.rb +1 -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 +22 -13
- data/lib/resque.rb +7 -7
- metadata +36 -20
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,28 @@
|
|
1
|
-
##
|
1
|
+
## 2.3.0
|
2
2
|
|
3
3
|
### Fixed
|
4
4
|
|
5
|
-
*
|
6
|
-
*
|
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)
|
7
10
|
|
8
11
|
### Added
|
9
12
|
|
10
|
-
*
|
11
|
-
|
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)
|
12
26
|
|
13
27
|
## 2.2.0
|
14
28
|
|
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
@@ -100,9 +100,9 @@ module Resque
|
|
100
100
|
@redis = redis
|
101
101
|
end
|
102
102
|
def push_to_queue(queue,encoded_item)
|
103
|
-
@redis.pipelined do
|
104
|
-
watch_queue(queue)
|
105
|
-
|
103
|
+
@redis.pipelined do |piped|
|
104
|
+
watch_queue(queue, redis: piped)
|
105
|
+
piped.rpush redis_key_for_queue(queue), encoded_item
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
@@ -129,9 +129,9 @@ module Resque
|
|
129
129
|
end
|
130
130
|
|
131
131
|
def remove_queue(queue)
|
132
|
-
@redis.pipelined do
|
133
|
-
|
134
|
-
|
132
|
+
@redis.pipelined do |piped|
|
133
|
+
piped.srem(:queues, queue.to_s)
|
134
|
+
piped.del(redis_key_for_queue(queue))
|
135
135
|
end
|
136
136
|
end
|
137
137
|
|
@@ -145,8 +145,8 @@ module Resque
|
|
145
145
|
end
|
146
146
|
|
147
147
|
# Private: do not call
|
148
|
-
def watch_queue(queue)
|
149
|
-
|
148
|
+
def watch_queue(queue, redis: @redis)
|
149
|
+
redis.sadd(:queues, queue.to_s)
|
150
150
|
end
|
151
151
|
|
152
152
|
# Private: do not call
|
@@ -237,24 +237,24 @@ module Resque
|
|
237
237
|
end
|
238
238
|
|
239
239
|
def register_worker(worker)
|
240
|
-
@redis.pipelined do
|
241
|
-
|
242
|
-
worker_started(worker)
|
240
|
+
@redis.pipelined do |piped|
|
241
|
+
piped.sadd(:workers, worker)
|
242
|
+
worker_started(worker, redis: piped)
|
243
243
|
end
|
244
244
|
end
|
245
245
|
|
246
|
-
def worker_started(worker)
|
247
|
-
|
246
|
+
def worker_started(worker, redis: @redis)
|
247
|
+
redis.set(redis_key_for_worker_start_time(worker), Time.now.to_s)
|
248
248
|
end
|
249
249
|
|
250
250
|
def unregister_worker(worker, &block)
|
251
|
-
@redis.pipelined do
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
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)
|
256
256
|
|
257
|
-
block.call
|
257
|
+
block.call redis: piped
|
258
258
|
end
|
259
259
|
end
|
260
260
|
|
@@ -288,9 +288,9 @@ module Resque
|
|
288
288
|
end
|
289
289
|
|
290
290
|
def worker_done_working(worker, &block)
|
291
|
-
@redis.pipelined do
|
292
|
-
|
293
|
-
block.call
|
291
|
+
@redis.pipelined do |piped|
|
292
|
+
piped.del(redis_key_for_worker(worker))
|
293
|
+
block.call redis: piped
|
294
294
|
end
|
295
295
|
end
|
296
296
|
|
@@ -317,16 +317,16 @@ module Resque
|
|
317
317
|
@redis.get("stat:#{stat}").to_i
|
318
318
|
end
|
319
319
|
|
320
|
-
def increment_stat(stat, by = 1)
|
321
|
-
|
320
|
+
def increment_stat(stat, by = 1, redis: @redis)
|
321
|
+
redis.incrby("stat:#{stat}", by)
|
322
322
|
end
|
323
323
|
|
324
324
|
def decremet_stat(stat, by = 1)
|
325
325
|
@redis.decrby("stat:#{stat}", by)
|
326
326
|
end
|
327
327
|
|
328
|
-
def clear_stat(stat)
|
329
|
-
|
328
|
+
def clear_stat(stat, redis: @redis)
|
329
|
+
redis.del("stat:#{stat}")
|
330
330
|
end
|
331
331
|
end
|
332
332
|
end
|
@@ -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,12 +1,12 @@
|
|
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
11
|
|
12
12
|
<% unless params[:queue] %>
|
@@ -15,7 +15,7 @@
|
|
15
15
|
</form>
|
16
16
|
<% end %>
|
17
17
|
<form method="POST" action="<%= u "failed#{'/' + params[:queue] if params[:queue]}/requeue/all" %>">
|
18
|
-
<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" />
|
19
19
|
</form>
|
20
20
|
<% end %>
|
21
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 %>
|
@@ -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
|
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.
|
data/lib/resque.rb
CHANGED
@@ -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,17 +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
|
+
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date:
|
14
|
+
date: 2022-08-20 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: redis-namespace
|
@@ -27,20 +27,6 @@ dependencies:
|
|
27
27
|
- - "~>"
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '1.6'
|
30
|
-
- !ruby/object:Gem::Dependency
|
31
|
-
name: vegas
|
32
|
-
requirement: !ruby/object:Gem::Requirement
|
33
|
-
requirements:
|
34
|
-
- - "~>"
|
35
|
-
- !ruby/object:Gem::Version
|
36
|
-
version: 0.1.2
|
37
|
-
type: :runtime
|
38
|
-
prerelease: false
|
39
|
-
version_requirements: !ruby/object:Gem::Requirement
|
40
|
-
requirements:
|
41
|
-
- - "~>"
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
version: 0.1.2
|
44
30
|
- !ruby/object:Gem::Dependency
|
45
31
|
name: sinatra
|
46
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -83,6 +69,34 @@ dependencies:
|
|
83
69
|
- - "~>"
|
84
70
|
- !ruby/object:Gem::Version
|
85
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'
|
86
100
|
description: |2
|
87
101
|
Resque is a Redis-backed Ruby library for creating background jobs,
|
88
102
|
placing those jobs on multiple queues, and processing them later.
|
@@ -163,6 +177,7 @@ files:
|
|
163
177
|
- lib/resque/thread_signal.rb
|
164
178
|
- lib/resque/vendor/utf8_util.rb
|
165
179
|
- lib/resque/version.rb
|
180
|
+
- lib/resque/web_runner.rb
|
166
181
|
- lib/resque/worker.rb
|
167
182
|
- lib/tasks/redis.rake
|
168
183
|
- lib/tasks/resque.rake
|
@@ -171,7 +186,8 @@ licenses:
|
|
171
186
|
- MIT
|
172
187
|
metadata:
|
173
188
|
changelog_uri: https://github.com/resque/resque/blob/master/HISTORY.md
|
174
|
-
|
189
|
+
rubygems_mfa_required: 'true'
|
190
|
+
post_install_message:
|
175
191
|
rdoc_options:
|
176
192
|
- "--charset=UTF-8"
|
177
193
|
require_paths:
|
@@ -187,8 +203,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
187
203
|
- !ruby/object:Gem::Version
|
188
204
|
version: '0'
|
189
205
|
requirements: []
|
190
|
-
rubygems_version: 3.
|
191
|
-
signing_key:
|
206
|
+
rubygems_version: 3.3.5
|
207
|
+
signing_key:
|
192
208
|
specification_version: 4
|
193
209
|
summary: Resque is a Redis-backed queueing system.
|
194
210
|
test_files: []
|