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.
Files changed (45) hide show
  1. checksums.yaml +5 -5
  2. data/HISTORY.md +122 -3
  3. data/README.markdown +441 -500
  4. data/bin/resque-web +10 -26
  5. data/lib/resque/data_store.rb +52 -58
  6. data/lib/resque/errors.rb +7 -1
  7. data/lib/resque/failure/airbrake.rb +19 -7
  8. data/lib/resque/failure/multiple.rb +6 -2
  9. data/lib/resque/failure/redis.rb +1 -1
  10. data/lib/resque/failure/redis_multi_queue.rb +1 -1
  11. data/lib/resque/failure.rb +7 -0
  12. data/lib/resque/job.rb +2 -2
  13. data/lib/resque/logging.rb +1 -1
  14. data/lib/resque/railtie.rb +10 -0
  15. data/lib/resque/server/public/jquery-3.6.0.min.js +2 -0
  16. data/lib/resque/server/public/main.js +3 -0
  17. data/lib/resque/server/public/ranger.js +7 -4
  18. data/lib/resque/server/public/style.css +3 -3
  19. data/lib/resque/server/views/error.erb +1 -1
  20. data/lib/resque/server/views/failed.erb +9 -3
  21. data/lib/resque/server/views/failed_job.erb +2 -2
  22. data/lib/resque/server/views/job_class.erb +3 -1
  23. data/lib/resque/server/views/key_string.erb +1 -1
  24. data/lib/resque/server/views/layout.erb +5 -4
  25. data/lib/resque/server/views/next_more.erb +14 -14
  26. data/lib/resque/server/views/queues.erb +6 -6
  27. data/lib/resque/server/views/stats.erb +5 -5
  28. data/lib/resque/server/views/working.erb +7 -7
  29. data/lib/resque/server.rb +11 -119
  30. data/lib/resque/server_helper.rb +185 -0
  31. data/lib/resque/stat.rb +16 -9
  32. data/lib/resque/tasks.rb +3 -11
  33. data/lib/resque/thread_signal.rb +13 -34
  34. data/lib/resque/vendor/utf8_util.rb +2 -8
  35. data/lib/resque/version.rb +1 -1
  36. data/lib/resque/web_runner.rb +374 -0
  37. data/lib/resque/worker.rb +76 -48
  38. data/lib/resque.rb +100 -27
  39. data/lib/tasks/redis.rake +10 -10
  40. metadata +44 -28
  41. data/lib/resque/server/helpers.rb +0 -64
  42. data/lib/resque/server/public/jquery-1.12.4.min.js +0 -5
  43. data/lib/resque/server/test_helper.rb +0 -19
  44. data/lib/resque/vendor/utf8_util/utf8_util_18.rb +0 -91
  45. 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 Rack::Utils
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 redirect_url_path(:overview)
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 redirect_url_path("/failed/#{params[:queue]}")
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 redirect_url_path("/stats/resque")
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.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
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.decremet_stat(stat,by)
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 #{self}"
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::VERSION::MAJOR > 3
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
@@ -1,45 +1,24 @@
1
1
  class Resque::ThreadSignal
2
- if RUBY_VERSION <= "1.9"
3
- def initialize
4
- @signaled = false
5
- end
2
+ def initialize
3
+ @mutex = Mutex.new
4
+ @signaled = false
5
+ @received = ConditionVariable.new
6
+ end
6
7
 
7
- def signal
8
+ def signal
9
+ @mutex.synchronize do
8
10
  @signaled = true
11
+ @received.signal
9
12
  end
13
+ end
10
14
 
11
- def wait_for_signal(timeout)
12
- (10 * timeout).times do
13
- sleep(0.1)
14
- return true if @signaled
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
- raise NotImplementedError
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
@@ -1,3 +1,3 @@
1
1
  module Resque
2
- Version = VERSION = '1.27.4'
2
+ VERSION = '2.6.0'
3
3
  end