amqp-client 0.3.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,40 +2,61 @@
2
2
 
3
3
  module AMQP
4
4
  class Client
5
- class Error < StandardError; end
5
+ # All errors raised inherit from this class
6
+ class Error < StandardError
7
+ # Raised when a frame that wasn't expected arrives
8
+ class UnexpectedFrame < Error
9
+ def initialize(expected, actual)
10
+ super "Expected frame type '#{expected}' but got '#{actual}'"
11
+ end
12
+ end
6
13
 
7
- # Raised when a frame that wasn't expected arrives
8
- class UnexpectedFrame < Error
9
- def initialize(expected, actual)
10
- super "Expected frame type '#{expected}' but got '#{actual}'"
14
+ # Raised when a frame doesn't end with 206
15
+ class UnexpectedFrameEnd < Error
16
+ def initialize(actual)
17
+ super "Expected frame end 206 but got '#{actual}'"
18
+ end
11
19
  end
12
- end
13
20
 
14
- # Raised when a frame doesn't end with 206
15
- class UnexpectedFrameEnd < Error
16
- def initialize(actual)
17
- super "Expected frame end 206 but got '#{actual}'"
21
+ # Should never be raised as we support all official frame types
22
+ class UnsupportedFrameType < Error
23
+ def initialize(type)
24
+ super "Unsupported frame type '#{type}'"
25
+ end
18
26
  end
19
- end
20
27
 
21
- # Should never be raised as we support all offical frame types
22
- class UnsupportedFrameType < Error
23
- def initialize(type)
24
- super "Unsupported frame type '#{type}'"
28
+ # Raised if a frame is received but not implemented
29
+ class UnsupportedMethodFrame < Error
30
+ def initialize(class_id, method_id)
31
+ super "Unsupported class/method: #{class_id} #{method_id}"
32
+ end
25
33
  end
26
- end
27
34
 
28
- # Raised if a frame is received but not implemented
29
- class UnsupportedMethodFrame < Error
30
- def initialize(class_id, method_id)
31
- super "Unsupported class/method: #{class_id} #{method_id}"
35
+ # Depending on close level a ConnectionClosed or ChannelClosed error is returned
36
+ class Closed < Error
37
+ def self.new(id, level, code, reason, classid = 0, methodid = 0)
38
+ case level
39
+ when :connection
40
+ ConnectionClosed.new(code, reason, classid, methodid)
41
+ when :channel
42
+ ChannelClosed.new(id, code, reason, classid, methodid)
43
+ else raise ArgumentError, "invalid level '#{level}'"
44
+ end
45
+ end
46
+ end
47
+
48
+ # Raised if channel is already closed
49
+ class ChannelClosed < Error
50
+ def initialize(id, code, reason, classid = 0, methodid = 0)
51
+ super "Channel[#{id}] closed (#{code}) #{reason} (#{classid}/#{methodid})"
52
+ end
32
53
  end
33
- end
34
54
 
35
- # Raised if channel is already closed
36
- class ChannelClosedError < Error
37
- def initialize(id, code, reason, classid = 0, methodid = 0)
38
- super "Channel[#{id}] closed (#{code}) #{reason} (#{classid}/#{methodid})"
55
+ # Raised if connection is unexpectedly closed
56
+ class ConnectionClosed < Error
57
+ def initialize(code, reason, classid = 0, methodid = 0)
58
+ super "Connection closed (#{code}) #{reason} (#{classid}/#{methodid})"
59
+ end
39
60
  end
40
61
  end
41
62
  end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AMQP
4
+ class Client
5
+ # High level representation of an exchange
6
+ class Exchange
7
+ # Should only be initialized from the Client
8
+ # @api private
9
+ def initialize(client, name)
10
+ @client = client
11
+ @name = name
12
+ end
13
+
14
+ # Publish to the exchange
15
+ # @param body [String] The message body
16
+ # @param routing_key [String] The routing key of the message,
17
+ # the exchange may use this when routing the message to bound queues
18
+ # @param properties [Properties]
19
+ # @option properties [String] content_type Content type of the message body
20
+ # @option properties [String] content_encoding Content encoding of the body
21
+ # @option properties [Hash<String, Object>] headers Custom headers
22
+ # @option properties [Integer] delivery_mode 2 for persisted message, transient messages for all other values
23
+ # @option properties [Integer] priority A priority of the message (between 0 and 255)
24
+ # @option properties [Integer] correlation_id A correlation id, most often used used for RPC communication
25
+ # @option properties [String] reply_to Queue to reply RPC responses to
26
+ # @option properties [Integer, String] expiration Number of seconds the message will stay in the queue
27
+ # @option properties [String] message_id Can be used to uniquely identify the message, e.g. for deduplication
28
+ # @option properties [Date] timestamp Often used for the time the message was originally generated
29
+ # @option properties [String] type Can indicate what kind of message this is
30
+ # @option properties [String] user_id Can be used to verify that this is the user that published the message
31
+ # @option properties [String] app_id Can be used to indicates which app that generated the message
32
+ # @return [Exchange] self
33
+ def publish(body, routing_key, **properties)
34
+ @client.publish(body, @name, routing_key, **properties)
35
+ self
36
+ end
37
+
38
+ # Bind to another exchange
39
+ # @param exchange [String] Name of the exchange to bind to
40
+ # @param binding_key [String] Binding key on which messages that match might be routed (depending on exchange type)
41
+ # @param arguments [Hash] Message headers to match on (only relevant for header exchanges)
42
+ # @return [Exchange] self
43
+ def bind(exchange, binding_key, arguments: {})
44
+ @client.exchange_bind(@name, exchange, binding_key, arguments: arguments)
45
+ self
46
+ end
47
+
48
+ # Unbind from another exchange
49
+ # @param exchange [String] Name of the exchange to unbind from
50
+ # @param binding_key [String] Binding key which the queue is bound to the exchange with
51
+ # @param arguments [Hash] Arguments matching the binding that's being removed
52
+ # @return [Exchange] self
53
+ def unbind(exchange, binding_key, arguments: {})
54
+ @client.exchange_unbind(@name, exchange, binding_key, arguments: arguments)
55
+ self
56
+ end
57
+
58
+ # Delete the exchange
59
+ # @return [nil]
60
+ def delete
61
+ @client.delete_exchange(@name)
62
+ nil
63
+ end
64
+ end
65
+ end
66
+ end
@@ -4,528 +4,530 @@ require_relative "./properties"
4
4
  require_relative "./table"
