amqp-client 0.2.3 → 0.3.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 83f84f34aa2aacb3719e300483d4a874bc54892e12165b74f895a7503fd3c550
4
- data.tar.gz: b53ba2a5bdbb1620f839f2cca8d66c1ee3db13549360b04e51d018208c1f7b49
3
+ metadata.gz: 30006ba97b26d7e73cf9503841e2248744db3d9e86d1a32fe4c9abecd9ee69f7
4
+ data.tar.gz: a59d667d971da49c2657e57efe385853adbef958fd191a01f0d1f4dbaaa1b8a8
5
5
  SHA512:
6
- metadata.gz: 62aa1fddfbc285ab34e52b3f0421c2a017e157a1e4e6d7c887da78f55c56bb4717a4466bf0ad1ee08a03b485dd55910d38a1b6809d35e373eda1eb248e4cdd33
7
- data.tar.gz: e60e191045e97a268faceb9e3a8112458aa920307e0bf29cdf0d24194c10b0c4254794ab335995019c7b3b41a2fafc383aaee1736584cd618684f6044d760f15
6
+ metadata.gz: 7ddb8f409abf9e773a6551ff53629b702e8324ea7ff794f6b14f09ef9dd7cb27a752e853bb312a8d9da88b826a7714e84006d5bb01b5efeef7bbaed56f14323a
7
+ data.tar.gz: 642e332c0a031d27d7f364b66e0ae5beefef4bad402336f24052eef2679e306eec219369d7b8b2c1d8324eabafd0c40d45aa8feb474c3cd11ddc4578203f5bea
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.3.0] - 2021-08-20
4
+
5
+ - Channel#wait_for_confirms is a smarter way of waiting for publish confirms
6
+ - Default connection_name to $PROGRAM_NAME
3
7
 
4
8
  ## [0.2.3] - 2021-08-19
5
9
 
@@ -6,15 +6,16 @@ module AMQP
6
6
  # AMQP Channel
7
7
  class Channel
8
8
  def initialize(connection, id)
9
- @replies = ::Queue.new
10
9
  @connection = connection
11
10
  @id = id
11
+ @replies = ::Queue.new
12
12
  @consumers = {}
13
- @confirm = nil
14
- @last_confirmed = 0
15
13
  @closed = nil
16
- @on_return = nil
17
14
  @open = false
15
+ @on_return = nil
16
+ @confirm = nil
17
+ @unconfirmed = ::Queue.new
18
+ @unconfirmed_empty = ::Queue.new
18
19
  end
19
20
 
20
21
  attr_reader :id, :consumers
@@ -124,15 +125,17 @@ module AMQP
124
125
  def basic_publish(body, exchange, routing_key, **properties)
125
126
  frame_max = @connection.frame_max - 8
126
127
  id = @id
128
+ mandatory = properties.delete(:mandatory) || false
127
129
 
128
130
  if 0 < body.bytesize && body.bytesize <= frame_max
129
- write_bytes FrameBytes.basic_publish(id, exchange, routing_key, properties.delete(:mandatory) || false),
131
+ write_bytes FrameBytes.basic_publish(id, exchange, routing_key, mandatory),
130
132
  FrameBytes.header(id, body.bytesize, properties),
131
133
  FrameBytes.body(id, body)
132
- return @confirm ? @confirm += 1 : nil
134
+ @unconfirmed.push @confirm += 1 if @confirm
135
+ return
133
136
  end
134
137
 
135
- write_bytes FrameBytes.basic_publish(id, exchange, routing_key, properties.delete(:mandatory) || false),
138
+ write_bytes FrameBytes.basic_publish(id, exchange, routing_key, mandatory),
136
139
  FrameBytes.header(id, body.bytesize, properties)
137
140
  pos = 0
138
141
  while pos < body.bytesize # split body into multiple frame_max frames
@@ -141,13 +144,14 @@ module AMQP
141
144
  write_bytes FrameBytes.body(id, body_part)
142
145
  pos += len
143
146
  end
144
- @confirm += 1 if @confirm
147
+ @unconfirmed.push @confirm += 1 if @confirm
148
+ nil
145
149
  end
146
150
 
147
151
  def basic_publish_confirm(body, exchange, routing_key, **properties)
148
152
  confirm_select(no_wait: true)
149
- id = basic_publish(body, exchange, routing_key, **properties)
150
- wait_for_confirm(id)
153
+ basic_publish(body, exchange, routing_key, **properties)
154
+ wait_for_confirms
151
155
  end
152
156
 
153
157
  # Consume from a queue
@@ -211,20 +215,32 @@ module AMQP
211
215
 
