bunny 2.19.0 → 2.20.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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +26 -32
  3. data/lib/bunny/channel.rb +86 -10
  4. data/lib/bunny/consumer.rb +2 -2
  5. data/lib/bunny/delivery_info.rb +1 -1
  6. data/lib/bunny/queue.rb +33 -2
  7. data/lib/bunny/session.rb +1 -1
  8. data/lib/bunny/transport.rb +30 -1
  9. data/lib/bunny/version.rb +1 -1
  10. data/lib/bunny.rb +45 -4
  11. metadata +4 -144
  12. data/spec/config/enabled_plugins +0 -1
  13. data/spec/config/rabbitmq.conf +0 -13
  14. data/spec/higher_level_api/integration/basic_ack_spec.rb +0 -230
  15. data/spec/higher_level_api/integration/basic_cancel_spec.rb +0 -142
  16. data/spec/higher_level_api/integration/basic_consume_spec.rb +0 -357
  17. data/spec/higher_level_api/integration/basic_consume_with_objects_spec.rb +0 -54
  18. data/spec/higher_level_api/integration/basic_get_spec.rb +0 -80
  19. data/spec/higher_level_api/integration/basic_nack_spec.rb +0 -82
  20. data/spec/higher_level_api/integration/basic_publish_spec.rb +0 -74
  21. data/spec/higher_level_api/integration/basic_qos_spec.rb +0 -57
  22. data/spec/higher_level_api/integration/basic_reject_spec.rb +0 -152
  23. data/spec/higher_level_api/integration/basic_return_spec.rb +0 -33
  24. data/spec/higher_level_api/integration/channel_close_spec.rb +0 -66
  25. data/spec/higher_level_api/integration/channel_open_spec.rb +0 -57
  26. data/spec/higher_level_api/integration/connection_recovery_spec.rb +0 -483
  27. data/spec/higher_level_api/integration/connection_spec.rb +0 -589
  28. data/spec/higher_level_api/integration/connection_stop_spec.rb +0 -83
  29. data/spec/higher_level_api/integration/consumer_cancellation_notification_spec.rb +0 -128
  30. data/spec/higher_level_api/integration/dead_lettering_spec.rb +0 -75
  31. data/spec/higher_level_api/integration/exchange_bind_spec.rb +0 -31
  32. data/spec/higher_level_api/integration/exchange_declare_spec.rb +0 -237
  33. data/spec/higher_level_api/integration/exchange_delete_spec.rb +0 -105
  34. data/spec/higher_level_api/integration/exchange_unbind_spec.rb +0 -40
  35. data/spec/higher_level_api/integration/exclusive_queue_spec.rb +0 -28
  36. data/spec/higher_level_api/integration/heartbeat_spec.rb +0 -49
  37. data/spec/higher_level_api/integration/message_properties_access_spec.rb +0 -95
  38. data/spec/higher_level_api/integration/predeclared_exchanges_spec.rb +0 -24
  39. data/spec/higher_level_api/integration/publisher_confirms_spec.rb +0 -191
  40. data/spec/higher_level_api/integration/publishing_edge_cases_spec.rb +0 -87
  41. data/spec/higher_level_api/integration/queue_bind_spec.rb +0 -109
  42. data/spec/higher_level_api/integration/queue_declare_spec.rb +0 -285
  43. data/spec/higher_level_api/integration/queue_delete_spec.rb +0 -41
  44. data/spec/higher_level_api/integration/queue_purge_spec.rb +0 -30
  45. data/spec/higher_level_api/integration/queue_unbind_spec.rb +0 -54
  46. data/spec/higher_level_api/integration/read_only_consumer_spec.rb +0 -60
  47. data/spec/higher_level_api/integration/sender_selected_distribution_spec.rb +0 -36
  48. data/spec/higher_level_api/integration/tls_connection_spec.rb +0 -255
  49. data/spec/higher_level_api/integration/toxiproxy_spec.rb +0 -76
  50. data/spec/higher_level_api/integration/tx_commit_spec.rb +0 -21
  51. data/spec/higher_level_api/integration/tx_rollback_spec.rb +0 -21
  52. data/spec/higher_level_api/integration/with_channel_spec.rb +0 -25
  53. data/spec/issues/issue100_spec.rb +0 -42
  54. data/spec/issues/issue141_spec.rb +0 -43
  55. data/spec/issues/issue202_spec.rb +0 -15
  56. data/spec/issues/issue224_spec.rb +0 -40
  57. data/spec/issues/issue465_spec.rb +0 -32
  58. data/spec/issues/issue549_spec.rb +0 -30
  59. data/spec/issues/issue609_spec.rb +0 -84
  60. data/spec/issues/issue78_spec.rb +0 -72
  61. data/spec/issues/issue83_spec.rb +0 -30
  62. data/spec/issues/issue97_attachment.json +0 -1
  63. data/spec/issues/issue97_spec.rb +0 -175
  64. data/spec/lower_level_api/integration/basic_cancel_spec.rb +0 -83
  65. data/spec/lower_level_api/integration/basic_consume_spec.rb +0 -99
  66. data/spec/spec_helper.rb +0 -47
  67. data/spec/stress/channel_close_stress_spec.rb +0 -64
  68. data/spec/stress/channel_open_stress_spec.rb +0 -84
  69. data/spec/stress/channel_open_stress_with_single_threaded_connection_spec.rb +0 -28
  70. data/spec/stress/concurrent_consumers_stress_spec.rb +0 -71
  71. data/spec/stress/concurrent_publishers_stress_spec.rb +0 -54
  72. data/spec/stress/connection_open_close_spec.rb +0 -52
  73. data/spec/stress/merry_go_round_spec.rb +0 -105
  74. data/spec/toxiproxy_helper.rb +0 -28
  75. data/spec/unit/bunny_spec.rb +0 -15
  76. data/spec/unit/concurrent/atomic_fixnum_spec.rb +0 -35
  77. data/spec/unit/concurrent/condition_spec.rb +0 -82
  78. data/spec/unit/concurrent/linked_continuation_queue_spec.rb +0 -35
  79. data/spec/unit/concurrent/synchronized_sorted_set_spec.rb +0 -73
  80. data/spec/unit/exchange_recovery_spec.rb +0 -39
  81. data/spec/unit/version_delivery_tag_spec.rb +0 -28
