gorgon 0.5.0.rc1 → 0.6.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +2 -4
- data/gorgon.gemspec +0 -1
- data/lib/gorgon/amqp_service.rb +5 -5
- data/lib/gorgon/gem_command_handler.rb +2 -1
- data/lib/gorgon/listener.rb +7 -5
- data/lib/gorgon/originator_protocol.rb +1 -0
- data/lib/gorgon/version.rb +1 -1
- data/lib/gorgon/worker_manager.rb +5 -2
- data/lib/gorgon_amq-protocol/.gitignore +15 -0
- data/lib/gorgon_amq-protocol/.gitmodules +3 -0
- data/lib/gorgon_amq-protocol/.rspec +3 -0
- data/lib/gorgon_amq-protocol/.travis.yml +19 -0
- data/lib/gorgon_amq-protocol/lib/gorgon_amq/bit_set.rb +82 -0
- data/lib/gorgon_amq-protocol/lib/gorgon_amq/endianness.rb +15 -0
- data/lib/gorgon_amq-protocol/lib/gorgon_amq/int_allocator.rb +96 -0
- data/lib/gorgon_amq-protocol/lib/gorgon_amq/pack.rb +53 -0
- data/lib/gorgon_amq-protocol/lib/gorgon_amq/protocol.rb +4 -0
- data/lib/gorgon_amq-protocol/lib/gorgon_amq/protocol/client.rb +2322 -0
- data/lib/gorgon_amq-protocol/lib/gorgon_amq/protocol/constants.rb +22 -0
- data/lib/gorgon_amq-protocol/lib/gorgon_amq/protocol/exceptions.rb +60 -0
- data/lib/gorgon_amq-protocol/lib/gorgon_amq/protocol/float_32bit.rb +14 -0
- data/lib/gorgon_amq-protocol/lib/gorgon_amq/protocol/frame.rb +210 -0
- data/lib/gorgon_amq-protocol/lib/gorgon_amq/protocol/table.rb +142 -0
- data/lib/gorgon_amq-protocol/lib/gorgon_amq/protocol/table_value_decoder.rb +190 -0
- data/lib/gorgon_amq-protocol/lib/gorgon_amq/protocol/table_value_encoder.rb +123 -0
- data/lib/gorgon_amq-protocol/lib/gorgon_amq/protocol/type_constants.rb +26 -0
- data/lib/gorgon_amq-protocol/lib/gorgon_amq/protocol/version.rb +5 -0
- data/lib/gorgon_amq-protocol/lib/gorgon_amq/settings.rb +114 -0
- data/lib/gorgon_amq-protocol/lib/gorgon_amq/uri.rb +37 -0
- data/lib/gorgon_bunny/lib/gorgon_amq/protocol/extensions.rb +16 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny.rb +89 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/authentication/credentials_encoder.rb +55 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/authentication/external_mechanism_encoder.rb +27 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/authentication/plain_mechanism_encoder.rb +19 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/channel.rb +1875 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/channel_id_allocator.rb +80 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/compatibility.rb +24 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/concurrent/atomic_fixnum.rb +74 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/concurrent/condition.rb +66 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/concurrent/continuation_queue.rb +41 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/concurrent/linked_continuation_queue.rb +61 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/concurrent/synchronized_sorted_set.rb +56 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/consumer.rb +123 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/consumer_tag_generator.rb +23 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/consumer_work_pool.rb +94 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/delivery_info.rb +93 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/exceptions.rb +236 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/exchange.rb +271 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/framing.rb +56 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/heartbeat_sender.rb +70 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/message_properties.rb +119 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/queue.rb +387 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/reader_loop.rb +116 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/return_info.rb +74 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/session.rb +1044 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/socket.rb +83 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/ssl_socket.rb +57 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/system_timer.rb +20 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/test_kit.rb +27 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/timeout.rb +18 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/transport.rb +398 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/version.rb +6 -0
- data/lib/gorgon_bunny/lib/gorgon_bunny/versioned_delivery_tag.rb +28 -0
- data/spec/crash_reporter_spec.rb +1 -1
- data/spec/gem_command_handler_spec.rb +2 -2
- data/spec/listener_spec.rb +5 -5
- data/spec/worker_manager_spec.rb +3 -3
- metadata +56 -17
@@ -0,0 +1,80 @@
|
|
1
|
+
require "thread"
|
2
|
+
require "monitor"
|
3
|
+
require "gorgon_amq/int_allocator"
|
4
|
+
|
5
|
+
module GorgonBunny
|
6
|
+
# Bitset-based channel id allocator. When channels are closed,
|
7
|
+
# ids are released back to the pool.
|
8
|
+
#
|
9
|
+
# Every connection has its own allocator.
|
10
|
+
#
|
11
|
+
# Allocating and releasing ids is synchronized and can be performed
|
12
|
+
# from multiple threads.
|
13
|
+
class ChannelIdAllocator
|
14
|
+
|
15
|
+
#
|
16
|
+
# API
|
17
|
+
#
|
18
|
+
|
19
|
+
# @param [Integer] max_channel Max allowed channel id
|
20
|
+
def initialize(max_channel = ((1 << 16) - 1))
|
21
|
+
@allocator = GorgonAMQ::IntAllocator.new(1, max_channel)
|
22
|
+
@mutex = Monitor.new
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
# Returns next available channel id. This method is thread safe.
|
27
|
+
#
|
28
|
+
# @return [Fixnum]
|
29
|
+
# @api public
|
30
|
+
# @see ChannelManager#release_channel_id
|
31
|
+
# @see ChannelManager#reset_channel_id_allocator
|
32
|
+
def next_channel_id
|
33
|
+
@mutex.synchronize do
|
34
|
+
@allocator.allocate
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Releases previously allocated channel id. This method is thread safe.
|
39
|
+
#
|
40
|
+
# @param [Fixnum] i Channel id to release
|
41
|
+
# @api public
|
42
|
+
# @see ChannelManager#next_channel_id
|
43
|
+
# @see ChannelManager#reset_channel_id_allocator
|
44
|
+
def release_channel_id(i)
|
45
|
+
@mutex.synchronize do
|
46
|
+
@allocator.release(i)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
# Returns true if given channel id has been previously allocated and not yet released.
|
52
|
+
# This method is thread safe.
|
53
|
+
#
|
54
|
+
# @param [Fixnum] i Channel id to check
|
55
|
+
# @return [Boolean] true if given channel id has been previously allocated and not yet released
|
56
|
+
# @api public
|
57
|
+
# @see ChannelManager#next_channel_id
|
58
|
+
# @see ChannelManager#release_channel_id
|
59
|
+
def allocated_channel_id?(i)
|
60
|
+
@mutex.synchronize do
|
61
|
+
@allocator.allocated?(i)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Resets channel allocator. This method is thread safe.
|
66
|
+
# @api public
|
67
|
+
# @see Channel.next_channel_id
|
68
|
+
# @see Channel.release_channel_id
|
69
|
+
def reset_channel_id_allocator
|
70
|
+
@mutex.synchronize do
|
71
|
+
@allocator.reset
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# @private
|
76
|
+
def synchronize(&block)
|
77
|
+
@mutex.synchronize(&block)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module GorgonBunny
|
2
|
+
# Helper methods necessary to stay mostly backwards-compatible with legacy (0.7.x, 0.8.x) GorgonBunny
|
3
|
+
# releases that hide channels completely from the API.
|
4
|
+
#
|
5
|
+
# @private
|
6
|
+
module Compatibility
|
7
|
+
|
8
|
+
#
|
9
|
+
# API
|
10
|
+
#
|
11
|
+
|
12
|
+
# @private
|
13
|
+
def channel_from(channel_or_connection)
|
14
|
+
# GorgonBunny 0.8.x and earlier completely hide channels from the API. So, queues and exchanges are
|
15
|
+
# instantiated with a "GorgonBunny object", which is a session. This function coerces two types of input to a
|
16
|
+
# channel.
|
17
|
+
if channel_or_connection.is_a?(GorgonBunny::Session)
|
18
|
+
channel_or_connection.default_channel
|
19
|
+
else
|
20
|
+
channel_or_connection
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require "set"
|
2
|
+
require "thread"
|
3
|
+
require "monitor"
|
4
|
+
|
5
|
+
module GorgonBunny
|
6
|
+
module Concurrent
|
7
|
+
# Minimalistic implementation of a synchronized fixnum value,
|
8
|
+
# designed after (but not implementing the entire API of!)
|
9
|
+
#
|
10
|
+
# @note Designed to be intentionally minimalistic and only cover GorgonBunny's needs.
|
11
|
+
#
|
12
|
+
# @api public
|
13
|
+
class AtomicFixnum
|
14
|
+
def initialize(n = 0)
|
15
|
+
@n = n
|
16
|
+
@mutex = Monitor.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def get
|
20
|
+
@mutex.synchronize do
|
21
|
+
@n
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def set(n)
|
26
|
+
@mutex.synchronize do
|
27
|
+
@n = n
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def increment
|
32
|
+
@mutex.synchronize do
|
33
|
+
@n = @n + 1
|
34
|
+
end
|
35
|
+
end
|
36
|
+
alias inc increment
|
37
|
+
alias increment_and_get increment
|
38
|
+
|
39
|
+
def get_and_add(i)
|
40
|
+
@mutex.synchronize do
|
41
|
+
v = @n
|
42
|
+
@n = @n + i
|
43
|
+
|
44
|
+
v
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_and_increment
|
49
|
+
@mutex.synchronize do
|
50
|
+
v = @n
|
51
|
+
@n = @n + 1
|
52
|
+
|
53
|
+
v
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def decrement
|
58
|
+
@mutex.synchronize do
|
59
|
+
@n = @n - 1
|
60
|
+
end
|
61
|
+
end
|
62
|
+
alias dec decrement
|
63
|
+
alias decrement_and_get decrement
|
64
|
+
|
65
|
+
def ==(m)
|
66
|
+
@mutex.synchronize { @n == m }
|
67
|
+
end
|
68
|
+
|
69
|
+
def ===(v)
|
70
|
+
@mutex.synchronize { @n === v }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require "thread"
|
2
|
+
require "monitor"
|
3
|
+
|
4
|
+
module GorgonBunny
|
5
|
+
# @private
|
6
|
+
module Concurrent
|
7
|
+
# Akin to java.util.concurrent.Condition and intrinsic object monitors (Object#wait, Object#notify, Object#notifyAll) in Java:
|
8
|
+
# threads can wait (block until notified) on a condition other threads notify them about.
|
9
|
+
# Unlike the j.u.c. version, this one has a single waiting set.
|
10
|
+
#
|
11
|
+
# Conditions can optionally be annotated with a description string for ease of debugging.
|
12
|
+
# @private
|
13
|
+
class Condition
|
14
|
+
attr_reader :waiting_threads, :description
|
15
|
+
|
16
|
+
|
17
|
+
def initialize(description = nil)
|
18
|
+
@mutex = Monitor.new
|
19
|
+
@waiting_threads = []
|
20
|
+
@description = description
|
21
|
+
end
|
22
|
+
|
23
|
+
def wait
|
24
|
+
@mutex.synchronize do
|
25
|
+
t = Thread.current
|
26
|
+
@waiting_threads.push(t)
|
27
|
+
end
|
28
|
+
|
29
|
+
Thread.stop
|
30
|
+
end
|
31
|
+
|
32
|
+
def notify
|
33
|
+
@mutex.synchronize do
|
34
|
+
t = @waiting_threads.shift
|
35
|
+
begin
|
36
|
+
t.run if t
|
37
|
+
rescue ThreadError
|
38
|
+
retry
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def notify_all
|
44
|
+
@mutex.synchronize do
|
45
|
+
@waiting_threads.each do |t|
|
46
|
+
t.run
|
47
|
+
end
|
48
|
+
|
49
|
+
@waiting_threads.clear
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def waiting_set_size
|
54
|
+
@mutex.synchronize { @waiting_threads.size }
|
55
|
+
end
|
56
|
+
|
57
|
+
def any_threads_waiting?
|
58
|
+
@mutex.synchronize { !@waiting_threads.empty? }
|
59
|
+
end
|
60
|
+
|
61
|
+
def none_threads_waiting?
|
62
|
+
@mutex.synchronize { @waiting_threads.empty? }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "thread"
|
2
|
+
|
3
|
+
module GorgonBunny
|
4
|
+
module Concurrent
|
5
|
+
# Continuation queue implementation for MRI and Rubinius
|
6
|
+
#
|
7
|
+
# @private
|
8
|
+
class ContinuationQueue
|
9
|
+
def initialize(*args, &block)
|
10
|
+
@q = ::Queue.new(*args)
|
11
|
+
end
|
12
|
+
|
13
|
+
def push(*args)
|
14
|
+
@q.push(*args)
|
15
|
+
end
|
16
|
+
alias << push
|
17
|
+
|
18
|
+
def pop
|
19
|
+
@q.pop
|
20
|
+
end
|
21
|
+
|
22
|
+
def poll(timeout_in_ms = nil)
|
23
|
+
if timeout_in_ms
|
24
|
+
GorgonBunny::Timeout.timeout(timeout_in_ms / 1000, ::Timeout::Error) do
|
25
|
+
@q.pop
|
26
|
+
end
|
27
|
+
else
|
28
|
+
@q.pop
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def clear
|
33
|
+
@q.clear
|
34
|
+
end
|
35
|
+
|
36
|
+
def method_missing(selector, *args, &block)
|
37
|
+
@q.__send__(selector, *args, &block)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
if !defined?(JRUBY_VERSION)
|
2
|
+
raise "GorgonBunny::Concurrent::LinkedContinuationQueue can only be used on JRuby!"
|
3
|
+
end
|
4
|
+
|
5
|
+
require "java"
|
6
|
+
|
7
|
+
java_import java.util.concurrent.LinkedBlockingQueue
|
8
|
+
java_import java.util.concurrent.TimeUnit
|
9
|
+
|
10
|
+
module GorgonBunny
|
11
|
+
module Concurrent
|
12
|
+
# Continuation queue implementation for JRuby.
|
13
|
+
#
|
14
|
+
# On JRuby, we'd rather use reliable and heavily battle tested j.u.c.
|
15
|
+
# primitives with well described semantics than informally specified, clumsy
|
16
|
+
# and limited Ruby standard library parts.
|
17
|
+
#
|
18
|
+
# This is an implementation of the continuation queue on top of the linked blocking
|
19
|
+
# queue in j.u.c.
|
20
|
+
#
|
21
|
+
# Compared to the Ruby standard library Queue, there is one limitation: you cannot
|
22
|
+
# push a nil on the queue, it will fail with a null pointer exception.
|
23
|
+
# @private
|
24
|
+
class LinkedContinuationQueue
|
25
|
+
def initialize(*args, &block)
|
26
|
+
@q = LinkedBlockingQueue.new
|
27
|
+
end
|
28
|
+
|
29
|
+
def push(el, timeout_in_ms = nil)
|
30
|
+
if timeout_in_ms
|
31
|
+
@q.offer(el, timeout_in_ms, TimeUnit::MILLISECONDS)
|
32
|
+
else
|
33
|
+
@q.offer(el)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
alias << push
|
37
|
+
|
38
|
+
def pop
|
39
|
+
@q.take
|
40
|
+
end
|
41
|
+
|
42
|
+
def poll(timeout_in_ms = nil)
|
43
|
+
if timeout_in_ms
|
44
|
+
v = @q.poll(timeout_in_ms, TimeUnit::MILLISECONDS)
|
45
|
+
raise ::Timeout::Error.new("operation did not finish in #{timeout_in_ms} ms") if v.nil?
|
46
|
+
v
|
47
|
+
else
|
48
|
+
@q.poll
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def clear
|
53
|
+
@q.clear
|
54
|
+
end
|
55
|
+
|
56
|
+
def method_missing(selector, *args, &block)
|
57
|
+
@q.__send__(selector, *args, &block)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require "set"
|
2
|
+
require "thread"
|
3
|
+
|
4
|
+
module GorgonBunny
|
5
|
+
module Concurrent
|
6
|
+
# A SortedSet variation that synchronizes key mutation operations.
|
7
|
+
#
|
8
|
+
# @note This is NOT a complete SortedSet replacement. It only synchronizes operations needed by GorgonBunny.
|
9
|
+
# @api public
|
10
|
+
class SynchronizedSortedSet < SortedSet
|
11
|
+
def initialize(enum = nil)
|
12
|
+
@mutex = Mutex.new
|
13
|
+
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
def add(o)
|
18
|
+
# avoid using Mutex#synchronize because of a Ruby 1.8.7-specific
|
19
|
+
# bug that prevents super from being called from within a block. MK.
|
20
|
+
@mutex.lock
|
21
|
+
begin
|
22
|
+
super
|
23
|
+
ensure
|
24
|
+
@mutex.unlock
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def delete(o)
|
29
|
+
@mutex.lock
|
30
|
+
begin
|
31
|
+
super
|
32
|
+
ensure
|
33
|
+
@mutex.unlock
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def delete_if(&block)
|
38
|
+
@mutex.lock
|
39
|
+
begin
|
40
|
+
super
|
41
|
+
ensure
|
42
|
+
@mutex.unlock
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def include?(o)
|
47
|
+
@mutex.lock
|
48
|
+
begin
|
49
|
+
super
|
50
|
+
ensure
|
51
|
+
@mutex.unlock
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
module GorgonBunny
|
2
|
+
# Base class that represents consumer interface. Subclasses of this class implement
|
3
|
+
# specific logic of handling consumer life cycle events. Note that when the only event
|
4
|
+
# you are interested in is message deliveries, it is recommended to just use
|
5
|
+
# {GorgonBunny::Queue#subscribe} instead of subclassing this class.
|
6
|
+
#
|
7
|
+
# @see GorgonBunny::Queue#subscribe
|
8
|
+
# @see GorgonBunny::Queue#subscribe_with
|
9
|
+
# @see http://rubybunny.info/articles/queues.html Queues and Consumers guide
|
10
|
+
# @api public
|
11
|
+
class Consumer
|
12
|
+
|
13
|
+
#
|
14
|
+
# API
|
15
|
+
#
|
16
|
+
|
17
|
+
attr_reader :channel
|
18
|
+
attr_reader :queue
|
19
|
+
attr_accessor :consumer_tag
|
20
|
+
attr_reader :arguments
|
21
|
+
attr_reader :no_ack
|
22
|
+
attr_reader :exclusive
|
23
|
+
|
24
|
+
|
25
|
+
# @param [GorgonBunny::Channel] channel Channel this consumer will use
|
26
|
+
# @param [GorgonBunny::Queue,String] queue Queue messages will be consumed from
|
27
|
+
# @param [String] consumer_tag Consumer tag (unique identifier). Generally it is better to let GorgonBunny generate one.
|
28
|
+
# Empty string means RabbitMQ will generate consumer tag.
|
29
|
+
# @param [Boolean] no_ack (true) If true, delivered messages will be automatically acknowledged.
|
30
|
+
# If false, manual acknowledgements will be necessary.
|
31
|
+
# @param [Boolean] exclusive (false) Should this consumer be exclusive?
|
32
|
+
# @param [Hash] arguments (nil) Optional arguments that may be used by RabbitMQ extensions, etc
|
33
|
+
# @api public
|
34
|
+
def initialize(channel, queue, consumer_tag = channel.generate_consumer_tag, no_ack = true, exclusive = false, arguments = {})
|
35
|
+
@channel = channel || raise(ArgumentError, "channel is nil")
|
36
|
+
@queue = queue || raise(ArgumentError, "queue is nil")
|
37
|
+
@consumer_tag = consumer_tag
|
38
|
+
@exclusive = exclusive
|
39
|
+
@arguments = arguments
|
40
|
+
# no_ack set to true = no manual ack = automatic ack. MK.
|
41
|
+
@no_ack = no_ack
|
42
|
+
end
|
43
|
+
|
44
|
+
# Defines message delivery handler
|
45
|
+
# @api public
|
46
|
+
def on_delivery(&block)
|
47
|
+
@on_delivery = block
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
# Invokes message delivery handler
|
52
|
+
# @private
|
53
|
+
def call(*args)
|
54
|
+
@on_delivery.call(*args) if @on_delivery
|
55
|
+
end
|
56
|
+
alias handle_delivery call
|
57
|
+
|
58
|
+
# Defines consumer cancellation notification handler
|
59
|
+
#
|
60
|
+
# @see http://rubybunny.info/articles/queues.html Queues and Consumers guide
|
61
|
+
# @see http://rubybunny.info/articles/extensions.html RabbitMQ Extensions guide
|
62
|
+
# @api public
|
63
|
+
def on_cancellation(&block)
|
64
|
+
@on_cancellation = block
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
# Invokes consumer cancellation notification handler
|
69
|
+
# @private
|
70
|
+
def handle_cancellation(basic_cancel)
|
71
|
+
@on_cancellation.call(basic_cancel) if @on_cancellation
|
72
|
+
end
|
73
|
+
|
74
|
+
# Cancels this consumer. Messages for this consumer will no longer be delivered. If the queue
|
75
|
+
# it was on is auto-deleted and this consumer was the last one, the queue will be deleted.
|
76
|
+
#
|
77
|
+
# @see http://rubybunny.info/articles/queues.html Queues and Consumers guide
|
78
|
+
# @api public
|
79
|
+
def cancel
|
80
|
+
@channel.basic_cancel(@consumer_tag)
|
81
|
+
end
|
82
|
+
|
83
|
+
# @return [String] More detailed human-readable string representation of this consumer
|
84
|
+
def inspect
|
85
|
+
"#<#{self.class.name}:#{object_id} @channel_id=#{@channel.number} @queue=#{self.queue_name}> @consumer_tag=#{@consumer_tag} @exclusive=#{@exclusive} @no_ack=#{@no_ack}>"
|
86
|
+
end
|
87
|
+
|
88
|
+
# @return [String] Brief human-readable string representation of this consumer
|
89
|
+
def to_s
|
90
|
+
"#<#{self.class.name}:#{object_id} @channel_id=#{@channel.number} @queue=#{self.queue_name}> @consumer_tag=#{@consumer_tag}>"
|
91
|
+
end
|
92
|
+
|
93
|
+
# @return [Boolean] true if this consumer uses automatic acknowledgement mode
|
94
|
+
# @api public
|
95
|
+
def automatic_acknowledgement?
|
96
|
+
@no_ack == true
|
97
|
+
end
|
98
|
+
|
99
|
+
# @return [Boolean] true if this consumer uses manual (explicit) acknowledgement mode
|
100
|
+
# @api public
|
101
|
+
def manual_acknowledgement?
|
102
|
+
@no_ack == false
|
103
|
+
end
|
104
|
+
|
105
|
+
#
|
106
|
+
# Recovery
|
107
|
+
#
|
108
|
+
|
109
|
+
# @private
|
110
|
+
def recover_from_network_failure
|
111
|
+
@channel.basic_consume_with(self)
|
112
|
+
end
|
113
|
+
|
114
|
+
# @private
|
115
|
+
def queue_name
|
116
|
+
if @queue.respond_to?(:name)
|
117
|
+
@queue.name
|
118
|
+
else
|
119
|
+
@queue
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|