rock-queue 0.2.0 → 0.3.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.
- data/Rakefile +18 -4
- data/lib/rock-queue.rb +54 -53
- data/lib/rock-queue/active_record_helper.rb +10 -4
- data/lib/rock-queue/adapters/beanstalkd.rb +29 -6
- data/lib/rock-queue/adapters/delayed_job.rb +3 -4
- data/lib/rock-queue/adapters/resque.rb +34 -5
- data/lib/rock-queue/notifiers/email_notifier.rb +13 -18
- data/lib/rock-queue/tasks.rb +2 -2
- data/lib/rock-queue/worker.rb +25 -17
- metadata +3 -3
data/Rakefile
CHANGED
@@ -5,9 +5,9 @@ require 'spec/rake/spectask'
|
|
5
5
|
require 'date'
|
6
6
|
$LOAD_PATH.unshift 'lib'
|
7
7
|
require 'rock-queue/tasks'
|
8
|
-
|
8
|
+
|
9
9
|
GEM = "rock-queue"
|
10
|
-
GEM_VERSION = "0.
|
10
|
+
GEM_VERSION = "0.3.0"
|
11
11
|
AUTHOR = "Grzegorz Kazulak"
|
12
12
|
EMAIL = "gregorz.kazulak@gmail.com"
|
13
13
|
HOMEPAGE = "http://github.com/grzegorzkazulak/rock-queue"
|
@@ -34,7 +34,7 @@ Rake::GemPackageTask.new(spec) do |pkg|
|
|
34
34
|
pkg.gem_spec = spec
|
35
35
|
end
|
36
36
|
|
37
|
-
task :default => :
|
37
|
+
task :default => :spec
|
38
38
|
|
39
39
|
desc "install the gem locally"
|
40
40
|
task :install => [:package] do
|
@@ -56,4 +56,18 @@ task :test do
|
|
56
56
|
Dir['test/*_test.rb'].each do |f|
|
57
57
|
require f
|
58
58
|
end
|
59
|
-
end
|
59
|
+
end
|
60
|
+
|
61
|
+
desc "Run all examples"
|
62
|
+
Spec::Rake::SpecTask.new('spec') do |t|
|
63
|
+
t.spec_opts = ["-cfs"]
|
64
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
65
|
+
end
|
66
|
+
|
67
|
+
desc "Run all examples with RCov"
|
68
|
+
Spec::Rake::SpecTask.new('spec:rcov') do |t|
|
69
|
+
t.spec_opts = ["-cfs"]
|
70
|
+
t.rcov = true
|
71
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
72
|
+
t.rcov_opts = ['--exclude spec,/home']
|
73
|
+
end
|
data/lib/rock-queue.rb
CHANGED
@@ -2,9 +2,7 @@ $:.unshift File.expand_path(File.dirname(__FILE__))
|
|
2
2
|
require 'logger'
|
3
3
|
|
4
4
|
module RockQueue
|
5
|
-
|
6
5
|
autoload :Config, 'rock-queue/config'
|
7
|
-
|
8
6
|
autoload :AbstractNotifier, 'rock-queue/notifiers/abstract_notifier'
|
9
7
|
autoload :Notifiers, 'rock-queue/notifiers'
|
10
8
|
autoload :EmailNotifier, 'rock-queue/notifiers/email_notifier'
|
@@ -22,64 +20,67 @@ module RockQueue
|
|
22
20
|
autoload :QueueingServerNotRunning, 'rock-queue/errors'
|
23
21
|
autoload :ActiveRecordHelper, 'rock-queue/active_record_helper'
|
24
22
|
|
25
|
-
|
23
|
+
extend self
|
26
24
|
|
25
|
+
# setup a connection
|
26
|
+
# options: adapter, server, port, log
|
27
|
+
def setup(options)
|
28
|
+
case options[:adapter]
|
29
|
+
when :beanstalkd
|
30
|
+
@adapter = Beanstalkd.new(options)
|
31
|
+
when :resque
|
32
|
+
@adapter = ResqueQueue.new(options)
|
33
|
+
when :delayed_job
|
34
|
+
@adapter = DelayedJob.new(options)
|
35
|
+
else
|
36
|
+
raise ArgumentError
|
37
|
+
end
|
38
|
+
@logger = Logger.new(options[:log].nil? ? STDOUT : options[:log])
|
39
|
+
end
|
27
40
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
# queueing server using selected adapter (passed as lowercased symbol)
|
32
|
-
def initialize(adapter, *options)
|
33
|
-
# Any better way to do this? :-)
|
34
|
-
options = options.first
|
35
|
-
if options.include?(:server) && options.include?(:port)
|
36
|
-
case adapter
|
37
|
-
when :beanstalkd
|
38
|
-
@adapter = Beanstalkd.new(options)
|
39
|
-
when :resque
|
40
|
-
@adapter = ResqueQueue.new(options)
|
41
|
-
when :delayed_job
|
42
|
-
@adapter = DelayedJob.new(options)
|
43
|
-
end
|
44
|
-
else
|
45
|
-
raise ArgumentError
|
46
|
-
end
|
41
|
+
def disconnect
|
42
|
+
@adapter = nil
|
43
|
+
end
|
47
44
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
# onto the queue using previously selected adapter
|
55
|
-
def push(value, *args)
|
56
|
-
@adapter.push(value, args)
|
57
|
-
end
|
58
|
-
|
59
|
-
|
60
|
-
# Pulls the data off the queue. There are two ways to do so:
|
61
|
-
# - Call receive with no block (gets you a single item)
|
62
|
-
# - Pass a block to it (creates and endles loop that constantly pulls items from the queue as they become available)
|
63
|
-
# All calls to the queueing server are made through the previosuly selected adaper.
|
64
|
-
def receive
|
65
|
-
if block_given?
|
66
|
-
obj, args = @adapter.pop
|
67
|
-
yield QueueObject.new(obj, args) if obj
|
68
|
-
else
|
69
|
-
raise 'No block given'
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
# Calling adapter method
|
74
|
-
def method_missing(sym, *args, &block)
|
75
|
-
@adapter.send sym, *args, &block
|
45
|
+
# return current connection
|
46
|
+
def adapter
|
47
|
+
if @adapter
|
48
|
+
@adapter
|
49
|
+
else
|
50
|
+
raise RuntimeError, "RockQueue is not connected. Use setup"
|
76
51
|
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def push(queue, value, *args)
|
55
|
+
adapter.push(queue, value, args)
|
56
|
+
end
|
77
57
|
|
78
|
-
|
79
|
-
|
80
|
-
|
58
|
+
def logger
|
59
|
+
@logger
|
60
|
+
end
|
61
|
+
|
62
|
+
# Pulls the data off the queue. There are two ways to do so:
|
63
|
+
# - Call receive with no block (gets you a single item)
|
64
|
+
# - Pass a block to it (creates and endles loop that constantly pulls
|
65
|
+
# items from the queue as they become available)
|
66
|
+
# All calls to the queueing server are made through the previosuly
|
67
|
+
# selecte adaper.
|
68
|
+
def receive(queue)
|
69
|
+
if block_given?
|
70
|
+
obj, args = @adapter.pop(queue)
|
71
|
+
yield QueueObject.new(obj, args) if obj
|
72
|
+
else
|
73
|
+
raise 'No block given'
|
81
74
|
end
|
75
|
+
end
|
82
76
|
|
77
|
+
# Register worker for web interface
|
78
|
+
def register_worker(worker)
|
79
|
+
@adapter.register_worker(worker) if @adapter.respond_to?(:register_worker)
|
83
80
|
end
|
84
81
|
|
82
|
+
# Calling adapter method
|
83
|
+
def method_missing(sym, *args, &block)
|
84
|
+
adapter.send sym, *args, &block
|
85
|
+
end
|
85
86
|
end
|
@@ -14,15 +14,21 @@ module RockQueue
|
|
14
14
|
method = args.shift
|
15
15
|
find(id).send(method, *args)
|
16
16
|
end
|
17
|
+
|
18
|
+
def queue
|
19
|
+
const_defined?(:QUEUE) ? self::QUEUE : :default
|
20
|
+
end
|
17
21
|
end
|
18
22
|
|
19
23
|
module InstanceMethods
|
20
24
|
def async(method, *args)
|
21
|
-
|
22
|
-
|
23
|
-
|
25
|
+
RockQueue.push self.class.queue, self.class, id, method, *args
|
26
|
+
end
|
27
|
+
|
28
|
+
def async_at(method, time_to_run_at, *args)
|
29
|
+
RockQueue.push_at(
|
30
|
+
self.class.queue, self.class, time_to_run_at, id, method, *args)
|
24
31
|
end
|
25
32
|
end
|
26
|
-
|
27
33
|
end
|
28
34
|
end
|
@@ -1,21 +1,44 @@
|
|
1
1
|
begin
|
2
2
|
require "beanstalk-client"
|
3
3
|
rescue
|
4
|
-
RockQueue
|
4
|
+
RockQueue.logger.error "You need `beanstalk-client` gem to use" \
|
5
|
+
"the Beanstalkd rock-queue interface"
|
5
6
|
exit
|
6
7
|
end
|
7
8
|
|
8
9
|
module RockQueue
|
9
10
|
class Beanstalkd
|
10
|
-
|
11
11
|
attr_reader :obj
|
12
12
|
|
13
13
|
def initialize(options = {})
|
14
|
-
@
|
14
|
+
@options = options
|
15
|
+
@addr = "#{options[:server]}:#{options[:port]}"
|
16
|
+
@obj = Beanstalk::Pool.new([@addr])
|
15
17
|
end
|
16
18
|
|
17
|
-
def
|
18
|
-
|
19
|
+
def push(queue, value, *args)
|
20
|
+
@obj.send(:send_to_rand_conn, :use, queue)
|
21
|
+
@obj.put [value.name, args].to_yaml
|
22
|
+
end
|
23
|
+
|
24
|
+
def pop(queue)
|
25
|
+
@obj.send(:send_to_rand_conn, :use, queue)
|
26
|
+
r = YAML.load(@obj.reserve.body)
|
27
|
+
r[0] = Kernel.const_get(r[0])
|
28
|
+
r
|
19
29
|
end
|
30
|
+
|
31
|
+
def clear
|
32
|
+
system "pkill beanstalkd"
|
33
|
+
system "beanstalkd -d -p #{@options[:port]}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def size(queue)
|
37
|
+
@obj.stats_tube(queue)["current-jobs-ready"]
|
38
|
+
end
|
39
|
+
|
40
|
+
def queues
|
41
|
+
@obj.list_tubes[@addr].map(&:to_sym)
|
42
|
+
end
|
20
43
|
end
|
21
|
-
end
|
44
|
+
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
begin
|
2
2
|
require "delayed_job"
|
3
3
|
rescue
|
4
|
-
RockQueue
|
4
|
+
RockQueue.logger.error "You need `delayed_job` gem to use" \
|
5
|
+
"the Delayed Job rock-queue interface"
|
5
6
|
exit
|
6
7
|
end
|
7
8
|
|
8
9
|
module RockQueue
|
9
10
|
class DelayedJob
|
10
|
-
|
11
11
|
attr_reader :obj
|
12
12
|
|
13
13
|
def initialize(options = {})
|
@@ -18,7 +18,6 @@ module RockQueue
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def pop
|
21
|
-
|
22
21
|
end
|
23
22
|
end
|
24
|
-
end
|
23
|
+
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
begin
|
2
2
|
require 'resque'
|
3
3
|
rescue
|
4
|
-
RockQueue
|
4
|
+
RockQueue.logger.error "You need `resque` gem to use" \
|
5
|
+
"the Resque rock-queue interface"
|
5
6
|
exit
|
6
7
|
end
|
7
8
|
|
@@ -13,23 +14,51 @@ module RockQueue
|
|
13
14
|
# Contructor of Resque adapter
|
14
15
|
def initialize(options)
|
15
16
|
Resque.redis = "#{options[:server]}:#{options[:port]}"
|
17
|
+
Resque.redis.sadd(:queues, :default)
|
16
18
|
end
|
17
19
|
|
18
20
|
# Push item from Resque queue
|
19
|
-
def push(value, args)
|
21
|
+
def push(queue, value, args)
|
20
22
|
if !defined?(value.queue)
|
21
23
|
value.class_eval do
|
22
|
-
@queue =
|
24
|
+
@queue = queue
|
23
25
|
end
|
24
26
|
end
|
25
27
|
Resque.enqueue value, args
|
26
28
|
end
|
29
|
+
|
30
|
+
# Push items to Resque queue to be picked up by the worker on specified time
|
31
|
+
def push_at(value, time_to_run_at ,*args)
|
32
|
+
if !defined?(value.queue)
|
33
|
+
value.class_eval do
|
34
|
+
@queue = :default
|
35
|
+
end
|
36
|
+
end
|
37
|
+
Resque.enqueue_at time_to_run_at, value, args
|
38
|
+
end
|
27
39
|
|
28
40
|
# Retrieve item from Resque queue
|
29
|
-
def pop
|
30
|
-
job = Resque.reserve
|
41
|
+
def pop(queue)
|
42
|
+
job = Resque.reserve(queue)
|
31
43
|
[job.payload_class, job.args] if job
|
32
44
|
end
|
33
45
|
|
46
|
+
# Register worker for web interface
|
47
|
+
def register_worker(worker)
|
48
|
+
Resque.redis.sadd(:workers, worker)
|
49
|
+
end
|
50
|
+
|
51
|
+
def clear
|
52
|
+
Resque.redis.flushall
|
53
|
+
Resque.redis.sadd(:queues, :default)
|
54
|
+
end
|
55
|
+
|
56
|
+
def size(queue)
|
57
|
+
Resque.size(queue)
|
58
|
+
end
|
59
|
+
|
60
|
+
def queues
|
61
|
+
Resque.queues.sort.map(&:to_sym)
|
62
|
+
end
|
34
63
|
end
|
35
64
|
end
|
@@ -1,39 +1,34 @@
|
|
1
1
|
module RockQueue
|
2
|
-
|
3
2
|
class EmailNotifier < AbstractNotifier
|
4
|
-
|
5
3
|
def initialize(config)
|
6
4
|
$server_config = config
|
5
|
+
|
6
|
+
Mail.defaults do
|
7
|
+
delivery_method :smtp, {
|
8
|
+
:address => $server_config[:server],
|
9
|
+
:port => $server_config[:port],
|
10
|
+
:user_name => $server_config[:username],
|
11
|
+
:password => $server_config[:password]
|
12
|
+
}
|
13
|
+
end
|
7
14
|
end
|
8
15
|
|
9
16
|
# Notify by email
|
10
17
|
def update(error)
|
11
|
-
|
12
18
|
begin
|
13
19
|
require 'mail'
|
14
20
|
rescue
|
15
|
-
RockQueue
|
21
|
+
RockQueue.logger.error "You need `mail` gem to use the Email Notifier"
|
16
22
|
end
|
17
23
|
|
18
|
-
RockQueue
|
19
|
-
|
20
|
-
Mail.defaults do
|
21
|
-
smtp do
|
22
|
-
host $server_config[:server]
|
23
|
-
port $server_config[:port]
|
24
|
-
user $server_config[:username]
|
25
|
-
pass $server_config[:password]
|
26
|
-
end
|
27
|
-
end
|
24
|
+
RockQueue.logger.info "Sending e-mail message: #{error.message}"
|
28
25
|
|
29
26
|
Mail.deliver do
|
30
27
|
from $server_config[:from]
|
31
28
|
to $server_config[:to]
|
32
|
-
subject "Processing error - '#{error.message}'
|
29
|
+
subject "Processing error - '#{error.message}'"
|
33
30
|
body error.backtrace.join("\n")
|
34
31
|
end
|
35
|
-
|
36
32
|
end
|
37
|
-
|
38
33
|
end
|
39
|
-
end
|
34
|
+
end
|
data/lib/rock-queue/tasks.rb
CHANGED
@@ -9,9 +9,9 @@ namespace :rock_queue do
|
|
9
9
|
file_path = "#{RAILS_ROOT}/tmp/pids/rock-queue.pid"
|
10
10
|
|
11
11
|
task :work do
|
12
|
-
worker = RockQueue::Worker.new
|
12
|
+
worker = RockQueue::Worker.new(ENV['QUEUE'].split(/,/))
|
13
13
|
worker.verbose = ENV['VERBOSE']
|
14
|
-
RockQueue
|
14
|
+
RockQueue.logger.info "=> Rock-queue worker initialized (#{worker})"
|
15
15
|
pid = fork do
|
16
16
|
File.open(file_path, "wb") { |f| f.write(Process.pid) }
|
17
17
|
worker.work
|
data/lib/rock-queue/worker.rb
CHANGED
@@ -4,42 +4,50 @@ module RockQueue
|
|
4
4
|
attr_accessor :verbose
|
5
5
|
|
6
6
|
# Initialize connection to queue server
|
7
|
-
def initialize
|
8
|
-
|
9
|
-
@
|
10
|
-
|
11
|
-
:port => config.port,
|
12
|
-
:log => config.log
|
13
|
-
}
|
14
|
-
RockQueue::Base.logger.info "=> Initializing..."
|
7
|
+
def initialize(*queues)
|
8
|
+
queues = [:default] if queues.size == 0
|
9
|
+
@queues = queues
|
10
|
+
RockQueue.logger.info "=> Initializing..."
|
15
11
|
end
|
16
12
|
|
17
13
|
# Main worker loop where all jobs are beeing pulled of the queue.
|
18
14
|
# This is also a place where every job starts and ends it's lifecycle.
|
19
|
-
def work
|
20
|
-
RockQueue
|
15
|
+
def work(interval = 5)
|
16
|
+
RockQueue.logger.info "=> Worker ready. Hold your horses!"
|
17
|
+
stop = false
|
21
18
|
loop do
|
22
19
|
ActiveRecord::Base.verify_active_connections!
|
23
|
-
|
24
|
-
|
20
|
+
queues.each do |qname|
|
21
|
+
obj, args = RockQueue.pop(qname)
|
22
|
+
if obj
|
23
|
+
queue = QueueObject.new(obj, args)
|
25
24
|
begin
|
26
25
|
# code that actually performs the action
|
27
26
|
args = queue.args.first
|
28
|
-
RockQueue
|
27
|
+
RockQueue.logger.info "=> Processing class #{queue.object.name} with params: #{args.inspect}"
|
29
28
|
args.empty? ? queue.object.perform : queue.object.perform(args)
|
30
29
|
rescue Object => e
|
31
30
|
# Add failed processing and retry
|
32
31
|
if queue.add_fail(e)
|
33
32
|
sleep(queue.get_sleep_time)
|
34
|
-
RockQueue
|
35
|
-
RockQueue
|
33
|
+
RockQueue.logger.error "=> Processing fail! Retrying #{queue.fails.length}"
|
34
|
+
RockQueue.logger.error " Message: #{e.message}"
|
36
35
|
retry
|
37
36
|
end
|
38
37
|
end
|
38
|
+
stop = false
|
39
|
+
else
|
40
|
+
stop = true if interval == 0
|
39
41
|
end
|
40
42
|
end
|
43
|
+
break if stop
|
41
44
|
end
|
42
45
|
end
|
43
|
-
|
46
|
+
|
47
|
+
# Returns a list of queues
|
48
|
+
# A single '*' means all queues
|
49
|
+
def queues
|
50
|
+
@queues[0] == "*" ? RockQueue.queues : @queues
|
51
|
+
end
|
44
52
|
end
|
45
|
-
end
|
53
|
+
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
7
|
+
- 3
|
8
8
|
- 0
|
9
|
-
version: 0.
|
9
|
+
version: 0.3.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Grzegorz Kazulak
|
@@ -14,7 +14,7 @@ autorequire: rock-queue
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-05-
|
17
|
+
date: 2010-05-28 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|