resque 1.23.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/HISTORY.md +271 -0
- data/README.markdown +454 -484
- data/Rakefile +4 -17
- data/bin/resque-web +10 -22
- data/lib/resque/data_store.rb +335 -0
- data/lib/resque/errors.rb +15 -1
- data/lib/resque/failure/airbrake.rb +32 -4
- data/lib/resque/failure/base.rb +16 -7
- data/lib/resque/failure/multiple.rb +26 -8
- data/lib/resque/failure/redis.rb +92 -15
- data/lib/resque/failure/redis_multi_queue.rb +104 -0
- data/lib/resque/failure.rb +62 -32
- data/lib/resque/helpers.rb +11 -57
- data/lib/resque/job.rb +79 -12
- data/lib/resque/log_formatters/quiet_formatter.rb +7 -0
- data/lib/resque/log_formatters/verbose_formatter.rb +7 -0
- data/lib/resque/log_formatters/very_verbose_formatter.rb +8 -0
- data/lib/resque/logging.rb +18 -0
- data/lib/resque/plugin.rb +22 -10
- data/lib/resque/railtie.rb +10 -0
- data/lib/resque/server/public/jquery-3.6.0.min.js +2 -0
- data/lib/resque/server/public/jquery.relatize_date.js +4 -4
- data/lib/resque/server/public/main.js +3 -0
- data/lib/resque/server/public/ranger.js +16 -8
- data/lib/resque/server/public/style.css +13 -8
- data/lib/resque/server/views/error.erb +1 -1
- data/lib/resque/server/views/failed.erb +27 -59
- data/lib/resque/server/views/failed_job.erb +50 -0
- data/lib/resque/server/views/failed_queues_overview.erb +24 -0
- data/lib/resque/server/views/job_class.erb +8 -0
- data/lib/resque/server/views/key_sets.erb +2 -4
- data/lib/resque/server/views/key_string.erb +1 -1
- data/lib/resque/server/views/layout.erb +7 -6
- data/lib/resque/server/views/next_more.erb +22 -10
- data/lib/resque/server/views/processing.erb +2 -0
- data/lib/resque/server/views/queues.erb +22 -13
- data/lib/resque/server/views/stats.erb +5 -5
- data/lib/resque/server/views/workers.erb +4 -4
- data/lib/resque/server/views/working.erb +10 -11
- data/lib/resque/server.rb +51 -108
- data/lib/resque/server_helper.rb +185 -0
- data/lib/resque/stat.rb +19 -7
- data/lib/resque/tasks.rb +26 -25
- data/lib/resque/thread_signal.rb +24 -0
- data/lib/resque/vendor/utf8_util.rb +2 -8
- data/lib/resque/version.rb +1 -1
- data/lib/resque/web_runner.rb +374 -0
- data/lib/resque/worker.rb +487 -163
- data/lib/resque.rb +332 -52
- data/lib/tasks/redis.rake +11 -11
- metadata +169 -149
- data/lib/resque/failure/hoptoad.rb +0 -33
- data/lib/resque/failure/thoughtbot.rb +0 -33
- data/lib/resque/server/public/jquery-1.3.2.min.js +0 -19
- data/lib/resque/server/test_helper.rb +0 -19
- data/lib/resque/vendor/utf8_util/utf8_util_18.rb +0 -91
- data/lib/resque/vendor/utf8_util/utf8_util_19.rb +0 -5
- data/test/airbrake_test.rb +0 -27
- data/test/hoptoad_test.rb +0 -26
- data/test/job_hooks_test.rb +0 -464
- data/test/job_plugins_test.rb +0 -230
- data/test/plugin_test.rb +0 -116
- data/test/redis-test-cluster.conf +0 -115
- data/test/redis-test.conf +0 -115
- data/test/resque-web_test.rb +0 -59
- data/test/resque_failure_redis_test.rb +0 -19
- data/test/resque_test.rb +0 -278
- data/test/test_helper.rb +0 -178
- data/test/worker_test.rb +0 -657
@@ -0,0 +1,185 @@
|
|
1
|
+
require 'rack/utils'
|
2
|
+
|
3
|
+
module Resque
|
4
|
+
module ServerHelper
|
5
|
+
include Rack::Utils
|
6
|
+
alias_method :h, :escape_html
|
7
|
+
|
8
|
+
def current_section
|
9
|
+
url_path request.path_info.sub('/','').split('/')[0].downcase
|
10
|
+
end
|
11
|
+
|
12
|
+
def current_page
|
13
|
+
url_path request.path_info.sub('/','')
|
14
|
+
end
|
15
|
+
|
16
|
+
def url_path(*path_parts)
|
17
|
+
[ url_prefix, path_prefix, path_parts ].join("/").squeeze('/')
|
18
|
+
end
|
19
|
+
alias_method :u, :url_path
|
20
|
+
|
21
|
+
def path_prefix
|
22
|
+
request.env['SCRIPT_NAME']
|
23
|
+
end
|
24
|
+
|
25
|
+
def class_if_current(path = '')
|
26
|
+
'class="current"' if current_page[0, path.size] == path
|
27
|
+
end
|
28
|
+
|
29
|
+
def tab(name)
|
30
|
+
dname = name.to_s.downcase
|
31
|
+
path = url_path(dname)
|
32
|
+
"<li #{class_if_current(path)}><a href='#{path.gsub(" ", "_")}'>#{name}</a></li>"
|
33
|
+
end
|
34
|
+
|
35
|
+
def tabs
|
36
|
+
Resque::Server.tabs
|
37
|
+
end
|
38
|
+
|
39
|
+
def url_prefix
|
40
|
+
Resque::Server.url_prefix
|
41
|
+
end
|
42
|
+
|
43
|
+
def redis_get_size(key)
|
44
|
+
case Resque.redis.type(key)
|
45
|
+
when 'none'
|
46
|
+
0
|
47
|
+
when 'hash'
|
48
|
+
Resque.redis.hlen(key)
|
49
|
+
when 'list'
|
50
|
+
Resque.redis.llen(key)
|
51
|
+
when 'set'
|
52
|
+
Resque.redis.scard(key)
|
53
|
+
when 'string'
|
54
|
+
Resque.redis.get(key).length
|
55
|
+
when 'zset'
|
56
|
+
Resque.redis.zcard(key)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def redis_get_value_as_array(key, start=0)
|
61
|
+
case Resque.redis.type(key)
|
62
|
+
when 'none'
|
63
|
+
[]
|
64
|
+
when 'hash'
|
65
|
+
Resque.redis.hgetall(key).to_a[start..(start + 20)]
|
66
|
+
when 'list'
|
67
|
+
Resque.redis.lrange(key, start, start + 20)
|
68
|
+
when 'set'
|
69
|
+
Resque.redis.smembers(key)[start..(start + 20)]
|
70
|
+
when 'string'
|
71
|
+
[Resque.redis.get(key)]
|
72
|
+
when 'zset'
|
73
|
+
Resque.redis.zrange(key, start, start + 20)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def show_args(args)
|
78
|
+
Array(args).map do |a|
|
79
|
+
a.to_yaml
|
80
|
+
end.join("\n")
|
81
|
+
rescue
|
82
|
+
args.to_s
|
83
|
+
end
|
84
|
+
|
85
|
+
def worker_hosts
|
86
|
+
@worker_hosts ||= worker_hosts!
|
87
|
+
end
|
88
|
+
|
89
|
+
def worker_hosts!
|
90
|
+
hosts = Hash.new { [] }
|
91
|
+
|
92
|
+
Resque.workers.each do |worker|
|
93
|
+
host, _ = worker.to_s.split(':')
|
94
|
+
hosts[host] += [worker.to_s]
|
95
|
+
end
|
96
|
+
|
97
|
+
hosts
|
98
|
+
end
|
99
|
+
|
100
|
+
def partial?
|
101
|
+
@partial
|
102
|
+
end
|
103
|
+
|
104
|
+
def partial(template, local_vars = {})
|
105
|
+
@partial = true
|
106
|
+
erb(template.to_sym, {:layout => false}, local_vars)
|
107
|
+
ensure
|
108
|
+
@partial = false
|
109
|
+
end
|
110
|
+
|
111
|
+
def poll
|
112
|
+
if defined?(@polling) && @polling
|
113
|
+
text = "Last Updated: #{Time.now.strftime("%H:%M:%S")}"
|
114
|
+
else
|
115
|
+
text = "<a href='#{u(request.path_info)}.poll' rel='poll'>Live Poll!!</a>"
|
116
|
+
end
|
117
|
+
"<p class='poll'>#{text}</p>"
|
118
|
+
end
|
119
|
+
|
120
|
+
####################
|
121
|
+
#failed.erb helpers#
|
122
|
+
####################
|
123
|
+
|
124
|
+
def failed_date_format
|
125
|
+
"%Y/%m/%d %T %z"
|
126
|
+
end
|
127
|
+
|
128
|
+
def failed_multiple_queues?
|
129
|
+
return @multiple_failed_queues if defined?(@multiple_failed_queues)
|
130
|
+
|
131
|
+
@multiple_failed_queues = Resque::Failure.queues.size > 1 ||
|
132
|
+
(defined?(Resque::Failure::RedisMultiQueue) && Resque::Failure.backend == Resque::Failure::RedisMultiQueue)
|
133
|
+
end
|
134
|
+
|
135
|
+
def failed_size
|
136
|
+
@failed_size ||= Resque::Failure.count(params[:queue], params[:class])
|
137
|
+
end
|
138
|
+
|
139
|
+
def failed_per_page
|
140
|
+
@failed_per_page = if params[:class]
|
141
|
+
failed_size
|
142
|
+
else
|
143
|
+
20
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def failed_start_at
|
148
|
+
params[:start].to_i
|
149
|
+
end
|
150
|
+
|
151
|
+
def failed_end_at
|
152
|
+
if failed_start_at + failed_per_page > failed_size
|
153
|
+
failed_size
|
154
|
+
else
|
155
|
+
failed_start_at + failed_per_page - 1
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def failed_order
|
160
|
+
params[:order] || 'desc'
|
161
|
+
end
|
162
|
+
|
163
|
+
def failed_class_counts(queue = params[:queue])
|
164
|
+
classes = Hash.new(0)
|
165
|
+
Resque::Failure.each(0, Resque::Failure.count(queue), queue) do |_, item|
|
166
|
+
class_name = item['payload']['class'] if item['payload']
|
167
|
+
class_name ||= "nil"
|
168
|
+
classes[class_name] += 1
|
169
|
+
end
|
170
|
+
classes
|
171
|
+
end
|
172
|
+
|
173
|
+
def page_entries_info(start, stop, size, name = nil)
|
174
|
+
if size == 0
|
175
|
+
name ? "No #{name}s" : '<b>0</b>'
|
176
|
+
elsif size == 1
|
177
|
+
'Showing <b>1</b>' + (name ? " #{name}" : '')
|
178
|
+
elsif size > failed_per_page
|
179
|
+
"Showing #{start}-#{stop} of <b>#{size}</b>" + (name ? " #{name}s" : '')
|
180
|
+
else
|
181
|
+
"Showing #{start} to <b>#{size - 1}</b>" + (name ? " #{name}s" : '')
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
data/lib/resque/stat.rb
CHANGED
@@ -7,11 +7,23 @@ module Resque
|
|
7
7
|
# Kill a stat: Stat.clear(name)
|
8
8
|
module Stat
|
9
9
|
extend self
|
10
|
-
|
10
|
+
|
11
|
+
def redis
|
12
|
+
warn '[Resque] [Deprecation] Resque::Stat #redis method is deprecated (please use #data_strore)'
|
13
|
+
data_store
|
14
|
+
end
|
15
|
+
|
16
|
+
def data_store
|
17
|
+
@data_store ||= Resque.redis
|
18
|
+
end
|
19
|
+
|
20
|
+
def data_store=(data_store)
|
21
|
+
@data_store = data_store
|
22
|
+
end
|
11
23
|
|
12
24
|
# Returns the int value of a stat, given a string stat name.
|
13
25
|
def get(stat)
|
14
|
-
|
26
|
+
data_store.stat(stat)
|
15
27
|
end
|
16
28
|
|
17
29
|
# Alias of `get`
|
@@ -23,8 +35,8 @@ module Resque
|
|
23
35
|
#
|
24
36
|
# Can optionally accept a second int parameter. The stat is then
|
25
37
|
# incremented by that amount.
|
26
|
-
def incr(stat, by = 1)
|
27
|
-
|
38
|
+
def incr(stat, by = 1, **opts)
|
39
|
+
data_store.increment_stat(stat, by, **opts)
|
28
40
|
end
|
29
41
|
|
30
42
|
# Increments a stat by one.
|
@@ -37,7 +49,7 @@ module Resque
|
|
37
49
|
# Can optionally accept a second int parameter. The stat is then
|
38
50
|
# decremented by that amount.
|
39
51
|
def decr(stat, by = 1)
|
40
|
-
|
52
|
+
data_store.decrement_stat(stat,by)
|
41
53
|
end
|
42
54
|
|
43
55
|
# Decrements a stat by one.
|
@@ -46,8 +58,8 @@ module Resque
|
|
46
58
|
end
|
47
59
|
|
48
60
|
# Removes a stat from Redis, effectively setting it to 0.
|
49
|
-
def clear(stat)
|
50
|
-
|
61
|
+
def clear(stat, **opts)
|
62
|
+
data_store.clear_stat(stat, **opts)
|
51
63
|
end
|
52
64
|
end
|
53
65
|
end
|
data/lib/resque/tasks.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# require 'resque/tasks'
|
2
2
|
# will give you the resque tasks
|
3
3
|
|
4
|
+
|
4
5
|
namespace :resque do
|
5
6
|
task :setup
|
6
7
|
|
@@ -8,31 +9,14 @@ namespace :resque do
|
|
8
9
|
task :work => [ :preload, :setup ] do
|
9
10
|
require 'resque'
|
10
11
|
|
11
|
-
queues = (ENV['QUEUES'] || ENV['QUEUE']).to_s.split(',')
|
12
|
-
|
13
12
|
begin
|
14
|
-
worker = Resque::Worker.new
|
15
|
-
worker.verbose = ENV['LOGGING'] || ENV['VERBOSE']
|
16
|
-
worker.very_verbose = ENV['VVERBOSE']
|
17
|
-
worker.term_timeout = ENV['RESQUE_TERM_TIMEOUT'] || 4.0
|
18
|
-
worker.term_child = ENV['TERM_CHILD']
|
13
|
+
worker = Resque::Worker.new
|
19
14
|
rescue Resque::NoQueueError
|
20
15
|
abort "set QUEUE env var, e.g. $ QUEUE=critical,high rake resque:work"
|
21
16
|
end
|
22
17
|
|
23
|
-
|
24
|
-
unless Process.respond_to?('daemon')
|
25
|
-
abort "env var BACKGROUND is set, which requires ruby >= 1.9"
|
26
|
-
end
|
27
|
-
Process.daemon(true)
|
28
|
-
end
|
29
|
-
|
30
|
-
if ENV['PIDFILE']
|
31
|
-
File.open(ENV['PIDFILE'], 'w') { |f| f << worker.pid }
|
32
|
-
end
|
33
|
-
|
18
|
+
worker.prepare
|
34
19
|
worker.log "Starting worker #{worker}"
|
35
|
-
|
36
20
|
worker.work(ENV['INTERVAL'] || 5) # interval, will block
|
37
21
|
end
|
38
22
|
|
@@ -40,6 +24,10 @@ namespace :resque do
|
|
40
24
|
task :workers do
|
41
25
|
threads = []
|
42
26
|
|
27
|
+
if ENV['COUNT'].to_i < 1
|
28
|
+
abort "set COUNT env var, e.g. $ COUNT=2 rake resque:workers"
|
29
|
+
end
|
30
|
+
|
43
31
|
ENV['COUNT'].to_i.times do
|
44
32
|
threads << Thread.new do
|
45
33
|
system "rake resque:work"
|
@@ -52,12 +40,25 @@ namespace :resque do
|
|
52
40
|
# Preload app files if this is Rails
|
53
41
|
task :preload => :setup do
|
54
42
|
if defined?(Rails) && Rails.respond_to?(:application)
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
43
|
+
if Rails.application.config.eager_load
|
44
|
+
ActiveSupport.run_load_hooks(:before_eager_load, Rails.application)
|
45
|
+
Rails.application.config.eager_load_namespaces.each(&:eager_load!)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
namespace :failures do
|
51
|
+
desc "Sort the 'failed' queue for the redis_multi_queue failure backend"
|
52
|
+
task :sort do
|
53
|
+
require 'resque'
|
54
|
+
require 'resque/failure/redis'
|
55
|
+
|
56
|
+
warn "Sorting #{Resque::Failure.count} failures..."
|
57
|
+
Resque::Failure.each(0, Resque::Failure.count) do |_, failure|
|
58
|
+
data = Resque.encode(failure)
|
59
|
+
Resque.redis.rpush(Resque::Failure.failure_queue_name(failure['queue']), data)
|
60
|
+
end
|
61
|
+
warn "done!"
|
61
62
|
end
|
62
63
|
end
|
63
64
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class Resque::ThreadSignal
|
2
|
+
def initialize
|
3
|
+
@mutex = Mutex.new
|
4
|
+
@signaled = false
|
5
|
+
@received = ConditionVariable.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def signal
|
9
|
+
@mutex.synchronize do
|
10
|
+
@signaled = true
|
11
|
+
@received.signal
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def wait_for_signal(timeout)
|
16
|
+
@mutex.synchronize do
|
17
|
+
unless @signaled
|
18
|
+
@received.wait(@mutex, timeout)
|
19
|
+
end
|
20
|
+
|
21
|
+
@signaled
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -7,7 +7,8 @@ module UTF8Util
|
|
7
7
|
#
|
8
8
|
# Returns self as valid UTF-8.
|
9
9
|
def self.clean!(str)
|
10
|
-
|
10
|
+
return str if str.encoding.to_s == "UTF-8"
|
11
|
+
str.force_encoding("binary").encode("UTF-8", :invalid => :replace, :undef => :replace, :replace => REPLACEMENT_CHAR)
|
11
12
|
end
|
12
13
|
|
13
14
|
# Replace invalid UTF-8 character sequences with a replacement character
|
@@ -16,11 +17,4 @@ module UTF8Util
|
|
16
17
|
def self.clean(str)
|
17
18
|
clean!(str.dup)
|
18
19
|
end
|
19
|
-
|
20
|
-
end
|
21
|
-
|
22
|
-
if RUBY_VERSION <= '1.9'
|
23
|
-
require 'resque/vendor/utf8_util/utf8_util_18'
|
24
|
-
else
|
25
|
-
require 'resque/vendor/utf8_util/utf8_util_19'
|
26
20
|
end
|
data/lib/resque/version.rb
CHANGED