5
5
 
6
6
  module AMQP
7
- # Generate binary data for different frames
8
- # Each frame type implemented as a method
9
- # Having a class for each frame type is more expensive in terms of CPU and memory
10
- module FrameBytes
11
- module_function
12
-
13
- def connection_start_ok(response, properties)
14
- prop_tbl = Table.encode(properties)
15
- [
16
- 1, # type: method
17
- 0, # channel id
18
- 2 + 2 + 4 + prop_tbl.bytesize + 6 + 4 + response.bytesize + 1, # frame size
19
- 10, # class id
20
- 11, # method id
21
- prop_tbl.bytesize, prop_tbl, # client props
22
- 5, "PLAIN", # mechanism
23
- response.bytesize, response,
24
- 0, "", # locale
25
- 206 # frame end
26
- ].pack("C S> L> S> S> L>a* Ca* L>a* Ca* C")
27
- end
28
-
29
- def connection_tune_ok(channel_max, frame_max, heartbeat)
30
- [
31
- 1, # type: method
32
- 0, # channel id
33
- 12, # frame size
34
- 10, # class: connection
35
- 31, # method: tune-ok
36
- channel_max,
37
- frame_max,
38
- heartbeat,
39
- 206 # frame end
40
- ].pack("CS>L>S>S>S>L>S>C")
41
- end
42
-
43
- def connection_open(vhost)
44
- [
45
- 1, # type: method
46
- 0, # channel id
47
- 2 + 2 + 1 + vhost.bytesize + 1 + 1, # frame_size
48
- 10, # class: connection
49
- 40, # method: open
50
- vhost.bytesize, vhost,
51
- 0, # reserved1
52
- 0, # reserved2
53
- 206 # frame end
54
- ].pack("C S> L> S> S> Ca* CCC")
55
- end
56
-
57
- def connection_close(code, reason)
58
- frame_size = 2 + 2 + 2 + 1 + reason.bytesize + 2 + 2
59
- [
60
- 1, # type: method
61
- 0, # channel id
62
- frame_size, # frame size
63
- 10, # class: connection
64
- 50, # method: close
65
- code,
66
- reason.bytesize, reason,
67
- 0, # error class id
68
- 0, # error method id
69
- 206 # frame end
70
- ].pack("C S> L> S> S> S> Ca* S> S> C")
71
- end
72
-
73
- def connection_close_ok
74
- [
75
- 1, # type: method
76
- 0, # channel id
77
- 4, # frame size
78
- 10, # class: connection
79
- 51, # method: close-ok
80
- 206 # frame end
81
- ].pack("C S> L> S> S> C")
82
- end
83
-
84
- def channel_open(id)
85
- [
86
- 1, # type: method
87
- id, # channel id
88
- 5, # frame size
89
- 20, # class: channel
90
- 10, # method: open
91
- 0, # reserved1
92
- 206 # frame end
93
- ].pack("C S> L> S> S> C C")
94
- end
95
-
96
- def channel_close(id, reason, code)
97
- frame_size = 2 + 2 + 2 + 1 + reason.bytesize + 2 + 2
98
- [
99
- 1, # type: method
100
- id, # channel id
101
- frame_size, # frame size
102
- 20, # class: channel
103
- 40, # method: close
104
- code,
105
- reason.bytesize, reason,
106
- 0, # error class id
107
- 0, # error method id
108
- 206 # frame end
109
- ].pack("C S> L> S> S> S> Ca* S> S> C")
110
- end
111
-
112
- def channel_close_ok(id)
113
- [
114
- 1, # type: method
115
- id, # channel id
116
- 4, # frame size
117
- 20, # class: channel
118
- 41, # method: close-ok
119
- 206 # frame end
120
- ].pack("C S> L> S> S> C")
121
- end
122
-
123
- def exchange_declare(id, name, type, passive, durable, auto_delete, internal, arguments)
124
- no_wait = false
125
- bits = 0
126
- bits |= (1 << 0) if passive
127
- bits |= (1 << 1) if durable
128
- bits |= (1 << 2) if auto_delete
129
- bits |= (1 << 3) if internal
130
- bits |= (1 << 4) if no_wait
131
- tbl = Table.encode(arguments)
132
- frame_size = 2 + 2 + 2 + 1 + name.bytesize + 1 + type.bytesize + 1 + 4 + tbl.bytesize
133
- [
134
- 1, # type: method
135
- id, # channel id
136
- frame_size, # frame size
137
- 40, # class: exchange
138
- 10, # method: declare
139
- 0, # reserved1
140
- name.bytesize, name,
141
- type.bytesize, type,
142
- bits,
143
- tbl.bytesize, tbl, # arguments
144
- 206 # frame end
145
- ].pack("C S> L> S> S> S> Ca* Ca* C L>a* C")
146
- end
147
-
148
- def exchange_delete(id, name, if_unused, no_wait)
149
- bits = 0
150
- bits |= (1 << 0) if if_unused
151
- bits |= (1 << 1) if no_wait
152
- frame_size = 2 + 2 + 2 + 1 + name.bytesize + 1
153
- [
154
- 1, # type: method
155
- id, # channel id
156
- frame_size, # frame size
157
- 40, # class: exchange
158
- 20, # method: delete
159
- 0, # reserved1
160
- name.bytesize, name,
161
- bits,
162
- 206 # frame end
163
- ].pack("C S> L> S> S> S> Ca* C C")
164
- end
165
-
166
- def exchange_bind(id, destination, source, binding_key, no_wait, arguments)
167
- tbl = Table.encode(arguments)
168
- frame_size = 2 + 2 + 2 + 1 + destination.bytesize + 1 + source.bytesize + 1 +
169
- binding_key.bytesize + 1 + 4 + tbl.bytesize
170
- [
171
- 1, # type: method
172
- id, # channel id
173
- frame_size, # frame size
174
- 40, # class: exchange
175
- 30, # method: bind
176
- 0, # reserved1
177
- destination.bytesize, destination,
178
- source.bytesize, source,
179
- binding_key.bytesize, binding_key,
180
- no_wait ? 1 : 0,
181
- tbl.bytesize, tbl, # arguments
182
- 206 # frame end
183
- ].pack("C S> L> S> S> S> Ca* Ca* Ca* C L>a* C")
184
- end
185
-
186
- def exchange_unbind(id, destination, source, binding_key, no_wait, arguments)
187
- tbl = Table.encode(arguments)
188
- frame_size = 2 + 2 + 2 + 1 + destination.bytesize + 1 + source.bytesize + 1 +
189
- binding_key.bytesize + 1 + 4 + tbl.bytesize
190
- [
191
- 1, # type: method
192
- id, # channel id
193
- frame_size, # frame size
194
- 40, # class: exchange
195
- 40, # method: unbind
196
- 0, # reserved1
197
- destination.bytesize, destination,
198
- source.bytesize, source,
199
- binding_key.bytesize, binding_key,
200
- no_wait ? 1 : 0,
201
- tbl.bytesize, tbl, # arguments
202
- 206 # frame end
203
- ].pack("C S> L> S> S> S> Ca* Ca* Ca* C L>a* C")
204
- end
205
-
206
- def queue_declare(id, name, passive, durable, exclusive, auto_delete, arguments)
207
- no_wait = false
208
- bits = 0
209
- bits |= (1 << 0) if passive
210
- bits |= (1 << 1) if durable
211
- bits |= (1 << 2) if exclusive
212
- bits |= (1 << 3) if auto_delete
213
- bits |= (1 << 4) if no_wait
214
- tbl = Table.encode(arguments)
215
- frame_size = 2 + 2 + 2 + 1 + name.bytesize + 1 + 4 + tbl.bytesize
216
- [
217
- 1, # type: method
218
- id, # channel id
219
- frame_size, # frame size
220
- 50, # class: queue
221
- 10, # method: declare
222
- 0, # reserved1
223
- name.bytesize, name,
224
- bits,
225
- tbl.bytesize, tbl, # arguments
226
- 206 # frame end
227
- ].pack("C S> L> S> S> S> Ca* C L>a* C")
228
- end
229
-
230
- def queue_delete(id, name, if_unused, if_empty, no_wait)
231
- bits = 0
232
- bits |= (1 << 0) if if_unused
233
- bits |= (1 << 1) if if_empty
234
- bits |= (1 << 2) if no_wait
235
- frame_size = 2 + 2 + 2 + 1 + name.bytesize + 1
236
- [
237
- 1, # type: method
238
- id, # channel id
239
- frame_size, # frame size
240
- 50, # class: queue
241
- 40, # method: declare
242
- 0, # reserved1
243
- name.bytesize, name,
244
- bits,
245
- 206 # frame end
246
- ].pack("C S> L> S> S> S> Ca* C C")
247
- end
248
-
249
- def queue_bind(id, queue, exchange, binding_key, no_wait, arguments)
250
- tbl = Table.encode(arguments)
251
- frame_size = 2 + 2 + 2 + 1 + queue.bytesize + 1 + exchange.bytesize + 1 +
252
- binding_key.bytesize + 1 + 4 + tbl.bytesize
253
- [
254
- 1, # type: method
255
- id, # channel id
256
- frame_size, # frame size
257
- 50, # class: queue
258
- 20, # method: bind
259
- 0, # reserved1
260
- queue.bytesize, queue,
261
- exchange.bytesize, exchange,
262
- binding_key.bytesize, binding_key,
263
- no_wait ? 1 : 0,
264
- tbl.bytesize, tbl, # arguments
265
- 206 # frame end
266
- ].pack("C S> L> S> S> S> Ca* Ca* Ca* C L>a* C")
267
- end
268
-
269
- def queue_unbind(id, queue, exchange, binding_key, arguments)
270
- tbl = Table.encode(arguments)
271
- frame_size = 2 + 2 + 2 + 1 + queue.bytesize + 1 + exchange.bytesize + 1 + binding_key.bytesize + 4 + tbl.bytesize
272
- [
273
- 1, # type: method
274
- id, # channel id
275
- frame_size, # frame size
276
- 50, # class: queue
277
- 50, # method: unbind
278
- 0, # reserved1
279
- queue.bytesize, queue,
280
- exchange.bytesize, exchange,
281
- binding_key.bytesize, binding_key,
282
- tbl.bytesize, tbl, # arguments
283
- 206 # frame end
284
- ].pack("C S> L> S> S> S> Ca* Ca* Ca* L>a* C")
285
- end
286
-
287
- def queue_purge(id, queue, no_wait)
288
- frame_size = 2 + 2 + 2 + 1 + queue.bytesize + 1
289
- [
290
- 1, # type: method
291
- id, # channel id
292
- frame_size, # frame size
293
- 50, # class: queue
294
- 30, # method: purge
295
- 0, # reserved1
296
- queue.bytesize, queue,
297
- no_wait ? 1 : 0,
298
- 206 # frame end
299
- ].pack("C S> L> S> S> S> Ca* C C")
300
- end
301
-
302
- def basic_get(id, queue, no_ack)
303
- frame_size = 2 + 2 + 2 + 1 + queue.bytesize + 1
304
- [
305
- 1, # type: method
306
- id, # channel id
307
- frame_size, # frame size
308
- 60, # class: basic
309
- 70, # method: get
310
- 0, # reserved1
311
- queue.bytesize, queue,
312
- no_ack ? 1 : 0,
313
- 206 # frame end
314
- ].pack("C S> L> S> S> S> Ca* C C")
315
- end
316
-
317
- def basic_publish(id, exchange, routing_key, mandatory)
318
- frame_size = 2 + 2 + 2 + 1 + exchange.bytesize + 1 + routing_key.bytesize + 1
319
- [
320
- 1, # type: method
321
- id, # channel id
322
- frame_size, # frame size
323
- 60, # class: basic
324
- 40, # method: publish
325
- 0, # reserved1
326
- exchange.bytesize, exchange,
327
- routing_key.bytesize, routing_key,
328
- mandatory ? 1 : 0, # bits, mandatory/immediate
329
- 206 # frame end
330
- ].pack("C S> L> S> S> S> Ca* Ca* C C")
331
- end
332
-
333
- def header(id, body_size, properties)
334
- props = Properties.new(**properties).encode
335
- frame_size = 2 + 2 + 8 + props.bytesize
336
- [
337
- 2, # type: header
338
- id, # channel id
339
- frame_size, # frame size
340
- 60, # class: basic
341
- 0, # weight
342
- body_size,
343
- props, # properties
344
- 206 # frame end
345
- ].pack("C S> L> S> S> Q> a* C")
346
- end
347
-
348
- def body(id, body_part)
349
- [
350
- 3, # type: body
351
- id, # channel id
352
- body_part.bytesize, # frame size
353
- body_part,
354
- 206 # frame end
355
- ].pack("C S> L> a* C")
356
- end
357
-
358
- def basic_consume(id, queue, tag, no_ack, exclusive, arguments)
359
- no_local = false
360
- no_wait = false
361
- bits = 0
362
- bits |= (1 << 0) if no_local
363
- bits |= (1 << 1) if no_ack
364
- bits |= (1 << 2) if exclusive
365
- bits |= (1 << 3) if no_wait
366
- tbl = Table.encode(arguments)
367
- frame_size = 2 + 2 + 2 + 1 + queue.bytesize + 1 + tag.bytesize + 1 + 4 + tbl.bytesize
368
- [
369
- 1, # type: method
370
- id, # channel id
371
- frame_size, # frame size
372
- 60, # class: basic
373
- 20, # method: consume
374
- 0, # reserved1
375
- queue.bytesize, queue,
376
- tag.bytesize, tag,
377
- bits, # bits
378
- tbl.bytesize, tbl, # arguments
379
- 206 # frame end
380
- ].pack("C S> L> S> S> S> Ca* Ca* C L>a* C")
381
- end
382
-
383
- def basic_cancel(id, consumer_tag, no_wait: false)
384
- frame_size = 2 + 2 + 1 + consumer_tag.bytesize + 1
385
- [
386
- 1, # type: method
387
- id, # channel id
388
- frame_size, # frame size
389
- 60, # class: basic
390
- 30, # method: cancel
391
- consumer_tag.bytesize, consumer_tag,
392
- no_wait ? 1 : 0,
393
- 206 # frame end
394
- ].pack("C S> L> S> S> Ca* C C")
395
- end
396
-
397
- def basic_cancel_ok(id, consumer_tag)
398
- frame_size = 2 + 2 + 1 + consumer_tag.bytesize + 1
399
- [
400
- 1, # type: method
401
- id, # channel id
402
- frame_size, # frame size
403
- 60, # class: basic
404
- 31, # method: cancel-ok
405
- consumer_tag.bytesize, consumer_tag,
406
- 206 # frame end
407
- ].pack("C S> L> S> S> Ca* C")
408
- end
409
-
410
- def basic_ack(id, delivery_tag, multiple)
411
- frame_size = 2 + 2 + 8 + 1
412
- [
413
- 1, # type: method
414
- id, # channel id
415
- frame_size, # frame size
416
- 60, # class: basic
417
- 80, # method: ack
418
- delivery_tag,
419
- multiple ? 1 : 0,
420
- 206 # frame end
421
- ].pack("C S> L> S> S> Q> C C")
422
- end
423
-
424
- def basic_nack(id, delivery_tag, multiple, requeue)
425
- bits = 0
426
- bits |= (1 << 0) if multiple
427
- bits |= (1 << 1) if requeue
428
- frame_size = 2 + 2 + 8 + 1
429
- [
430
- 1, # type: method
431
- id, # channel id
432
- frame_size, # frame size
433
- 60, # class: basic
434
- 120, # method: nack
435
- delivery_tag,
436
- bits,
437
- 206 # frame end
438
- ].pack("C S> L> S> S> Q> C C")
439
- end
440
-
441
- def basic_reject(id, delivery_tag, requeue)
442
- frame_size = 2 + 2 + 8 + 1
443
- [
444
- 1, # type: method
445
- id, # channel id
446
- frame_size, # frame size
447
- 60, # class: basic
448
- 90, # method: reject
449
- delivery_tag,
450
- requeue ? 1 : 0,
451
- 206 # frame end
452
- ].pack("C S> L> S> S> Q> C C")
453
- end
454
-
455
- def basic_qos(id, prefetch_size, prefetch_count, global)
456
- frame_size = 2 + 2 + 4 + 2 + 1
457
- [
458
- 1, # type: method
459
- id, # channel id
460
- frame_size, # frame size
461
- 60, # class: basic
462
- 10, # method: qos
463
- prefetch_size,
464
- prefetch_count,
465
- global ? 1 : 0,
466
- 206 # frame end
467
- ].pack("C S> L> S> S> L> S> C C")
468
- end
469
-
470
- def basic_recover(id, requeue)
471
- frame_size = 2 + 2 + 1
472
- [
473
- 1, # type: method
474
- id, # channel id
475
- frame_size, # frame size
476
- 60, # class: basic
477
- 110, # method: recover
478
- requeue ? 1 : 0,
479
- 206 # frame end
480
- ].pack("C S> L> S> S> C C")
481
- end
482
-
483
- def confirm_select(id, no_wait)
484
- [
485
- 1, # type: method
486
- id, # channel id
487
- 5, # frame size
488
- 85, # class: confirm
489
- 10, # method: select
490
- no_wait ? 1 : 0,
491
- 206 # frame end
492
- ].pack("C S> L> S> S> C C")
493
- end
494
-
495
- def tx_select(id)
496
- frame_size = 2 + 2
497
- [
498
- 1, # type: method
499
- id, # channel id
500
- frame_size, # frame size
501
- 90, # class: tx
502
- 10, # method: select
503
- 206 # frame end
504
- ].pack("C S> L> S> S> C")
505
- end
506
-
507
- def tx_commit(id)
508
- frame_size = 2 + 2
509
- [
510
- 1, # type: method
511
- id, # channel id
512
- frame_size, # frame size
513
- 90, # class: tx
514
- 20, # method: commit
515
- 206 # frame end
516
- ].pack("C S> L> S> S> C")
517
- end
518
-
519
- def tx_rollback(id)
520
- frame_size = 2 + 2
521
- [
522
- 1, # type: method
523
- id, # channel id
524
- frame_size, # frame size
525
- 90, # class: tx
526
- 30, # method: rollback
527
- 206 # frame end
528
- ].pack("C S> L> S> S> C")
7
+ class Client
8
+ # Generate binary data for different frames
9
+ # Each frame type implemented as a method
10
+ # Having a class for each frame type is more expensive in terms of CPU and memory
11
+ # @api private
12
+ module FrameBytes
13
+ def self.connection_start_ok(response, properties)
14
+ prop_tbl = Table.encode(properties)
15
+ [
16
+ 1, # type: method
17
+ 0, # channel id
18
+ 2 + 2 + 4 + prop_tbl.bytesize + 6 + 4 + response.bytesize + 1, # frame size
19
+ 10, # class id
20
+ 11, # method id
21
+ prop_tbl.bytesize, prop_tbl, # client props
22
+ 5, "PLAIN", # mechanism
23
+ response.bytesize, response,
24
+ 0, "", # locale
25
+ 206 # frame end
26
+ ].pack("C S> L> S> S> L>a* Ca* L>a* Ca* C")
27
+ end
28
+
29
+ def self.connection_tune_ok(channel_max, frame_max, heartbeat)
30
+ [
31
+ 1, # type: method
32
+ 0, # channel id
33
+ 12, # frame size
34
+ 10, # class: connection
35
+ 31, # method: tune-ok
36
+ channel_max,
37
+ frame_max,
38
+ heartbeat,
39
+ 206 # frame end
40
+ ].pack("CS>L>S>S>S>L>S>C")
41
+ end
42
+
43
+ def self.connection_open(vhost)
44
+ [
45
+ 1, # type: method
46
+ 0, # channel id
47
+ 2 + 2 + 1 + vhost.bytesize + 1 + 1, # frame_size
48
+ 10, # class: connection
49
+ 40, # method: open
50
+ vhost.bytesize, vhost,
51
+ 0, # reserved1
52
+ 0, # reserved2
53
+ 206 # frame end
54
+ ].pack("C S> L> S> S> Ca* CCC")
55
+ end
56
+
57
+ def self.connection_close(code, reason)
58
+ frame_size = 2 + 2 + 2 + 1 + reason.bytesize + 2 + 2
59
+ [
60
+ 1, # type: method
61
+ 0, # channel id
62
+ frame_size, # frame size
63
+ 10, # class: connection
64
+ 50, # method: close
65
+ code,
66
+ reason.bytesize, reason,
67
+ 0, # error class id
68
+ 0, # error method id
69
+ 206 # frame end
70
+ ].pack("C S> L> S> S> S> Ca* S> S> C")
71
+ end
72
+
73
+ def self.connection_close_ok
74
+ [
75
+ 1, # type: method
76
+ 0, # channel id
77
+ 4, # frame size
78
+ 10, # class: connection
79
+ 51, # method: close-ok
80
+ 206 # frame end
81
+ ].pack("C S> L> S> S> C")
82
+ end
83
+
84
+ def self.channel_open(id)
85
+ [
86
+ 1, # type: method
87
+ id, # channel id
88
+ 5, # frame size
89
+ 20, # class: channel
90
+ 10, # method: open
91
+ 0, # reserved1
92
+ 206 # frame end
93
+ ].pack("C S> L> S> S> C C")
94
+ end
95
+
96
+ def self.channel_close(id, reason, code)
97
+ frame_size = 2 + 2 + 2 + 1 + reason.bytesize + 2 + 2
98
+ [
99
+ 1, # type: method
100
+ id, # channel id
101
+ frame_size, # frame size
102
+ 20, # class: channel
103
+ 40, # method: close
104
+ code,
105
+ reason.bytesize, reason,
106
+ 0, # error class id
107
+ 0, # error method id
108
+ 206 # frame end
109
+ ].pack("C S> L> S> S> S> Ca* S> S> C")
110
+ end
111
+
112
+ def self.channel_close_ok(id)
113
+ [
114
+ 1, # type: method
115
+ id, # channel id
116
+ 4, # frame size
117
+ 20, # class: channel
118
+ 41, # method: close-ok
119
+ 206 # frame end
120
+ ].pack("C S> L> S> S> C")
121
+ end
122
+
123
+ def self.exchange_declare(id, name, type, passive, durable, auto_delete, internal, arguments)
124
+ no_wait = false
125
+ bits = 0
126
+ bits |= (1 << 0) if passive
127
+ bits |= (1 << 1) if durable
128
+ bits |= (1 << 2) if auto_delete
129
+ bits |= (1 << 3) if internal
130
+ bits |= (1 << 4) if no_wait
131
+ tbl = Table.encode(arguments)
132
+ frame_size = 2 + 2 + 2 + 1 + name.bytesize + 1 + type.bytesize + 1 + 4 + tbl.bytesize
133
+ [
134
+ 1, # type: method
135
+ id, # channel id
136
+ frame_size, # frame size
137
+ 40, # class: exchange
138
+ 10, # method: declare
139
+ 0, # reserved1
140
+ name.bytesize, name,
141
+ type.bytesize, type,
142
+ bits,
143
+ tbl.bytesize, tbl, # arguments
144
+ 206 # frame end
145
+ ].pack("C S> L> S> S> S> Ca* Ca* C L>a* C")
146
+ end
147
+
148
+ def self.exchange_delete(id, name, if_unused, no_wait)
149
+ bits = 0
150
+ bits |= (1 << 0) if if_unused
151
+ bits |= (1 << 1) if no_wait
152
+ frame_size = 2 + 2 + 2 + 1 + name.bytesize + 1
153
+ [
154
+ 1, # type: method
155
+ id, # channel id
156
+ frame_size, # frame size
157
+ 40, # class: exchange
158
+ 20, # method: delete
159
+ 0, # reserved1
160
+ name.bytesize, name,
161
+ bits,
162
+ 206 # frame end
163
+ ].pack("C S> L> S> S> S> Ca* C C")
164
+ end
165
+
166
+ def self.exchange_bind(id, destination, source, binding_key, no_wait, arguments)
167
+ tbl = Table.encode(arguments)
168
+ frame_size = 2 + 2 + 2 + 1 + destination.bytesize + 1 + source.bytesize + 1 +
169
+ binding_key.bytesize + 1 + 4 + tbl.bytesize
170
+ [
171
+ 1, # type: method
172
+ id, # channel id
173
+ frame_size, # frame size
174
+ 40, # class: exchange
175
+ 30, # method: bind
176
+ 0, # reserved1
177
+ destination.bytesize, destination,
178
+ source.bytesize, source,
179
+ binding_key.bytesize, binding_key,
180
+ no_wait ? 1 : 0,
181
+ tbl.bytesize, tbl, # arguments
182
+ 206 # frame end
183
+ ].pack("C S> L> S> S> S> Ca* Ca* Ca* C L>a* C")
184
+ end
185
+
186
+ def self.exchange_unbind(id, destination, source, binding_key, no_wait, arguments)
187
+ tbl = Table.encode(arguments)
188
+ frame_size = 2 + 2 + 2 + 1 + destination.bytesize + 1 + source.bytesize + 1 +
189
+ binding_key.bytesize + 1 + 4 + tbl.bytesize
190
+ [
191
+ 1, # type: method
192
+ id, # channel id
193
+ frame_size, # frame size
194
+ 40, # class: exchange
195
+ 40, # method: unbind
196
+ 0, # reserved1
197
+ destination.bytesize, destination,
198
+ source.bytesize, source,
199
+ binding_key.bytesize, binding_key,
200
+ no_wait ? 1 : 0,
201
+ tbl.bytesize, tbl, # arguments
202
+ 206 # frame end
203
+ ].pack("C S> L> S> S> S> Ca* Ca* Ca* C L>a* C")
204
+ end
205
+
206
+ def self.queue_declare(id, name, passive, durable, exclusive, auto_delete, arguments)
207
+ no_wait = false
208
+ bits = 0
209
+ bits |= (1 << 0) if passive
210
+ bits |= (1 << 1) if durable
211
+ bits |= (1 << 2) if exclusive
212
+ bits |= (1 << 3) if auto_delete
213
+ bits |= (1 << 4) if no_wait
214
+ tbl = Table.encode(arguments)
215
+ frame_size = 2 + 2 + 2 + 1 + name.bytesize + 1 + 4 + tbl.bytesize
216
+ [
217
+ 1, # type: method
218
+ id, # channel id
219
+ frame_size, # frame size
220
+ 50, # class: queue
221
+ 10, # method: declare
222
+ 0, # reserved1
223
+ name.bytesize, name,
224
+ bits,
225
+ tbl.bytesize, tbl, # arguments
226
+ 206 # frame end
227
+ ].pack("C S> L> S> S> S> Ca* C L>a* C")
228
+ end
229
+
230
+ def self.queue_delete(id, name, if_unused, if_empty, no_wait)
231
+ bits = 0
232
+ bits |= (1 << 0) if if_unused
233
+ bits |= (1 << 1) if if_empty
234
+ bits |= (1 << 2) if no_wait
235
+ frame_size = 2 + 2 + 2 + 1 + name.bytesize + 1
236
+ [
237
+ 1, # type: method
238
+ id, # channel id
239
+ frame_size, # frame size
240
+ 50, # class: queue
241
+ 40, # method: declare
242
+ 0, # reserved1
243
+ name.bytesize, name,
244
+ bits,
245
+ 206 # frame end
246
+ ].pack("C S> L> S> S> S> Ca* C C")
247
+ end
248
+
249
+ def self.queue_bind(id, queue, exchange, binding_key, no_wait, arguments)
250
+ tbl = Table.encode(arguments)
251
+ frame_size = 2 + 2 + 2 + 1 + queue.bytesize + 1 + exchange.bytesize + 1 +
252
+ binding_key.bytesize + 1 + 4 + tbl.bytesize
253
+ [
254
+ 1, # type: method
255
+ id, # channel id
256
+ frame_size, # frame size
257
+ 50, # class: queue
258
+ 20, # method: bind
259
+ 0, # reserved1
260
+ queue.bytesize, queue,
261
+ exchange.bytesize, exchange,
262
+ binding_key.bytesize, binding_key,
263
+ no_wait ? 1 : 0,
264
+ tbl.bytesize, tbl, # arguments
265
+ 206 # frame end
266
+ ].pack("C S> L> S> S> S> Ca* Ca* Ca* C L>a* C")
267
+ end
268
+
269
+ def self.queue_unbind(id, queue, exchange, binding_key, arguments)
270
+ tbl = Table.encode(arguments)
271
+ frame_size = 2 + 2 + 2 + 1 + queue.bytesize + 1 + exchange.bytesize + 1 +
272
+ binding_key.bytesize + 4 + tbl.bytesize
273
+ [
274
+ 1, # type: method
275
+ id, # channel id
276
+ frame_size, # frame size
277
+ 50, # class: queue
278
+ 50, # method: unbind
279
+ 0, # reserved1
280
+ queue.bytesize, queue,
281
+ exchange.bytesize, exchange,
282
+ binding_key.bytesize, binding_key,
283
+ tbl.bytesize, tbl, # arguments
284
+ 206 # frame end
285
+ ].pack("C S> L> S> S> S> Ca* Ca* Ca* L>a* C")
286
+ end
287
+
288
+ def self.queue_purge(id, queue, no_wait)
289
+ frame_size = 2 + 2 + 2 + 1 + queue.bytesize + 1
290
+ [
291
+ 1, # type: method
292
+ id, # channel id
293
+ frame_size, # frame size
294
+ 50, # class: queue
295
+ 30, # method: purge
296
+ 0, # reserved1
297
+ queue.bytesize, queue,
298
+ no_wait ? 1 : 0,
299
+ 206 # frame end
300
+ ].pack("C S> L> S> S> S> Ca* C C")
301
+ end
302
+
303
+ def self.basic_get(id, queue, no_ack)
304
+ frame_size = 2 + 2 + 2 + 1 + queue.bytesize + 1
305
+ [
306
+ 1, # type: method
307
+ id, # channel id
308
+ frame_size, # frame size
309
+ 60, # class: basic
310
+ 70, # method: get
311
+ 0, # reserved1
312
+ queue.bytesize, queue,
313
+ no_ack ? 1 : 0,
314
+ 206 # frame end
315
+ ].pack("C S> L> S> S> S> Ca* C C")
316
+ end
317
+
318
+ def self.basic_publish(id, exchange, routing_key, mandatory)
319
+ frame_size = 2 + 2 + 2 + 1 + exchange.bytesize + 1 + routing_key.bytesize + 1
320
+ [
321
+ 1, # type: method
322
+ id, # channel id
323
+ frame_size, # frame size
324
+ 60, # class: basic
325
+ 40, # method: publish
326
+ 0, # reserved1
327
+ exchange.bytesize, exchange,
328
+ routing_key.bytesize, routing_key,
329
+ mandatory ? 1 : 0, # bits, mandatory/immediate
330
+ 206 # frame end
331
+ ].pack("C S> L> S> S> S> Ca* Ca* C C")
332
+ end
333
+
334
+ def self.header(id, body_size, properties)
335
+ props = Properties.new(**properties).encode
336
+ frame_size = 2 + 2 + 8 + props.bytesize
337
+ [
338
+ 2, # type: header
339
+ id, # channel id
340
+ frame_size, # frame size
341
+ 60, # class: basic
342
+ 0, # weight
343
+ body_size,
344
+ props, # properties
345
+ 206 # frame end
346
+ ].pack("C S> L> S> S> Q> a* C")
347
+ end
348
+
349
+ def self.body(id, body_part)
350
+ [
351
+ 3, # type: body
352
+ id, # channel id
353
+ body_part.bytesize, # frame size
354
+ body_part,
355
+ 206 # frame end
356
+ ].pack("C S> L> a* C")
357
+ end
358
+
359
+ def self.basic_consume(id, queue, tag, no_ack, exclusive, arguments)
360
+ no_local = false
361
+ no_wait = false
362
+ bits = 0
363
+ bits |= (1 << 0) if no_local
364
+ bits |= (1 << 1) if no_ack
365
+ bits |= (1 << 2) if exclusive
366
+ bits |= (1 << 3) if no_wait
367
+ tbl = Table.encode(arguments)
368
+ frame_size = 2 + 2 + 2 + 1 + queue.bytesize + 1 + tag.bytesize + 1 + 4 + tbl.bytesize
369
+ [
370
+ 1, # type: method
371
+ id, # channel id
372
+ frame_size, # frame size
373
+ 60, # class: basic
374
+ 20, # method: consume
375
+ 0, # reserved1
376
+ queue.bytesize, queue,
377
+ tag.bytesize, tag,
378
+ bits, # bits
379
+ tbl.bytesize, tbl, # arguments
380
+ 206 # frame end
381
+ ].pack("C S> L> S> S> S> Ca* Ca* C L>a* C")
382
+ end
383
+
384
+ def self.basic_cancel(id, consumer_tag, no_wait: false)
385
+ frame_size = 2 + 2 + 1 + consumer_tag.bytesize + 1
386
+ [
387
+ 1, # type: method
388
+ id, # channel id
389
+ frame_size, # frame size
390
+ 60, # class: basic
391
+ 30, # method: cancel
392
+ consumer_tag.bytesize, consumer_tag,
393
+ no_wait ? 1 : 0,
394
+ 206 # frame end
395
+ ].pack("C S> L> S> S> Ca* C C")
396
+ end
397
+
398
+ def self.basic_cancel_ok(id, consumer_tag)
399
+ frame_size = 2 + 2 + 1 + consumer_tag.bytesize + 1
400
+ [
401
+ 1, # type: method
402
+ id, # channel id
403
+ frame_size, # frame size
404
+ 60, # class: basic
405
+ 31, # method: cancel-ok
406
+ consumer_tag.bytesize, consumer_tag,
407
+ 206 # frame end
408
+ ].pack("C S> L> S> S> Ca* C")
409
+ end
410
+
411
+ def self.basic_ack(id, delivery_tag, multiple)
412
+ frame_size = 2 + 2 + 8 + 1
413
+ [
414
+ 1, # type: method
415
+ id, # channel id
416
+ frame_size, # frame size
417
+ 60, # class: basic
418
+ 80, # method: ack
419
+ delivery_tag,
420
+ multiple ? 1 : 0,
421
+ 206 # frame end
422
+ ].pack("C S> L> S> S> Q> C C")
423
+ end
424
+
425
+ def self.basic_nack(id, delivery_tag, multiple, requeue)
426
+ bits = 0
427
+ bits |= (1 << 0) if multiple
428
+ bits |= (1 << 1) if requeue
429
+ frame_size = 2 + 2 + 8 + 1
430
+ [
431
+ 1, # type: method
432
+ id, # channel id
433
+ frame_size, # frame size
434
+ 60, # class: basic
435
+ 120, # method: nack
436
+ delivery_tag,
437
+ bits,
438
+ 206 # frame end
439
+ ].pack("C S> L> S> S> Q> C C")
440
+ end
441
+
442
+ def self.basic_reject(id, delivery_tag, requeue)
443
+ frame_size = 2 + 2 + 8 + 1
444
+ [
445
+ 1, # type: method
446
+ id, # channel id
447
+ frame_size, # frame size
448
+ 60, # class: basic
449
+ 90, # method: reject
450
+ delivery_tag,
451
+ requeue ? 1 : 0,
452
+ 206 # frame end
453
+ ].pack("C S> L> S> S> Q> C C")
454
+ end
455
+
456
+ def self.basic_qos(id, prefetch_size, prefetch_count, global)
457
+ frame_size = 2 + 2 + 4 + 2 + 1
458
+ [
459
+ 1, # type: method
460
+ id, # channel id
461
+ frame_size, # frame size
462
+ 60, # class: basic
463
+ 10, # method: qos
464
+ prefetch_size,
465
+ prefetch_count,
466
+ global ? 1 : 0,
467
+ 206 # frame end
468
+ ].pack("C S> L> S> S> L> S> C C")
469
+ end
470
+
471
+ def self.basic_recover(id, requeue)
472
+ frame_size = 2 + 2 + 1
473
+ [
474
+ 1, # type: method
475
+ id, # channel id
476
+ frame_size, # frame size
477
+ 60, # class: basic
478
+ 110, # method: recover
479
+ requeue ? 1 : 0,
480
+ 206 # frame end
481
+ ].pack("C S> L> S> S> C C")
482
+ end
483
+
484
+ def self.confirm_select(id, no_wait)
485
+ [
486
+ 1, # type: method
487
+ id, # channel id
488
+ 5, # frame size
489
+ 85, # class: confirm
490
+ 10, # method: select
491
+ no_wait ? 1 : 0,
492
+ 206 # frame end
493
+ ].pack("C S> L> S> S> C C")
494
+ end
495
+
496
+ def self.tx_select(id)
497
+ frame_size = 2 + 2
498
+ [
499
+ 1, # type: method
500
+ id, # channel id
501
+ frame_size, # frame size
502
+ 90, # class: tx
503
+ 10, # method: select
504
+ 206 # frame end
505
+ ].pack("C S> L> S> S> C")
506
+ end
507
+
508
+ def self.tx_commit(id)
509
+ frame_size = 2 + 2
510
+ [
511
+ 1, # type: method
512
+ id, # channel id
513
+ frame_size, # frame size
514
+ 90, # class: tx
515
+ 20, # method: commit
516
+ 206 # frame end
517
+ ].pack("C S> L> S> S> C")
518
+ end
519
+
520
+ def self.tx_rollback(id)
521
+ frame_size = 2 + 2
522
+ [
523
+ 1, # type: method
524
+ id, # channel id
525
+ frame_size, # frame size
526
+ 90, # class: tx
527
+ 30, # method: rollback
528
+ 206 # frame end
529
+ ].pack("C S> L> S> S> C")
530
+ end
529
531
  end
530
532
  end
531
533
  end