amqp-client 1.0.0 → 1.1.1

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.
@@ -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
@@ -0,0 +1,533 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./properties"
4
+ require_relative "./table"
5
+
6
+ module AMQP
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.encode(properties)
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
531
+ end
532
+ end
533
+ end