@@ -1,95 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe Bunny::Queue, "#subscribe" do
4
- let(:connection) do
5
- c = Bunny.new(username: "bunny_gem", password: "bunny_password", vhost: "bunny_testbed")
6
- c.start
7
- c
8
- end
9
-
10
- after :each do
11
- connection.close if connection.open?
12
- end
13
-
14
- let(:queue_name) { "bunny.basic_consume#{rand}" }
15
-
16
- it "provides delivery handler access to message properties" do
17
- @now = Time.now
18
- metadata = {}
19
- envelope = {}
20
-
21
- t = Thread.new do
22
- ch = connection.create_channel
23
- q = ch.queue(queue_name, auto_delete: true, durable: false)
24
- q.subscribe(exclusive: true, manual_ack: false) do |delivery_info, properties, payload|
25
- metadata = properties
26
- envelope = delivery_info
27
- end
28
- end
29
- t.abort_on_exception = true
30
- sleep 0.5
31
-
32
- ch = connection.create_channel
33
- x = ch.default_exchange
34
- x.publish("hello",
35
- routing_key: queue_name,
36
- app_id: "bunny.example",
37
- priority: 8,
38
- type: "kinda.checkin",
39
- # headers table keys can be anything
40
- headers: {
41
- coordinates: {
42
- latitude: 59.35,
43
- longitude: 18.066667
44
- },
45
- time: @now,
46
- participants: 11,
47
- venue: "Stockholm",
48
- true_field: true,
49
- false_field: false,
50
- nil_field: nil,
51
- ary_field: ["one", 2.0, 3, [{"abc" => 123}]]
52
- },
53
- timestamp: @now.to_i,
54
- reply_to: "a.sender",
55
- correlation_id: "r-1",
56
- message_id: "m-1")
57
-
58
- sleep 0.7
59
-
60
- expect(metadata.content_type).to eq "application/octet-stream"
61
- expect(metadata.priority).to eq 8
62
-
63
- time = metadata.headers["time"]
64
- expect(time.year).to eq @now.year
65
- expect(time.month).to eq @now.month
66
- expect(time.day).to eq @now.day
67
- expect(time.hour).to eq @now.hour
68
- expect(time.min).to eq @now.min
69
- expect(time.sec).to eq @now.sec
70
-
71
- expect(metadata.headers["coordinates"]["latitude"]).to eq 59.35
72
- expect(metadata.headers["participants"]).to eq 11
73
- expect(metadata.headers["venue"]).to eq "Stockholm"
74
- expect(metadata.headers["true_field"]).to eq true
75
- expect(metadata.headers["false_field"]).to eq false
76
- expect(metadata.headers["nil_field"]).to be_nil
77
- expect(metadata.headers["ary_field"]).to eq ["one", 2.0, 3, [{ "abc" => 123}]]
78
-
79
- expect(metadata.timestamp).to eq Time.at(@now.to_i)
80
- expect(metadata.type).to eq "kinda.checkin"
81
- expect(metadata.reply_to).to eq "a.sender"
82
- expect(metadata.correlation_id).to eq "r-1"
83
- expect(metadata.message_id).to eq "m-1"
84
- expect(metadata.app_id).to eq "bunny.example"
85
-
86
- expect(envelope.consumer_tag).not_to be_nil
87
- expect(envelope.consumer_tag).not_to be_empty
88
- expect(envelope).not_to be_redelivered
89
- expect(envelope.delivery_tag).to eq 1
90
- expect(envelope.routing_key).to eq queue_name
91
- expect(envelope.exchange).to eq ""
92
-
93
- ch.close
94
- end
95
- end
@@ -1,24 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe "amq.* exchanges" do
4
- let(:connection) do
5
- c = Bunny.new(username: "bunny_gem", password: "bunny_password", vhost: "bunny_testbed")
6
- c.start
7
- c
8
- end
9
-
10
- after :each do
11
- connection.close if connection.open?
12
- end
13
-
14
- it "are predeclared" do
15
- ch = connection.create_channel
16
-
17
- ["amq.fanout", "amq.direct", "amq.topic", "amq.match", "amq.headers"].each do |e|
18
- x = ch.exchange(e)
19
- expect(x).to be_predeclared
20
- end
21
-
22
- ch.close
23
- end
24
- end
@@ -1,191 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe Bunny::Channel do
4
- after :each do
5
- connection.close if connection.open?
6
- end
7
-
8
- let(:n) { 200 }
9
-
10
- shared_examples "publish confirms" do
11
- context "when publishing with confirms enabled" do
12
- it "increments delivery index" do
13
- ch = connection.create_channel
14
- expect(ch).not_to be_using_publisher_confirmations
15
-
16
- ch.confirm_select
17
- expect(ch).to be_using_publisher_confirmations
18
-
19
- q = ch.queue("", exclusive: true)
20
- x = ch.default_exchange
21
-
22
- n.times do
23
- x.publish("xyzzy", routing_key: q.name)
24
- end
25
-
26
- expect(ch.next_publish_seq_no).to eq n + 1
27
- expect(ch.wait_for_confirms).to eq true
28
- sleep 0.25
29
-
30
- expect(q.message_count).to eq n
31
- q.purge
32
-
33
- ch.close
34
- end
35
-
36
- describe "#wait_for_confirms" do
37
- it "should not hang when all the publishes are confirmed" do
38
- ch = connection.create_channel
39
- expect(ch).not_to be_using_publisher_confirmations
40
-
41
- ch.confirm_select
42
- expect(ch).to be_using_publisher_confirmations
43
-
44
- q = ch.queue("", exclusive: true)
45
- x = ch.default_exchange
46
-
47
- n.times do
48
- x.publish("xyzzy", routing_key: q.name)
49
- end
50
-
51
- expect(ch.next_publish_seq_no).to eq n + 1
52
- expect(ch.wait_for_confirms).to eq true
53
-
54
- sleep 0.25
55
-
56
- expect {
57
- Bunny::Timeout.timeout(2) do
58
- expect(ch.wait_for_confirms).to eq true
59
- end
60
- }.not_to raise_error
61
-
62
- end
63
-
64
- it "raises an error when called on a closed channel" do
65
- ch = connection.create_channel
66
-
67
- ch.confirm_select
68
-
69
- ch.close
70
-
71
- expect {
72
- ch.wait_for_confirms
73
- }.to raise_error(Bunny::ChannelAlreadyClosed)
74
- end
75
- end
76
-
77
- context "when some of the messages get nacked" do
78
- it "puts the nacks in the nacked_set" do
79
- ch = connection.create_channel
80
- expect(ch).not_to be_using_publisher_confirmations
81
-
82
- ch.confirm_select
83
- expect(ch).to be_using_publisher_confirmations
84
-
85
- q = ch.queue("", exclusive: true)
86
- x = ch.default_exchange
87
-
88
- n.times do
89
- x.publish("xyzzy", routing_key: q.name)
90
- end
91
-
92
- #be sneaky to simulate a nack
93
- nacked_tag = nil
94
- ch.instance_variable_get(:@unconfirmed_set_mutex).synchronize do
95
- expect(ch.unconfirmed_set).to_not be_empty
96
- nacked_tag = ch.unconfirmed_set.reduce(ch.next_publish_seq_no - 1) { |lowest, i| i < lowest ? i : lowest }
97
- ch.handle_ack_or_nack(nacked_tag, false, true)
98
- end
99
-
100
- expect(ch.nacked_set).not_to be_empty
101
- expect(ch.nacked_set).to include(nacked_tag)
102
-
103
- expect(ch.next_publish_seq_no).to eq n + 1
104
- expect(ch.wait_for_confirms).to eq false
105
-
106
- expect(ch.nacked_set).not_to be_empty
107
- expect(ch.nacked_set).to include(nacked_tag)
108
-
109
- sleep 0.25
110
- expect(q.message_count).to eq n
111
- q.purge
112
-
113
- ch.close
114
- end
115
- end
116
- end
117
- end
118
-
119
- context "with a multi-threaded connection" do
120
- let(:connection) do
121
- c = Bunny.new(username: "bunny_gem", password: "bunny_password", vhost: "bunny_testbed", continuation_timeout: 10000)
122
- c.start
123
- c
124
- end
125
-
126
- include_examples "publish confirms"
127
-
128
- it "returns only when all confirmations for publishes are received" do
129
- ch = connection.create_channel
130
-
131
- operations_log = []
132
- operations_log_mutex = Mutex.new
133
- acks_received = Queue.new
134
-
135
- log_acks = proc do |tag, _, is_nack|
136
- operations_log_mutex.synchronize do
137
- operation = "#{'n' if is_nack}ack_#{tag}"
138
- operations_log << operation unless operations_log.include?(operation)
139
- end
140
- acks_received << true
141
- end
142
-
143
- ch.confirm_select(log_acks)
144
-
145
- x = ch.default_exchange
146
- q = ch.temporary_queue
147
-
148
- x.publish('msg', routing_key: q.name)
149
-
150
- # wait for the confirmation to arrive
151
- acks_received.pop
152
-
153
- # artificially simulate a slower ack. the test should work properly even
154
- # without this patch, but it's here just to be sure we catch it.
155
- def (x.channel).handle_ack_or_nack(delivery_tag_before_offset, multiple, nack)
156
- sleep 0.1
157
- super
158
- end
159
-
160
- x.publish('msg', routing_key: q.name)
161
- x.publish('msg', routing_key: q.name)
162
-
163
- if x.wait_for_confirms
164
- operations_log_mutex.synchronize do
165
- operations_log << 'all_confirmed'
166
- end
167
- end
168
-
169
- # wait for all the confirmations to arrive
170
- acks_received.pop
171
- acks_received.pop
172
-
173
- expect(operations_log).to eq([
174
- 'ack_1',
175
- 'ack_2',
176
- 'ack_3',
177
- 'all_confirmed',
178
- ])
179
- end
180
- end
181
-
182
- context "with a single-threaded connection" do
183
- let(:connection) do
184
- c = Bunny.new(username: "bunny_gem", password: "bunny_password", vhost: "bunny_testbed", continuation_timeout: 10000, threaded: false)
185
- c.start
186
- c
187
- end
188
-
189
- include_examples "publish confirms"
190
- end
191
- end
@@ -1,87 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- require "spec_helper"
3
-
4
- unless ENV["CI"]
5
- describe "Message framing implementation" do
6
- let(:connection) do
7
- c = Bunny.new(username: "bunny_gem",
8
- password: "bunny_password",
9
- vhost: "bunny_testbed",
10
- port: ENV.fetch("RABBITMQ_PORT", 5672))
11
- c.start
12
- c
13
- end
14
-
15
- after :each do
16
- connection.close if connection.open?
17
- end
18
-
19
-
20
- context "with payload exceeding 128 Kb (max frame size)" do
21
- it "successfully frames the message" do
22
- ch = connection.create_channel
23
-
24
- q = ch.queue("", exclusive: true)
25
- x = ch.default_exchange
26
-
27
- as = ("a" * (1024 * 1024 * 4 + 28237777))
28
- x.publish(as, routing_key: q.name, persistent: true)
29
-
30
- sleep(1)
31
- expect(q.message_count).to eq 1
32
-
33
- _, _, payload = q.pop
34
- expect(payload.bytesize).to eq as.bytesize
35
-
36
- ch.close
37
- end
38
- end
39
-
40
-
41
- context "with payload of several MBs of non-ASCII characters" do
42
- it "successfully frames the message" do
43
- ch = connection.create_channel
44
-
45
- q = ch.queue("", exclusive: true)
46
- x = ch.default_exchange
47
-
48
- as = "кириллца, йо" * (1024 * 1024)
49
- x.publish(as, routing_key: q.name, persistent: true)
50
-
51
- sleep(1)
52
- expect(q.message_count).to eq 1
53
-
54
- _, _, payload = q.pop
55
- expect(payload.bytesize).to eq as.bytesize
56
-
57
- ch.close
58
- end
59
- end
60
-
61
-
62
-
63
- context "with empty message body" do
64
- it "successfully publishes the message" do
65
- ch = connection.create_channel
66
-
67
- q = ch.queue("", exclusive: true)
68
- x = ch.default_exchange
69
-
70
- x.publish("", routing_key: q.name, persistent: false, mandatory: true)
71
-
72
- sleep(0.5)
73
- expect(q.message_count).to eq 1
74
-
75
- envelope, headers, payload = q.pop
76
-
77
- expect(payload).to eq ""
78
-
79
- expect(headers[:content_type]).to eq "application/octet-stream"
80
- expect(headers[:delivery_mode]).to eq 1
81
- expect(headers[:priority]).to eq 0
82
-
83
- ch.close
84
- end
85
- end
86
- end
87
- end
@@ -1,109 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe "A client-named", Bunny::Queue do
4
- let(:connection) do
5
- c = Bunny.new(username: "bunny_gem", password: "bunny_password", vhost: "bunny_testbed")
6
- c.start
7
- c
8
- end
9
-
10
- it "can be bound to a pre-declared exchange" do
11
- ch = connection.create_channel
12
- q = ch.queue("bunny.tests.queues.client-named#{rand}", exclusive: true)
13
- expect(q).not_to be_server_named
14
-
15
- expect(q.bind("amq.fanout")).to eq q
16
-
17
- ch.close
18
- end
19
-
20
- it "can be unbound from a pre-declared exchange" do
21
- ch = connection.create_channel
22
- q = ch.queue("bunny.tests.queues.client-named#{rand}", exclusive: true)
23
- expect(q).not_to be_server_named
24
-
25
- q.bind("amq.fanout")
26
- expect(q.unbind("amq.fanout")).to eq q
27
-
28
- ch.close
29
- end
30
-
31
- it "can be bound to a custom exchange" do
32
- ch = connection.create_channel
33
- q = ch.queue("bunny.tests.queues.client-named#{rand}", exclusive: true)
34
-
35
- x = ch.fanout("bunny.tests.exchanges.fanout#{rand}")
36
- expect(q.bind(x)).to eq q
37
-
38
- x.delete
39
- ch.close
40
- end
41
-
42
- it "can be unbound from a custom exchange" do
43
- ch = connection.create_channel
44
- q = ch.queue("bunny.tests.queues.client-named#{rand}", exclusive: true)
45
- expect(q).not_to be_server_named
46
-
47
- x = ch.fanout("bunny.tests.fanout", auto_delete: true, durable: false)
48
-
49
- q.bind(x)
50
- expect(q.unbind(x)).to eq q
51
-
52
- ch.close
53
- end
54
- end
55
-
56
-
57
-
58
- describe "A server-named", Bunny::Queue do
59
- let(:connection) do
60
- c = Bunny.new
61
- c.start
62
- c
63
- end
64
-
65
- it "can be bound to a pre-declared exchange" do
66
- ch = connection.create_channel
67
- q = ch.queue("", exclusive: true)
68
- expect(q).to be_server_named
69
-
70
- expect(q.bind("amq.fanout")).to eq q
71
-
72
- ch.close
73
- end
74
-
75
- it "can be unbound from a pre-declared exchange" do
76
- ch = connection.create_channel
77
- q = ch.queue("", exclusive: true)
78
- expect(q).to be_server_named
79
-
80
- q.bind("amq.fanout")
81
- expect(q.unbind("amq.fanout")).to eq q
82
-
83
- ch.close
84
- end
85
-
86
- it "can be bound to a custom exchange" do
87
- ch = connection.create_channel
88
- q = ch.queue("", exclusive: true)
89
-
90
- x = ch.fanout("bunny.tests.exchanges.fanout#{rand}")
91
- expect(q.bind(x)).to eq q
92
-
93
- x.delete
94
- ch.close
95
- end
96
-
97
- it "can be bound from a custom exchange" do
98
- ch = connection.create_channel
99
- q = ch.queue("", exclusive: true)
100
-
101
- name = "bunny.tests.exchanges.fanout#{rand}"
102
- x = ch.fanout(name)
103
- q.bind(x)
104
- expect(q.unbind(name)).to eq q
105
-
106
- x.delete
107
- ch.close
108
- end
109
- end