bunny 0.4.3 → 0.4.4
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/README +8 -1
- data/bunny.gemspec +44 -0
- data/examples/simple_headers.rb +40 -0
- data/lib/bunny.rb +34 -11
- data/lib/bunny/client08.rb +421 -0
- data/lib/bunny/{client.rb → client091.rb} +22 -12
- data/lib/bunny/{exchange.rb → exchange08.rb} +0 -0
- data/lib/bunny/exchange091.rb +158 -0
- data/lib/bunny/{queue.rb → queue08.rb} +0 -0
- data/lib/bunny/queue091.rb +458 -0
- data/lib/qrack/protocol/{spec.rb → spec08.rb} +0 -0
- data/lib/qrack/protocol/spec091.rb +520 -0
- data/lib/qrack/{qrack.rb → qrack08.rb} +2 -2
- data/lib/qrack/qrack091.rb +28 -0
- data/lib/qrack/transport/{frame.rb → frame08.rb} +0 -0
- data/lib/qrack/transport/frame091.rb +94 -0
- data/spec/bunny_spec.rb +4 -0
- data/spec/exchange_spec.rb +31 -10
- data/spec/queue_spec.rb +1 -1
- metadata +17 -9
data/README
CHANGED
@@ -17,7 +17,7 @@ You can use Bunny to -
|
|
17
17
|
* Create and delete queues
|
18
18
|
* Publish and consume messages
|
19
19
|
|
20
|
-
Bunny is known to work with RabbitMQ versions 1.5.4, 1.5.5 and version 0-8 of the AMQP specification.
|
20
|
+
Bunny is known to work with RabbitMQ versions 1.5.4, 1.5.5, 1.6.0 and version 0-8 of the AMQP specification.
|
21
21
|
|
22
22
|
=== INSTALL:
|
23
23
|
|
@@ -48,5 +48,12 @@ Bunny is known to work with RabbitMQ versions 1.5.4, 1.5.5 and version 0-8 of th
|
|
48
48
|
# close the connection
|
49
49
|
b.stop
|
50
50
|
|
51
|
+
=== EVEN QUICKER START
|
52
|
+
|
53
|
+
require 'bunny'
|
54
|
+
|
55
|
+
# Create a direct queue named 'my_testq'
|
56
|
+
Bunny.run { |c| c.queue('my_testq') }
|
57
|
+
|
51
58
|
=== OTHER:
|
52
59
|
Please see the _examples_ directory for additional usage information.
|
data/bunny.gemspec
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = %q{bunny}
|
3
|
+
s.version = "0.4.4"
|
4
|
+
s.authors = ["Chris Duncan"]
|
5
|
+
s.date = %q{2009-06-19}
|
6
|
+
s.description = %q{Another synchronous Ruby AMQP client}
|
7
|
+
s.email = %q{celldee@gmail.com}
|
8
|
+
s.rubyforge_project = %q{bunny-amqp}
|
9
|
+
s.has_rdoc = true
|
10
|
+
s.extra_rdoc_files = [ "README" ]
|
11
|
+
s.rdoc_options = [ "--main", "README" ]
|
12
|
+
s.homepage = %q{http://github.com/celldee/bunny/tree/master}
|
13
|
+
s.summary = %q{A synchronous Ruby AMQP client that enables interaction with AMQP-compliant brokers/servers.}
|
14
|
+
s.files = ["LICENSE",
|
15
|
+
"README",
|
16
|
+
"Rakefile",
|
17
|
+
"bunny.gemspec",
|
18
|
+
"examples/simple.rb",
|
19
|
+
"examples/simple_ack.rb",
|
20
|
+
"examples/simple_consumer.rb",
|
21
|
+
"examples/simple_fanout.rb",
|
22
|
+
"examples/simple_publisher.rb",
|
23
|
+
"examples/simple_topic.rb",
|
24
|
+
"examples/simple_headers.rb",
|
25
|
+
"lib/bunny.rb",
|
26
|
+
"lib/bunny/client08.rb",
|
27
|
+
"lib/bunny/client091.rb",
|
28
|
+
"lib/bunny/exchange08.rb",
|
29
|
+
"lib/bunny/exchange091.rb",
|
30
|
+
"lib/bunny/queue08.rb",
|
31
|
+
"lib/bunny/queue091.rb",
|
32
|
+
"lib/qrack/client.rb",
|
33
|
+
"lib/qrack/protocol/protocol.rb",
|
34
|
+
"lib/qrack/protocol/spec08.rb",
|
35
|
+
"lib/qrack/protocol/spec091.rb",
|
36
|
+
"lib/qrack/qrack08.rb",
|
37
|
+
"lib/qrack/qrack091.rb",
|
38
|
+
"lib/qrack/transport/buffer.rb",
|
39
|
+
"lib/qrack/transport/frame08.rb",
|
40
|
+
"lib/qrack/transport/frame091.rb",
|
41
|
+
"spec/bunny_spec.rb",
|
42
|
+
"spec/exchange_spec.rb",
|
43
|
+
"spec/queue_spec.rb"]
|
44
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# simple_headers.rb
|
2
|
+
|
3
|
+
# Assumes that target message broker/server has a user called 'guest' with a password 'guest'
|
4
|
+
# and that it is running on 'localhost'.
|
5
|
+
|
6
|
+
# If this is not the case, please change the 'Bunny.new' call below to include
|
7
|
+
# the relevant arguments e.g. b = Bunny.new(:user => 'john', :pass => 'doe', :host => 'foobar')
|
8
|
+
|
9
|
+
$:.unshift File.dirname(__FILE__) + '/../lib'
|
10
|
+
|
11
|
+
require 'bunny'
|
12
|
+
|
13
|
+
b = Bunny.new
|
14
|
+
|
15
|
+
# start a communication session with the amqp server
|
16
|
+
b.start
|
17
|
+
|
18
|
+
# declare queues
|
19
|
+
q = b.queue('header_q1')
|
20
|
+
|
21
|
+
# create a headers exchange
|
22
|
+
header_exch = b.exchange('header_exch', :type => :headers)
|
23
|
+
|
24
|
+
# bind the queue to the exchange
|
25
|
+
q.bind(header_exch, :arguments => {'h1'=>'a','x-match'=>'all'})
|
26
|
+
|
27
|
+
# publish messages to the exchange
|
28
|
+
header_exch.publish('Headers test msg 1', :headers => {'h1'=>'a'})
|
29
|
+
header_exch.publish('Headers test msg 2', :headers => {'h1'=>'z'})
|
30
|
+
|
31
|
+
|
32
|
+
# get messages from the queue - should only be msg 1 that got through
|
33
|
+
msg = ""
|
34
|
+
until msg == :queue_empty do
|
35
|
+
msg = q.pop
|
36
|
+
puts 'This is a message from the header_q1 queue: ' + msg + "\n" unless msg == :queue_empty
|
37
|
+
end
|
38
|
+
|
39
|
+
# close the client connection
|
40
|
+
b.stop
|
data/lib/bunny.rb
CHANGED
@@ -1,26 +1,18 @@
|
|
1
1
|
$:.unshift File.expand_path(File.dirname(__FILE__))
|
2
2
|
|
3
3
|
# Ruby standard libraries
|
4
|
-
%w[socket thread timeout].each do |file|
|
4
|
+
%w[socket thread timeout logger].each do |file|
|
5
5
|
require file
|
6
6
|
end
|
7
7
|
|
8
|
-
require 'qrack/qrack'
|
9
|
-
|
10
|
-
require 'bunny/client'
|
11
|
-
require 'bunny/exchange'
|
12
|
-
require 'bunny/queue'
|
13
|
-
|
14
8
|
module Bunny
|
15
|
-
|
16
|
-
include Qrack
|
17
9
|
|
18
10
|
class ProtocolError < StandardError; end
|
19
11
|
class ServerDownError < StandardError; end
|
20
12
|
class ConnectionError < StandardError; end
|
21
13
|
class MessageError < StandardError; end
|
22
14
|
|
23
|
-
VERSION = '0.4.
|
15
|
+
VERSION = '0.4.4'
|
24
16
|
|
25
17
|
# Returns the Bunny version number
|
26
18
|
|
@@ -29,14 +21,24 @@ module Bunny
|
|
29
21
|
end
|
30
22
|
|
31
23
|
# Instantiates new Bunny::Client
|
32
|
-
|
24
|
+
|
33
25
|
def self.new(opts = {})
|
26
|
+
# Set up Bunny according to AMQP spec version required
|
27
|
+
spec_version = opts[:spec] || '08'
|
28
|
+
setup(spec_version)
|
29
|
+
|
34
30
|
Bunny::Client.new(opts)
|
35
31
|
end
|
32
|
+
|
33
|
+
# Runs a code block using a short-lived connection
|
36
34
|
|
37
35
|
def self.run(opts = {}, &block)
|
38
36
|
raise ArgumentError, 'Bunny#run requires a block' unless block
|
39
37
|
|
38
|
+
# Set up Bunny according to AMQP spec version required
|
39
|
+
spec_version = opts[:spec] || '08'
|
40
|
+
setup(spec_version)
|
41
|
+
|
40
42
|
client = Bunny::Client.new(opts)
|
41
43
|
client.start
|
42
44
|
|
@@ -48,4 +50,25 @@ module Bunny
|
|
48
50
|
:run_ok
|
49
51
|
end
|
50
52
|
|
53
|
+
private
|
54
|
+
|
55
|
+
def self.setup(version)
|
56
|
+
|
57
|
+
if version == '08'
|
58
|
+
# AMQP 0-8 specification
|
59
|
+
require 'qrack/qrack08'
|
60
|
+
require 'bunny/client08'
|
61
|
+
require 'bunny/exchange08'
|
62
|
+
require 'bunny/queue08'
|
63
|
+
else
|
64
|
+
# AMQP 0-9-1 specification
|
65
|
+
require 'qrack/qrack091'
|
66
|
+
require 'bunny/client091'
|
67
|
+
require 'bunny/exchange091'
|
68
|
+
require 'bunny/queue091'
|
69
|
+
end
|
70
|
+
|
71
|
+
include Qrack
|
72
|
+
end
|
73
|
+
|
51
74
|
end
|
@@ -0,0 +1,421 @@
|
|
1
|
+
module Bunny
|
2
|
+
|
3
|
+
=begin rdoc
|
4
|
+
|
5
|
+
=== DESCRIPTION:
|
6
|
+
|
7
|
+
The Client class provides the major Bunny API methods.
|
8
|
+
|
9
|
+
=end
|
10
|
+
|
11
|
+
class Client < Qrack::Client
|
12
|
+
CONNECT_TIMEOUT = 1.0
|
13
|
+
RETRY_DELAY = 10.0
|
14
|
+
|
15
|
+
attr_reader :status, :host, :vhost, :port, :logging, :spec
|
16
|
+
attr_accessor :channel, :logfile, :exchanges, :queues, :ticket
|
17
|
+
|
18
|
+
=begin rdoc
|
19
|
+
|
20
|
+
=== DESCRIPTION:
|
21
|
+
|
22
|
+
Sets up a Bunny::Client object ready for connection to a broker/server. _Client_._status_ is set to
|
23
|
+
<tt>:not_connected</tt>.
|
24
|
+
|
25
|
+
==== OPTIONS:
|
26
|
+
|
27
|
+
* <tt>:host => '_hostname_' (default = 'localhost')</tt>
|
28
|
+
* <tt>:port => _portno_ (default = 5672)</tt>
|
29
|
+
* <tt>:vhost => '_vhostname_' (default = '/')</tt>
|
30
|
+
* <tt>:user => '_username_' (default = 'guest')</tt>
|
31
|
+
* <tt>:pass => '_password_' (default = 'guest')</tt>
|
32
|
+
* <tt>:logfile => '_logfilepath_' (default = nil)</tt>
|
33
|
+
* <tt>:logging => true or false (_default_)</tt> - If set to _true_, session information is sent
|
34
|
+
to STDOUT if <tt>:logfile</tt> has not been specified. Otherwise, session information is written to
|
35
|
+
<tt>:logfile</tt>.
|
36
|
+
* <tt>:insist => true or false (_default_)</tt> - In a configuration with multiple load-sharing
|
37
|
+
servers, the server may respond to a Connection::Open method with a Connection::Redirect. The insist
|
38
|
+
option, if set to _true_, tells the server that the client is insisting on a connection to the
|
39
|
+
specified server.
|
40
|
+
|
41
|
+
=end
|
42
|
+
|
43
|
+
def initialize(opts = {})
|
44
|
+
@spec = opts[:spec] || '08'
|
45
|
+
@host = opts[:host] || 'localhost'
|
46
|
+
@port = opts[:port] || Qrack::Protocol::PORT
|
47
|
+
@user = opts[:user] || 'guest'
|
48
|
+
@pass = opts[:pass] || 'guest'
|
49
|
+
@vhost = opts[:vhost] || '/'
|
50
|
+
@logfile = opts[:logfile] || nil
|
51
|
+
@logging = opts[:logging] || false
|
52
|
+
@insist = opts[:insist]
|
53
|
+
@status = :not_connected
|
54
|
+
@logger = nil
|
55
|
+
create_logger if @logging
|
56
|
+
end
|
57
|
+
|
58
|
+
=begin rdoc
|
59
|
+
|
60
|
+
=== DESCRIPTION:
|
61
|
+
|
62
|
+
Declares an exchange to the broker/server. If the exchange does not exist, a new one is created
|
63
|
+
using the arguments passed in. If the exchange already exists, a reference to it is created, provided
|
64
|
+
that the arguments passed in do not conflict with the existing attributes of the exchange. If an error
|
65
|
+
occurs a _Bunny_::_ProtocolError_ is raised.
|
66
|
+
|
67
|
+
==== OPTIONS:
|
68
|
+
|
69
|
+
* <tt>:type => one of :direct (_default_), :fanout, :topic, :headers</tt>
|
70
|
+
* <tt>:passive => true or false</tt> - If set to _true_, the server will not create the exchange.
|
71
|
+
The client can use this to check whether an exchange exists without modifying the server state.
|
72
|
+
* <tt>:durable => true or false (_default_)</tt> - If set to _true_ when creating a new exchange, the exchange
|
73
|
+
will be marked as durable. Durable exchanges remain active when a server restarts. Non-durable
|
74
|
+
exchanges (transient exchanges) are purged if/when a server restarts.
|
75
|
+
* <tt>:auto_delete => true or false (_default_)</tt> - If set to _true_, the exchange is deleted
|
76
|
+
when all queues have finished using it.
|
77
|
+
* <tt>:nowait => true or false (_default_)</tt> - Ignored by Bunny, always _false_.
|
78
|
+
|
79
|
+
==== RETURNS:
|
80
|
+
|
81
|
+
Exchange
|
82
|
+
|
83
|
+
=end
|
84
|
+
|
85
|
+
def exchange(name, opts = {})
|
86
|
+
exchanges[name] ||= Bunny::Exchange.new(self, name, opts)
|
87
|
+
end
|
88
|
+
|
89
|
+
=begin rdoc
|
90
|
+
|
91
|
+
=== DESCRIPTION:
|
92
|
+
|
93
|
+
Returns hash of exchanges declared by Bunny.
|
94
|
+
|
95
|
+
=end
|
96
|
+
|
97
|
+
def exchanges
|
98
|
+
@exchanges ||= {}
|
99
|
+
end
|
100
|
+
|
101
|
+
=begin rdoc
|
102
|
+
|
103
|
+
=== DESCRIPTION:
|
104
|
+
|
105
|
+
Declares a queue to the broker/server. If the queue does not exist, a new one is created
|
106
|
+
using the arguments passed in. If the queue already exists, a reference to it is created, provided
|
107
|
+
that the arguments passed in do not conflict with the existing attributes of the queue. If an error
|
108
|
+
occurs a _Bunny_::_ProtocolError_ is raised.
|
109
|
+
|
110
|
+
==== OPTIONS:
|
111
|
+
|
112
|
+
* <tt>:passive => true or false (_default_)</tt> - If set to _true_, the server will not create
|
113
|
+
the queue. The client can use this to check whether a queue exists without modifying the server
|
114
|
+
state.
|
115
|
+
* <tt>:durable => true or false (_default_)</tt> - If set to _true_ when creating a new queue, the
|
116
|
+
queue will be marked as durable. Durable queues remain active when a server restarts. Non-durable
|
117
|
+
queues (transient queues) are purged if/when a server restarts. Note that durable queues do not
|
118
|
+
necessarily hold persistent messages, although it does not make sense to send persistent messages
|
119
|
+
to a transient queue.
|
120
|
+
* <tt>:exclusive => true or false (_default_)</tt> - If set to _true_, requests an exclusive queue.
|
121
|
+
Exclusive queues may only be consumed from by the current connection. Setting the 'exclusive'
|
122
|
+
flag always implies 'auto-delete'.
|
123
|
+
* <tt>:auto_delete => true or false (_default_)</tt> - If set to _true_, the queue is deleted
|
124
|
+
when all consumers have finished using it. Last consumer can be cancelled either explicitly
|
125
|
+
or because its channel is closed. If there has never been a consumer on the queue, it is not
|
126
|
+
deleted.
|
127
|
+
* <tt>:nowait => true or false (_default_)</tt> - Ignored by Bunny, always _false_.
|
128
|
+
|
129
|
+
==== RETURNS:
|
130
|
+
|
131
|
+
Queue
|
132
|
+
|
133
|
+
=end
|
134
|
+
|
135
|
+
def queue(name = nil, opts = {})
|
136
|
+
if name.is_a?(Hash)
|
137
|
+
opts = name
|
138
|
+
name = nil
|
139
|
+
end
|
140
|
+
|
141
|
+
return queues[name] if queues.has_key?(name)
|
142
|
+
|
143
|
+
queue = Bunny::Queue.new(self, name, opts)
|
144
|
+
queues[queue.name] = queue
|
145
|
+
end
|
146
|
+
|
147
|
+
=begin rdoc
|
148
|
+
|
149
|
+
=== DESCRIPTION:
|
150
|
+
|
151
|
+
Returns hash of queues declared by Bunny.
|
152
|
+
|
153
|
+
=end
|
154
|
+
|
155
|
+
def queues
|
156
|
+
@queues ||= {}
|
157
|
+
end
|
158
|
+
|
159
|
+
def send_frame(*args)
|
160
|
+
args.each do |data|
|
161
|
+
data.ticket = ticket if ticket and data.respond_to?(:ticket=)
|
162
|
+
data = data.to_frame(channel) unless data.is_a?(Qrack::Transport::Frame)
|
163
|
+
data.channel = channel
|
164
|
+
|
165
|
+
@logger.info("send") { data } if @logging
|
166
|
+
write(data.to_s)
|
167
|
+
end
|
168
|
+
nil
|
169
|
+
end
|
170
|
+
|
171
|
+
def next_frame
|
172
|
+
frame = Qrack::Transport::Frame.parse(buffer)
|
173
|
+
@logger.info("received") { frame } if @logging
|
174
|
+
frame
|
175
|
+
end
|
176
|
+
|
177
|
+
def next_method
|
178
|
+
next_payload
|
179
|
+
end
|
180
|
+
|
181
|
+
def next_payload
|
182
|
+
frame = next_frame
|
183
|
+
frame and frame.payload
|
184
|
+
end
|
185
|
+
|
186
|
+
=begin rdoc
|
187
|
+
|
188
|
+
=== DESCRIPTION:
|
189
|
+
|
190
|
+
Closes the current communication channel and connection. If an error occurs a
|
191
|
+
_Bunny_::_ProtocolError_ is raised. If successful, _Client_._status_ is set to <tt>:not_connected</tt>.
|
192
|
+
|
193
|
+
==== RETURNS:
|
194
|
+
|
195
|
+
<tt>:not_connected</tt> if successful.
|
196
|
+
|
197
|
+
=end
|
198
|
+
|
199
|
+
def close
|
200
|
+
send_frame(
|
201
|
+
Qrack::Protocol::Channel::Close.new(:reply_code => 200, :reply_text => 'bye', :method_id => 0, :class_id => 0)
|
202
|
+
)
|
203
|
+
raise Bunny::ProtocolError, "Error closing channel #{channel}" unless next_method.is_a?(Qrack::Protocol::Channel::CloseOk)
|
204
|
+
|
205
|
+
self.channel = 0
|
206
|
+
send_frame(
|
207
|
+
Qrack::Protocol::Connection::Close.new(:reply_code => 200, :reply_text => 'Goodbye', :class_id => 0, :method_id => 0)
|
208
|
+
)
|
209
|
+
raise Bunny::ProtocolError, "Error closing connection" unless next_method.is_a?(Qrack::Protocol::Connection::CloseOk)
|
210
|
+
|
211
|
+
close_socket
|
212
|
+
end
|
213
|
+
|
214
|
+
alias stop close
|
215
|
+
|
216
|
+
def read(*args)
|
217
|
+
send_command(:read, *args)
|
218
|
+
end
|
219
|
+
|
220
|
+
def write(*args)
|
221
|
+
send_command(:write, *args)
|
222
|
+
end
|
223
|
+
|
224
|
+
=begin rdoc
|
225
|
+
|
226
|
+
=== DESCRIPTION:
|
227
|
+
|
228
|
+
Opens a communication channel and starts a connection. If an error occurs, a
|
229
|
+
_Bunny_::_ProtocolError_ is raised. If successful, _Client_._status_ is set to <tt>:connected</tt>.
|
230
|
+
|
231
|
+
==== RETURNS:
|
232
|
+
|
233
|
+
<tt>:connected</tt> if successful.
|
234
|
+
|
235
|
+
=end
|
236
|
+
|
237
|
+
def start_session
|
238
|
+
loop do
|
239
|
+
# Create/get socket
|
240
|
+
socket
|
241
|
+
|
242
|
+
@channel = 0
|
243
|
+
write(Qrack::Protocol::HEADER)
|
244
|
+
write([1, 1, Qrack::Protocol::VERSION_MAJOR, Qrack::Protocol::VERSION_MINOR].pack('C4'))
|
245
|
+
raise Bunny::ProtocolError, 'Connection initiation failed' unless next_method.is_a?(Qrack::Protocol::Connection::Start)
|
246
|
+
|
247
|
+
send_frame(
|
248
|
+
Qrack::Protocol::Connection::StartOk.new(
|
249
|
+
{:platform => 'Ruby', :product => 'Bunny', :information => 'http://github.com/celldee/bunny', :version => VERSION},
|
250
|
+
'AMQPLAIN',
|
251
|
+
{:LOGIN => @user, :PASSWORD => @pass},
|
252
|
+
'en_US'
|
253
|
+
)
|
254
|
+
)
|
255
|
+
|
256
|
+
method = next_method
|
257
|
+
raise Bunny::ProtocolError, "Connection failed - user: #{@user}, pass: #{@pass}" if method.nil?
|
258
|
+
|
259
|
+
if method.is_a?(Qrack::Protocol::Connection::Tune)
|
260
|
+
send_frame(
|
261
|
+
Qrack::Protocol::Connection::TuneOk.new( :channel_max => 0, :frame_max => 131072, :heartbeat => 0)
|
262
|
+
)
|
263
|
+
end
|
264
|
+
|
265
|
+
send_frame(
|
266
|
+
Qrack::Protocol::Connection::Open.new(:virtual_host => @vhost, :capabilities => '', :insist => @insist)
|
267
|
+
)
|
268
|
+
|
269
|
+
case method = next_method
|
270
|
+
when Qrack::Protocol::Connection::OpenOk
|
271
|
+
break
|
272
|
+
when Qrack::Protocol::Connection::Redirect
|
273
|
+
raise Bunny::ConnectionError, "Cannot connect to the specified server - host: #{@host}, port: #{@port}" if @insist
|
274
|
+
|
275
|
+
@host, @port = method.host.split(':')
|
276
|
+
close_socket
|
277
|
+
else
|
278
|
+
raise Bunny::ProtocolError, 'Cannot open connection'
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
@channel = 1
|
283
|
+
send_frame(Qrack::Protocol::Channel::Open.new)
|
284
|
+
raise Bunny::ProtocolError, "Cannot open channel #{channel}" unless next_method.is_a?(Qrack::Protocol::Channel::OpenOk)
|
285
|
+
|
286
|
+
send_frame(
|
287
|
+
Qrack::Protocol::Access::Request.new(:realm => '/data', :read => true, :write => true, :active => true, :passive => true)
|
288
|
+
)
|
289
|
+
method = next_method
|
290
|
+
raise Bunny::ProtocolError, 'Access denied' unless method.is_a?(Qrack::Protocol::Access::RequestOk)
|
291
|
+
self.ticket = method.ticket
|
292
|
+
|
293
|
+
# return status
|
294
|
+
status
|
295
|
+
end
|
296
|
+
|
297
|
+
alias start start_session
|
298
|
+
|
299
|
+
=begin rdoc
|
300
|
+
|
301
|
+
=== DESCRIPTION:
|
302
|
+
|
303
|
+
Asks the broker to redeliver all unacknowledged messages on a specifieid channel. Zero or
|
304
|
+
more messages may be redelivered.
|
305
|
+
|
306
|
+
==== Options:
|
307
|
+
|
308
|
+
* <tt>:requeue => true or false (_default_)</tt> - If set to _false_, the message will be
|
309
|
+
redelivered to the original recipient. If set to _true_, the server will attempt to requeue
|
310
|
+
the message, potentially then delivering it to an alternative subscriber.
|
311
|
+
|
312
|
+
=end
|
313
|
+
|
314
|
+
def recover(opts = {})
|
315
|
+
|
316
|
+
send_frame(
|
317
|
+
Qrack::Protocol::Basic::Recover.new({ :requeue => false }.merge(opts))
|
318
|
+
)
|
319
|
+
|
320
|
+
end
|
321
|
+
|
322
|
+
=begin rdoc
|
323
|
+
|
324
|
+
=== DESCRIPTION:
|
325
|
+
|
326
|
+
Requests a specific quality of service. The QoS can be specified for the current channel
|
327
|
+
or for all channels on the connection. The particular properties and semantics of a QoS
|
328
|
+
method always depend on the content class semantics. Though the QoS method could in principle
|
329
|
+
apply to both peers, it is currently meaningful only for the server.
|
330
|
+
|
331
|
+
==== Options:
|
332
|
+
|
333
|
+
* <tt>:prefetch_size => size in no. of octets (default = 0)</tt> - The client can request that
|
334
|
+
messages be sent in advance so that when the client finishes processing a message, the following
|
335
|
+
message is already held locally, rather than needing to be sent down the channel. Prefetching gives
|
336
|
+
a performance improvement. This field specifies the prefetch window size in octets. The server
|
337
|
+
will send a message in advance if it is equal to or smaller in size than the available prefetch
|
338
|
+
size (and also falls into other prefetch limits). May be set to zero, meaning "no specific limit",
|
339
|
+
although other prefetch limits may still apply. The prefetch-size is ignored if the no-ack option
|
340
|
+
is set.
|
341
|
+
* <tt>:prefetch_count => no. messages (default = 1)</tt> - Specifies a prefetch window in terms
|
342
|
+
of whole messages. This field may be used in combination with the prefetch-size field; a message
|
343
|
+
will only be sent in advance if both prefetch windows (and those at the channel and connection level)
|
344
|
+
allow it. The prefetch-count is ignored if the no-ack option is set.
|
345
|
+
* <tt>:global => true or false (_default_)</tt> - By default the QoS settings apply to the current channel only. If set to
|
346
|
+
true, they are applied to the entire connection.
|
347
|
+
|
348
|
+
=end
|
349
|
+
|
350
|
+
def qos(opts = {})
|
351
|
+
|
352
|
+
send_frame(
|
353
|
+
Qrack::Protocol::Basic::Qos.new({ :prefetch_size => 0, :prefetch_count => 1, :global => false }.merge(opts))
|
354
|
+
)
|
355
|
+
|
356
|
+
raise Bunny::ProtocolError,
|
357
|
+
"Error specifying Quality of Service" unless
|
358
|
+
next_method.is_a?(Qrack::Protocol::Basic::QosOk)
|
359
|
+
|
360
|
+
# return confirmation
|
361
|
+
:qos_ok
|
362
|
+
end
|
363
|
+
|
364
|
+
def logging=(bool)
|
365
|
+
@logging = bool
|
366
|
+
create_logger if @logging
|
367
|
+
end
|
368
|
+
|
369
|
+
private
|
370
|
+
|
371
|
+
def buffer
|
372
|
+
@buffer ||= Qrack::Transport::Buffer.new(self)
|
373
|
+
end
|
374
|
+
|
375
|
+
def send_command(cmd, *args)
|
376
|
+
begin
|
377
|
+
raise Bunny::ConnectionError, 'No connection - socket has not been created' if !@socket
|
378
|
+
@socket.__send__(cmd, *args)
|
379
|
+
rescue Errno::EPIPE, IOError => e
|
380
|
+
raise Bunny::ServerDownError, e.message
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
def socket
|
385
|
+
return @socket if @socket and (@status == :connected) and not @socket.closed?
|
386
|
+
|
387
|
+
begin
|
388
|
+
@status = :not_connected
|
389
|
+
|
390
|
+
# Attempt to connect.
|
391
|
+
@socket = timeout(CONNECT_TIMEOUT) do
|
392
|
+
TCPSocket.new(host, port)
|
393
|
+
end
|
394
|
+
|
395
|
+
if Socket.constants.include? 'TCP_NODELAY'
|
396
|
+
@socket.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1
|
397
|
+
end
|
398
|
+
@status = :connected
|
399
|
+
rescue => e
|
400
|
+
@status = :not_connected
|
401
|
+
raise Bunny::ServerDownError, e.message
|
402
|
+
end
|
403
|
+
|
404
|
+
@socket
|
405
|
+
end
|
406
|
+
|
407
|
+
def close_socket(reason=nil)
|
408
|
+
# Close the socket. The server is not considered dead.
|
409
|
+
@socket.close if @socket and not @socket.closed?
|
410
|
+
@socket = nil
|
411
|
+
@status = :not_connected
|
412
|
+
end
|
413
|
+
|
414
|
+
def create_logger
|
415
|
+
@logfile ? @logger = Logger.new("#{logfile}") : @logger = Logger.new(STDOUT)
|
416
|
+
@logger.level = Logger::INFO
|
417
|
+
@logger.datetime_format = "%Y-%m-%d %H:%M:%S"
|
418
|
+
end
|
419
|
+
|
420
|
+
end
|
421
|
+
end
|