bunny 0.7.12 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/.gitignore +2 -2
  2. data/.travis.yml +7 -16
  3. data/CHANGELOG +3 -21
  4. data/Gemfile +2 -4
  5. data/README.textile +31 -9
  6. data/Rakefile +3 -3
  7. data/bunny.gemspec +6 -3
  8. data/examples/{simple_08.rb → simple.rb} +1 -1
  9. data/examples/{simple_ack_08.rb → simple_ack.rb} +1 -1
  10. data/examples/{simple_consumer_08.rb → simple_consumer.rb} +4 -4
  11. data/examples/{simple_fanout_08.rb → simple_fanout.rb} +1 -1
  12. data/examples/{simple_headers_08.rb → simple_headers.rb} +2 -2
  13. data/examples/{simple_publisher_09.rb → simple_publisher.rb} +1 -1
  14. data/examples/{simple_topic_09.rb → simple_topic.rb} +2 -2
  15. data/ext/amqp-0.9.1.json +1 -0
  16. data/ext/config.yml +3 -3
  17. data/ext/qparser.rb +9 -52
  18. data/lib/bunny.rb +15 -33
  19. data/lib/bunny/{channel08.rb → channel.rb} +0 -0
  20. data/lib/bunny/{client09.rb → client.rb} +34 -46
  21. data/lib/bunny/{exchange09.rb → exchange.rb} +16 -15
  22. data/lib/bunny/{queue09.rb → queue.rb} +26 -23
  23. data/lib/bunny/{subscription09.rb → subscription.rb} +11 -6
  24. data/lib/bunny/version.rb +1 -1
  25. data/lib/qrack/client.rb +30 -21
  26. data/lib/qrack/protocol/{protocol08.rb → protocol.rb} +2 -1
  27. data/lib/qrack/protocol/{spec09.rb → spec.rb} +8 -7
  28. data/lib/qrack/{qrack08.rb → qrack.rb} +4 -4
  29. data/lib/qrack/subscription.rb +58 -9
  30. data/lib/qrack/transport/{buffer08.rb → buffer.rb} +8 -0
  31. data/lib/qrack/transport/{frame08.rb → frame.rb} +7 -22
  32. data/spec/spec_09/bunny_spec.rb +10 -8
  33. data/spec/spec_09/connection_spec.rb +8 -3
  34. data/spec/spec_09/exchange_spec.rb +22 -19
  35. data/spec/spec_09/queue_spec.rb +32 -18
  36. metadata +69 -76
  37. checksums.yaml +0 -7
  38. data/examples/simple_09.rb +0 -32
  39. data/examples/simple_ack_09.rb +0 -35
  40. data/examples/simple_consumer_09.rb +0 -55
  41. data/examples/simple_fanout_09.rb +0 -41
  42. data/examples/simple_headers_09.rb +0 -42
  43. data/examples/simple_publisher_08.rb +0 -29
  44. data/examples/simple_topic_08.rb +0 -61
  45. data/ext/amqp-0.8.json +0 -616
  46. data/lib/bunny/channel09.rb +0 -39
  47. data/lib/bunny/client08.rb +0 -480
  48. data/lib/bunny/exchange08.rb +0 -177
  49. data/lib/bunny/queue08.rb +0 -403
  50. data/lib/bunny/subscription08.rb +0 -87
  51. data/lib/qrack/protocol/protocol09.rb +0 -135
  52. data/lib/qrack/protocol/spec08.rb +0 -828
  53. data/lib/qrack/qrack09.rb +0 -20
  54. data/lib/qrack/transport/buffer09.rb +0 -305
  55. data/lib/qrack/transport/frame09.rb +0 -97
  56. data/spec/spec_08/bunny_spec.rb +0 -75
  57. data/spec/spec_08/connection_spec.rb +0 -24
  58. data/spec/spec_08/exchange_spec.rb +0 -170
  59. data/spec/spec_08/queue_spec.rb +0 -239
