amqp 0.9.10 → 1.0.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +0 -3
- data/CHANGELOG +4 -0
- data/Gemfile +1 -0
- data/README.md +72 -81
- data/amqp.gemspec +14 -5
- data/docs/08Migration.textile +0 -4
- data/docs/AMQP091ModelExplained.textile +0 -5
- data/docs/Bindings.textile +0 -4
- data/docs/Clustering.textile +0 -4
- data/docs/ConnectingToTheBroker.textile +1 -5
- data/docs/ConnectionEncryptionWithTLS.textile +0 -4
- data/docs/DocumentationGuidesIndex.textile +0 -4
- data/docs/Durability.textile +0 -4
- data/docs/ErrorHandling.textile +40 -106
- data/docs/Exchanges.textile +0 -4
- data/docs/GettingStarted.textile +6 -10
- data/docs/PatternsAndUseCases.textile +1 -4
- data/docs/Queues.textile +0 -4
- data/docs/RabbitMQVersions.textile +0 -4
- data/docs/RunningTests.textile +0 -4
- data/docs/TestingWithEventedSpec.textile +0 -4
- data/docs/Troubleshooting.textile +0 -4
- data/docs/VendorSpecificExtensions.textile +0 -4
- data/examples/error_handling/hello_world_producer.rb +1 -1
- data/examples/issues/issue_121.rb +23 -0
- data/examples/patterns/request_reply/client.rb +2 -1
- data/examples/patterns/request_reply/server.rb +1 -0
- data/examples/publishing/returned_messages.rb +1 -1
- data/lib/amqp.rb +0 -7
- data/lib/amqp/channel.rb +15 -33
- data/lib/amqp/client.rb +2 -2
- data/lib/amqp/compatibility/ruby187_patchlevel_check.rb +4 -4
- data/lib/amqp/connection.rb +0 -1
- data/lib/amqp/consumer.rb +2 -2
- data/lib/amqp/exceptions.rb +1 -10
- data/lib/amqp/exchange.rb +5 -5
- data/lib/amqp/queue.rb +23 -47
- data/lib/amqp/session.rb +4 -4
- data/lib/amqp/version.rb +1 -1
- data/spec/integration/basic_get_spec.rb +24 -80
- data/spec/integration/basic_return_spec.rb +3 -3
- data/spec/integration/channel_level_exception_with_multiple_channels_spec.rb +1 -0
- data/spec/integration/exchange_declaration_spec.rb +102 -71
- data/spec/integration/extensions/rabbitmq/publisher_confirmations_spec.rb +17 -1
- data/spec/integration/fanout_exchange_routing_spec.rb +1 -1
- data/spec/integration/immediate_messages_spec.rb +59 -0
- data/spec/integration/multiple_consumers_per_queue_spec.rb +101 -39
- data/spec/integration/queue_redeclaration_with_incompatible_attributes_spec.rb +12 -25
- data/spec/integration/regressions/concurrent_publishing_on_the_same_channel_spec.rb +1 -1
- data/spec/integration/reply_queue_communication_spec.rb +2 -1
- data/spec/integration/store_and_forward_spec.rb +9 -6
- data/spec/integration/topic_subscription_spec.rb +4 -5
- data/spec/spec_helper.rb +2 -8
- data/spec/unit/amqp/connection_spec.rb +1 -3
- metadata +112 -116
- data/examples/deprecated/default_thread_local_channel_instance.rb +0 -34
- data/examples/legacy/ack.rb +0 -70
- data/examples/legacy/callbacks.rb +0 -45
- data/examples/legacy/clock.rb +0 -74
- data/examples/legacy/hashtable.rb +0 -60
- data/examples/legacy/logger.rb +0 -92
- data/examples/legacy/multiclock.rb +0 -56
- data/examples/legacy/pingpong.rb +0 -51
- data/examples/legacy/primes-simple.rb +0 -29
- data/examples/legacy/primes.rb +0 -74
- data/examples/legacy/stocks.rb +0 -59
- data/lib/amqp/deprecated/fork.rb +0 -17
- data/lib/amqp/deprecated/logger.rb +0 -100
- data/lib/amqp/deprecated/mq.rb +0 -22
- data/lib/amqp/deprecated/rpc.rb +0 -169
- data/lib/amqp/ext/em.rb +0 -3
- data/lib/amqp/ext/emfork.rb +0 -72
- data/lib/amqp/logger.rb +0 -19
- data/lib/amqp/rpc.rb +0 -20
- data/lib/mq.rb +0 -35
- data/lib/mq/logger.rb +0 -4
- data/lib/mq/rpc.rb +0 -4
- data/spec/integration/remove_individual_binding_spec.rb +0 -51
data/lib/amqp/deprecated/fork.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require "amqp/ext/em"
|
4
|
-
|
5
|
-
module AMQP
|
6
|
-
# @deprecated
|
7
|
-
# @private
|
8
|
-
def self.fork(workers)
|
9
|
-
EM.fork(workers) do
|
10
|
-
# clean up globals in the fork
|
11
|
-
Thread.current[:mq] = nil
|
12
|
-
AMQP.instance_variable_set('@conn', nil)
|
13
|
-
|
14
|
-
yield
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,100 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module AMQP
|
4
|
-
# @private
|
5
|
-
class Logger
|
6
|
-
def initialize(*args, &block)
|
7
|
-
opts = args.pop if args.last.is_a? Hash
|
8
|
-
opts ||= {}
|
9
|
-
|
10
|
-
printer(block) if block
|
11
|
-
|
12
|
-
@prop = opts
|
13
|
-
@tags = ([:timestamp] + args).uniq
|
14
|
-
end
|
15
|
-
|
16
|
-
attr_reader :prop
|
17
|
-
alias :base :prop
|
18
|
-
|
19
|
-
def log(severity, *args)
|
20
|
-
opts = args.pop if args.last.is_a? Hash and args.size != 1
|
21
|
-
opts ||= {}
|
22
|
-
opts = @prop.clone.update(opts)
|
23
|
-
|
24
|
-
data = args.shift
|
25
|
-
|
26
|
-
data = {:type => :exception,
|
27
|
-
:name => data.class.to_s.intern,
|
28
|
-
:backtrace => data.backtrace,
|
29
|
-
:message => data.message} if data.is_a? Exception
|
30
|
-
|
31
|
-
(@tags + args).each do |tag|
|
32
|
-
tag = tag.to_sym
|
33
|
-
case tag
|
34
|
-
when :timestamp
|
35
|
-
opts.update :timestamp => Time.now
|
36
|
-
when :hostname
|
37
|
-
@hostname ||= { :hostname => `hostname`.strip }
|
38
|
-
opts.update @hostname
|
39
|
-
when :process
|
40
|
-
@process_id ||= { :process_id => Process.pid,
|
41
|
-
:process_name => $0,
|
42
|
-
:process_parent_id => Process.ppid,
|
43
|
-
:thread_id => Thread.current.object_id }
|
44
|
-
opts.update :process => @process_id
|
45
|
-
else
|
46
|
-
(opts[:tags] ||= []) << tag
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
opts.update(:severity => severity,
|
51
|
-
:msg => data)
|
52
|
-
|
53
|
-
print(opts)
|
54
|
-
unless Logger.disabled?
|
55
|
-
AMQP::Channel.new.fanout('logging', :durable => true).publish Marshal.dump(opts)
|
56
|
-
end
|
57
|
-
|
58
|
-
opts
|
59
|
-
end
|
60
|
-
alias :method_missing :log
|
61
|
-
|
62
|
-
def print(data = nil, &block)
|
63
|
-
if block
|
64
|
-
@printer = block
|
65
|
-
elsif data.is_a? Proc
|
66
|
-
@printer = data
|
67
|
-
elsif data
|
68
|
-
(pr = @printer || self.class.printer) and pr.call(data)
|
69
|
-
else
|
70
|
-
@printer
|
71
|
-
end
|
72
|
-
end
|
73
|
-
alias :printer :print
|
74
|
-
|
75
|
-
def self.printer &block
|
76
|
-
@printer = block if block
|
77
|
-
@printer
|
78
|
-
end
|
79
|
-
|
80
|
-
def self.disabled?
|
81
|
-
!!@disabled
|
82
|
-
end
|
83
|
-
|
84
|
-
def self.enable
|
85
|
-
@disabled = false
|
86
|
-
end
|
87
|
-
|
88
|
-
def self.disable
|
89
|
-
@disabled = true
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
|
95
|
-
require "amqp/deprecated/mq"
|
96
|
-
class MQ
|
97
|
-
# @note This class will be removed before 1.0 release.
|
98
|
-
# @deprecated
|
99
|
-
class Logger < ::AMQP::Logger; end
|
100
|
-
end
|
data/lib/amqp/deprecated/mq.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
# Alias for AMQP::Channel.
|
4
|
-
#
|
5
|
-
# @note This class will be removed before 1.0 release.
|
6
|
-
# @deprecated
|
7
|
-
class MQ < AMQP::Channel; end
|
8
|
-
|
9
|
-
|
10
|
-
class MQ
|
11
|
-
# Alias for AMQP::Exchange.
|
12
|
-
#
|
13
|
-
# @note This class will be removed before 1.0 release.
|
14
|
-
# @deprecated
|
15
|
-
class Exchange < ::AMQP::Exchange; end
|
16
|
-
|
17
|
-
# Alias for AMQP::Queue.
|
18
|
-
#
|
19
|
-
# @note This class will be removed before 1.0 release.
|
20
|
-
# @deprecated
|
21
|
-
class Queue < ::AMQP::Queue; end
|
22
|
-
end
|
data/lib/amqp/deprecated/rpc.rb
DELETED
@@ -1,169 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module AMQP
|
4
|
-
if defined?(BasicObject)
|
5
|
-
# @private
|
6
|
-
class BlankSlate < BasicObject; end
|
7
|
-
else
|
8
|
-
# @private
|
9
|
-
class BlankSlate
|
10
|
-
instance_methods.each { |m| undef_method m unless m =~ /^__/ }
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
|
15
|
-
# Basic RPC (remote procedure call) facility.
|
16
|
-
#
|
17
|
-
# Needs more detail and explanation.
|
18
|
-
#
|
19
|
-
# EM.run do
|
20
|
-
# server = AMQP::Channel.new.rpc('hash table node', Hash)
|
21
|
-
#
|
22
|
-
# client = AMQP::Channel.new.rpc('hash table node')
|
23
|
-
# client[:now] = Time.now
|
24
|
-
# client[:one] = 1
|
25
|
-
#
|
26
|
-
# client.values do |res|
|
27
|
-
# p 'client', :values => res
|
28
|
-
# end
|
29
|
-
#
|
30
|
-
# client.keys do |res|
|
31
|
-
# p 'client', :keys => res
|
32
|
-
# EM.stop_event_loop
|
33
|
-
# end
|
34
|
-
# end
|
35
|
-
#
|
36
|
-
#
|
37
|
-
# @note This class will be removed before 1.0 release.
|
38
|
-
# @deprecated
|
39
|
-
# @private
|
40
|
-
class RPC < ::AMQP::BlankSlate
|
41
|
-
|
42
|
-
#
|
43
|
-
# API
|
44
|
-
#
|
45
|
-
|
46
|
-
|
47
|
-
attr_reader :name
|
48
|
-
|
49
|
-
# Takes a channel, queue and optional object.
|
50
|
-
#
|
51
|
-
# The optional object may be a class name, module name or object
|
52
|
-
# instance. When given a class or module name, the object is instantiated
|
53
|
-
# during this setup. The passed queue is automatically subscribed to so
|
54
|
-
# it passes all messages (and their arguments) to the object.
|
55
|
-
#
|
56
|
-
# Marshalling and unmarshalling the objects is handled internally. This
|
57
|
-
# marshalling is subject to the same restrictions as defined in the
|
58
|
-
# {http://ruby-doc.org/core/classes/Marshal.html Marshal} standard
|
59
|
-
# library. See that documentation for further reference.
|
60
|
-
#
|
61
|
-
# When the optional object is not passed, the returned rpc reference is
|
62
|
-
# used to send messages and arguments to the queue. See #method_missing
|
63
|
-
# which does all of the heavy lifting with the proxy. Some client
|
64
|
-
# elsewhere must call this method *with* the optional block so that
|
65
|
-
# there is a valid destination. Failure to do so will just enqueue
|
66
|
-
# marshalled messages that are never consumed.
|
67
|
-
#
|
68
|
-
def initialize(channel, queue, obj = nil)
|
69
|
-
@name = queue
|
70
|
-
@channel = channel
|
71
|
-
@channel.register_rpc(self)
|
72
|
-
|
73
|
-
if @obj = normalize(obj)
|
74
|
-
@delegate = Server.new(channel, queue, @obj)
|
75
|
-
else
|
76
|
-
@delegate = Client.new(channel, queue)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
|
81
|
-
def client?
|
82
|
-
@obj.nil?
|
83
|
-
end
|
84
|
-
|
85
|
-
def server?
|
86
|
-
!client?
|
87
|
-
end
|
88
|
-
|
89
|
-
|
90
|
-
def method_missing(selector, *args, &block)
|
91
|
-
@delegate.__send__(selector, *args, &block)
|
92
|
-
end
|
93
|
-
|
94
|
-
|
95
|
-
# @private
|
96
|
-
class Client
|
97
|
-
attr_accessor :identifier
|
98
|
-
|
99
|
-
def initialize(channel, server_queue_name)
|
100
|
-
@channel = channel
|
101
|
-
@exchange = AMQP::Exchange.default(@channel)
|
102
|
-
@server_queue_name = server_queue_name
|
103
|
-
|
104
|
-
@handlers = Hash.new
|
105
|
-
@queue = channel.queue("__amqp_gem_rpc_client_#{rand(1_000_000)}", :auto_delete => true)
|
106
|
-
|
107
|
-
@queue.subscribe do |header, payload|
|
108
|
-
*response_args = Marshal.load(payload)
|
109
|
-
handler = @handlers[header.message_id]
|
110
|
-
|
111
|
-
handler.call(*response_args)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
def method_missing(selector, *args, &block)
|
116
|
-
@channel.once_open do
|
117
|
-
message_id = "message_identifier_#{rand(1_000_000)}"
|
118
|
-
|
119
|
-
if block
|
120
|
-
@handlers[message_id] = block
|
121
|
-
@exchange.publish(Marshal.dump([selector, *args]), :routing_key => @server_queue_name, :reply_to => @queue.name, :message_id => message_id)
|
122
|
-
else
|
123
|
-
@exchange.publish(Marshal.dump([selector, *args]), :routing_key => @server_queue_name, :message_id => message_id)
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end # Client
|
128
|
-
|
129
|
-
# @private
|
130
|
-
class Server
|
131
|
-
def initialize(channel, queue_name, impl)
|
132
|
-
@channel = channel
|
133
|
-
@exchange = AMQP::Exchange.default(@channel)
|
134
|
-
@queue = @channel.queue(queue_name)
|
135
|
-
@impl = impl
|
136
|
-
|
137
|
-
@handlers = Hash.new
|
138
|
-
@id = "client_identifier_#{rand(1_000_000)}"
|
139
|
-
|
140
|
-
@queue.subscribe(:ack => true) do |header, payload|
|
141
|
-
selector, *args = Marshal.load(payload)
|
142
|
-
result = @impl.__send__(selector, *args)
|
143
|
-
|
144
|
-
respond_to(header, result) if header.to_hash[:reply_to]
|
145
|
-
header.ack
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
def respond_to(header, result)
|
150
|
-
@exchange.publish(Marshal.dump(result), :message_id => header.message_id, :routing_key => header.reply_to)
|
151
|
-
end
|
152
|
-
end # Server
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
protected
|
157
|
-
|
158
|
-
def normalize(input)
|
159
|
-
case input
|
160
|
-
when ::Class
|
161
|
-
input.new
|
162
|
-
when ::Module
|
163
|
-
(::Class.new do include(obj) end).new
|
164
|
-
else
|
165
|
-
input
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end # RPC
|
169
|
-
end # AMQP
|
data/lib/amqp/ext/em.rb
DELETED
data/lib/amqp/ext/emfork.rb
DELETED
@@ -1,72 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
# @private
|
4
|
-
EMFORK = $0 == __FILE__
|
5
|
-
|
6
|
-
if EMFORK
|
7
|
-
require 'rubygems'
|
8
|
-
end
|
9
|
-
|
10
|
-
require 'eventmachine'
|
11
|
-
|
12
|
-
# helper to fork off EM reactors
|
13
|
-
# @private
|
14
|
-
def EM.fork num = 1, &blk
|
15
|
-
unless @forks
|
16
|
-
trap('CHLD') {
|
17
|
-
pid = Process.wait
|
18
|
-
p [:pid, pid, :died] if EMFORK
|
19
|
-
block = @forks.delete(pid)
|
20
|
-
EM.fork(1, &block)
|
21
|
-
}
|
22
|
-
|
23
|
-
trap('EXIT') {
|
24
|
-
p [:pid, Process.pid, :exit] if EMFORK
|
25
|
-
@forks.keys.each { |pid|
|
26
|
-
p [:pid, Process.pid, :killing, pid] if EMFORK
|
27
|
-
Process.kill('USR1', pid)
|
28
|
-
}
|
29
|
-
}
|
30
|
-
|
31
|
-
@forks = {}
|
32
|
-
end
|
33
|
-
|
34
|
-
num.times do
|
35
|
-
pid = EM.fork_reactor do
|
36
|
-
p [:pid, Process.pid, :started] if EMFORK
|
37
|
-
|
38
|
-
trap('USR1') { EM.stop_event_loop }
|
39
|
-
trap('CHLD') {}
|
40
|
-
trap('EXIT') {}
|
41
|
-
|
42
|
-
blk.call
|
43
|
-
end
|
44
|
-
|
45
|
-
@forks[pid] = blk
|
46
|
-
p [:children, EM.forks] if EMFORK
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
# @private
|
51
|
-
def EM.forks
|
52
|
-
@forks ? @forks.keys : []
|
53
|
-
end
|
54
|
-
|
55
|
-
if EMFORK
|
56
|
-
p 'starting reactor'
|
57
|
-
|
58
|
-
trap('INT') { EM.stop_event_loop }
|
59
|
-
|
60
|
-
EM.run {
|
61
|
-
p [:parent, Process.pid]
|
62
|
-
|
63
|
-
EM.fork(2) {
|
64
|
-
EM.add_periodic_timer(1) do
|
65
|
-
p [:fork, Process.pid, :ping]
|
66
|
-
end
|
67
|
-
}
|
68
|
-
|
69
|
-
}
|
70
|
-
|
71
|
-
p 'reactor stopped'
|
72
|
-
end
|
data/lib/amqp/logger.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
$stdout.puts <<-MESSAGE
|
4
|
-
-------------------------------------------------------------------------------------
|
5
|
-
DEPRECATION WARNING!
|
6
|
-
|
7
|
-
Use of amqp/logger.rb is deprecated. Instead of
|
8
|
-
|
9
|
-
require "amqp/logger"
|
10
|
-
|
11
|
-
please use
|
12
|
-
|
13
|
-
require "amqp/deprecated/logger"
|
14
|
-
|
15
|
-
|
16
|
-
Both amqp/logger.rb and AMQP::Logger will be REMOVED before 1.0 release.
|
17
|
-
MESSAGE
|
18
|
-
|
19
|
-
require "amqp/deprecated/logger"
|
data/lib/amqp/rpc.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
$stdout.puts <<-MESSAGE
|
4
|
-
-------------------------------------------------------------------------------------
|
5
|
-
DEPRECATION WARNING!
|
6
|
-
|
7
|
-
Use of amqp/rpc.rb is deprecated. Instead of
|
8
|
-
|
9
|
-
require "amqp/rpc"
|
10
|
-
|
11
|
-
please use
|
12
|
-
|
13
|
-
require "amqp/deprecated/rpc"
|
14
|
-
|
15
|
-
|
16
|
-
Both amqp/rpc.rb and AMQP::RPC implementation will be REMOVED before 1.0 release.
|
17
|
-
If you need RPC, we recommend the rpc gem (see https://github.com/ruby-amqp/rpc).
|
18
|
-
MESSAGE
|
19
|
-
|
20
|
-
require "amqp/deprecated/rpc"
|
data/lib/mq.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
$stdout.puts <<-MESSAGE
|
4
|
-
-------------------------------------------------------------------------------------
|
5
|
-
DEPRECATION WARNING!
|
6
|
-
|
7
|
-
Use of mq.rb is deprecated. Instead of
|
8
|
-
|
9
|
-
require "mq"
|
10
|
-
|
11
|
-
please use
|
12
|
-
|
13
|
-
require "amqp"
|
14
|
-
|
15
|
-
|
16
|
-
mq.rb will be REMOVED in AMQP gem version 1.0.
|
17
|
-
|
18
|
-
Why is it deprecated? Because it was a poor name choice all along. We better not
|
19
|
-
release 1.0 with it. Both mq.rb and MQ class step away from AMQP terminology and
|
20
|
-
make 8 out of 10 engineers think it has something to do with AMQP queues (in fact,
|
21
|
-
MQ should have been called Channel all along). No other AMQP client library we know
|
22
|
-
of invents its own terminology when it comes to AMQP entities, and amqp gem shouldn't,
|
23
|
-
too.
|
24
|
-
|
25
|
-
Learn more at http://bit.ly/amqp-gem-080-migration, all documentation guides are at
|
26
|
-
http://bit.ly/amqp-gem-docs, AMQP Model Explained at http://bit.ly/amqp-model-explained.
|
27
|
-
|
28
|
-
We are also in #rabbitmq on irc.freenode.net.
|
29
|
-
|
30
|
-
Thank you for understanding. AMQP gem maintainers team.
|
31
|
-
|
32
|
-
-------------------------------------------------------------------------------------
|
33
|
-
MESSAGE
|
34
|
-
|
35
|
-
require "amqp"
|