bunny 0.5.2 → 0.5.3
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/bunny.gemspec +4 -2
- data/examples/simple_consumer_08.rb +6 -6
- data/examples/simple_consumer_09.rb +6 -6
- data/lib/bunny.rb +1 -1
- data/lib/bunny/channel08.rb +3 -8
- data/lib/bunny/channel09.rb +3 -8
- data/lib/bunny/client08.rb +217 -344
- data/lib/bunny/client09.rb +175 -301
- data/lib/bunny/exchange08.rb +6 -1
- data/lib/bunny/exchange09.rb +6 -1
- data/lib/bunny/queue08.rb +144 -170
- data/lib/bunny/queue09.rb +160 -185
- data/lib/qrack/channel.rb +18 -0
- data/lib/qrack/client.rb +175 -2
- data/lib/qrack/qrack08.rb +2 -0
- data/lib/qrack/qrack09.rb +2 -0
- data/lib/qrack/queue.rb +53 -0
- data/spec/spec_08/exchange_spec.rb +8 -1
- data/spec/spec_08/queue_spec.rb +26 -0
- data/spec/spec_09/exchange_spec.rb +8 -1
- data/spec/spec_09/queue_spec.rb +26 -0
- metadata +4 -2
@@ -0,0 +1,18 @@
|
|
1
|
+
module Qrack
|
2
|
+
# Channel ancestor class
|
3
|
+
class Channel
|
4
|
+
|
5
|
+
attr_accessor :number, :active, :frame_buffer
|
6
|
+
attr_reader :client
|
7
|
+
|
8
|
+
def initialize(client)
|
9
|
+
@frame_buffer = []
|
10
|
+
@client = client
|
11
|
+
@number = client.channels.size
|
12
|
+
@active = false
|
13
|
+
client.channels[@number] = self
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
data/lib/qrack/client.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
module Qrack
|
2
|
+
|
3
|
+
class ClientTimeout < Timeout::Error; end
|
4
|
+
|
2
5
|
# Client ancestor class
|
3
6
|
class Client
|
4
7
|
|
@@ -6,7 +9,177 @@ module Qrack
|
|
6
9
|
RETRY_DELAY = 10.0
|
7
10
|
|
8
11
|
attr_reader :status, :host, :vhost, :port, :logging, :spec, :heartbeat
|
9
|
-
attr_accessor :channel, :logfile, :exchanges, :queues, :channels, :
|
12
|
+
attr_accessor :channel, :logfile, :exchanges, :queues, :channels, :message_in, :message_out,
|
13
|
+
:connecting
|
10
14
|
|
15
|
+
def initialize(opts = {})
|
16
|
+
@host = opts[:host] || 'localhost'
|
17
|
+
@user = opts[:user] || 'guest'
|
18
|
+
@pass = opts[:pass] || 'guest'
|
19
|
+
@vhost = opts[:vhost] || '/'
|
20
|
+
@logfile = opts[:logfile] || nil
|
21
|
+
@logging = opts[:logging] || false
|
22
|
+
@status = :not_connected
|
23
|
+
@frame_max = opts[:frame_max] || 131072
|
24
|
+
@channel_max = opts[:channel_max] || 0
|
25
|
+
@heartbeat = opts[:heartbeat] || 0
|
26
|
+
@logger = nil
|
27
|
+
create_logger if @logging
|
28
|
+
@message_in = false
|
29
|
+
@message_out = false
|
30
|
+
@connecting = false
|
31
|
+
@channels ||= []
|
32
|
+
# Create channel 0
|
33
|
+
@channel = create_channel()
|
34
|
+
@exchanges ||= {}
|
35
|
+
@queues ||= {}
|
36
|
+
end
|
37
|
+
|
38
|
+
=begin rdoc
|
39
|
+
|
40
|
+
=== DESCRIPTION:
|
41
|
+
|
42
|
+
Closes all active communication channels and connection. If an error occurs a
|
43
|
+
_Bunny_::_ProtocolError_ is raised. If successful, _Client_._status_ is set to <tt>:not_connected</tt>.
|
44
|
+
|
45
|
+
==== RETURNS:
|
46
|
+
|
47
|
+
<tt>:not_connected</tt> if successful.
|
48
|
+
|
49
|
+
=end
|
50
|
+
|
51
|
+
def close
|
52
|
+
# Close all active channels
|
53
|
+
channels.each do |c|
|
54
|
+
c.close if c.open?
|
55
|
+
end
|
56
|
+
|
57
|
+
# Close connection to AMQP server
|
58
|
+
close_connection
|
59
|
+
|
60
|
+
# Close TCP Socket
|
61
|
+
close_socket
|
62
|
+
end
|
63
|
+
|
64
|
+
alias stop close
|
65
|
+
|
66
|
+
def connected?
|
67
|
+
status == :connected
|
68
|
+
end
|
69
|
+
|
70
|
+
def connecting?
|
71
|
+
connecting
|
72
|
+
end
|
73
|
+
|
74
|
+
def logging=(bool)
|
75
|
+
@logging = bool
|
76
|
+
create_logger if @logging
|
77
|
+
end
|
78
|
+
|
79
|
+
def next_payload(options = {})
|
80
|
+
next_frame(options).payload
|
81
|
+
end
|
82
|
+
|
83
|
+
alias next_method next_payload
|
84
|
+
|
85
|
+
def read(*args)
|
86
|
+
send_command(:read, *args)
|
87
|
+
end
|
88
|
+
|
89
|
+
=begin rdoc
|
90
|
+
|
91
|
+
=== DESCRIPTION:
|
92
|
+
|
93
|
+
Checks to see whether or not an undeliverable message has been returned as a result of a publish
|
94
|
+
with the <tt>:immediate</tt> or <tt>:mandatory</tt> options.
|
95
|
+
|
96
|
+
==== OPTIONS:
|
97
|
+
|
98
|
+
* <tt>:timeout => number of seconds (default = 0.1) - The method will wait for a return
|
99
|
+
message until this timeout interval is reached.
|
100
|
+
|
101
|
+
==== RETURNS:
|
102
|
+
|
103
|
+
<tt>:no_return</tt> if message was not returned before timeout .
|
104
|
+
<tt>{:header, :return_details, :payload}</tt> if message is returned. <tt>:return_details</tt> is
|
105
|
+
a hash <tt>{:reply_code, :reply_text, :exchange, :routing_key}</tt>.
|
106
|
+
|
107
|
+
=end
|
108
|
+
|
109
|
+
def returned_message(opts = {})
|
110
|
+
secs = opts[:timeout] || 0.1
|
111
|
+
frame = next_frame(:timeout => secs)
|
112
|
+
|
113
|
+
if frame.is_a?(Symbol)
|
114
|
+
return :no_return if frame == :timed_out
|
115
|
+
end
|
116
|
+
|
117
|
+
method = frame.payload
|
118
|
+
header = next_payload
|
119
|
+
msg = next_payload
|
120
|
+
raise Bunny::MessageError, 'unexpected length' if msg.length < header.size
|
121
|
+
|
122
|
+
# Return the message and related info
|
123
|
+
{:header => header, :payload => msg, :return_details => method.arguments}
|
124
|
+
end
|
125
|
+
|
126
|
+
def switch_channel(chann)
|
127
|
+
if (0...channels.size).include? chann
|
128
|
+
@channel = channels[chann]
|
129
|
+
chann
|
130
|
+
else
|
131
|
+
raise RuntimeError, "Invalid channel number - #{chann}"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def write(*args)
|
136
|
+
send_command(:write, *args)
|
137
|
+
end
|
138
|
+
|
139
|
+
private
|
140
|
+
|
141
|
+
def close_socket(reason=nil)
|
142
|
+
# Close the socket. The server is not considered dead.
|
143
|
+
@socket.close if @socket and not @socket.closed?
|
144
|
+
@socket = nil
|
145
|
+
@status = :not_connected
|
146
|
+
end
|
147
|
+
|
148
|
+
def create_logger
|
149
|
+
@logfile ? @logger = Logger.new("#{logfile}") : @logger = Logger.new(STDOUT)
|
150
|
+
@logger.level = Logger::INFO
|
151
|
+
@logger.datetime_format = "%Y-%m-%d %H:%M:%S"
|
152
|
+
end
|
153
|
+
|
154
|
+
def send_command(cmd, *args)
|
155
|
+
begin
|
156
|
+
raise Bunny::ConnectionError, 'No connection - socket has not been created' if !@socket
|
157
|
+
@socket.__send__(cmd, *args)
|
158
|
+
rescue Errno::EPIPE, IOError => e
|
159
|
+
raise Bunny::ServerDownError, e.message
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def socket
|
164
|
+
return @socket if @socket and (@status == :connected) and not @socket.closed?
|
165
|
+
|
166
|
+
begin
|
167
|
+
# Attempt to connect.
|
168
|
+
@socket = timeout(CONNECT_TIMEOUT) do
|
169
|
+
TCPSocket.new(host, port)
|
170
|
+
end
|
171
|
+
|
172
|
+
if Socket.constants.include? 'TCP_NODELAY'
|
173
|
+
@socket.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1
|
174
|
+
end
|
175
|
+
rescue => e
|
176
|
+
@status = :not_connected
|
177
|
+
raise Bunny::ServerDownError, e.message
|
178
|
+
end
|
179
|
+
|
180
|
+
@socket
|
181
|
+
end
|
182
|
+
|
11
183
|
end
|
12
|
-
|
184
|
+
|
185
|
+
end
|
data/lib/qrack/qrack08.rb
CHANGED
data/lib/qrack/qrack09.rb
CHANGED
data/lib/qrack/queue.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
module Qrack
|
2
|
+
|
3
|
+
# Queue ancestor class
|
4
|
+
class Queue
|
5
|
+
|
6
|
+
attr_reader :name, :client
|
7
|
+
attr_accessor :delivery_tag
|
8
|
+
|
9
|
+
=begin rdoc
|
10
|
+
|
11
|
+
=== DESCRIPTION:
|
12
|
+
|
13
|
+
Returns consumer count from Queue#status.
|
14
|
+
|
15
|
+
=end
|
16
|
+
|
17
|
+
def consumer_count
|
18
|
+
s = status
|
19
|
+
s[:consumer_count]
|
20
|
+
end
|
21
|
+
|
22
|
+
=begin rdoc
|
23
|
+
|
24
|
+
=== DESCRIPTION:
|
25
|
+
|
26
|
+
Returns message count from Queue#status.
|
27
|
+
|
28
|
+
=end
|
29
|
+
|
30
|
+
def message_count
|
31
|
+
s = status
|
32
|
+
s[:message_count]
|
33
|
+
end
|
34
|
+
|
35
|
+
=begin rdoc
|
36
|
+
|
37
|
+
=== DESCRIPTION:
|
38
|
+
|
39
|
+
Publishes a message to the queue via the default nameless '' direct exchange.
|
40
|
+
|
41
|
+
==== RETURNS:
|
42
|
+
|
43
|
+
nil
|
44
|
+
|
45
|
+
=end
|
46
|
+
|
47
|
+
def publish(data, opts = {})
|
48
|
+
exchange.publish(data, opts)
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -115,6 +115,13 @@ describe Bunny do
|
|
115
115
|
exch = @b.exchange('direct_exchange')
|
116
116
|
exch.publish('This is a published message')
|
117
117
|
end
|
118
|
+
|
119
|
+
it "should not modify the passed options hash when publishing a message" do
|
120
|
+
exch = @b.exchange('direct_exchange')
|
121
|
+
opts = {:key => 'a', :persistent => true}
|
122
|
+
exch.publish('', opts)
|
123
|
+
opts.should == {:key => 'a', :persistent => true}
|
124
|
+
end
|
118
125
|
|
119
126
|
it "should be able to return an undeliverable message" do
|
120
127
|
exch = @b.exchange('')
|
@@ -136,4 +143,4 @@ describe Bunny do
|
|
136
143
|
exch.delete(:nowait => true)
|
137
144
|
end
|
138
145
|
|
139
|
-
end
|
146
|
+
end
|
data/spec/spec_08/queue_spec.rb
CHANGED
@@ -67,6 +67,14 @@ describe Bunny do
|
|
67
67
|
q.message_count.should == 0
|
68
68
|
end
|
69
69
|
|
70
|
+
it "should be able to pop a message where body length exceeds max frame size" do
|
71
|
+
q = @b.queue('test1')
|
72
|
+
lg_msg = 'z' * 142000
|
73
|
+
q.publish(lg_msg)
|
74
|
+
msg = q.pop
|
75
|
+
msg.should == lg_msg
|
76
|
+
end
|
77
|
+
|
70
78
|
it "should be able to be purged to remove all of its messages" do
|
71
79
|
q = @b.queue('test1')
|
72
80
|
5.times {q.publish('This is another test message')}
|
@@ -82,6 +90,24 @@ describe Bunny do
|
|
82
90
|
msg = q.pop
|
83
91
|
msg.should == :queue_empty
|
84
92
|
end
|
93
|
+
|
94
|
+
it "should stop subscription without processing messages if max specified is 0" do
|
95
|
+
q = @b.queue('test1')
|
96
|
+
5.times {q.publish('Yet another test message')}
|
97
|
+
q.message_count.should == 5
|
98
|
+
q.subscribe(:message_max => 0){|msg| x = 1}
|
99
|
+
q.message_count.should == 5
|
100
|
+
q.unsubscribe.should == :unsubscribe_ok
|
101
|
+
q.purge.should == :purge_ok
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should stop subscription after processing number of messages specified > 0" do
|
105
|
+
q = @b.queue('test1')
|
106
|
+
5.times {q.publish('Yet another test message')}
|
107
|
+
q.message_count.should == 5
|
108
|
+
q.subscribe(:message_max => 5){|msg| x = 1}
|
109
|
+
q.unsubscribe.should == :unsubscribe_ok
|
110
|
+
end
|
85
111
|
|
86
112
|
it "should be able to be deleted" do
|
87
113
|
q = @b.queue('test1')
|
@@ -115,6 +115,13 @@ describe Bunny do
|
|
115
115
|
exch = @b.exchange('direct_exchange')
|
116
116
|
exch.publish('This is a published message')
|
117
117
|
end
|
118
|
+
|
119
|
+
it "should not modify the passed options hash when publishing a message" do
|
120
|
+
exch = @b.exchange('direct_exchange')
|
121
|
+
opts = {:key => 'a', :persistent => true}
|
122
|
+
exch.publish('', opts)
|
123
|
+
opts.should == {:key => 'a', :persistent => true}
|
124
|
+
end
|
118
125
|
|
119
126
|
it "should be able to return an undeliverable message" do
|
120
127
|
exch = @b.exchange('')
|
@@ -136,4 +143,4 @@ describe Bunny do
|
|
136
143
|
exch.delete(:nowait => true)
|
137
144
|
end
|
138
145
|
|
139
|
-
end
|
146
|
+
end
|
data/spec/spec_09/queue_spec.rb
CHANGED
@@ -67,6 +67,14 @@ describe Bunny do
|
|
67
67
|
q.message_count.should == 0
|
68
68
|
end
|
69
69
|
|
70
|
+
it "should be able to pop a message where body length exceeds max frame size" do
|
71
|
+
q = @b.queue('test1')
|
72
|
+
lg_msg = 'z' * 142000
|
73
|
+
q.publish(lg_msg)
|
74
|
+
msg = q.pop
|
75
|
+
msg.should == lg_msg
|
76
|
+
end
|
77
|
+
|
70
78
|
it "should be able to be purged to remove all of its messages" do
|
71
79
|
q = @b.queue('test1')
|
72
80
|
5.times {q.publish('This is another test message')}
|
@@ -82,6 +90,24 @@ describe Bunny do
|
|
82
90
|
msg = q.pop
|
83
91
|
msg.should == :queue_empty
|
84
92
|
end
|
93
|
+
|
94
|
+
it "should stop subscription without processing messages if max specified is 0" do
|
95
|
+
q = @b.queue('test1')
|
96
|
+
5.times {q.publish('Yet another test message')}
|
97
|
+
q.message_count.should == 5
|
98
|
+
q.subscribe(:message_max => 0){|msg| x = 1}
|
99
|
+
q.message_count.should == 5
|
100
|
+
q.unsubscribe.should == :unsubscribe_ok
|
101
|
+
q.purge.should == :purge_ok
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should stop subscription after processing number of messages specified > 0" do
|
105
|
+
q = @b.queue('test1')
|
106
|
+
5.times {q.publish('Yet another test message')}
|
107
|
+
q.message_count.should == 5
|
108
|
+
q.subscribe(:message_max => 5){|msg| x = 1}
|
109
|
+
q.unsubscribe.should == :unsubscribe_ok
|
110
|
+
end
|
85
111
|
|
86
112
|
it "should be able to be deleted" do
|
87
113
|
q = @b.queue('test1')
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bunny
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Duncan
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-09-07 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -50,6 +50,8 @@ files:
|
|
50
50
|
- lib/bunny/queue08.rb
|
51
51
|
- lib/bunny/queue09.rb
|
52
52
|
- lib/qrack/client.rb
|
53
|
+
- lib/qrack/channel.rb
|
54
|
+
- lib/qrack/queue.rb
|
53
55
|
- lib/qrack/protocol/protocol08.rb
|
54
56
|
- lib/qrack/protocol/protocol09.rb
|
55
57
|
- lib/qrack/protocol/spec08.rb
|