@@ -1,39 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Bunny
4
- class Channel09 < Qrack::Channel
5
-
6
- def initialize(client)
7
- super
8
- end
9
-
10
- def open
11
- client.channel = self
12
- client.send_frame(Qrack::Protocol09::Channel::Open.new)
13
-
14
- method = client.next_method
15
-
16
- client.check_response(method, Qrack::Protocol09::Channel::OpenOk, "Cannot open channel #{number}")
17
-
18
- @active = true
19
- :open_ok
20
- end
21
-
22
- def close
23
- client.channel = self
24
- client.send_frame(Qrack::Protocol09::Channel::Close.new(:reply_code => 200, :reply_text => 'bye', :method_id => 0, :class_id => 0))
25
-
26
- method = client.next_method
27
-
28
- client.check_response(method, Qrack::Protocol09::Channel::CloseOk, "Error closing channel #{number}")
29
-
30
- @active = false
31
- :close_ok
32
- end
33
-
34
- def open?
35
- active
36
- end
37
-
38
- end
39
- end
@@ -1,480 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Bunny
4
-
5
- =begin rdoc
6
-
7
- === DESCRIPTION:
8
-
9
- The Client class provides the major Bunny API methods.
10
-
11
- =end
12
-
13
- class Client < Qrack::Client
14
-
15
- attr_accessor :ticket
16
-
17
- =begin rdoc
18
-
19
- === DESCRIPTION:
20
-
21
- Sets up a Bunny::Client object ready for connection to a broker/server. _Client_._status_ is set to
22
- <tt>:not_connected</tt>.
23
-
24
- ==== OPTIONS:
25
-
26
- * <tt>:host => '_hostname_' (default = 'localhost')</tt>
27
- * <tt>:port => _portno_ (default = 5672 or 5671 if :ssl set to true)</tt>
28
- * <tt>:vhost => '_vhostname_' (default = '/')</tt>
29
- * <tt>:user => '_username_' (default = 'guest')</tt>
30
- * <tt>:pass => '_password_' (default = 'guest')</tt>
31
- * <tt>:ssl => true or false (default = false)</tt> - If set to _true_, ssl
32
- encryption will be used and port will default to 5671.
33
- * <tt>:verify_ssl => true or false (default = true)</tt> - If ssl is enabled,
34
- this will cause OpenSSL to validate the server certificate unless this
35
- parameter is set to _false_.
36
- * <tt>:logfile => '_logfilepath_' (default = nil)</tt>
37
- * <tt>:logging => true or false (_default_)</tt> - If set to _true_, session information is sent
38
- to STDOUT if <tt>:logfile</tt> has not been specified. Otherwise, session information is written to
39
- <tt>:logfile</tt>.
40
- * <tt>:insist => true or false (_default_)</tt> - In a configuration with multiple load-sharing
41
- servers, the server may respond to a Connection::Open method with a Connection::Redirect. The insist
42
- option, if set to _true_, tells the server that the client is insisting on a connection to the
43
- specified server.
44
- * <tt>:frame_max => maximum frame size in bytes (default = 131072)</tt>
45
- * <tt>:channel_max => maximum number of channels (default = 0 no maximum)</tt>
46
- * <tt>:heartbeat => number of seconds (default = 0 no heartbeat)</tt>
47
- * <tt>:connect_timeout => number of seconds before Qrack::ConnectionTimeout is raised (default = 5)</tt>
48
-
49
- =end
50
-
51
- def initialize(connection_string_or_opts = Hash.new, opts = Hash.new)
52
- super
53
- @spec = '0-8'
54
- @port = self.__opts__[:port] || (self.__opts__[:ssl] ? Qrack::Protocol::SSL_PORT : Qrack::Protocol::PORT)
55
- @insist = self.__opts__[:insist]
56
- end
57
-
58
- =begin rdoc
59
-
60
- === DESCRIPTION:
61
-
62
- Checks response from AMQP methods and takes appropriate action
63
-
64
- =end
65
-
66
- def check_response(received_method, expected_method, err_msg, err_class = Bunny::ProtocolError)
67
- case
68
- when received_method.is_a?(Qrack::Protocol::Connection::Close)
69
- # Clean up the socket
70
- close_socket
71
-
72
- raise Bunny::ForcedConnectionCloseError, "Error Reply Code: #{received_method.reply_code}\nError Reply Text: #{received_method.reply_text}"
73
-
74
- when received_method.is_a?(Qrack::Protocol::Channel::Close)
75
- # Clean up the channel
76
- channel.active = false
77
-
78
- raise Bunny::ForcedChannelCloseError, "Error Reply Code: #{received_method.reply_code}\nError Reply Text: #{received_method.reply_text}"
79
-
80
- when !received_method.is_a?(expected_method)
81
- raise err_class, err_msg
82
-
83
- else
84
- :response_ok
85
- end
86
- end
87
-
88
- def close_connection
89
- # Set client channel to zero
90
- switch_channel(0)
91
-
92
- send_frame(Qrack::Protocol::Connection::Close.new(:reply_code => 200, :reply_text => 'Goodbye', :class_id => 0, :method_id => 0))
93
-
94
- method = next_method
95
-
96
- check_response(method, Qrack::Protocol::Connection::CloseOk, "Error closing connection")
97
- end
98
-
99
- def create_channel
100
- channels.each do |c|
101
- return c if (!c.open? and c.number != 0)
102
- end
103
- # If no channel to re-use instantiate new one
104
- Bunny::Channel.new(self)
105
- end
106
-
107
- =begin rdoc
108
-
109
- === DESCRIPTION:
110
-
111
- Declares an exchange to the broker/server. If the exchange does not exist, a new one is created
112
- using the arguments passed in. If the exchange already exists, the existing object is returned.
113
- If an error occurs a _Bunny_::_ProtocolError_ is raised.
114
-
115
- ==== OPTIONS:
116
-
117
- * <tt>:type => one of :direct (_default_), :fanout, :topic, :headers</tt>
118
- * <tt>:passive => true or false</tt> - If set to _true_, the server will not create the exchange.
119
- The client can use this to check whether an exchange exists without modifying the server state.
120
- * <tt>:durable => true or false (_default_)</tt> - If set to _true_ when creating a new exchange, the exchange
121
- will be marked as durable. Durable exchanges remain active when a server restarts. Non-durable
122
- exchanges (transient exchanges) are purged if/when a server restarts.
123
- * <tt>:auto_delete => true or false (_default_)</tt> - If set to _true_, the exchange is deleted
124
- when all queues have finished using it.
125
- * <tt>:nowait => true or false (_default_)</tt> - Ignored by Bunny, always _false_.
126
-
127
- ==== RETURNS:
128
-
129
- Exchange
130
-
131
- =end
132
-
133
- def exchange(name, opts = {})
134
- exchanges[name] || Bunny::Exchange.new(self, name, opts)
135
- end
136
-
137
- def init_connection
138
- write(Qrack::Protocol::HEADER)
139
- write([1, 1, Qrack::Protocol::VERSION_MAJOR, Qrack::Protocol::VERSION_MINOR].pack('C4'))
140
-
141
- frame = next_frame
142
- if frame.nil? or !frame.payload.is_a?(Qrack::Protocol::Connection::Start)
143
- raise Bunny::ProtocolError, 'Connection initiation failed'
144
- end
145
- end
146
-
147
- def next_frame(opts = {})
148
- frame = nil
149
-
150
- case
151
- when channel.frame_buffer.size > 0
152
- frame = channel.frame_buffer.shift
153
- when (timeout = opts[:timeout]) && timeout > 0
154
- Bunny::Timer::timeout(timeout, Qrack::FrameTimeout) do
155
- frame = Qrack::Transport::Frame.parse(buffer)
156
- end
157
- else
158
- frame = Qrack::Transport::Frame.parse(buffer)
159
- end
160
-
161
- @logger.info("received") { frame } if @logging
162
-
163
- raise Bunny::ConnectionError, 'No connection to server' if (frame.nil? and !connecting?)
164
-
165
- # Monitor server activity and discard heartbeats
166
- @message_in = true
167
-
168
- case
169
- when frame.is_a?(Qrack::Transport::Heartbeat)
170
- next_frame(opts)
171
- when frame.nil?
172
- frame
173
- when ((frame.channel != channel.number) and (frame.channel != 0))
174
- channel.frame_buffer << frame
175
- next_frame(opts)
176
- else
177
- frame
178
- end
179
- end
180
-
181
- def open_connection
182
- client_opts = { :platform => 'Ruby', :product => 'Bunny', :information => 'http://github.com/ruby-amqp/bunny', :version => VERSION }
183
-
184
- send_frame(Qrack::Protocol::Connection::StartOk.new(client_opts, 'AMQPLAIN', {:LOGIN => @user, :PASSWORD => @pass}, 'en_US'))
185
-
186
- frame = next_frame
187
- raise Bunny::ProtocolError, "Connection failed - user: #{@user}" if frame.nil?
188
-
189
- method = frame.payload
190
-
191
- if method.is_a?(Qrack::Protocol::Connection::Tune)
192
- @frame_max = method.frame_max if method.frame_max > 0 && method.frame_max < @frame_max
193
- @channel_max = method.channel_max if method.channel_max > 0 && method.channel_max < @channel_max
194
- send_frame(Qrack::Protocol::Connection::TuneOk.new( :channel_max => @channel_max, :frame_max => @frame_max, :heartbeat => @heartbeat))
195
- end
196
-
197
- send_frame(Qrack::Protocol::Connection::Open.new(:virtual_host => @vhost, :capabilities => '', :insist => @insist))
198
-
199
- case method = next_method
200
- when Qrack::Protocol::Connection::OpenOk
201
- :ok
202
- when Qrack::Protocol::Connection::Redirect
203
- raise Bunny::ConnectionError, "Cannot connect to the specified server - host: #{@host}, port: #{@port}" if @insist
204
-
205
- @host, @port = method.host.split(':')
206
- close_socket
207
- else
208
- raise Bunny::ProtocolError, 'Cannot open connection'
209
- end
210
- end
211
-
212
- =begin rdoc
213
-
214
- === DESCRIPTION:
215
-
216
- Requests a specific quality of service. The QoS can be specified for the current channel
217
- or for all channels on the connection. The particular properties and semantics of a QoS
218
- method always depend on the content class semantics. Though the QoS method could in principle
219
- apply to both peers, it is currently meaningful only for the server.
220
-
221
- ==== Options:
222
-
223
- * <tt>:prefetch_size => size in no. of octets (default = 0)</tt> - The client can request that
224
- messages be sent in advance so that when the client finishes processing a message, the following
225
- message is already held locally, rather than needing to be sent down the channel. Prefetching gives
226
- a performance improvement. This field specifies the prefetch window size in octets. The server
227
- will send a message in advance if it is equal to or smaller in size than the available prefetch
228
- size (and also falls into other prefetch limits). May be set to zero, meaning "no specific limit",
229
- although other prefetch limits may still apply. The prefetch-size is ignored if the no-ack option
230
- is set.
231
- * <tt>:prefetch_count => no. messages (default = 1)</tt> - Specifies a prefetch window in terms
232
- of whole messages. This field may be used in combination with the prefetch-size field; a message
233
- will only be sent in advance if both prefetch windows (and those at the channel and connection level)
234
- allow it. The prefetch-count is ignored if the no-ack option is set.
235
- * <tt>:global => true or false (_default_)</tt> - By default the QoS settings apply to the current channel only. If set to
236
- true, they are applied to the entire connection.
237
-
238
- ==== RETURNS:
239
-
240
- <tt>:qos_ok</tt> if successful.
241
-
242
- =end
243
-
244
- def qos(opts = {})
245
- send_frame(Qrack::Protocol::Basic::Qos.new({ :prefetch_size => 0, :prefetch_count => 1, :global => false }.merge(opts)))
246
-
247
- method = next_method
248
-
249
- check_response(method, Qrack::Protocol::Basic::QosOk, "Error specifying Quality of Service")
250
-
251
- # return confirmation
252
- :qos_ok
253
- end
254
-
255
- =begin rdoc
256
-
257
- === DESCRIPTION:
258
-
259
- Declares a queue to the broker/server. If the queue does not exist, a new one is created
260
- using the arguments passed in. If the queue already exists, a reference to it is created, provided
261
- that the arguments passed in do not conflict with the existing attributes of the queue. If an error
262
- occurs a _Bunny_::_ProtocolError_ is raised.
263
-
264
- ==== OPTIONS:
265
-
266
- * <tt>:passive => true or false (_default_)</tt> - If set to _true_, the server will not create
267
- the queue. The client can use this to check whether a queue exists without modifying the server
268
- state.
269
- * <tt>:durable => true or false (_default_)</tt> - If set to _true_ when creating a new queue, the
270
- queue will be marked as durable. Durable queues remain active when a server restarts. Non-durable
271
- queues (transient queues) are purged if/when a server restarts. Note that durable queues do not
272
- necessarily hold persistent messages, although it does not make sense to send persistent messages
273
- to a transient queue.
274
- * <tt>:exclusive => true or false (_default_)</tt> - If set to _true_, requests an exclusive queue.
275
- Exclusive queues may only be consumed from by the current connection. Setting the 'exclusive'
276
- flag always implies 'auto-delete'.
277
- * <tt>:auto_delete => true or false (_default_)</tt> - If set to _true_, the queue is deleted
278
- when all consumers have finished using it. Last consumer can be cancelled either explicitly
279
- or because its channel is closed. If there has never been a consumer on the queue, it is not
280
- deleted.
281
- * <tt>:nowait => true or false (_default_)</tt> - Ignored by Bunny, always _false_.
282
-
283
- ==== RETURNS:
284
-
285
- Queue
286
-
287
- =end
288
-
289
- def queue(name = nil, opts = {})
290
- if name.is_a?(Hash)
291
- opts = name
292
- name = nil
293
- end
294
-
295
- # Queue is responsible for placing itself in the list of queues
296
- queues[name] || Bunny::Queue.new(self, name, opts)
297
- end
298
-
299
- =begin rdoc
300
-
301
- === DESCRIPTION:
302
-
303
- Asks the broker to redeliver all unacknowledged messages on a specified 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
- send_frame(Qrack::Protocol::Basic::Recover.new({ :requeue => false }.merge(opts)))
316
- end
317
-
318
- def request_access
319
- send_frame(Qrack::Protocol::Access::Request.new(:realm => '/data', :read => true, :write => true, :active => true, :passive => true))
320
-
321
- method = next_method
322
-
323
- check_response(method, Qrack::Protocol::Access::RequestOk, "Access denied")
324
-
325
- self.ticket = method.ticket
326
- end
327
-
328
- def send_frame(*args)
329
- args.each do |data|
330
- data.ticket = ticket if ticket and data.respond_to?(:ticket=)
331
- data = data.to_frame(channel.number) unless data.is_a?(Qrack::Transport::Frame)
332
- data.channel = channel.number
333
-
334
- @logger.info("send") { data } if @logging
335
- write(data.to_s)
336
-
337
- # Monitor client activity for heartbeat purposes
338
- @message_out = true
339
- end
340
-
341
- nil
342
- end
343
-
344
- def send_heartbeat
345
- # Create a new heartbeat frame
346
- hb = Qrack::Transport::Heartbeat.new('')
347
- # Channel 0 must be used
348
- switch_channel(0) if @channel.number > 0
349
- # Send the heartbeat to server
350
- send_frame(hb)
351
- end
352
-
353
- =begin rdoc
354
-
355
- === DESCRIPTION:
356
-
357
- Opens a communication channel and starts a connection. If an error occurs, a
358
- _Bunny_::_ProtocolError_ is raised. If successful, _Client_._status_ is set to <tt>:connected</tt>.
359
-
360
- ==== RETURNS:
361
-
362
- <tt>:connected</tt> if successful.
363
-
364
- =end
365
-
366
- def start_session
367
- @connecting = true
368
-
369
- loop do
370
- # Create/get socket
371
- socket
372
-
373
- # Initiate connection
374
- init_connection
375
-
376
- # Open connection
377
- break if open_connection == :ok
378
- end
379
-
380
- # Open another channel because channel zero is used for specific purposes
381
- c = create_channel()
382
- c.open
383
-
384
- # Get access ticket
385
- request_access
386
-
387
- @connecting = false
388
-
389
- # return status
390
- @status = :connected
391
- end
392
-
393
- alias start start_session
394
-
395
- =begin rdoc
396
-
397
- === DESCRIPTION:
398
- This method commits all messages published and acknowledged in
399
- the current transaction. A new transaction starts immediately
400
- after a commit.
401
-
402
- ==== RETURNS:
403
-
404
- <tt>:commit_ok</tt> if successful.
405
-
406
- =end
407
-
408
- def tx_commit
409
- send_frame(Qrack::Protocol::Tx::Commit.new())
410
-
411
- method = next_method
412
-
413
- check_response(method, Qrack::Protocol::Tx::CommitOk, "Error commiting transaction")
414
-
415
- # return confirmation
416
- :commit_ok
417
- end
418
-
419
- =begin rdoc
420
-
421
- === DESCRIPTION:
422
- This method abandons all messages published and acknowledged in
423
- the current transaction. A new transaction starts immediately
424
- after a rollback.
425
-
426
- ==== RETURNS:
427
-
428
- <tt>:rollback_ok</tt> if successful.
429
-
430
- =end
431
-
432
- def tx_rollback
433
- send_frame(Qrack::Protocol::Tx::Rollback.new())
434
-
435
- method = next_method
436
-
437
- check_response(method, Qrack::Protocol::Tx::RollbackOk, "Error rolling back transaction")
438
-
439
- # return confirmation
440
- :rollback_ok
441
- end
442
-
443
- =begin rdoc
444
-
445
- === DESCRIPTION:
446
- This method sets the channel to use standard transactions. The
447
- client must use this method at least once on a channel before
448
- using the Commit or Rollback methods.
449
-
450
- ==== RETURNS:
451
-
452
- <tt>:select_ok</tt> if successful.
453
-
454
- =end
455
-
456
- def tx_select
457
- send_frame(Qrack::Protocol::Tx::Select.new())
458
-
459
- method = next_method
460
-
461
- check_response(method, Qrack::Protocol::Tx::SelectOk, "Error initiating transactions for current channel")
462
-
463
- # return confirmation
464
- :select_ok
465
- end
466
-
467
- protected
468
-
469
- def check_returned_message(method)
470
- check_response(method, Qrack::Protocol::Basic::Return, "Expected a returned message")
471
- end
472
-
473
- private
474
-
475
- def buffer
476
- @buffer ||= Qrack::Transport::Buffer.new(self)
477
- end
478
-
479
- end
480
- end