resque 1.27.4 → 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 +5 -5
- data/HISTORY.md +122 -3
- data/README.markdown +441 -500
- data/bin/resque-web +10 -26
- data/lib/resque/data_store.rb +52 -58
- data/lib/resque/errors.rb +7 -1
- data/lib/resque/failure/airbrake.rb +19 -7
- data/lib/resque/failure/multiple.rb +6 -2
- data/lib/resque/failure/redis.rb +1 -1
- data/lib/resque/failure/redis_multi_queue.rb +1 -1
- data/lib/resque/failure.rb +7 -0
- data/lib/resque/job.rb +2 -2
- data/lib/resque/logging.rb +1 -1
- 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/main.js +3 -0
- data/lib/resque/server/public/ranger.js +7 -4
- data/lib/resque/server/public/style.css +3 -3
- data/lib/resque/server/views/error.erb +1 -1
- data/lib/resque/server/views/failed.erb +9 -3
- data/lib/resque/server/views/failed_job.erb +2 -2
- 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 +5 -4
- data/lib/resque/server/views/next_more.erb +14 -14
- data/lib/resque/server/views/queues.erb +6 -6
- data/lib/resque/server/views/stats.erb +5 -5
- data/lib/resque/server/views/working.erb +7 -7
- data/lib/resque/server.rb +11 -119
- data/lib/resque/server_helper.rb +185 -0
- data/lib/resque/stat.rb +16 -9
- data/lib/resque/tasks.rb +3 -11
- data/lib/resque/thread_signal.rb +13 -34
- 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 +76 -48
- data/lib/resque.rb +100 -27
- data/lib/tasks/redis.rake +10 -10
- metadata +44 -28
- data/lib/resque/server/helpers.rb +0 -64
- data/lib/resque/server/public/jquery-1.12.4.min.js +0 -5
- 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 -6
data/lib/resque/server.rb
CHANGED
@@ -1,18 +1,17 @@
|
|
1
1
|
require 'sinatra/base'
|
2
2
|
require 'tilt/erb'
|
3
3
|
require 'resque'
|
4
|
+
require 'resque/server_helper'
|
4
5
|
require 'resque/version'
|
5
6
|
require 'time'
|
6
7
|
require 'yaml'
|
7
8
|
|
8
|
-
if defined? Encoding
|
9
|
+
if defined?(Encoding) && Encoding.default_external != Encoding::UTF_8
|
9
10
|
Encoding.default_external = Encoding::UTF_8
|
10
11
|
end
|
11
12
|
|
12
13
|
module Resque
|
13
14
|
class Server < Sinatra::Base
|
14
|
-
require 'resque/server/helpers'
|
15
|
-
|
16
15
|
dir = File.dirname(File.expand_path(__FILE__))
|
17
16
|
|
18
17
|
set :views, "#{dir}/server/views"
|
@@ -26,119 +25,7 @@ module Resque
|
|
26
25
|
set :static, true
|
27
26
|
|
28
27
|
helpers do
|
29
|
-
include
|
30
|
-
alias_method :h, :escape_html
|
31
|
-
|
32
|
-
def current_section
|
33
|
-
url_path request.path_info.sub('/','').split('/')[0].downcase
|
34
|
-
end
|
35
|
-
|
36
|
-
def current_page
|
37
|
-
url_path request.path_info.sub('/','')
|
38
|
-
end
|
39
|
-
|
40
|
-
def url_path(*path_parts)
|
41
|
-
[ url_prefix, path_prefix, path_parts ].join("/").squeeze('/')
|
42
|
-
end
|
43
|
-
alias_method :u, :url_path
|
44
|
-
|
45
|
-
def redirect_url_path(*path_parts)
|
46
|
-
[ path_prefix, path_parts ].join("/").squeeze('/')
|
47
|
-
end
|
48
|
-
|
49
|
-
def path_prefix
|
50
|
-
request.env['SCRIPT_NAME']
|
51
|
-
end
|
52
|
-
|
53
|
-
def class_if_current(path = '')
|
54
|
-
'class="current"' if current_page[0, path.size] == path
|
55
|
-
end
|
56
|
-
|
57
|
-
def tab(name)
|
58
|
-
dname = name.to_s.downcase
|
59
|
-
path = url_path(dname)
|
60
|
-
"<li #{class_if_current(path)}><a href='#{path}'>#{name}</a></li>"
|
61
|
-
end
|
62
|
-
|
63
|
-
def tabs
|
64
|
-
Resque::Server.tabs
|
65
|
-
end
|
66
|
-
|
67
|
-
def url_prefix
|
68
|
-
Resque::Server.url_prefix
|
69
|
-
end
|
70
|
-
|
71
|
-
def redis_get_size(key)
|
72
|
-
case Resque.redis.type(key)
|
73
|
-
when 'none'
|
74
|
-
[]
|
75
|
-
when 'list'
|
76
|
-
Resque.redis.llen(key)
|
77
|
-
when 'set'
|
78
|
-
Resque.redis.scard(key)
|
79
|
-
when 'string'
|
80
|
-
Resque.redis.get(key).length
|
81
|
-
when 'zset'
|
82
|
-
Resque.redis.zcard(key)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def redis_get_value_as_array(key, start=0)
|
87
|
-
case Resque.redis.type(key)
|
88
|
-
when 'none'
|
89
|
-
[]
|
90
|
-
when 'list'
|
91
|
-
Resque.redis.lrange(key, start, start + 20)
|
92
|
-
when 'set'
|
93
|
-
Resque.redis.smembers(key)[start..(start + 20)]
|
94
|
-
when 'string'
|
95
|
-
[Resque.redis.get(key)]
|
96
|
-
when 'zset'
|
97
|
-
Resque.redis.zrange(key, start, start + 20)
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def show_args(args)
|
102
|
-
Array(args).map do |a|
|
103
|
-
a.to_yaml
|
104
|
-
end.join("\n")
|
105
|
-
end
|
106
|
-
|
107
|
-
def worker_hosts
|
108
|
-
@worker_hosts ||= worker_hosts!
|
109
|
-
end
|
110
|
-
|
111
|
-
def worker_hosts!
|
112
|
-
hosts = Hash.new { [] }
|
113
|
-
|
114
|
-
Resque.workers.each do |worker|
|
115
|
-
host, _ = worker.to_s.split(':')
|
116
|
-
hosts[host] += [worker.to_s]
|
117
|
-
end
|
118
|
-
|
119
|
-
hosts
|
120
|
-
end
|
121
|
-
|
122
|
-
def partial?
|
123
|
-
@partial
|
124
|
-
end
|
125
|
-
|
126
|
-
def partial(template, local_vars = {})
|
127
|
-
@partial = true
|
128
|
-
erb(template.to_sym, {:layout => false}, local_vars)
|
129
|
-
ensure
|
130
|
-
@partial = false
|
131
|
-
end
|
132
|
-
|
133
|
-
def poll
|
134
|
-
if @polling
|
135
|
-
text = "Last Updated: #{Time.now.strftime("%H:%M:%S")}"
|
136
|
-
else
|
137
|
-
text = "<a href='#{u(request.path_info)}.poll' rel='poll'>Live Poll</a>"
|
138
|
-
end
|
139
|
-
"<p class='poll'>#{text}</p>"
|
140
|
-
end
|
141
|
-
|
28
|
+
include Resque::ServerHelper
|
142
29
|
end
|
143
30
|
|
144
31
|
def show(page, layout = true)
|
@@ -158,7 +45,7 @@ module Resque
|
|
158
45
|
|
159
46
|
# to make things easier on ourselves
|
160
47
|
get "/?" do
|
161
|
-
redirect
|
48
|
+
redirect url_path(:overview)
|
162
49
|
end
|
163
50
|
|
164
51
|
%w( overview workers ).each do |page|
|
@@ -207,6 +94,11 @@ module Resque
|
|
207
94
|
redirect u('failed')
|
208
95
|
end
|
209
96
|
|
97
|
+
post "/failed/clear_retried" do
|
98
|
+
Resque::Failure.clear_retried
|
99
|
+
redirect u('failed')
|
100
|
+
end
|
101
|
+
|
210
102
|
post "/failed/:queue/clear" do
|
211
103
|
Resque::Failure.clear params[:queue]
|
212
104
|
redirect u('failed')
|
@@ -219,7 +111,7 @@ module Resque
|
|
219
111
|
|
220
112
|
post "/failed/:queue/requeue/all" do
|
221
113
|
Resque::Failure.requeue_queue Resque::Failure.job_queue_name(params[:queue])
|
222
|
-
redirect
|
114
|
+
redirect url_path("/failed/#{params[:queue]}")
|
223
115
|
end
|
224
116
|
|
225
117
|
get "/failed/requeue/:index/?" do
|
@@ -251,7 +143,7 @@ module Resque
|
|
251
143
|
end
|
252
144
|
|
253
145
|
get "/stats/?" do
|
254
|
-
redirect
|
146
|
+
redirect url_path("/stats/resque")
|
255
147
|
end
|
256
148
|
|
257
149
|
get "/stats/:id/?" do
|
@@ -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,12 +7,19 @@ module Resque
|
|
7
7
|
# Kill a stat: Stat.clear(name)
|
8
8
|
module Stat
|
9
9
|
extend self
|
10
|
-
|
11
|
-
# Direct access to the Redis instance.
|
10
|
+
|
12
11
|
def redis
|
13
|
-
Resque
|
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
|
14
22
|
end
|
15
|
-
alias :data_store :redis
|
16
23
|
|
17
24
|
# Returns the int value of a stat, given a string stat name.
|
18
25
|
def get(stat)
|
@@ -28,8 +35,8 @@ module Resque
|
|
28
35
|
#
|
29
36
|
# Can optionally accept a second int parameter. The stat is then
|
30
37
|
# incremented by that amount.
|
31
|
-
def incr(stat, by = 1)
|
32
|
-
data_store.increment_stat(stat,by)
|
38
|
+
def incr(stat, by = 1, **opts)
|
39
|
+
data_store.increment_stat(stat, by, **opts)
|
33
40
|
end
|
34
41
|
|
35
42
|
# Increments a stat by one.
|
@@ -42,7 +49,7 @@ module Resque
|
|
42
49
|
# Can optionally accept a second int parameter. The stat is then
|
43
50
|
# decremented by that amount.
|
44
51
|
def decr(stat, by = 1)
|
45
|
-
data_store.
|
52
|
+
data_store.decrement_stat(stat,by)
|
46
53
|
end
|
47
54
|
|
48
55
|
# Decrements a stat by one.
|
@@ -51,8 +58,8 @@ module Resque
|
|
51
58
|
end
|
52
59
|
|
53
60
|
# Removes a stat from Redis, effectively setting it to 0.
|
54
|
-
def clear(stat)
|
55
|
-
data_store.clear_stat(stat)
|
61
|
+
def clear(stat, **opts)
|
62
|
+
data_store.clear_stat(stat, **opts)
|
56
63
|
end
|
57
64
|
end
|
58
65
|
end
|
data/lib/resque/tasks.rb
CHANGED
@@ -16,7 +16,7 @@ namespace :resque do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
worker.prepare
|
19
|
-
worker.log "Starting worker #{
|
19
|
+
worker.log "Starting worker #{worker}"
|
20
20
|
worker.work(ENV['INTERVAL'] || 5) # interval, will block
|
21
21
|
end
|
22
22
|
|
@@ -39,18 +39,10 @@ namespace :resque do
|
|
39
39
|
|
40
40
|
# Preload app files if this is Rails
|
41
41
|
task :preload => :setup do
|
42
|
-
if defined?(Rails)
|
43
|
-
if Rails
|
42
|
+
if defined?(Rails) && Rails.respond_to?(:application)
|
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!)
|
46
|
-
|
47
|
-
elsif Rails::VERSION::MAJOR == 3
|
48
|
-
ActiveSupport.run_load_hooks(:before_eager_load, Rails.application)
|
49
|
-
Rails.application.eager_load!
|
50
|
-
|
51
|
-
elsif defined?(Rails::Initializer)
|
52
|
-
$rails_rake_task = false
|
53
|
-
Rails::Initializer.run :load_application_classes
|
54
46
|
end
|
55
47
|
end
|
56
48
|
end
|
data/lib/resque/thread_signal.rb
CHANGED
@@ -1,45 +1,24 @@
|
|
1
1
|
class Resque::ThreadSignal
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
def initialize
|
3
|
+
@mutex = Mutex.new
|
4
|
+
@signaled = false
|
5
|
+
@received = ConditionVariable.new
|
6
|
+
end
|
6
7
|
|
7
|
-
|
8
|
+
def signal
|
9
|
+
@mutex.synchronize do
|
8
10
|
@signaled = true
|
11
|
+
@received.signal
|
9
12
|
end
|
13
|
+
end
|
10
14
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
+
def wait_for_signal(timeout)
|
16
|
+
@mutex.synchronize do
|
17
|
+
unless @signaled
|
18
|
+
@received.wait(@mutex, timeout)
|
15
19
|
end
|
16
20
|
|
17
21
|
@signaled
|
18
22
|
end
|
19
|
-
|
20
|
-
else
|
21
|
-
def initialize
|
22
|
-
@mutex = Mutex.new
|
23
|
-
@signaled = false
|
24
|
-
@received = ConditionVariable.new
|
25
|
-
end
|
26
|
-
|
27
|
-
def signal
|
28
|
-
@mutex.synchronize do
|
29
|
-
@signaled = true
|
30
|
-
@received.signal
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def wait_for_signal(timeout)
|
35
|
-
@mutex.synchronize do
|
36
|
-
unless @signaled
|
37
|
-
@received.wait(@mutex, timeout)
|
38
|
-
end
|
39
|
-
|
40
|
-
@signaled
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
23
|
end
|
45
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