resque_sqs 1.25.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +7 -0
  2. data/HISTORY.md +467 -0
  3. data/LICENSE +20 -0
  4. data/README.markdown +866 -0
  5. data/Rakefile +70 -0
  6. data/bin/resque-sqs +81 -0
  7. data/bin/resque-sqs-web +27 -0
  8. data/lib/resque_sqs/errors.rb +13 -0
  9. data/lib/resque_sqs/failure/airbrake.rb +33 -0
  10. data/lib/resque_sqs/failure/base.rb +73 -0
  11. data/lib/resque_sqs/failure/multiple.rb +59 -0
  12. data/lib/resque_sqs/failure/redis.rb +108 -0
  13. data/lib/resque_sqs/failure/redis_multi_queue.rb +89 -0
  14. data/lib/resque_sqs/failure.rb +113 -0
  15. data/lib/resque_sqs/helpers.rb +107 -0
  16. data/lib/resque_sqs/job.rb +346 -0
  17. data/lib/resque_sqs/log_formatters/quiet_formatter.rb +7 -0
  18. data/lib/resque_sqs/log_formatters/verbose_formatter.rb +7 -0
  19. data/lib/resque_sqs/log_formatters/very_verbose_formatter.rb +8 -0
  20. data/lib/resque_sqs/logging.rb +18 -0
  21. data/lib/resque_sqs/plugin.rb +66 -0
  22. data/lib/resque_sqs/server/helpers.rb +52 -0
  23. data/lib/resque_sqs/server/public/favicon.ico +0 -0
  24. data/lib/resque_sqs/server/public/idle.png +0 -0
  25. data/lib/resque_sqs/server/public/jquery-1.3.2.min.js +19 -0
  26. data/lib/resque_sqs/server/public/jquery.relatize_date.js +95 -0
  27. data/lib/resque_sqs/server/public/poll.png +0 -0
  28. data/lib/resque_sqs/server/public/ranger.js +78 -0
  29. data/lib/resque_sqs/server/public/reset.css +44 -0
  30. data/lib/resque_sqs/server/public/style.css +91 -0
  31. data/lib/resque_sqs/server/public/working.png +0 -0
  32. data/lib/resque_sqs/server/test_helper.rb +19 -0
  33. data/lib/resque_sqs/server/views/error.erb +1 -0
  34. data/lib/resque_sqs/server/views/failed.erb +29 -0
  35. data/lib/resque_sqs/server/views/failed_job.erb +50 -0
  36. data/lib/resque_sqs/server/views/failed_queues_overview.erb +24 -0
  37. data/lib/resque_sqs/server/views/key_sets.erb +19 -0
  38. data/lib/resque_sqs/server/views/key_string.erb +11 -0
  39. data/lib/resque_sqs/server/views/layout.erb +44 -0
  40. data/lib/resque_sqs/server/views/next_more.erb +22 -0
  41. data/lib/resque_sqs/server/views/overview.erb +4 -0
  42. data/lib/resque_sqs/server/views/queues.erb +58 -0
  43. data/lib/resque_sqs/server/views/stats.erb +62 -0
  44. data/lib/resque_sqs/server/views/workers.erb +109 -0
  45. data/lib/resque_sqs/server/views/working.erb +72 -0
  46. data/lib/resque_sqs/server.rb +271 -0
  47. data/lib/resque_sqs/stat.rb +57 -0
  48. data/lib/resque_sqs/tasks.rb +83 -0
  49. data/lib/resque_sqs/vendor/utf8_util/utf8_util_18.rb +91 -0
  50. data/lib/resque_sqs/vendor/utf8_util/utf8_util_19.rb +5 -0
  51. data/lib/resque_sqs/vendor/utf8_util.rb +20 -0
  52. data/lib/resque_sqs/version.rb +3 -0
  53. data/lib/resque_sqs/worker.rb +779 -0
  54. data/lib/resque_sqs.rb +479 -0
  55. data/lib/tasks/redis_sqs.rake +161 -0
  56. data/lib/tasks/resque_sqs.rake +2 -0
  57. data/test/airbrake_test.rb +27 -0
  58. data/test/failure_base_test.rb +15 -0
  59. data/test/job_hooks_test.rb +465 -0
  60. data/test/job_plugins_test.rb +230 -0
  61. data/test/logging_test.rb +24 -0
  62. data/test/plugin_test.rb +116 -0
  63. data/test/redis-test-cluster.conf +115 -0
  64. data/test/redis-test.conf +115 -0
  65. data/test/resque-web_test.rb +59 -0
  66. data/test/resque_failure_redis_test.rb +19 -0
  67. data/test/resque_hook_test.rb +165 -0
  68. data/test/resque_test.rb +278 -0
  69. data/test/stdout +42 -0
  70. data/test/test_helper.rb +228 -0
  71. data/test/worker_test.rb +1080 -0
  72. metadata +202 -0
data/Rakefile ADDED
@@ -0,0 +1,70 @@
1
+ #
2
+ # Setup
3
+ #
4
+
5
+ load 'lib/tasks/redis_sqs.rake'
6
+
7
+ $LOAD_PATH.unshift 'lib'
8
+ require 'resque_sqs/tasks'
9
+
10
+ def command?(command)
11
+ system("type #{command} > /dev/null 2>&1")
12
+ end
13
+
14
+
15
+ #
16
+ # Tests
17
+ #
18
+
19
+ require 'rake/testtask'
20
+
21
+ task :default => :test
22
+
23
+ Rake::TestTask.new do |test|
24
+ test.verbose = true
25
+ test.libs << "test"
26
+ test.libs << "lib"
27
+ test.test_files = FileList['test/**/*_test.rb']
28
+ end
29
+
30
+ if command? :kicker
31
+ desc "Launch Kicker (like autotest)"
32
+ task :kicker do
33
+ puts "Kicking... (ctrl+c to cancel)"
34
+ exec "kicker -e rake test lib examples"
35
+ end
36
+ end
37
+
38
+
39
+ #
40
+ # Install
41
+ #
42
+
43
+ task :install => [ 'redis_sqs:install', 'dtach_sqs:install' ]
44
+
45
+
46
+ #
47
+ # Documentation
48
+ #
49
+
50
+ begin
51
+ require 'sdoc_helpers'
52
+ rescue LoadError
53
+ end
54
+
55
+
56
+ #
57
+ # Publishing
58
+ #
59
+
60
+ desc "Push a new version to Gemcutter"
61
+ task :sqs_publish do
62
+ require 'resque_sqs/version'
63
+
64
+ sh "gem build resque_sqs.gemspec"
65
+ sh "gem push resque_sqs-#{ResqueSqs::Version}.gem"
66
+ sh "git tag v#{ResqueSqs::Version}"
67
+ sh "git push origin v#{ResqueSqs::Version}"
68
+ sh "git push origin master"
69
+ sh "git clean -fd"
70
+ end
data/bin/resque-sqs ADDED
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
4
+ begin
5
+ require 'redis-namespace'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'redis-namespace'
9
+ end
10
+ require 'resque_sqs'
11
+ require 'optparse'
12
+
13
+ parser = OptionParser.new do |opts|
14
+ opts.banner = "Usage: resque [options] COMMAND"
15
+
16
+ opts.separator ""
17
+ opts.separator "Options:"
18
+
19
+ opts.on("-r", "--redis [HOST:PORT]", "Redis connection string") do |host|
20
+ ResqueSqs.redis = host
21
+ end
22
+
23
+ opts.on("-N", "--namespace [NAMESPACE]", "Redis namespace") do |namespace|
24
+ ResqueSqs.redis.namespace = namespace
25
+ end
26
+
27
+ opts.on("-h", "--help", "Show this message") do
28
+ puts opts
29
+ exit
30
+ end
31
+
32
+ opts.separator ""
33
+ opts.separator "Commands:"
34
+ opts.separator " remove WORKER Removes a worker"
35
+ opts.separator " kill WORKER Kills a worker"
36
+ opts.separator " list Lists known workers"
37
+ end
38
+
39
+ def kill(worker)
40
+ abort "** resque kill WORKER_ID" if worker.nil?
41
+ pid = worker.split(':')[1].to_i
42
+
43
+ begin
44
+ Process.kill("KILL", pid)
45
+ puts "** killed #{worker}"
46
+ rescue Errno::ESRCH
47
+ puts "** worker #{worker} not running"
48
+ end
49
+
50
+ remove worker
51
+ end
52
+
53
+ def remove(worker)
54
+ abort "** resque remove WORKER_ID" if worker.nil?
55
+
56
+ ResqueSqs.remove_worker(worker)
57
+ puts "** removed #{worker}"
58
+ end
59
+
60
+ def list
61
+ if ResqueSqs.workers.any?
62
+ ResqueSqs.workers.each do |worker|
63
+ puts "#{worker} (#{worker.state})"
64
+ end
65
+ else
66
+ puts "None"
67
+ end
68
+ end
69
+
70
+ parser.parse!
71
+
72
+ case ARGV[0]
73
+ when 'kill'
74
+ kill ARGV[1]
75
+ when 'remove'
76
+ remove ARGV[1]
77
+ when 'list'
78
+ list
79
+ else
80
+ puts parser.help
81
+ end
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
4
+ begin
5
+ require 'vegas'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'vegas'
9
+ end
10
+ require 'resque_sqs/server'
11
+
12
+
13
+ Vegas::Runner.new(ResqueSqs::Server, 'resque-web', {
14
+ :before_run => lambda {|v|
15
+ path = (ENV['RESQUECONFIG'] || v.args.first)
16
+ load path.to_s.strip if path
17
+ }
18
+ }) do |runner, opts, app|
19
+ opts.on('-N NAMESPACE', "--namespace NAMESPACE", "set the Redis namespace") {|namespace|
20
+ runner.logger.info "Using Redis namespace '#{namespace}'"
21
+ ResqueSqs.redis.namespace = namespace
22
+ }
23
+ opts.on('-r redis-connection', "--redis redis-connection", "set the Redis connection string") {|redis_conf|
24
+ runner.logger.info "Using Redis connection '#{redis_conf}'"
25
+ ResqueSqs.redis = redis_conf
26
+ }
27
+ end
@@ -0,0 +1,13 @@
1
+ module ResqueSqs
2
+ # Raised whenever we need a queue but none is provided.
3
+ class NoQueueError < RuntimeError; end
4
+
5
+ # Raised when trying to create a job without a class
6
+ class NoClassError < RuntimeError; end
7
+
8
+ # Raised when a worker was killed while processing a job.
9
+ class DirtyExit < RuntimeError; end
10
+
11
+ # Raised when child process is TERM'd so job can rescue this to do shutdown work.
12
+ class TermException < SignalException; end
13
+ end
@@ -0,0 +1,33 @@
1
+ begin
2
+ require 'airbrake'
3
+ rescue LoadError
4
+ raise "Can't find 'airbrake' gem. Please add it to your Gemfile or install it."
5
+ end
6
+
7
+ module ResqueSqs
8
+ module Failure
9
+ class Airbrake < Base
10
+ def self.configure(&block)
11
+ ResqueSqs.logger.warn "This actually sets global Airbrake configuration, " \
12
+ "which is probably not what you want. This will be gone in 2.0."
13
+ ResqueSqs::Failure.backend = self
14
+ ::Airbrake.configure(&block)
15
+ end
16
+
17
+ def self.count(queue = nil, class_name = nil)
18
+ # We can't get the total # of errors from Airbrake so we fake it
19
+ # by asking Resque how many errors it has seen.
20
+ Stat[:failed]
21
+ end
22
+
23
+ def save
24
+ ::Airbrake.notify_or_ignore(exception,
25
+ :parameters => {
26
+ :payload_class => payload['class'].to_s,
27
+ :payload_args => payload['args'].inspect
28
+ }
29
+ )
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,73 @@
1
+ module ResqueSqs
2
+ module Failure
3
+ # All Failure classes are expected to subclass Base.
4
+ #
5
+ # When a job fails, a new instance of your Failure backend is created
6
+ # and #save is called.
7
+ class Base
8
+ # The exception object raised by the failed job
9
+ attr_accessor :exception
10
+
11
+ # The worker object who detected the failure
12
+ attr_accessor :worker
13
+
14
+ # The string name of the queue from which the failed job was pulled
15
+ attr_accessor :queue
16
+
17
+ # The payload object associated with the failed job
18
+ attr_accessor :payload
19
+
20
+ def initialize(exception, worker, queue, payload)
21
+ @exception = exception
22
+ @worker = worker
23
+ @queue = queue
24
+ @payload = payload
25
+ end
26
+
27
+ # When a job fails, a new instance of your Failure backend is created
28
+ # and #save is called.
29
+ #
30
+ # This is where you POST or PUT or whatever to your Failure service.
31
+ def save
32
+ end
33
+
34
+ # The number of failures.
35
+ def self.count(queue = nil, class_name = nil)
36
+ 0
37
+ end
38
+
39
+ # Returns an array of all available failure queues
40
+ def self.queues
41
+ []
42
+ end
43
+
44
+ # Returns a paginated array of failure objects.
45
+ def self.all(offset = 0, limit = 1, queue = nil)
46
+ []
47
+ end
48
+
49
+ # Iterate across failed objects
50
+ def self.each(*args)
51
+ end
52
+
53
+ # A URL where someone can go to view failures.
54
+ def self.url
55
+ end
56
+
57
+ # Clear all failure objects
58
+ def self.clear(*args)
59
+ end
60
+
61
+ def self.requeue(index)
62
+ end
63
+
64
+ def self.remove(index)
65
+ end
66
+
67
+ # Logging!
68
+ def log(message)
69
+ @worker.log(message)
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,59 @@
1
+ module ResqueSqs
2
+ module Failure
3
+ # A Failure backend that uses multiple backends
4
+ # delegates all queries to the first backend
5
+ class Multiple < Base
6
+
7
+ class << self
8
+ attr_accessor :classes
9
+ end
10
+
11
+ def self.configure
12
+ yield self
13
+ ResqueSqs::Failure.backend = self
14
+ end
15
+
16
+ def initialize(*args)
17
+ super
18
+ @backends = self.class.classes.map {|klass| klass.new(*args)}
19
+ end
20
+
21
+ def save
22
+ @backends.each(&:save)
23
+ end
24
+
25
+ # The number of failures.
26
+ def self.count(*args)
27
+ classes.first.count(*args)
28
+ end
29
+
30
+ # Returns a paginated array of failure objects.
31
+ def self.all(*args)
32
+ classes.first.all(*args)
33
+ end
34
+
35
+ # Iterate across failed objects
36
+ def self.each(*args, &block)
37
+ classes.first.each(*args, &block)
38
+ end
39
+
40
+ # A URL where someone can go to view failures.
41
+ def self.url
42
+ classes.first.url
43
+ end
44
+
45
+ # Clear all failure objects
46
+ def self.clear(*args)
47
+ classes.first.clear(*args)
48
+ end
49
+
50
+ def self.requeue(*args)
51
+ classes.first.requeue(*args)
52
+ end
53
+
54
+ def self.remove(index)
55
+ classes.each { |klass| klass.remove(index) }
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,108 @@
1
+ module ResqueSqs
2
+ module Failure
3
+ # A Failure backend that stores exceptions in Redis. Very simple but
4
+ # works out of the box, along with support in the Resque web app.
5
+ class Redis < Base
6
+ def save
7
+ data = {
8
+ :failed_at => UTF8Util.clean(Time.now.strftime("%Y/%m/%d %H:%M:%S %Z")),
9
+ :payload => payload,
10
+ :exception => exception.class.to_s,
11
+ :error => UTF8Util.clean(exception.to_s),
12
+ :backtrace => filter_backtrace(Array(exception.backtrace)),
13
+ :worker => worker.to_s,
14
+ :queue => queue
15
+ }
16
+ data = ResqueSqs.encode(data)
17
+ ResqueSqs.redis.rpush(:failed, data)
18
+ end
19
+
20
+ def self.count(queue = nil, class_name = nil)
21
+ check_queue(queue)
22
+
23
+ if class_name
24
+ n = 0
25
+ each(0, count(queue), queue, class_name) { n += 1 }
26
+ n
27
+ else
28
+ ResqueSqs.redis.llen(:failed).to_i
29
+ end
30
+ end
31
+
32
+ def self.queues
33
+ [:failed]
34
+ end
35
+
36
+ def self.all(offset = 0, limit = 1, queue = nil)
37
+ check_queue(queue)
38
+ ResqueSqs.list_range(:failed, offset, limit)
39
+ end
40
+
41
+ def self.each(offset = 0, limit = self.count, queue = :failed, class_name = nil, order = 'desc')
42
+ all_items = Array(all(offset, limit, queue))
43
+ reversed = false
44
+ if order.eql? 'desc'
45
+ all_items.reverse!
46
+ reversed = true
47
+ end
48
+ all_items.each_with_index do |item, i|
49
+ if !class_name || (item['payload'] && item['payload']['class'] == class_name)
50
+ if reversed
51
+ id = (all_items.length - 1) - (offset + i)
52
+ else
53
+ id = offset + i
54
+ end
55
+ yield id, item
56
+ end
57
+ end
58
+ end
59
+
60
+ def self.clear(queue = nil)
61
+ check_queue(queue)
62
+ ResqueSqs.redis.del(:failed)
63
+ end
64
+
65
+ def self.requeue(id)
66
+ item = all(id)
67
+ item['retried_at'] = Time.now.strftime("%Y/%m/%d %H:%M:%S")
68
+ ResqueSqs.redis.lset(:failed, id, ResqueSqs.encode(item))
69
+ Job.create(item['queue'], item['payload']['class'], *item['payload']['args'])
70
+ end
71
+
72
+ def self.remove(id)
73
+ sentinel = ""
74
+ ResqueSqs.redis.lset(:failed, id, sentinel)
75
+ ResqueSqs.redis.lrem(:failed, 1, sentinel)
76
+ end
77
+
78
+ def self.requeue_queue(queue)
79
+ i = 0
80
+ while job = all(i)
81
+ requeue(i) if job['queue'] == queue
82
+ i += 1
83
+ end
84
+ end
85
+
86
+ def self.remove_queue(queue)
87
+ i = 0
88
+ while job = all(i)
89
+ if job['queue'] == queue
90
+ # This will remove the failure from the array so do not increment the index.
91
+ remove(i)
92
+ else
93
+ i += 1
94
+ end
95
+ end
96
+ end
97
+
98
+ def self.check_queue(queue)
99
+ raise ArgumentError, "invalid queue: #{queue}" if queue && queue.to_s != "failed"
100
+ end
101
+
102
+ def filter_backtrace(backtrace)
103
+ index = backtrace.index { |item| item.include?('/lib/resque/job.rb') }
104
+ backtrace.first(index.to_i)
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,89 @@
1
+ module ResqueSqs
2
+ module Failure
3
+ # A Failure backend that stores exceptions in Redis. Very simple but
4
+ # works out of the box, along with support in the Resque web app.
5
+ class RedisMultiQueue < Base
6
+ def save
7
+ data = {
8
+ :failed_at => Time.now.strftime("%Y/%m/%d %H:%M:%S %Z"),
9
+ :payload => payload,
10
+ :exception => exception.class.to_s,
11
+ :error => UTF8Util.clean(exception.to_s),
12
+ :backtrace => filter_backtrace(Array(exception.backtrace)),
13
+ :worker => worker.to_s,
14
+ :queue => queue
15
+ }
16
+ data = ResqueSqs.encode(data)
17
+ ResqueSqs.redis.rpush(ResqueSqs::Failure.failure_queue_name(queue), data)
18
+ end
19
+
20
+ def self.count(queue = nil, class_name = nil)
21
+ if queue
22
+ if class_name
23
+ n = 0
24
+ each(0, count(queue), queue, class_name) { n += 1 }
25
+ n
26
+ else
27
+ ResqueSqs.redis.llen(queue).to_i
28
+ end
29
+ else
30
+ total = 0
31
+ queues.each { |q| total += count(q) }
32
+ total
33
+ end
34
+ end
35
+
36
+ def self.all(offset = 0, limit = 1, queue = :failed, order = 'desc')
37
+ ResqueSqs.list_range(queue, offset, limit, order)
38
+ end
39
+
40
+ def self.queues
41
+ Array(ResqueSqs.redis.smembers(:failed_queues))
42
+ end
43
+
44
+ def self.each(offset = 0, limit = self.count, queue = :failed, class_name = nil, order = 'desc')
45
+ items = all(offset, limit, queue, order)
46
+ items = [items] unless items.is_a? Array
47
+ if order.eql? 'desc'
48
+ items.reverse!
49
+ end
50
+ items.each_with_index do |item, i|
51
+ if !class_name || (item['payload'] && item['payload']['class'] == class_name)
52
+ yield offset + i, item
53
+ end
54
+ end
55
+ end
56
+
57
+ def self.clear(queue = :failed)
58
+ ResqueSqs.redis.del(queue)
59
+ end
60
+
61
+ def self.requeue(id, queue = :failed)
62
+ item = all(id, 1, queue)
63
+ item['retried_at'] = Time.now.strftime("%Y/%m/%d %H:%M:%S")
64
+ ResqueSqs.redis.lset(queue, id, ResqueSqs.encode(item))
65
+ Job.create(item['queue'], item['payload']['class'], *item['payload']['args'])
66
+ end
67
+
68
+ def self.remove(id, queue = :failed)
69
+ sentinel = ""
70
+ ResqueSqs.redis.lset(queue, id, sentinel)
71
+ ResqueSqs.redis.lrem(queue, 1, sentinel)
72
+ end
73
+
74
+ def self.requeue_queue(queue)
75
+ failure_queue = ResqueSqs::Failure.failure_queue_name(queue)
76
+ each(0, count(failure_queue), failure_queue) { |id, _| requeue(id, failure_queue) }
77
+ end
78
+
79
+ def self.remove_queue(queue)
80
+ ResqueSqs.redis.del(ResqueSqs::Failure.failure_queue_name(queue))
81
+ end
82
+
83
+ def filter_backtrace(backtrace)
84
+ index = backtrace.index { |item| item.include?('/lib/resque/job.rb') }
85
+ backtrace.first(index.to_i)
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,113 @@
1
+ module ResqueSqs
2
+ # The Failure module provides an interface for working with different
3
+ # failure backends.
4
+ #
5
+ # You can use it to query the failure backend without knowing which specific
6
+ # backend is being used. For instance, the Resque web app uses it to display
7
+ # stats and other information.
8
+ module Failure
9
+ # Creates a new failure, which is delegated to the appropriate backend.
10
+ #
11
+ # Expects a hash with the following keys:
12
+ # :exception - The Exception object
13
+ # :worker - The Worker object who is reporting the failure
14
+ # :queue - The string name of the queue from which the job was pulled
15
+ # :payload - The job's payload
16
+ def self.create(options = {})
17
+ backend.new(*options.values_at(:exception, :worker, :queue, :payload)).save
18
+ end
19
+
20
+ #
21
+ # Sets the current backend. Expects a class descendent of
22
+ # `ResqueSqs::Failure::Base`.
23
+ #
24
+ # Example use:
25
+ # require 'resque_sqs/failure/airbrake'
26
+ # ResqueSqs::Failure.backend = ResqueSqs::Failure::Airbrake
27
+ def self.backend=(backend)
28
+ @backend = backend
29
+ end
30
+
31
+ # Returns the current backend class. If none has been set, falls
32
+ # back to `ResqueSqs::Failure::Redis`
33
+ def self.backend
34
+ return @backend if @backend
35
+
36
+ case ENV['FAILURE_BACKEND']
37
+ when 'redis_multi_queue'
38
+ require 'resque_sqs/failure/redis_multi_queue'
39
+ @backend = Failure::RedisMultiQueue
40
+ when 'redis', nil
41
+ require 'resque_sqs/failure/redis'
42
+ @backend = Failure::Redis
43
+ else
44
+ raise ArgumentError, "invalid failure backend: #{FAILURE_BACKEND}"
45
+ end
46
+ end
47
+
48
+ # Obtain the failure queue name for a given job queue
49
+ def self.failure_queue_name(job_queue_name)
50
+ name = "#{job_queue_name}_failed"
51
+ ResqueSqs.redis.sadd(:failed_queues, name)
52
+ name
53
+ end
54
+
55
+ # Obtain the job queue name for a given failure queue
56
+ def self.job_queue_name(failure_queue_name)
57
+ failure_queue_name.sub(/_failed$/, '')
58
+ end
59
+
60
+ # Returns an array of all the failed queues in the system
61
+ def self.queues
62
+ backend.queues
63
+ end
64
+
65
+ # Returns the int count of how many failures we have seen.
66
+ def self.count(queue = nil, class_name = nil)
67
+ backend.count(queue, class_name)
68
+ end
69
+
70
+ # Returns an array of all the failures, paginated.
71
+ #
72
+ # `offset` is the int of the first item in the page, `limit` is the
73
+ # number of items to return.
74
+ def self.all(offset = 0, limit = 1, queue = nil)
75
+ backend.all(offset, limit, queue)
76
+ end
77
+
78
+ # Iterate across all failures with the given options
79
+ def self.each(offset = 0, limit = self.count, queue = nil, class_name = nil, order = 'desc', &block)
80
+ backend.each(offset, limit, queue, class_name, order, &block)
81
+ end
82
+
83
+ # The string url of the backend's web interface, if any.
84
+ def self.url
85
+ backend.url
86
+ end
87
+
88
+ # Clear all failure jobs
89
+ def self.clear(queue = nil)
90
+ backend.clear(queue)
91
+ end
92
+
93
+ def self.requeue(id)
94
+ backend.requeue(id)
95
+ end
96
+
97
+ def self.remove(id)
98
+ backend.remove(id)
99
+ end
100
+
101
+ # Requeues all failed jobs in a specific queue.
102
+ # Queue name should be a string.
103
+ def self.requeue_queue(queue)
104
+ backend.requeue_queue(queue)
105
+ end
106
+
107
+ # Removes all failed jobs in a specific queue.
108
+ # Queue name should be a string.
109
+ def self.remove_queue(queue)
110
+ backend.remove_queue(queue)
111
+ end
112
+ end
113
+ end