opengotham_resque 1.8.2
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.
- data/.gitignore +2 -0
- data/.kick +26 -0
- data/HISTORY.md +142 -0
- data/LICENSE +20 -0
- data/README.markdown +794 -0
- data/Rakefile +112 -0
- data/bin/resque +57 -0
- data/bin/resque-web +23 -0
- data/config.ru +14 -0
- data/deps.rip +7 -0
- data/docs/HOOKS.md +121 -0
- data/docs/PLUGINS.md +93 -0
- data/examples/async_helper.rb +31 -0
- data/examples/demo/README.markdown +71 -0
- data/examples/demo/Rakefile +8 -0
- data/examples/demo/app.rb +38 -0
- data/examples/demo/config.ru +19 -0
- data/examples/demo/job.rb +22 -0
- data/examples/god/resque.god +53 -0
- data/examples/god/stale.god +26 -0
- data/examples/instance.rb +11 -0
- data/examples/monit/resque.monit +6 -0
- data/examples/simple.rb +30 -0
- data/init.rb +1 -0
- data/lib/resque.rb +287 -0
- data/lib/resque/errors.rb +10 -0
- data/lib/resque/failure.rb +66 -0
- data/lib/resque/failure/base.rb +61 -0
- data/lib/resque/failure/hoptoad.rb +132 -0
- data/lib/resque/failure/multiple.rb +48 -0
- data/lib/resque/failure/redis.rb +40 -0
- data/lib/resque/helpers.rb +63 -0
- data/lib/resque/job.rb +207 -0
- data/lib/resque/plugin.rb +46 -0
- data/lib/resque/server.rb +201 -0
- data/lib/resque/server/public/idle.png +0 -0
- data/lib/resque/server/public/jquery-1.3.2.min.js +19 -0
- data/lib/resque/server/public/jquery.relatize_date.js +95 -0
- data/lib/resque/server/public/poll.png +0 -0
- data/lib/resque/server/public/ranger.js +67 -0
- data/lib/resque/server/public/reset.css +48 -0
- data/lib/resque/server/public/style.css +81 -0
- data/lib/resque/server/public/working.png +0 -0
- data/lib/resque/server/test_helper.rb +19 -0
- data/lib/resque/server/views/error.erb +1 -0
- data/lib/resque/server/views/failed.erb +53 -0
- data/lib/resque/server/views/key_sets.erb +20 -0
- data/lib/resque/server/views/key_string.erb +11 -0
- data/lib/resque/server/views/layout.erb +44 -0
- data/lib/resque/server/views/next_more.erb +10 -0
- data/lib/resque/server/views/overview.erb +4 -0
- data/lib/resque/server/views/queues.erb +49 -0
- data/lib/resque/server/views/stats.erb +62 -0
- data/lib/resque/server/views/workers.erb +78 -0
- data/lib/resque/server/views/working.erb +69 -0
- data/lib/resque/stat.rb +53 -0
- data/lib/resque/tasks.rb +39 -0
- data/lib/resque/version.rb +3 -0
- data/lib/resque/worker.rb +478 -0
- data/tasks/redis.rake +159 -0
- data/tasks/resque.rake +2 -0
- data/test/job_hooks_test.rb +302 -0
- data/test/job_plugins_test.rb +209 -0
- data/test/plugin_test.rb +116 -0
- data/test/redis-test.conf +132 -0
- data/test/resque-web_test.rb +54 -0
- data/test/resque_test.rb +225 -0
- data/test/test_helper.rb +111 -0
- data/test/worker_test.rb +302 -0
- metadata +199 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
Resque Demo
|
2
|
+
-----------
|
3
|
+
|
4
|
+
This is a dirt simple Resque setup for you to play with.
|
5
|
+
|
6
|
+
|
7
|
+
### Starting the Demo App
|
8
|
+
|
9
|
+
Here's how to run the Sinatra app:
|
10
|
+
|
11
|
+
$ git clone git://github.com/defunkt/resque.git
|
12
|
+
$ cd resque/examples/demo
|
13
|
+
$ rackup config.ru
|
14
|
+
$ open http://localhost:9292/
|
15
|
+
|
16
|
+
Click 'Create New Job' a few times. You should see the number of
|
17
|
+
pending jobs rising.
|
18
|
+
|
19
|
+
|
20
|
+
### Starting the Demo Worker
|
21
|
+
|
22
|
+
Now in another shell terminal start the worker:
|
23
|
+
|
24
|
+
$ cd resque/examples/demo
|
25
|
+
$ VERBOSE=true QUEUE=default rake resque:work
|
26
|
+
|
27
|
+
You should see the following output:
|
28
|
+
|
29
|
+
*** Starting worker hostname:90185:default
|
30
|
+
*** got: (Job{default} | Demo::Job | [{}])
|
31
|
+
Processed a job!
|
32
|
+
*** done: (Job{default} | Demo::Job | [{}])
|
33
|
+
|
34
|
+
You can also use `VVERBOSE` (very verbose) if you want to see more:
|
35
|
+
|
36
|
+
$ VERBOSE=true QUEUE=default rake resque:work
|
37
|
+
*** Starting worker hostname:90399:default
|
38
|
+
** [05:55:09 2009-09-16] 90399: Registered signals
|
39
|
+
** [05:55:09 2009-09-16] 90399: Checking default
|
40
|
+
** [05:55:09 2009-09-16] 90399: Found job on default
|
41
|
+
** [05:55:09 2009-09-16] 90399: got: (Job{default} | Demo::Job | [{}])
|
42
|
+
** [05:55:09 2009-09-16] 90399: resque: Forked 90401 at 1253141709
|
43
|
+
** [05:55:09 2009-09-16] 90401: resque: Processing default since 1253141709
|
44
|
+
Processed a job!
|
45
|
+
** [05:55:10 2009-09-16] 90401: done: (Job{default} | Demo::Job | [{}])
|
46
|
+
|
47
|
+
Notice that our workers `require 'job'` in our `Rakefile`. This
|
48
|
+
ensures they have our app loaded and can access the job classes.
|
49
|
+
|
50
|
+
|
51
|
+
### Starting the Resque frontend
|
52
|
+
|
53
|
+
Great, now let's check out the Resque frontend. Either click on 'View
|
54
|
+
Resque' in your web browser or run:
|
55
|
+
|
56
|
+
$ open http://localhost:9292/resque/
|
57
|
+
|
58
|
+
You should see the Resque web frontend. 404 page? Don't forget the
|
59
|
+
trailing slash!
|
60
|
+
|
61
|
+
|
62
|
+
### config.ru
|
63
|
+
|
64
|
+
The `config.ru` shows you how to mount multiple Rack apps. Resque
|
65
|
+
should work fine on a subpath - feel free to load it up in your
|
66
|
+
Passenger app and protect it with some basic auth.
|
67
|
+
|
68
|
+
|
69
|
+
### That's it!
|
70
|
+
|
71
|
+
Click around, add some more queues, add more jobs, do whatever, have fun.
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'resque'
|
3
|
+
require 'job'
|
4
|
+
|
5
|
+
module Demo
|
6
|
+
class App < Sinatra::Base
|
7
|
+
get '/' do
|
8
|
+
info = Resque.info
|
9
|
+
out = "<html><head><title>Resque Demo</title></head><body>"
|
10
|
+
out << "<p>"
|
11
|
+
out << "There are #{info[:pending]} pending and "
|
12
|
+
out << "#{info[:processed]} processed jobs across #{info[:queues]} queues."
|
13
|
+
out << "</p>"
|
14
|
+
out << '<form method="POST">'
|
15
|
+
out << '<input type="submit" value="Create New Job"/>'
|
16
|
+
out << ' <a href="/resque/">View Resque</a>'
|
17
|
+
out << '</form>'
|
18
|
+
|
19
|
+
out << "<form action='/failing' method='POST''>"
|
20
|
+
out << '<input type="submit" value="Create Failing New Job"/>'
|
21
|
+
out << ' <a href="/resque/">View Resque</a>'
|
22
|
+
out << '</form>'
|
23
|
+
|
24
|
+
out << "</body></html>"
|
25
|
+
out
|
26
|
+
end
|
27
|
+
|
28
|
+
post '/' do
|
29
|
+
Resque.enqueue(Job, params)
|
30
|
+
redirect "/"
|
31
|
+
end
|
32
|
+
|
33
|
+
post '/failing' do
|
34
|
+
Resque.enqueue(FailingJob, params)
|
35
|
+
redirect "/"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'logger'
|
3
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../../lib'
|
4
|
+
require 'app'
|
5
|
+
require 'resque/server'
|
6
|
+
|
7
|
+
use Rack::ShowExceptions
|
8
|
+
|
9
|
+
# Set the AUTH env variable to your basic auth password to protect Resque.
|
10
|
+
AUTH_PASSWORD = ENV['AUTH']
|
11
|
+
if AUTH_PASSWORD
|
12
|
+
Resque::Server.use Rack::Auth::Basic do |username, password|
|
13
|
+
password == AUTH_PASSWORD
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
run Rack::URLMap.new \
|
18
|
+
"/" => Demo::App.new,
|
19
|
+
"/resque" => Resque::Server.new
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'resque'
|
2
|
+
|
3
|
+
module Demo
|
4
|
+
module Job
|
5
|
+
@queue = :default
|
6
|
+
|
7
|
+
def self.perform(params)
|
8
|
+
sleep 1
|
9
|
+
puts "Processed a job!"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module FailingJob
|
14
|
+
@queue = :failing
|
15
|
+
|
16
|
+
def self.perform(params)
|
17
|
+
sleep 1
|
18
|
+
raise 'not processable!'
|
19
|
+
puts "Processed a job!"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
rails_env = ENV['RAILS_ENV'] || "production"
|
2
|
+
rails_root = ENV['RAILS_ROOT'] || "/data/github/current"
|
3
|
+
num_workers = rails_env == 'production' ? 5 : 2
|
4
|
+
|
5
|
+
num_workers.times do |num|
|
6
|
+
God.watch do |w|
|
7
|
+
w.name = "resque-#{num}"
|
8
|
+
w.group = 'resque'
|
9
|
+
w.interval = 30.seconds
|
10
|
+
w.env = {"QUEUE"=>"critical,high,low", "RAILS_ENV"=>rails_env}
|
11
|
+
w.start = "/usr/bin/rake -f #{rails_root}/Rakefile environment resque:work"
|
12
|
+
|
13
|
+
w.uid = 'git'
|
14
|
+
w.gid = 'git'
|
15
|
+
|
16
|
+
# retart if memory gets too high
|
17
|
+
w.transition(:up, :restart) do |on|
|
18
|
+
on.condition(:memory_usage) do |c|
|
19
|
+
c.above = 350.megabytes
|
20
|
+
c.times = 2
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# determine the state on startup
|
25
|
+
w.transition(:init, { true => :up, false => :start }) do |on|
|
26
|
+
on.condition(:process_running) do |c|
|
27
|
+
c.running = true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# determine when process has finished starting
|
32
|
+
w.transition([:start, :restart], :up) do |on|
|
33
|
+
on.condition(:process_running) do |c|
|
34
|
+
c.running = true
|
35
|
+
c.interval = 5.seconds
|
36
|
+
end
|
37
|
+
|
38
|
+
# failsafe
|
39
|
+
on.condition(:tries) do |c|
|
40
|
+
c.times = 5
|
41
|
+
c.transition = :start
|
42
|
+
c.interval = 5.seconds
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# start if process is not running
|
47
|
+
w.transition(:up, :start) do |on|
|
48
|
+
on.condition(:process_running) do |c|
|
49
|
+
c.running = false
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# This will ride alongside god and kill any rogue stale worker
|
2
|
+
# processes. Their sacrifice is for the greater good.
|
3
|
+
|
4
|
+
WORKER_TIMEOUT = 60 * 10 # 10 minutes
|
5
|
+
|
6
|
+
Thread.new do
|
7
|
+
loop do
|
8
|
+
begin
|
9
|
+
`ps -e -o pid,command | grep [r]esque`.split("\n").each do |line|
|
10
|
+
parts = line.split(' ')
|
11
|
+
next if parts[-2] != "at"
|
12
|
+
started = parts[-1].to_i
|
13
|
+
elapsed = Time.now - Time.at(started)
|
14
|
+
|
15
|
+
if elapsed >= WORKER_TIMEOUT
|
16
|
+
::Process.kill('USR1', parts[0].to_i)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
rescue
|
20
|
+
# don't die because of stupid exceptions
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
|
24
|
+
sleep 30
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
check process resque_worker_QUEUE
|
2
|
+
with pidfile /data/APP_NAME/current/tmp/pids/resque_worker_QUEUE.pid
|
3
|
+
start program = "/bin/sh -c 'cd /data/APP_NAME/current; RAILS_ENV=production QUEUE=queue_name VERBOSE=1 nohup rake resque:work& &> log/resque_worker_QUEUE.log && echo $! > tmp/pids/resque_worker_QUEUE.pid'" as uid deploy and gid deploy
|
4
|
+
stop program = "/bin/sh -c 'cd /data/APP_NAME/current && kill -s QUIT `cat tmp/pids/resque_worker_QUEUE.pid` && rm -f tmp/pids/resque_worker_QUEUE.pid; exit 0;'"
|
5
|
+
if totalmem is greater than 300 MB for 10 cycles then restart # eating up memory?
|
6
|
+
group resque_workers
|
data/examples/simple.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# This is a simple Resque job.
|
2
|
+
class Archive
|
3
|
+
@queue = :file_serve
|
4
|
+
|
5
|
+
def self.perform(repo_id, branch = 'master')
|
6
|
+
repo = Repository.find(repo_id)
|
7
|
+
repo.create_archive(branch)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# This is in our app code
|
12
|
+
class Repository < Model
|
13
|
+
# ... stuff ...
|
14
|
+
|
15
|
+
def async_create_archive(branch)
|
16
|
+
Resque.enqueue(Archive, self.id, branch)
|
17
|
+
end
|
18
|
+
|
19
|
+
# ... more stuff ...
|
20
|
+
end
|
21
|
+
|
22
|
+
# Calling this code:
|
23
|
+
repo = Repository.find(22)
|
24
|
+
repo.async_create_archive('homebrew')
|
25
|
+
|
26
|
+
# Will return immediately and create a Resque job which is later
|
27
|
+
# processed.
|
28
|
+
|
29
|
+
# Essentially, this code is run by the worker when processing:
|
30
|
+
Archive.perform(22, 'homebrew')
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'resque'
|
data/lib/resque.rb
ADDED
@@ -0,0 +1,287 @@
|
|
1
|
+
require 'redis/namespace'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'yajl'
|
5
|
+
rescue LoadError
|
6
|
+
require 'json'
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'resque/version'
|
10
|
+
|
11
|
+
require 'resque/errors'
|
12
|
+
|
13
|
+
require 'resque/failure'
|
14
|
+
require 'resque/failure/base'
|
15
|
+
|
16
|
+
require 'resque/helpers'
|
17
|
+
require 'resque/stat'
|
18
|
+
require 'resque/job'
|
19
|
+
require 'resque/worker'
|
20
|
+
require 'resque/plugin'
|
21
|
+
|
22
|
+
module Resque
|
23
|
+
include Helpers
|
24
|
+
extend self
|
25
|
+
|
26
|
+
# Accepts:
|
27
|
+
# 1. A 'hostname:port' string
|
28
|
+
# 2. A 'hostname:port:db' string (to select the Redis db)
|
29
|
+
# 3. An instance of `Redis`, `Redis::Client`, `Redis::DistRedis`,
|
30
|
+
# or `Redis::Namespace`.
|
31
|
+
def redis=(server)
|
32
|
+
case server
|
33
|
+
when String
|
34
|
+
host, port, db = server.split(':')
|
35
|
+
redis = Redis.new(:host => host, :port => port,
|
36
|
+
:thread_safe => true, :db => db)
|
37
|
+
@redis = Redis::Namespace.new(:resque, :redis => redis)
|
38
|
+
when Redis, Redis::Client, Redis::DistRedis
|
39
|
+
@redis = Redis::Namespace.new(:resque, :redis => server)
|
40
|
+
when Redis::Namespace
|
41
|
+
@redis = server
|
42
|
+
else
|
43
|
+
raise "I don't know what to do with #{server.inspect}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns the current Redis connection. If none has been created, will
|
48
|
+
# create a new one.
|
49
|
+
def redis
|
50
|
+
return @redis if @redis
|
51
|
+
self.redis = 'localhost:6379'
|
52
|
+
self.redis
|
53
|
+
end
|
54
|
+
|
55
|
+
# The `before_first_fork` hook will be run in the **parent** process
|
56
|
+
# only once, before forking to run the first job. Be careful- any
|
57
|
+
# changes you make will be permanent for the lifespan of the
|
58
|
+
# worker.
|
59
|
+
#
|
60
|
+
# Call with a block to set the hook.
|
61
|
+
# Call with no arguments to return the hook.
|
62
|
+
def before_first_fork(&block)
|
63
|
+
block ? (@before_first_fork = block) : @before_first_fork
|
64
|
+
end
|
65
|
+
|
66
|
+
# Set a proc that will be called in the parent process before the
|
67
|
+
# worker forks for the first time.
|
68
|
+
def before_first_fork=(before_first_fork)
|
69
|
+
@before_first_fork = before_first_fork
|
70
|
+
end
|
71
|
+
|
72
|
+
# The `before_fork` hook will be run in the **parent** process
|
73
|
+
# before every job, so be careful- any changes you make will be
|
74
|
+
# permanent for the lifespan of the worker.
|
75
|
+
#
|
76
|
+
# Call with a block to set the hook.
|
77
|
+
# Call with no arguments to return the hook.
|
78
|
+
def before_fork(&block)
|
79
|
+
block ? (@before_fork = block) : @before_fork
|
80
|
+
end
|
81
|
+
|
82
|
+
# Set the before_fork proc.
|
83
|
+
def before_fork=(before_fork)
|
84
|
+
@before_fork = before_fork
|
85
|
+
end
|
86
|
+
|
87
|
+
# The `after_fork` hook will be run in the child process and is passed
|
88
|
+
# the current job. Any changes you make, therefor, will only live as
|
89
|
+
# long as the job currently being processes.
|
90
|
+
#
|
91
|
+
# Call with a block to set the hook.
|
92
|
+
# Call with no arguments to return the hook.
|
93
|
+
def after_fork(&block)
|
94
|
+
block ? (@after_fork = block) : @after_fork
|
95
|
+
end
|
96
|
+
|
97
|
+
# Set the after_fork proc.
|
98
|
+
def after_fork=(after_fork)
|
99
|
+
@after_fork = after_fork
|
100
|
+
end
|
101
|
+
|
102
|
+
def to_s
|
103
|
+
"Resque Client connected to #{redis.server}"
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
#
|
108
|
+
# queue manipulation
|
109
|
+
#
|
110
|
+
|
111
|
+
# Pushes a job onto a queue. Queue name should be a string and the
|
112
|
+
# item should be any JSON-able Ruby object.
|
113
|
+
def push(queue, item)
|
114
|
+
watch_queue(queue)
|
115
|
+
redis.rpush "queue:#{queue}", encode(item)
|
116
|
+
end
|
117
|
+
|
118
|
+
# Pops a job off a queue. Queue name should be a string.
|
119
|
+
#
|
120
|
+
# Returns a Ruby object.
|
121
|
+
def pop(queue)
|
122
|
+
decode redis.lpop("queue:#{queue}")
|
123
|
+
end
|
124
|
+
|
125
|
+
# Returns an int representing the size of a queue.
|
126
|
+
# Queue name should be a string.
|
127
|
+
def size(queue)
|
128
|
+
redis.llen("queue:#{queue}").to_i
|
129
|
+
end
|
130
|
+
|
131
|
+
# Returns an array of items currently queued. Queue name should be
|
132
|
+
# a string.
|
133
|
+
#
|
134
|
+
# start and count should be integer and can be used for pagination.
|
135
|
+
# start is the item to begin, count is how many items to return.
|
136
|
+
#
|
137
|
+
# To get the 3rd page of a 30 item, paginatied list one would use:
|
138
|
+
# Resque.peek('my_list', 59, 30)
|
139
|
+
def peek(queue, start = 0, count = 1)
|
140
|
+
list_range("queue:#{queue}", start, count)
|
141
|
+
end
|
142
|
+
|
143
|
+
# Does the dirty work of fetching a range of items from a Redis list
|
144
|
+
# and converting them into Ruby objects.
|
145
|
+
def list_range(key, start = 0, count = 1)
|
146
|
+
if count == 1
|
147
|
+
decode redis.lindex(key, start)
|
148
|
+
else
|
149
|
+
Array(redis.lrange(key, start, start+count-1)).map do |item|
|
150
|
+
decode item
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# Returns an array of all known Resque queues as strings.
|
156
|
+
def queues
|
157
|
+
redis.smembers(:queues)
|
158
|
+
end
|
159
|
+
|
160
|
+
# Given a queue name, completely deletes the queue.
|
161
|
+
def remove_queue(queue)
|
162
|
+
redis.srem(:queues, queue.to_s)
|
163
|
+
redis.del("queue:#{queue}")
|
164
|
+
end
|
165
|
+
|
166
|
+
# Used internally to keep track of which queues we've created.
|
167
|
+
# Don't call this directly.
|
168
|
+
def watch_queue(queue)
|
169
|
+
redis.sadd(:queues, queue.to_s)
|
170
|
+
end
|
171
|
+
|
172
|
+
|
173
|
+
#
|
174
|
+
# job shortcuts
|
175
|
+
#
|
176
|
+
|
177
|
+
# This method can be used to conveniently add a job to a queue.
|
178
|
+
# It assumes the class you're passing it is a real Ruby class (not
|
179
|
+
# a string or reference) which either:
|
180
|
+
#
|
181
|
+
# a) has a @queue ivar set
|
182
|
+
# b) responds to `queue`
|
183
|
+
#
|
184
|
+
# If either of those conditions are met, it will use the value obtained
|
185
|
+
# from performing one of the above operations to determine the queue.
|
186
|
+
#
|
187
|
+
# If no queue can be inferred this method will raise a `Resque::NoQueueError`
|
188
|
+
#
|
189
|
+
# This method is considered part of the `stable` API.
|
190
|
+
def enqueue(klass, *args)
|
191
|
+
Job.create(queue_from_class(klass), klass, *args)
|
192
|
+
end
|
193
|
+
|
194
|
+
# This method can be used to conveniently remove a job from a queue.
|
195
|
+
# It assumes the class you're passing it is a real Ruby class (not
|
196
|
+
# a string or reference) which either:
|
197
|
+
#
|
198
|
+
# a) has a @queue ivar set
|
199
|
+
# b) responds to `queue`
|
200
|
+
#
|
201
|
+
# If either of those conditions are met, it will use the value obtained
|
202
|
+
# from performing one of the above operations to determine the queue.
|
203
|
+
#
|
204
|
+
# If no queue can be inferred this method will raise a `Resque::NoQueueError`
|
205
|
+
#
|
206
|
+
# If no args are given, this method will dequeue *all* jobs matching
|
207
|
+
# the provided class. See `Resque::Job.destroy` for more
|
208
|
+
# information.
|
209
|
+
#
|
210
|
+
# Returns the number of jobs destroyed.
|
211
|
+
#
|
212
|
+
# Example:
|
213
|
+
#
|
214
|
+
# # Removes all jobs of class `UpdateNetworkGraph`
|
215
|
+
# Resque.dequeue(GitHub::Jobs::UpdateNetworkGraph)
|
216
|
+
#
|
217
|
+
# # Removes all jobs of class `UpdateNetworkGraph` with matching args.
|
218
|
+
# Resque.dequeue(GitHub::Jobs::UpdateNetworkGraph, 'repo:135325')
|
219
|
+
#
|
220
|
+
# This method is considered part of the `stable` API.
|
221
|
+
def dequeue(klass, *args)
|
222
|
+
Job.destroy(queue_from_class(klass), klass, *args)
|
223
|
+
end
|
224
|
+
|
225
|
+
# Given a class, try to extrapolate an appropriate queue based on a
|
226
|
+
# class instance variable or `queue` method.
|
227
|
+
def queue_from_class(klass)
|
228
|
+
klass.instance_variable_get(:@queue) ||
|
229
|
+
(klass.respond_to?(:queue) and klass.queue)
|
230
|
+
end
|
231
|
+
|
232
|
+
# This method will return a `Resque::Job` object or a non-true value
|
233
|
+
# depending on whether a job can be obtained. You should pass it the
|
234
|
+
# precise name of a queue: case matters.
|
235
|
+
#
|
236
|
+
# This method is considered part of the `stable` API.
|
237
|
+
def reserve(queue)
|
238
|
+
Job.reserve(queue)
|
239
|
+
end
|
240
|
+
|
241
|
+
|
242
|
+
#
|
243
|
+
# worker shortcuts
|
244
|
+
#
|
245
|
+
|
246
|
+
# A shortcut to Worker.all
|
247
|
+
def workers
|
248
|
+
Worker.all
|
249
|
+
end
|
250
|
+
|
251
|
+
# A shortcut to Worker.working
|
252
|
+
def working
|
253
|
+
Worker.working
|
254
|
+
end
|
255
|
+
|
256
|
+
# A shortcut to unregister_worker
|
257
|
+
# useful for command line tool
|
258
|
+
def remove_worker(worker_id)
|
259
|
+
worker = Resque::Worker.find(worker_id)
|
260
|
+
worker.unregister_worker
|
261
|
+
end
|
262
|
+
|
263
|
+
#
|
264
|
+
# stats
|
265
|
+
#
|
266
|
+
|
267
|
+
# Returns a hash, similar to redis-rb's #info, of interesting stats.
|
268
|
+
def info
|
269
|
+
return {
|
270
|
+
:pending => queues.inject(0) { |m,k| m + size(k) },
|
271
|
+
:processed => Stat[:processed],
|
272
|
+
:queues => queues.size,
|
273
|
+
:workers => workers.size.to_i,
|
274
|
+
:working => working.size,
|
275
|
+
:failed => Stat[:failed],
|
276
|
+
:servers => [redis.server]
|
277
|
+
}
|
278
|
+
end
|
279
|
+
|
280
|
+
# Returns an array of all known Resque keys in Redis. Redis' KEYS operation
|
281
|
+
# is O(N) for the keyspace, so be careful - this can be slow for big databases.
|
282
|
+
def keys
|
283
|
+
redis.keys("*").map do |key|
|
284
|
+
key.sub("#{redis.namespace}:", '')
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|