amqp 0.7.0.pre → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/.gitignore +4 -0
  2. data/.rspec +2 -0
  3. data/CHANGELOG +8 -2
  4. data/CONTRIBUTORS +22 -0
  5. data/Gemfile +3 -3
  6. data/README.md +20 -11
  7. data/Rakefile +30 -6
  8. data/amqp.gemspec +1 -1
  9. data/bin/cleanify.rb +50 -0
  10. data/examples/amqp/simple.rb +6 -4
  11. data/examples/mq/ack.rb +8 -6
  12. data/examples/mq/automatic_binding_for_default_direct_exchange.rb +65 -0
  13. data/examples/mq/callbacks.rb +9 -1
  14. data/examples/mq/clock.rb +17 -17
  15. data/examples/mq/hashtable.rb +19 -10
  16. data/examples/mq/internal.rb +13 -11
  17. data/examples/mq/logger.rb +38 -36
  18. data/examples/mq/multiclock.rb +16 -7
  19. data/examples/mq/pingpong.rb +16 -7
  20. data/examples/mq/pop.rb +8 -6
  21. data/examples/mq/primes-simple.rb +2 -0
  22. data/examples/mq/primes.rb +7 -5
  23. data/examples/mq/stocks.rb +14 -5
  24. data/lib/amqp.rb +12 -8
  25. data/lib/amqp/buffer.rb +35 -158
  26. data/lib/amqp/client.rb +34 -22
  27. data/lib/amqp/frame.rb +8 -64
  28. data/lib/amqp/protocol.rb +21 -70
  29. data/lib/amqp/server.rb +11 -9
  30. data/lib/amqp/spec.rb +8 -6
  31. data/lib/amqp/version.rb +2 -0
  32. data/lib/ext/blankslate.rb +3 -1
  33. data/lib/ext/em.rb +2 -0
  34. data/lib/ext/emfork.rb +13 -11
  35. data/lib/mq.rb +253 -156
  36. data/lib/mq/collection.rb +6 -88
  37. data/lib/mq/exchange.rb +70 -13
  38. data/lib/mq/header.rb +12 -6
  39. data/lib/mq/logger.rb +9 -7
  40. data/lib/mq/queue.rb +42 -30
  41. data/lib/mq/rpc.rb +6 -4
  42. data/protocol/codegen.rb +20 -18
  43. data/research/api.rb +10 -46
  44. data/research/primes-forked.rb +9 -7
  45. data/research/primes-processes.rb +74 -72
  46. data/research/primes-threaded.rb +9 -7
  47. data/spec/integration/automatic_binding_for_default_direct_exchange_spec.rb +61 -0
  48. data/spec/mq_helper.rb +70 -0
  49. data/spec/spec_helper.rb +84 -29
  50. data/spec/unit/amqp/buffer_spec.rb +178 -0
  51. data/spec/unit/amqp/client_spec.rb +472 -0
  52. data/spec/unit/amqp/frame_spec.rb +60 -0
  53. data/spec/unit/amqp/misc_spec.rb +123 -0
  54. data/spec/unit/amqp/protocol_spec.rb +53 -0
  55. data/spec/unit/mq/channel_close_spec.rb +15 -0
  56. data/spec/unit/mq/collection_spec.rb +129 -0
  57. data/spec/unit/mq/exchange_declaration_spec.rb +524 -0
  58. data/spec/unit/mq/misc_spec.rb +228 -0
  59. data/spec/unit/mq/mq_basic_spec.rb +39 -0
  60. data/spec/unit/mq/queue_declaration_spec.rb +97 -0
  61. data/spec/unit/mq/queue_spec.rb +71 -0
  62. metadata +33 -21
  63. data/Gemfile.lock +0 -16
  64. data/old/README +0 -30
  65. data/old/Rakefile +0 -12
  66. data/old/amqp-0.8.json +0 -606
  67. data/old/amqp_spec.rb +0 -796
  68. data/old/amqpc.rb +0 -695
  69. data/old/codegen.rb +0 -148
  70. data/spec/channel_close_spec.rb +0 -13
  71. data/spec/sync_async_spec.rb +0 -52
@@ -1,695 +0,0 @@
1
- require 'enumerator'
2
-
3
- require 'rubygems'
4
- require 'eventmachine'
5
-
6
- require 'amqp_spec'
7
-
8
- module AMQP
9
- class BufferOverflow < StandardError; end
10
- class InvalidFrame < StandardError; end
11
-
12
- module Protocol
13
- class Class::Method
14
- def initialize *args
15
- opts = args.pop if args.size == 1 and args.last.is_a? Hash
16
- opts ||= {}
17
-
18
- # XXX hack, p(obj) == '' if no instance vars are set
19
- @debug = 1
20
-
21
- if args.size == 1 and args.first.is_a? Buffer
22
- buf = args.first
23
- else
24
- buf = nil
25
- end
26
-
27
- self.class.arguments.each do |type, name|
28
- if buf
29
- val = buf.parse(type)
30
- else
31
- val = args.shift || opts[name] || opts[name.to_s]
32
- end
33
-
34
- instance_variable_set("@#{name}", val)
35
- end
36
- end
37
-
38
- def convert_bits
39
- if @bits.size > 0
40
- data = @bits.to_enum(:each_slice, 8).inject(''){|octet, list|
41
- octet + pack(:octet,
42
- list.enum_with_index.inject(0){ |byte, (bit, i)|
43
- byte |= 1<<i if bit
44
- byte
45
- }
46
- )
47
- }
48
- @bits = []
49
- end
50
-
51
- data || ''
52
- end
53
-
54
- def to_binary
55
- @bits = []
56
-
57
- pack(:short, self.class.parent.id) +
58
- pack(:short, self.class.id) +
59
- self.class.arguments.inject(''){ |data, (type, name)|
60
- if type == :bit
61
- @bits << (instance_variable_get("@#{name}") || false)
62
- data
63
- else
64
- data + convert_bits + pack(type, instance_variable_get("@#{name}"))
65
- end
66
- } + convert_bits
67
- end
68
- alias :to_s :to_binary
69
-
70
- def to_frame channel = 0
71
- Frame.new(:METHOD, channel, self)
72
- end
73
-
74
- private
75
-
76
- def pack type, data
77
- # p ['pack', type, data]
78
-
79
- case type
80
- when :octet
81
- [data].pack('C')
82
- when :short
83
- [data].pack('n')
84
- when :long
85
- [data].pack('N')
86
- when :shortstr
87
- data ||= ''
88
- len = data.length
89
- [len, data].pack("Ca#{len}")
90
- when :longstr
91
- if data.is_a? Hash
92
- pack(:table, data)
93
- else
94
- len = data.length
95
- [len, data].pack("Na#{len}")
96
- end
97
- when :table
98
- data ||= {}
99
- pack :longstr, (data.inject('') do |str, (key, value)|
100
- str +
101
- pack(:shortstr, key.to_s) +
102
- pack(:octet, ?S) +
103
- pack(:longstr, value.to_s) # XXX support other field types here
104
- end)
105
- when :longlong
106
- lower = l & 0xffffffff
107
- upper = (l & ~0xffffffff) >> 32
108
- pack(:long, upper) + pack(:long, lower)
109
- when :bit
110
- data = if data.nil? or data == false or data == 0
111
- 0
112
- else
113
- 1
114
- end
115
- pack(:octet, data)
116
- end
117
- end
118
- end
119
-
120
- def self.parse payload
121
- buf = Buffer.new(payload)
122
- class_id, method_id = buf.parse(:short, :short)
123
- classes[class_id].methods[method_id].new(buf)
124
- end
125
- end
126
-
127
- class Frame
128
- def initialize type, channel, payload
129
- @channel = channel
130
- @type = (1..8).include?(type) ? TYPES[type] :
131
- TYPES.include?(type) ? type : raise(InvalidFrame)
132
-
133
- if @type == :METHOD and payload.is_a? String
134
- @payload = Protocol.parse(payload)
135
- else
136
- @payload = payload
137
- end
138
- end
139
- attr_reader :type, :channel, :payload
140
-
141
- def to_binary
142
- data = payload.to_s
143
- size = data.length
144
- # XXX the spec falsely claims there is another empty 'cycle' octet in this header
145
- [TYPES.index(type), channel, size, data, FOOTER].pack("CnNa*C")
146
- end
147
- alias :to_s :to_binary
148
-
149
- def == b
150
- [ :type, :channel, :payload ].inject(true){|eql, field| eql and __send__(field) == b.__send__(field) }
151
- end
152
-
153
- def self.extract data
154
- (@buffer ||= Buffer.new).extract(data.to_s)
155
- end
156
- end
157
-
158
- class Buffer
159
- def initialize data = ''
160
- @data = data
161
- @pos = 0
162
- end
163
- attr_reader :pos
164
-
165
- def extract data = nil
166
- @data << data if data
167
-
168
- processed = 0
169
- frames = []
170
-
171
- while true
172
- type, channel, size = parse(:octet, :short, :long)
173
- payload = read(size)
174
- if read(1) == Frame::FOOTER.chr
175
- frames << Frame.new(type, channel, payload)
176
- else
177
- raise InvalidFrame
178
- end
179
- processed = @pos
180
- end
181
- rescue BufferOverflow
182
- # log 'buffer overflow', @pos, processed
183
- @data[0..processed] = '' if processed > 0
184
- @pos = 0
185
- frames
186
- end
187
-
188
- def parse *syms
189
- res = syms.map do |sym|
190
- # log 'parsing', sym
191
- case sym
192
- when :octet
193
- read(1, 'C')
194
- when :short
195
- read(2, 'n')
196
- when :long
197
- read(4, 'N')
198
- when :longlong
199
- # FIXME
200
- when :shortstr
201
- len = parse(:octet)
202
- read(len)
203
- when :longstr
204
- len = parse(:long)
205
- read(len)
206
- when :timestamp
207
- parse(:longlong)
208
- when :bit
209
- # FIXME
210
- when :table
211
- t = Hash.new
212
-
213
- table = Buffer.new(parse(:longstr))
214
- until table.eof?
215
- key, type = table.parse(:shortstr, :octet)
216
- t[key] = case type
217
- when ?S
218
- table.parse(:longstr)
219
- when ?I
220
- table.parse(:long)
221
- when ?D
222
- d = table.parse(:octet)
223
- table.parse(:long) / (10**d)
224
- when ?T
225
- table.parse(:timestamp)
226
- when ?F
227
- table.parse(:table)
228
- end
229
- end
230
-
231
- t
232
- else
233
- # FIXME remove
234
- end
235
- end
236
-
237
- syms.length == 1 ? res[0] : res
238
- end
239
-
240
- def read len, type = nil
241
- # log 'reading', len, type, :pos => @pos
242
- raise BufferOverflow if @pos+len > @data.length
243
-
244
- d = @data.slice(@pos, len)
245
- @pos += len
246
- d = d.unpack(type).pop if type
247
- # log 'read', d
248
- d
249
- end
250
-
251
- def eof?
252
- @pos == @data.length
253
- end
254
-
255
- private
256
-
257
- def log *args
258
- p args
259
- end
260
- end
261
-
262
- module Connection
263
- def initialize blk
264
- @blk = blk
265
- end
266
-
267
- def connection_completed
268
- log 'connected'
269
- send_data HEADER
270
- send_data [1, 1, VERSION_MAJOR, VERSION_MINOR].pack('CCCC')
271
- end
272
-
273
- def receive_data data
274
- # log 'receive_data', data
275
-
276
- Frame.extract(data).each do |frame|
277
- log 'receive', frame
278
-
279
- case method = frame.payload
280
- when Protocol::Connection::Start
281
- send Protocol::Connection::StartOk.new({:platform => 'Ruby/EventMachine',
282
- :product => 'AMQP',
283
- :information => 'http://github.com/tmm1/amqp',
284
- :version => '0.0.1'},
285
- 'AMQPLAIN',
286
- {:LOGIN => 'guest',
287
- :PASSWORD => 'guest'},
288
- 'en_US')
289
-
290
- when Protocol::Connection::Tune
291
- send Protocol::Connection::TuneOk.new :channel_max => 0,
292
- :frame_max => 131072,
293
- :heartbeat => 0
294
-
295
- send Protocol::Connection::Open.new :virtual_host => '/',
296
- :capabilities => '',
297
- :insist => false
298
-
299
- when Protocol::Connection::OpenOk
300
- send Protocol::Channel::Open.new, :channel => 1
301
-
302
- when Protocol::Channel::OpenOk
303
- send Protocol::Access::Request.new(:realm => '/data',
304
- :read => true,
305
- :write => true,
306
- :active => true), :channel => 1
307
-
308
- when Protocol::Access::RequestOk
309
- @ticket = method.ticket
310
- send Protocol::Queue::Declare.new(:ticket => @ticket,
311
- :queue => '',
312
- :exclusive => false,
313
- :auto_delete => true), :channel => 1
314
-
315
- when Protocol::Queue::DeclareOk
316
- @queue = method.queue
317
- send Protocol::Queue::Bind.new(:ticket => @ticket,
318
- :queue => @queue,
319
- :exchange => '',
320
- :routing_key => 'test_route'), :channel => 1
321
-
322
- when Protocol::Queue::BindOk
323
- send Protocol::Basic::Consume.new(:ticket => @ticket,
324
- :queue => @queue,
325
- :no_local => false,
326
- :no_ack => true), :channel => 1
327
-
328
- when Protocol::Basic::ConsumeOk
329
- send Protocol::Basic::Publish.new(:ticket => @ticket,
330
- :exchange => '',
331
- :routing_key => 'test_route'), :channel => 1, :content => 'this is a test!'
332
- end
333
- end
334
- end
335
-
336
- def send data, opts = {}
337
- channel = opts[:channel] ||= 0
338
- data = data.to_frame(channel) unless data.is_a? Frame
339
- log 'send', data
340
- send_data data.to_binary
341
-
342
- if content = opts[:content]
343
- size = content.length
344
-
345
- lower = size & 0xffffffff
346
- upper = (size & ~0xffffffff) >> 32
347
- # XXX rabbitmq only supports weight == 0
348
- data = [ 60, weight = 0, upper, lower, 0b1001_1000_0000_0000 ].pack("nnNNn")
349
- data += [ len = 'application/octet-stream'.length, 'application/octet-stream', 1, 1 ].pack("Ca*CC")
350
- send_data Frame.new(:HEADER, channel, data).to_binary
351
-
352
- # XXX spec says add FRAME_END, but rabbitmq doesn't support it
353
- # data = [ content, Frame::FOOTER ].pack('a*C')
354
- data = [ content ].pack("a*")
355
- send_data Frame.new(:BODY, channel, data).to_binary
356
- end
357
- end
358
-
359
- def send_data data
360
- log 'send_data', data
361
- super
362
- end
363
-
364
- def unbind
365
- log 'disconnected'
366
- end
367
-
368
- def self.start host = 'localhost', port = PORT, &blk
369
- EM.run{
370
- EM.connect host, port, self, blk
371
- }
372
- end
373
-
374
- private
375
-
376
- def log *args
377
- pp args
378
- puts
379
- end
380
- end
381
-
382
- def self.start *args, &blk
383
- Connection.start *args, &blk
384
- end
385
- end
386
-
387
- require 'pp'
388
-
389
- if $0 == __FILE__
390
- EM.run{
391
- AMQP.start do |amqp|
392
- amqp.test.integer { |meth|
393
- meth
394
- }.send(0)
395
-
396
- amqp(1).on(:method) {
397
-
398
- }
399
-
400
- amqp(1).test.integer
401
- end
402
- }
403
- elsif $0 =~ /bacon/
404
- include AMQP
405
-
406
- describe Frame do
407
- should 'convert to binary' do
408
- Frame.new(2, 0, 'abc').to_binary.should == "\002\000\000\000\000\000\003abc\316"
409
- end
410
-
411
- should 'return type as symbol' do
412
- Frame.new(3, 0, 'abc').type.should == :BODY
413
- Frame.new(:BODY, 0, 'abc').type.should == :BODY
414
- end
415
-
416
- should 'wrap Buffer#extract' do
417
- Frame.extract(frame = Frame.new(2,0,'abc')).first.should == frame
418
- end
419
- end
420
-
421
- describe Buffer do
422
- @frame = Frame.new(2, 0, 'abc')
423
-
424
- should 'parse complete frames' do
425
- frame = Buffer.new(@frame.to_binary).extract.first
426
-
427
- frame.should.be.kind_of? Frame
428
- frame.should.be == @frame
429
- end
430
-
431
- should 'not return incomplete frames until complete' do
432
- buffer = Buffer.new(@frame.to_binary[0..5])
433
- buffer.extract.should == []
434
- buffer.extract(@frame.to_binary[6..-1]).should == [@frame]
435
- buffer.extract.should == []
436
- end
437
- end
438
-
439
- describe Protocol do
440
- @start = Protocol::Connection::Start.new(:locales => 'en_US',
441
- :mechanisms => 'PLAIN AMQPLAIN',
442
- :version_major => 8,
443
- :version_minor => 0,
444
- :server_properties => {'product' => 'RabbitMQ'})
445
-
446
- @startok = Protocol::Connection::StartOk.new({:platform => 'Ruby/EventMachine',
447
- :product => 'AMQP',
448
- :information => 'http://github.com/tmm1/amqp',
449
- :version => '0.0.1'},
450
- 'PLAIN',
451
- {:LOGIN => 'guest',
452
- :PASSWORD => 'guest'},
453
- 'en_US')
454
-
455
- should 'generate method packets' do
456
- meth = Protocol::Connection::StartOk.new :locale => 'en_US',
457
- :mechanism => 'PLAIN'
458
- meth.locale.should == @startok.locale
459
- end
460
-
461
- should 'generate method frames' do
462
- @startok.to_frame.should == Frame.new(:METHOD, 0, @startok)
463
- end
464
-
465
- should 'convert to and from binary' do
466
- Protocol.parse(@start.to_binary).should == @start
467
- end
468
-
469
- should 'convert to and from frames' do
470
- # XXX make this Frame.parse (refactor Buffer#extract)
471
- Buffer.new(@start.to_frame.to_binary).extract.first.payload.should == @start
472
- end
473
- end
474
- end
475
-
476
- __END__
477
-
478
- ["connected"]
479
-
480
- ["receive",
481
- #<AMQP::Frame:0x1063834
482
- @channel=0,
483
- @payload=
484
- #<AMQP::Protocol::Connection::Start:0x1063500
485
- @debug=1,
486
- @locales="en_US",
487
- @mechanisms="PLAIN AMQPLAIN",
488
- @server_properties=
489
- {"platform"=>"Erlang/OTP",
490
- "product"=>"RabbitMQ",
491
- "information"=>"Licensed under the MPL. See http://www.rabbitmq.com/",
492
- "version"=>"%%VERSION%%",
493
- "copyright"=>
494
- "Copyright (C) 2007-2008 LShift Ltd., Cohesive Financial Technologies LLC., and Rabbit Technologies Ltd."},
495
- @version_major=8,
496
- @version_minor=0>,
497
- @type=:METHOD>]
498
-
499
- ["send",
500
- #<AMQP::Frame:0x104c5bc
501
- @channel=0,
502
- @payload=
503
- #<AMQP::Protocol::Connection::StartOk:0x104c7d8
504
- @client_properties=
505
- {:product=>"AMQP",
506
- :information=>"http://github.com/tmm1/amqp",
507
- :platform=>"Ruby/EventMachine",
508
- :version=>"0.0.1"},
509
- @debug=1,
510
- @locale="en_US",
511
- @mechanism="AMQPLAIN",
512
- @response={:PASSWORD=>"guest", :LOGIN=>"guest"}>,
513
- @type=:METHOD>]
514
-
515
- ["receive",
516
- #<AMQP::Frame:0x1035b78
517
- @channel=0,
518
- @payload=
519
- #<AMQP::Protocol::Connection::Tune:0x1035844
520
- @channel_max=0,
521
- @debug=1,
522
- @frame_max=131072,
523
- @heartbeat=0>,
524
- @type=:METHOD>]
525
-
526
- ["send",
527
- #<AMQP::Frame:0x102ad18
528
- @channel=0,
529
- @payload=
530
- #<AMQP::Protocol::Connection::TuneOk:0x102af34
531
- @channel_max=0,
532
- @debug=1,
533
- @frame_max=131072,
534
- @heartbeat=0>,
535
- @type=:METHOD>]
536
-
537
- ["send",
538
- #<AMQP::Frame:0x1020034
539
- @channel=0,
540
- @payload=
541
- #<AMQP::Protocol::Connection::Open:0x1020278
542
- @capabilities="",
543
- @debug=1,
544
- @insist=nil,
545
- @virtual_host="/">,
546
- @type=:METHOD>]
547
-
548
- ["receive",
549
- #<AMQP::Frame:0x1014e8c
550
- @channel=0,
551
- @payload=
552
- #<AMQP::Protocol::Connection::OpenOk:0x1014b58
553
- @debug=1,
554
- @known_hosts="julie.local:5672">,
555
- @type=:METHOD>]
556
-
557
- ["send",
558
- #<AMQP::Frame:0x100c138
559
- @channel=1,
560
- @payload=
561
- #<AMQP::Protocol::Channel::Open:0x100c37c @debug=1, @out_of_band=nil>,
562
- @type=:METHOD>]
563
-
564
- ["receive",
565
- #<AMQP::Frame:0x10036a0
566
- @channel=1,
567
- @payload=#<AMQP::Protocol::Channel::OpenOk:0x100336c @debug=1>,
568
- @type=:METHOD>]
569
-
570
- ["send",
571
- #<AMQP::Frame:0x60e7e4
572
- @channel=1,
573
- @payload=
574
- #<AMQP::Protocol::Access::Request:0x60ef14
575
- @active=true,
576
- @debug=1,
577
- @exclusive=nil,
578
- @passive=nil,
579
- @read=true,
580
- @realm="/data",
581
- @write=true>,
582
- @type=:METHOD>]
583
-
584
- ["receive",
585
- #<AMQP::Frame:0x5dd4b4
586
- @channel=1,
587
- @payload=#<AMQP::Protocol::Access::RequestOk:0x5dcc30 @debug=1, @ticket=101>,
588
- @type=:METHOD>]
589
-
590
- ["send",
591
- #<AMQP::Frame:0x5c02d8
592
- @channel=1,
593
- @payload=
594
- #<AMQP::Protocol::Queue::Declare:0x5c08dc
595
- @arguments=nil,
596
- @auto_delete=true,
597
- @debug=1,
598
- @durable=nil,
599
- @exclusive=nil,
600
- @nowait=nil,
601
- @passive=nil,
602
- @queue="",
603
- @ticket=101>,
604
- @type=:METHOD>]
605
-
606
- ["receive",
607
- #<AMQP::Frame:0x58d1bc
608
- @channel=1,
609
- @payload=
610
- #<AMQP::Protocol::Queue::DeclareOk:0x58cbb8
611
- @consumer_count=0,
612
- @debug=1,
613
- @message_count=0,
614
- @queue="amq.gen-FiDSuLv/KvSgdcIWrNOdYg==">,
615
- @type=:METHOD>]
616
-
617
- ["send",
618
- #<AMQP::Frame:0x570f44
619
- @channel=1,
620
- @payload=
621
- #<AMQP::Protocol::Queue::Bind:0x571624
622
- @arguments=nil,
623
- @debug=1,
624
- @exchange="",
625
- @nowait=nil,
626
- @queue="amq.gen-FiDSuLv/KvSgdcIWrNOdYg==",
627
- @routing_key="test_route",
628
- @ticket=101>,
629
- @type=:METHOD>]
630
-
631
- ["receive",
632
- #<AMQP::Frame:0x549124
633
- @channel=1,
634
- @payload=#<AMQP::Protocol::Queue::BindOk:0x54897c @debug=1>,
635
- @type=:METHOD>]
636
-
637
- ["send",
638
- #<AMQP::Frame:0x5339f0
639
- @channel=1,
640
- @payload=
641
- #<AMQP::Protocol::Basic::Consume:0x534120
642
- @consumer_tag=nil,
643
- @debug=1,
644
- @exclusive=nil,
645
- @no_ack=true,
646
- @no_local=nil,
647
- @nowait=nil,
648
- @queue="amq.gen-FiDSuLv/KvSgdcIWrNOdYg==",
649
- @ticket=101>,
650
- @type=:METHOD>]
651
-
652
- ["receive",
653
- #<AMQP::Frame:0x503d04
654
- @channel=1,
655
- @payload=
656
- #<AMQP::Protocol::Basic::ConsumeOk:0x5035d4
657
- @consumer_tag="amq.ctag-r6XkTE2+kN1qqbMG7FXraQ==",
658
- @debug=1>,
659
- @type=:METHOD>]
660
-
661
- ["send",
662
- #<AMQP::Frame:0x365498
663
- @channel=1,
664
- @payload=
665
- #<AMQP::Protocol::Basic::Publish:0x366cbc
666
- @debug=1,
667
- @exchange="",
668
- @immediate=nil,
669
- @mandatory=nil,
670
- @routing_key="test_route",
671
- @ticket=101>,
672
- @type=:METHOD>]
673
-
674
- ["receive",
675
- #<AMQP::Frame:0x11fd000
676
- @channel=1,
677
- @payload=
678
- #<AMQP::Protocol::Basic::Deliver:0x11fc4fc
679
- @consumer_tag="amq.ctag-r6XkTE2+kN1qqbMG7FXraQ==",
680
- @debug=1,
681
- @delivery_tag=nil,
682
- @exchange="",
683
- @redelivered=nil,
684
- @routing_key="">,
685
- @type=:METHOD>]
686
-
687
- ["receive",
688
- #<AMQP::Frame:0x11fb534
689
- @channel=1,
690
- @payload=
691
- "\000<\000\000\000\000\000\000\000\000\000\017\230\000\030application/octet-stream\001\001",
692
- @type=:HEADER>]
693
-
694
- ["receive",
695
- #<AMQP::Frame:0x11faef4 @channel=1, @payload="this is a test!", @type=:BODY>]