212
216
  write_bytes FrameBytes.confirm_select(@id, no_wait)
213
217
  expect :confirm_select_ok unless no_wait
214
- @confirms = ::Queue.new
215
218
  @confirm = 0
216
219
  end
217
220
 
218
- def wait_for_confirm(id)
219
- raise ArgumentError, "Confirm id has to a positive number" unless id&.positive?
220
- return true if @last_confirmed >= id
221
+ # Block until all publishes messages are confirmed
222
+ def wait_for_confirms
223
+ return true if @unconfirmed.empty?
224
+
225
+ @unconfirmed_empty.pop
226
+ end
221
227
 
228
+ def confirm(args)
229
+ ack_or_nack, delivery_tag, multiple = *args
222
230
  loop do
223
- ack, delivery_tag, multiple = @confirms.shift || break
224
- @last_confirmed = delivery_tag
225
- return ack if delivery_tag == id || (delivery_tag > id && multiple)
231
+ tag = @unconfirmed.pop(true)
232
+ break if tag == delivery_tag
233
+ next if multiple && tag < delivery_tag
234
+
235
+ @unconfirmed << tag # requeue
236
+ rescue ThreadError
237
+ break
238
+ end
239
+ return unless @unconfirmed.empty?
240
+
241
+ @unconfirmed_empty.num_waiting.times do
242
+ @unconfirmed_empty << ack_or_nack == :ack
226
243
  end
227
- false
228
244
  end
229
245
 
230
246
  def tx_select
@@ -246,10 +262,6 @@ module AMQP
246
262
  @replies.push(args)
247
263
  end
248
264
 
249
- def confirm(args)
250
- @confirms.push(args)
251
- end
252
-
253
265
  def message_returned(reply_code, reply_text, exchange, routing_key)
254
266
  Thread.new do
255
267
  body_size, properties = expect(:header)
@@ -164,7 +164,8 @@ module AMQP
164
164
  channel = @channels.delete(channel_id)
165
165
  channel.closed!(reply_code, reply_text, classid, methodid)
166
166
  when 41 # channel#close-ok
167
- @channels[channel_id].reply [:channel_close_ok]
167
+ channel = @channels.delete(channel_id)
168
+ channel.reply [:channel_close_ok]
168
169
  else raise AMQP::Client::UnsupportedMethodFrame, class_id, method_id
169
170
  end
170
171
  when 40 # exchange
@@ -263,10 +264,7 @@ module AMQP
263
264
  @channels[channel_id].reply [:basic_get_empty]
264
265
  when 80 # ack
265
266
  delivery_tag, multiple = buf.unpack("@11 Q> C")
266
- @channels[channel_id].confirm [:ack, delivery_tag, multiple]
267
- when 90 # reject
268
- delivery_tag, requeue = buf.unpack("@11 Q> C")
269
- @channels[channel_id].confirm [:reject, delivery_tag, requeue == 1]
267
+ @channels[channel_id].confirm [:ack, delivery_tag, multiple == 1]
270
268
  when 111 # recover-ok
271
269
  @channels[channel_id].reply [:basic_recover_ok]
272
270
  when 120 # nack
@@ -334,7 +332,8 @@ module AMQP
334
332
 
335
333
  case method_id
336
334
  when 10 # connection#start
337
- properties = CLIENT_PROPERTIES.merge({ connection_name: options[:connection_name] })
335
+ conn_name = options[:connection_name] || $PROGRAM_NAME
336
+ properties = CLIENT_PROPERTIES.merge({ connection_name: conn_name })
338
337
  socket.write FrameBytes.connection_start_ok "\u0000#{user}\u0000#{password}", properties
339
338
  when 30 # connection#tune
340
339
  channel_max, frame_max, heartbeat = buf.unpack("@11 S> L> S>")
@@ -69,7 +69,8 @@ module AMQP
69
69
  end
70
70
 
71
71
  if expiration
72
- expiration.is_a?(String) || raise(ArgumentError, "expiration must be a string")
72
+ expiration = expiration.to_s if expiration.is_a?(Integer)
73
+ expiration.is_a?(String) || raise(ArgumentError, "expiration must be a string or integer")
73
74
 
74
75
  flags |= (1 << 8)
75
76
  arr << expiration.bytesize << expiration
@@ -2,6 +2,6 @@
2
2
 
3
3
  module AMQP
4
4
  class Client
5
- VERSION = "0.2.3"
5
+ VERSION = "0.3.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: amqp-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carl Hörberg
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-08-19 00:00:00.000000000 Z
11
+ date: 2021-08-20 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Work in progress
14
14
  email: