resque_sqs 1.25.2
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 +467 -0
- data/LICENSE +20 -0
- data/README.markdown +866 -0
- data/Rakefile +70 -0
- data/bin/resque-sqs +81 -0
- data/bin/resque-sqs-web +27 -0
- data/lib/resque_sqs/errors.rb +13 -0
- data/lib/resque_sqs/failure/airbrake.rb +33 -0
- data/lib/resque_sqs/failure/base.rb +73 -0
- data/lib/resque_sqs/failure/multiple.rb +59 -0
- data/lib/resque_sqs/failure/redis.rb +108 -0
- data/lib/resque_sqs/failure/redis_multi_queue.rb +89 -0
- data/lib/resque_sqs/failure.rb +113 -0
- data/lib/resque_sqs/helpers.rb +107 -0
- data/lib/resque_sqs/job.rb +346 -0
- data/lib/resque_sqs/log_formatters/quiet_formatter.rb +7 -0
- data/lib/resque_sqs/log_formatters/verbose_formatter.rb +7 -0
- data/lib/resque_sqs/log_formatters/very_verbose_formatter.rb +8 -0
- data/lib/resque_sqs/logging.rb +18 -0
- data/lib/resque_sqs/plugin.rb +66 -0
- data/lib/resque_sqs/server/helpers.rb +52 -0
- data/lib/resque_sqs/server/public/favicon.ico +0 -0
- data/lib/resque_sqs/server/public/idle.png +0 -0
- data/lib/resque_sqs/server/public/jquery-1.3.2.min.js +19 -0
- data/lib/resque_sqs/server/public/jquery.relatize_date.js +95 -0
- data/lib/resque_sqs/server/public/poll.png +0 -0
- data/lib/resque_sqs/server/public/ranger.js +78 -0
- data/lib/resque_sqs/server/public/reset.css +44 -0
- data/lib/resque_sqs/server/public/style.css +91 -0
- data/lib/resque_sqs/server/public/working.png +0 -0
- data/lib/resque_sqs/server/test_helper.rb +19 -0
- data/lib/resque_sqs/server/views/error.erb +1 -0
- data/lib/resque_sqs/server/views/failed.erb +29 -0
- data/lib/resque_sqs/server/views/failed_job.erb +50 -0
- data/lib/resque_sqs/server/views/failed_queues_overview.erb +24 -0
- data/lib/resque_sqs/server/views/key_sets.erb +19 -0
- data/lib/resque_sqs/server/views/key_string.erb +11 -0
- data/lib/resque_sqs/server/views/layout.erb +44 -0
- data/lib/resque_sqs/server/views/next_more.erb +22 -0
- data/lib/resque_sqs/server/views/overview.erb +4 -0
- data/lib/resque_sqs/server/views/queues.erb +58 -0
- data/lib/resque_sqs/server/views/stats.erb +62 -0
- data/lib/resque_sqs/server/views/workers.erb +109 -0
- data/lib/resque_sqs/server/views/working.erb +72 -0
- data/lib/resque_sqs/server.rb +271 -0
- data/lib/resque_sqs/stat.rb +57 -0
- data/lib/resque_sqs/tasks.rb +83 -0
- data/lib/resque_sqs/vendor/utf8_util/utf8_util_18.rb +91 -0
- data/lib/resque_sqs/vendor/utf8_util/utf8_util_19.rb +5 -0
- data/lib/resque_sqs/vendor/utf8_util.rb +20 -0
- data/lib/resque_sqs/version.rb +3 -0
- data/lib/resque_sqs/worker.rb +779 -0
- data/lib/resque_sqs.rb +479 -0
- data/lib/tasks/redis_sqs.rake +161 -0
- data/lib/tasks/resque_sqs.rake +2 -0
- data/test/airbrake_test.rb +27 -0
- data/test/failure_base_test.rb +15 -0
- data/test/job_hooks_test.rb +465 -0
- data/test/job_plugins_test.rb +230 -0
- data/test/logging_test.rb +24 -0
- data/test/plugin_test.rb +116 -0
- data/test/redis-test-cluster.conf +115 -0
- data/test/redis-test.conf +115 -0
- data/test/resque-web_test.rb +59 -0
- data/test/resque_failure_redis_test.rb +19 -0
- data/test/resque_hook_test.rb +165 -0
- data/test/resque_test.rb +278 -0
- data/test/stdout +42 -0
- data/test/test_helper.rb +228 -0
- data/test/worker_test.rb +1080 -0
- metadata +202 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module ResqueSqs
|
|
2
|
+
# The stat subsystem. Used to keep track of integer counts.
|
|
3
|
+
#
|
|
4
|
+
# Get a stat: Stat[name]
|
|
5
|
+
# Incr a stat: Stat.incr(name)
|
|
6
|
+
# Decr a stat: Stat.decr(name)
|
|
7
|
+
# Kill a stat: Stat.clear(name)
|
|
8
|
+
module Stat
|
|
9
|
+
extend self
|
|
10
|
+
|
|
11
|
+
# Direct access to the Redis instance.
|
|
12
|
+
def redis
|
|
13
|
+
ResqueSqs.redis
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Returns the int value of a stat, given a string stat name.
|
|
17
|
+
def get(stat)
|
|
18
|
+
redis.get("stat:#{stat}").to_i
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Alias of `get`
|
|
22
|
+
def [](stat)
|
|
23
|
+
get(stat)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# For a string stat name, increments the stat by one.
|
|
27
|
+
#
|
|
28
|
+
# Can optionally accept a second int parameter. The stat is then
|
|
29
|
+
# incremented by that amount.
|
|
30
|
+
def incr(stat, by = 1)
|
|
31
|
+
redis.incrby("stat:#{stat}", by)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Increments a stat by one.
|
|
35
|
+
def <<(stat)
|
|
36
|
+
incr stat
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# For a string stat name, decrements the stat by one.
|
|
40
|
+
#
|
|
41
|
+
# Can optionally accept a second int parameter. The stat is then
|
|
42
|
+
# decremented by that amount.
|
|
43
|
+
def decr(stat, by = 1)
|
|
44
|
+
redis.decrby("stat:#{stat}", by)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Decrements a stat by one.
|
|
48
|
+
def >>(stat)
|
|
49
|
+
decr stat
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Removes a stat from Redis, effectively setting it to 0.
|
|
53
|
+
def clear(stat)
|
|
54
|
+
redis.del("stat:#{stat}")
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# require 'resque_sqs/tasks'
|
|
2
|
+
# will give you the resque tasks
|
|
3
|
+
|
|
4
|
+
namespace :resque_sqs do
|
|
5
|
+
task :setup
|
|
6
|
+
|
|
7
|
+
desc "Start a Resque worker"
|
|
8
|
+
task :work => [ :preload, :setup ] do
|
|
9
|
+
require 'resque_sqs'
|
|
10
|
+
|
|
11
|
+
queues = (ENV['QUEUES'] || ENV['QUEUE']).to_s.split(',')
|
|
12
|
+
|
|
13
|
+
begin
|
|
14
|
+
worker = ResqueSqs::Worker.new(*queues)
|
|
15
|
+
if ENV['LOGGING'] || ENV['VERBOSE']
|
|
16
|
+
worker.verbose = ENV['LOGGING'] || ENV['VERBOSE']
|
|
17
|
+
end
|
|
18
|
+
if ENV['VVERBOSE']
|
|
19
|
+
worker.very_verbose = ENV['VVERBOSE']
|
|
20
|
+
end
|
|
21
|
+
worker.term_timeout = ENV['RESQUE_TERM_TIMEOUT'] || 4.0
|
|
22
|
+
worker.term_child = ENV['TERM_CHILD']
|
|
23
|
+
worker.run_at_exit_hooks = ENV['RUN_AT_EXIT_HOOKS']
|
|
24
|
+
rescue ResqueSqs::NoQueueError
|
|
25
|
+
abort "set QUEUE env var, e.g. $ QUEUE=critical,high rake resque_sqs:work"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
if ENV['BACKGROUND']
|
|
29
|
+
unless Process.respond_to?('daemon')
|
|
30
|
+
abort "env var BACKGROUND is set, which requires ruby >= 1.9"
|
|
31
|
+
end
|
|
32
|
+
Process.daemon(true, true)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
if ENV['PIDFILE']
|
|
36
|
+
File.open(ENV['PIDFILE'], 'w') { |f| f << worker.pid }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
worker.log "Starting worker #{worker}"
|
|
40
|
+
|
|
41
|
+
worker.work(ENV['INTERVAL'] || 5) # interval, will block
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
desc "Start multiple Resque workers. Should only be used in dev mode."
|
|
45
|
+
task :workers do
|
|
46
|
+
threads = []
|
|
47
|
+
|
|
48
|
+
ENV['COUNT'].to_i.times do
|
|
49
|
+
threads << Thread.new do
|
|
50
|
+
system "rake resque_sqs:work"
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
threads.each { |thread| thread.join }
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Preload app files if this is Rails
|
|
58
|
+
task :preload => :setup do
|
|
59
|
+
if defined?(Rails) && Rails.respond_to?(:application)
|
|
60
|
+
# Rails 3
|
|
61
|
+
Rails.application.eager_load!
|
|
62
|
+
elsif defined?(Rails::Initializer)
|
|
63
|
+
# Rails 2.3
|
|
64
|
+
$rails_rake_task = false
|
|
65
|
+
Rails::Initializer.run :load_application_classes
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
namespace :failures do
|
|
70
|
+
desc "Sort the 'failed' queue for the redis_multi_queue failure backend"
|
|
71
|
+
task :sort do
|
|
72
|
+
require 'resque_sqs'
|
|
73
|
+
require 'resque_sqs/failure/redis'
|
|
74
|
+
|
|
75
|
+
warn "Sorting #{ResqueSqs::Failure.count} failures..."
|
|
76
|
+
ResqueSqs::Failure.each(0, ResqueSqs::Failure.count) do |_, failure|
|
|
77
|
+
data = ResqueSqs.encode(failure)
|
|
78
|
+
ResqueSqs.redis.rpush(ResqueSqs::Failure.failure_queue_name(failure['queue']), data)
|
|
79
|
+
end
|
|
80
|
+
warn "done!"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
require 'strscan'
|
|
2
|
+
|
|
3
|
+
module UTF8Util
|
|
4
|
+
HIGH_BIT_RANGE = /[\x80-\xff]/
|
|
5
|
+
|
|
6
|
+
# Check if this String is valid UTF-8
|
|
7
|
+
#
|
|
8
|
+
# Returns true or false.
|
|
9
|
+
def self.valid?(str)
|
|
10
|
+
sc = StringScanner.new(str)
|
|
11
|
+
|
|
12
|
+
while sc.skip_until(HIGH_BIT_RANGE)
|
|
13
|
+
sc.pos -= 1
|
|
14
|
+
|
|
15
|
+
if !sequence_length(sc)
|
|
16
|
+
return false
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
true
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Replace invalid UTF-8 character sequences with a replacement character
|
|
24
|
+
#
|
|
25
|
+
# Returns self as valid UTF-8.
|
|
26
|
+
def self.clean!(str)
|
|
27
|
+
sc = StringScanner.new(str)
|
|
28
|
+
while sc.skip_until(HIGH_BIT_RANGE)
|
|
29
|
+
pos = sc.pos = sc.pos-1
|
|
30
|
+
|
|
31
|
+
if !sequence_length(sc)
|
|
32
|
+
str[pos] = REPLACEMENT_CHAR
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
str
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Validate the UTF-8 sequence at the current scanner position.
|
|
40
|
+
#
|
|
41
|
+
# scanner - StringScanner instance so we can advance the pointer as we verify.
|
|
42
|
+
#
|
|
43
|
+
# Returns The length in bytes of this UTF-8 sequence, false if invalid.
|
|
44
|
+
def self.sequence_length(scanner)
|
|
45
|
+
leader = scanner.get_byte[0]
|
|
46
|
+
|
|
47
|
+
if (leader >> 5) == 0x6
|
|
48
|
+
if check_next_sequence(scanner)
|
|
49
|
+
return 2
|
|
50
|
+
else
|
|
51
|
+
scanner.pos -= 1
|
|
52
|
+
end
|
|
53
|
+
elsif (leader >> 4) == 0x0e
|
|
54
|
+
if check_next_sequence(scanner)
|
|
55
|
+
if check_next_sequence(scanner)
|
|
56
|
+
return 3
|
|
57
|
+
else
|
|
58
|
+
scanner.pos -= 2
|
|
59
|
+
end
|
|
60
|
+
else
|
|
61
|
+
scanner.pos -= 1
|
|
62
|
+
end
|
|
63
|
+
elsif (leader >> 3) == 0x1e
|
|
64
|
+
if check_next_sequence(scanner)
|
|
65
|
+
if check_next_sequence(scanner)
|
|
66
|
+
if check_next_sequence(scanner)
|
|
67
|
+
return 4
|
|
68
|
+
else
|
|
69
|
+
scanner.pos -= 3
|
|
70
|
+
end
|
|
71
|
+
else
|
|
72
|
+
scanner.pos -= 2
|
|
73
|
+
end
|
|
74
|
+
else
|
|
75
|
+
scanner.pos -= 1
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
false
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
private
|
|
83
|
+
|
|
84
|
+
# Read another byte off the scanner oving the scan position forward one place
|
|
85
|
+
#
|
|
86
|
+
# Returns nothing.
|
|
87
|
+
def self.check_next_sequence(scanner)
|
|
88
|
+
byte = scanner.get_byte[0]
|
|
89
|
+
(byte >> 6) == 0x2
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module UTF8Util
|
|
2
|
+
# use '?' intsead of the unicode replace char, since that is 3 bytes
|
|
3
|
+
# and can increase the string size if it's done a lot
|
|
4
|
+
REPLACEMENT_CHAR = "?"
|
|
5
|
+
|
|
6
|
+
# Replace invalid UTF-8 character sequences with a replacement character
|
|
7
|
+
#
|
|
8
|
+
# Returns self as valid UTF-8.
|
|
9
|
+
def self.clean!(str)
|
|
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)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Replace invalid UTF-8 character sequences with a replacement character
|
|
15
|
+
#
|
|
16
|
+
# Returns a copy of this String as valid UTF-8.
|
|
17
|
+
def self.clean(str)
|
|
18
|
+
clean!(str.dup)
|
|
19
|
+
end
|
|
20
|
+
end
|