resque 1.23.0 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/HISTORY.md +271 -0
  3. data/README.markdown +454 -484
  4. data/Rakefile +4 -17
  5. data/bin/resque-web +10 -22
  6. data/lib/resque/data_store.rb +335 -0
  7. data/lib/resque/errors.rb +15 -1
  8. data/lib/resque/failure/airbrake.rb +32 -4
  9. data/lib/resque/failure/base.rb +16 -7
  10. data/lib/resque/failure/multiple.rb +26 -8
  11. data/lib/resque/failure/redis.rb +92 -15
  12. data/lib/resque/failure/redis_multi_queue.rb +104 -0
  13. data/lib/resque/failure.rb +62 -32
  14. data/lib/resque/helpers.rb +11 -57
  15. data/lib/resque/job.rb +79 -12
  16. data/lib/resque/log_formatters/quiet_formatter.rb +7 -0
  17. data/lib/resque/log_formatters/verbose_formatter.rb +7 -0
  18. data/lib/resque/log_formatters/very_verbose_formatter.rb +8 -0
  19. data/lib/resque/logging.rb +18 -0
  20. data/lib/resque/plugin.rb +22 -10
  21. data/lib/resque/railtie.rb +10 -0
  22. data/lib/resque/server/public/jquery-3.6.0.min.js +2 -0
  23. data/lib/resque/server/public/jquery.relatize_date.js +4 -4
  24. data/lib/resque/server/public/main.js +3 -0
  25. data/lib/resque/server/public/ranger.js +16 -8
  26. data/lib/resque/server/public/style.css +13 -8
  27. data/lib/resque/server/views/error.erb +1 -1
  28. data/lib/resque/server/views/failed.erb +27 -59
  29. data/lib/resque/server/views/failed_job.erb +50 -0
  30. data/lib/resque/server/views/failed_queues_overview.erb +24 -0
  31. data/lib/resque/server/views/job_class.erb +8 -0
  32. data/lib/resque/server/views/key_sets.erb +2 -4
  33. data/lib/resque/server/views/key_string.erb +1 -1
  34. data/lib/resque/server/views/layout.erb +7 -6
  35. data/lib/resque/server/views/next_more.erb +22 -10
  36. data/lib/resque/server/views/processing.erb +2 -0
  37. data/lib/resque/server/views/queues.erb +22 -13
  38. data/lib/resque/server/views/stats.erb +5 -5
  39. data/lib/resque/server/views/workers.erb +4 -4
  40. data/lib/resque/server/views/working.erb +10 -11
  41. data/lib/resque/server.rb +51 -108
  42. data/lib/resque/server_helper.rb +185 -0
  43. data/lib/resque/stat.rb +19 -7
  44. data/lib/resque/tasks.rb +26 -25
  45. data/lib/resque/thread_signal.rb +24 -0
  46. data/lib/resque/vendor/utf8_util.rb +2 -8
  47. data/lib/resque/version.rb +1 -1
  48. data/lib/resque/web_runner.rb +374 -0
  49. data/lib/resque/worker.rb +487 -163
  50. data/lib/resque.rb +332 -52
  51. data/lib/tasks/redis.rake +11 -11
  52. metadata +169 -149
  53. data/lib/resque/failure/hoptoad.rb +0 -33
  54. data/lib/resque/failure/thoughtbot.rb +0 -33
  55. data/lib/resque/server/public/jquery-1.3.2.min.js +0 -19
  56. data/lib/resque/server/test_helper.rb +0 -19
  57. data/lib/resque/vendor/utf8_util/utf8_util_18.rb +0 -91
  58. data/lib/resque/vendor/utf8_util/utf8_util_19.rb +0 -5
  59. data/test/airbrake_test.rb +0 -27
  60. data/test/hoptoad_test.rb +0 -26
  61. data/test/job_hooks_test.rb +0 -464
  62. data/test/job_plugins_test.rb +0 -230
  63. data/test/plugin_test.rb +0 -116
  64. data/test/redis-test-cluster.conf +0 -115
  65. data/test/redis-test.conf +0 -115
  66. data/test/resque-web_test.rb +0 -59
  67. data/test/resque_failure_redis_test.rb +0 -19
  68. data/test/resque_test.rb +0 -278
  69. data/test/test_helper.rb +0 -178
  70. 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
- extend Helpers
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
- redis.get("stat:#{stat}").to_i
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
- redis.incrby("stat:#{stat}", by)
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
- redis.decrby("stat:#{stat}", by)
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
- redis.del("stat:#{stat}")
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(*queues)
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
- if ENV['BACKGROUND']
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
- # Rails 3
56
- Rails.application.eager_load!
57
- elsif defined?(Rails::Initializer)
58
- # Rails 2.3
59
- $rails_rake_task = false
60
- Rails::Initializer.run :load_application_classes
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
- 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.23.0'
2
+ VERSION = '2.6.0'
3
3
  end