amq-client 0.7.0.alpha3 → 0.7.0.alpha4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|