amq-client 0.7.0.alpha3 → 0.7.0.alpha4
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/.gitignore +1 -0
- data/Gemfile +4 -3
- data/amq-client.gemspec +1 -1
- data/examples/coolio_adapter/example_helper.rb +1 -1
- data/examples/eventmachine_adapter/connection_loss_handler.rb +43 -0
- data/lib/amq/client.rb +55 -0
- data/lib/amq/client/adapter.rb +17 -49
- data/lib/amq/client/adapters/coolio.rb +16 -66
- data/lib/amq/client/adapters/event_machine.rb +130 -45
- data/lib/amq/client/adapters/socket.rb +9 -8
- data/lib/amq/client/channel.rb +23 -5
- data/lib/amq/client/connection.rb +6 -5
- data/lib/amq/client/entity.rb +55 -40
- data/lib/amq/client/version.rb +1 -1
- data/spec/benchmarks/adapters.rb +1 -1
- data/spec/integration/coolio/basic_ack_spec.rb +1 -4
- data/spec/integration/coolio/basic_get_spec.rb +1 -1
- data/spec/integration/coolio/basic_return_spec.rb +1 -1
- data/spec/integration/coolio/channel_close_spec.rb +1 -1
- data/spec/integration/coolio/channel_flow_spec.rb +1 -1
- data/spec/integration/coolio/spec_helper.rb +1 -1
- data/spec/integration/coolio/tx_commit_spec.rb +1 -1
- data/spec/integration/coolio/tx_rollback_spec.rb +1 -1
- data/spec/regression/bad_frame_slicing_in_adapters_spec.rb +1 -1
- data/spec/spec_helper.rb +1 -0
- data/spec/unit/client_spec.rb +74 -0
- metadata +209 -187
@@ -2,9 +2,6 @@
|
|
2
2
|
|
3
3
|
require "socket"
|
4
4
|
require "amq/client"
|
5
|
-
require "amq/client/channel"
|
6
|
-
require "amq/client/exchange"
|
7
|
-
require "amq/client/queue"
|
8
5
|
require "amq/client/framing/io/frame"
|
9
6
|
|
10
7
|
module AMQ
|
@@ -19,11 +16,6 @@ module AMQ
|
|
19
16
|
|
20
17
|
self.sync = true
|
21
18
|
|
22
|
-
register_entity :channel, AMQ::Client::Channel
|
23
|
-
register_entity :exchange, AMQ::Client::Exchange
|
24
|
-
register_entity :queue, AMQ::Client::Queue
|
25
|
-
|
26
|
-
|
27
19
|
#
|
28
20
|
# API
|
29
21
|
#
|
@@ -43,6 +35,15 @@ module AMQ
|
|
43
35
|
raise exception
|
44
36
|
end
|
45
37
|
|
38
|
+
def register_connection_callback(&block)
|
39
|
+
if block
|
40
|
+
block.call(self)
|
41
|
+
self.disconnect
|
42
|
+
else
|
43
|
+
self
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
46
47
|
def connection
|
47
48
|
@socket
|
48
49
|
end # connection
|
data/lib/amq/client/channel.rb
CHANGED
@@ -1,12 +1,20 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
require "amq/client/entity"
|
4
|
-
require "amq/client/
|
4
|
+
require "amq/client/queue"
|
5
|
+
require "amq/client/exchange"
|
5
6
|
|
6
7
|
module AMQ
|
7
8
|
module Client
|
8
9
|
class Channel < Entity
|
9
10
|
|
11
|
+
#
|
12
|
+
# Behaviors
|
13
|
+
#
|
14
|
+
|
15
|
+
register_entity :queue, AMQ::Client::Queue
|
16
|
+
register_entity :exchange, AMQ::Client::Exchange
|
17
|
+
|
10
18
|
#
|
11
19
|
# API
|
12
20
|
#
|
@@ -42,7 +50,11 @@ module AMQ
|
|
42
50
|
# 65536 is here for cases when channel is opened without passing a callback in,
|
43
51
|
# otherwise channel_mix would be nil and it causes a lot of needless headaches.
|
44
52
|
# lets just have this default. MK.
|
45
|
-
channel_max = client.connection
|
53
|
+
channel_max = if client.connection
|
54
|
+
client.connection.channel_max || 65536
|
55
|
+
else
|
56
|
+
65536
|
57
|
+
end
|
46
58
|
|
47
59
|
if channel_max != 0 && !(0..channel_max).include?(id)
|
48
60
|
raise ChannelOutOfBadError.new(channel_max, id)
|
@@ -195,6 +207,10 @@ module AMQ
|
|
195
207
|
@flow_is_active
|
196
208
|
end # flow_is_active?
|
197
209
|
|
210
|
+
# Defines a callback that will be executed when channel is closed after
|
211
|
+
# channel-level exception.
|
212
|
+
#
|
213
|
+
# @api public
|
198
214
|
def on_error(&block)
|
199
215
|
self.define_callback(:close, &block)
|
200
216
|
end
|
@@ -244,9 +260,11 @@ module AMQ
|
|
244
260
|
end # reset_state!
|
245
261
|
|
246
262
|
|
247
|
-
def
|
263
|
+
def handle_connection_interruption(exception = nil)
|
248
264
|
self.reset_state!
|
249
|
-
end #
|
265
|
+
end # handle_connection_interruption
|
266
|
+
|
267
|
+
|
250
268
|
|
251
269
|
def handle_open_ok(method)
|
252
270
|
self.status = :opened
|
@@ -262,7 +280,7 @@ module AMQ
|
|
262
280
|
self.status = :closed
|
263
281
|
self.exec_callback_once_yielding_self(:close, method)
|
264
282
|
|
265
|
-
self.
|
283
|
+
self.handle_connection_interruption(exception)
|
266
284
|
end
|
267
285
|
|
268
286
|
# === Handlers ===
|
@@ -191,11 +191,12 @@ module AMQ
|
|
191
191
|
#
|
192
192
|
# @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.5.2.9)
|
193
193
|
def handle_close(method)
|
194
|
-
self.
|
194
|
+
self.handle_connection_interruption
|
195
195
|
|
196
196
|
closed!
|
197
197
|
# TODO: use proper exception class, provide protocol class (we know method.class_id and method.method_id) as well!
|
198
|
-
|
198
|
+
x = RuntimeError.new(method.reply_text)
|
199
|
+
self.error(x)
|
199
200
|
end
|
200
201
|
|
201
202
|
# Handles connection.close-ok
|
@@ -207,9 +208,9 @@ module AMQ
|
|
207
208
|
end # handle_close_ok(method)
|
208
209
|
|
209
210
|
|
210
|
-
def
|
211
|
-
@channels.each { |n, c| c.
|
212
|
-
end #
|
211
|
+
def handle_connection_interruption
|
212
|
+
@channels.each { |n, c| c.handle_connection_interruption }
|
213
|
+
end # handle_connection_interruption
|
213
214
|
|
214
215
|
|
215
216
|
|
data/lib/amq/client/entity.rb
CHANGED
@@ -4,48 +4,21 @@ require "amq/client/mixins/status"
|
|
4
4
|
|
5
5
|
module AMQ
|
6
6
|
module Client
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
include StatusMixin
|
20
|
-
|
21
|
-
#
|
22
|
-
# API
|
23
|
-
#
|
24
|
-
|
25
|
-
# @return [Array<#call>]
|
26
|
-
attr_reader :callbacks
|
27
|
-
|
28
|
-
@@handlers ||= Hash.new
|
29
|
-
|
30
|
-
def self.handle(klass, &block)
|
31
|
-
@@handlers[klass] = block
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.handlers
|
35
|
-
@@handlers
|
36
|
-
end
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
def initialize(client)
|
42
|
-
@client = client
|
43
|
-
# Be careful with default values for #ruby hashes: h = Hash.new(Array.new); h[:key] ||= 1
|
44
|
-
# won't assign anything to :key. MK.
|
45
|
-
@callbacks = Hash.new
|
7
|
+
module RegisterEntityMixin
|
8
|
+
# @example Registering Channel implementation
|
9
|
+
# Adapter.register_entity(:channel, Channel)
|
10
|
+
# # ... so then I can do:
|
11
|
+
# channel = client.channel(1)
|
12
|
+
# # instead of:
|
13
|
+
# channel = Channel.new(client, 1)
|
14
|
+
def register_entity(name, klass)
|
15
|
+
define_method(name) do |*args, &block|
|
16
|
+
klass.new(self, *args, &block)
|
17
|
+
end
|
46
18
|
end
|
19
|
+
end
|
47
20
|
|
48
|
-
|
21
|
+
module CallbacksMixin
|
49
22
|
def redefine_callback(event, callable = nil, &block)
|
50
23
|
f = (callable || block)
|
51
24
|
# yes, re-assign!
|
@@ -95,7 +68,49 @@ module AMQ
|
|
95
68
|
callbacks = Array(self.callbacks.delete(name))
|
96
69
|
callbacks.map { |c| c.call(self, *args, &block) } if callbacks.any?
|
97
70
|
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# AMQ entities, as implemented by AMQ::Client, have callbacks and can run them
|
74
|
+
# when necessary.
|
75
|
+
#
|
76
|
+
# @note Exchanges and queues implementation is based on this class.
|
77
|
+
#
|
78
|
+
# @abstract
|
79
|
+
class Entity
|
80
|
+
|
81
|
+
#
|
82
|
+
# Behaviors
|
83
|
+
#
|
84
|
+
|
85
|
+
include StatusMixin
|
86
|
+
include CallbacksMixin
|
87
|
+
|
88
|
+
extend RegisterEntityMixin
|
89
|
+
|
90
|
+
#
|
91
|
+
# API
|
92
|
+
#
|
98
93
|
|
94
|
+
# @return [Array<#call>]
|
95
|
+
attr_reader :callbacks
|
96
|
+
|
97
|
+
@@handlers ||= Hash.new
|
98
|
+
|
99
|
+
def self.handle(klass, &block)
|
100
|
+
@@handlers[klass] = block
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.handlers
|
104
|
+
@@handlers
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
def initialize(client)
|
109
|
+
@client = client
|
110
|
+
# Be careful with default values for #ruby hashes: h = Hash.new(Array.new); h[:key] ||= 1
|
111
|
+
# won't assign anything to :key. MK.
|
112
|
+
@callbacks = Hash.new
|
113
|
+
end
|
99
114
|
|
100
115
|
|
101
116
|
def error(exception)
|
data/lib/amq/client/version.rb
CHANGED
data/spec/benchmarks/adapters.rb
CHANGED
@@ -11,7 +11,7 @@ TOTAL_MESSAGES = 10000
|
|
11
11
|
# Short messages
|
12
12
|
# Cool.io
|
13
13
|
coolio_start = Time.now
|
14
|
-
AMQ::Client::
|
14
|
+
AMQ::Client::CoolioClient.connect(:port => 5672, :vhost => "/amq_client_testbed") do |client|
|
15
15
|
received_messages = 0
|
16
16
|
channel = AMQ::Client::Channel.new(client, 1)
|
17
17
|
channel.open { }
|
@@ -1,10 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'integration/coolio/spec_helper'
|
3
3
|
|
4
|
-
|
5
|
-
require 'integration/coolio/spec_helper'
|
6
|
-
|
7
|
-
describe "AMQ::Client::Coolio", "Basic.Ack", :nojruby => true do
|
4
|
+
describe "AMQ::Client::CoolioClient", "Basic.Ack", :nojruby => true do
|
8
5
|
include EventedSpec::SpecHelper
|
9
6
|
default_timeout 1
|
10
7
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'integration/coolio/spec_helper'
|
3
3
|
|
4
|
-
describe "AMQ::Client::
|
4
|
+
describe "AMQ::Client::CoolioClient", "Basic.Return", :nojruby => true do
|
5
5
|
include EventedSpec::SpecHelper
|
6
6
|
default_timeout 1.0
|
7
7
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'integration/coolio/spec_helper'
|
3
3
|
|
4
|
-
describe "AMQ::Client::
|
4
|
+
describe "AMQ::Client::CoolioClient", "Channel.Close", :nojruby => true do
|
5
5
|
include EventedSpec::SpecHelper
|
6
6
|
default_timeout 1
|
7
7
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'integration/coolio/spec_helper'
|
3
3
|
|
4
|
-
describe "AMQ::Client::
|
4
|
+
describe "AMQ::Client::CoolioClient", "Channel.Flow", :nojruby => true do
|
5
5
|
include EventedSpec::SpecHelper
|
6
6
|
default_timeout 1
|
7
7
|
|
@@ -24,7 +24,7 @@ end
|
|
24
24
|
|
25
25
|
def coolio_amqp_connect(&block)
|
26
26
|
coolio do
|
27
|
-
AMQ::Client::
|
27
|
+
AMQ::Client::CoolioClient.connect(:port => 5672, :vhost => "/amq_client_testbed", :frame_max => 2**16-1, :heartbeat_interval => 1) do |client|
|
28
28
|
yield client
|
29
29
|
end
|
30
30
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
require 'spec_helper'
|
3
3
|
require 'integration/coolio/spec_helper'
|
4
4
|
|
5
|
-
describe "AMQ::Client::
|
5
|
+
describe "AMQ::Client::CoolioClient", "Tx.Commit", :nojruby => true do
|
6
6
|
include EventedSpec::SpecHelper
|
7
7
|
default_timeout 2
|
8
8
|
let(:message) { "Hello, world!" }
|
@@ -2,7 +2,7 @@
|
|
2
2
|
require 'spec_helper'
|
3
3
|
require 'integration/coolio/spec_helper'
|
4
4
|
|
5
|
-
describe "AMQ::Client::
|
5
|
+
describe "AMQ::Client::CoolioClient", "Tx.Rollback", :nojruby => true do
|
6
6
|
include EventedSpec::SpecHelper
|
7
7
|
default_timeout 2
|
8
8
|
|
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
require 'integration/coolio/spec_helper'
|
3
3
|
require 'integration/eventmachine/spec_helper'
|
4
4
|
|
5
|
-
describe "AMQ::Client::
|
5
|
+
describe "AMQ::Client::CoolioClient", :nojruby => true do
|
6
6
|
include EventedSpec::SpecHelper
|
7
7
|
default_timeout 1
|
8
8
|
|
data/spec/spec_helper.rb
CHANGED
data/spec/unit/client_spec.rb
CHANGED
@@ -5,7 +5,81 @@ require "spec_helper"
|
|
5
5
|
require "amq/client"
|
6
6
|
|
7
7
|
describe AMQ::Client do
|
8
|
+
if RUBY_PLATFORM =~ /java/
|
9
|
+
ADAPTERS = {
|
10
|
+
:event_machine => "EventMachineClient",
|
11
|
+
:socket => "SocketClient"
|
12
|
+
}
|
13
|
+
else
|
14
|
+
ADAPTERS = {
|
15
|
+
:event_machine => "EventMachineClient",
|
16
|
+
:coolio => "CoolioClient",
|
17
|
+
:socket => "SocketClient"
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
8
21
|
it "should have VERSION" do
|
9
22
|
AMQ::Client::const_defined?(:VERSION).should be_true
|
10
23
|
end
|
24
|
+
|
25
|
+
ADAPTERS.each do |adapter_name, adapter_const_name|
|
26
|
+
describe ".adapters" do
|
27
|
+
before(:all) do
|
28
|
+
@meta = AMQ::Client.adapters[adapter_name]
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should provide info about path to the adapter" do
|
32
|
+
lambda { require @meta[:path] }.should_not raise_error
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should provide info about const_name" do
|
36
|
+
@meta[:const_name].should eql(adapter_const_name)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe ".connect(settings = nil, &block)" do
|
42
|
+
include EventedSpec::SpecHelper
|
43
|
+
default_timeout 1
|
44
|
+
|
45
|
+
context "with specified adapter" do
|
46
|
+
it "should connect using socket adapter" do
|
47
|
+
pending "Socket adapter is currently broken" do
|
48
|
+
AMQ::Client.connect(:adapter => :socket) do |client|
|
49
|
+
client.class.name.should eql("AMQ::Client::SocketClient")
|
50
|
+
done
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should connect using event_machine adapter" do
|
56
|
+
em do
|
57
|
+
AMQ::Client.connect(:adapter => :event_machine) do |client|
|
58
|
+
client.class.name.should eql("AMQ::Client::EventMachineClient")
|
59
|
+
done
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should connect using coolio adapter", :nojruby => true do
|
65
|
+
coolio do
|
66
|
+
AMQ::Client.connect(:adapter => :coolio) do |client|
|
67
|
+
client.class.name.should eql("AMQ::Client::CoolioClient")
|
68
|
+
done
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context "without any specified adapter" do
|
75
|
+
it "should default to the socket adapter" do
|
76
|
+
pending "Socket adapter is currently broken" do
|
77
|
+
AMQ::Client.connect do |client|
|
78
|
+
client.class.name.should eql("AMQ::Client::SocketClient")
|
79
|
+
done
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
11
85
|
end
|