bunny 2.7.4 → 2.22.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 +5 -5
- data/README.md +61 -35
- data/lib/bunny/channel.rb +186 -50
- data/lib/bunny/channel_id_allocator.rb +3 -1
- data/lib/bunny/consumer.rb +2 -2
- data/lib/bunny/consumer_work_pool.rb +2 -1
- data/lib/bunny/cruby/socket.rb +3 -0
- data/lib/bunny/cruby/ssl_socket.rb +6 -1
- data/lib/bunny/delivery_info.rb +1 -1
- data/lib/bunny/heartbeat_sender.rb +2 -1
- data/lib/bunny/jruby/ssl_socket.rb +5 -0
- data/lib/bunny/queue.rb +36 -8
- data/lib/bunny/reader_loop.rb +22 -10
- data/lib/bunny/session.rb +152 -65
- data/lib/bunny/test_kit.rb +14 -0
- data/lib/bunny/transport.rb +132 -49
- data/lib/bunny/version.rb +1 -1
- data/lib/bunny.rb +45 -4
- metadata +37 -225
- data/.github/ISSUE_TEMPLATE.md +0 -18
- data/.gitignore +0 -28
- data/.rspec +0 -1
- data/.travis.yml +0 -20
- data/.yardopts +0 -8
- data/CONTRIBUTING.md +0 -111
- data/ChangeLog.md +0 -1831
- data/Gemfile +0 -53
- data/LICENSE +0 -21
- data/Rakefile +0 -46
- data/benchmarks/basic_publish/with_128K_messages.rb +0 -35
- data/benchmarks/basic_publish/with_1k_messages.rb +0 -35
- data/benchmarks/basic_publish/with_4K_messages.rb +0 -35
- data/benchmarks/basic_publish/with_64K_messages.rb +0 -35
- data/benchmarks/channel_open.rb +0 -28
- data/benchmarks/mutex_and_monitor.rb +0 -42
- data/benchmarks/queue_declare.rb +0 -29
- data/benchmarks/queue_declare_and_bind.rb +0 -29
- data/benchmarks/queue_declare_bind_and_delete.rb +0 -29
- data/benchmarks/synchronized_sorted_set.rb +0 -53
- data/benchmarks/write_vs_write_nonblock.rb +0 -49
- data/bin/ci/before_build +0 -46
- data/bunny.gemspec +0 -35
- data/docker/Dockerfile +0 -16
- data/docker/docker-entrypoint.sh +0 -37
- data/docker-compose.yml +0 -18
- data/examples/connection/authentication_failure.rb +0 -16
- data/examples/connection/automatic_recovery_with_basic_get.rb +0 -40
- data/examples/connection/automatic_recovery_with_client_named_queues.rb +0 -36
- data/examples/connection/automatic_recovery_with_multiple_consumers.rb +0 -46
- data/examples/connection/automatic_recovery_with_republishing.rb +0 -109
- data/examples/connection/automatic_recovery_with_server_named_queues.rb +0 -35
- data/examples/connection/channel_level_exception.rb +0 -27
- data/examples/connection/disabled_automatic_recovery.rb +0 -34
- data/examples/connection/heartbeat.rb +0 -17
- data/examples/connection/manually_reconnecting_consumer.rb +0 -23
- data/examples/connection/manually_reconnecting_publisher.rb +0 -28
- data/examples/connection/unknown_host.rb +0 -16
- data/examples/consumers/high_and_low_priority.rb +0 -50
- data/examples/guides/exchanges/direct_exchange_routing.rb +0 -36
- data/examples/guides/exchanges/fanout_exchange_routing.rb +0 -28
- data/examples/guides/exchanges/headers_exchange_routing.rb +0 -31
- data/examples/guides/exchanges/mandatory_messages.rb +0 -30
- data/examples/guides/extensions/alternate_exchange.rb +0 -30
- data/examples/guides/extensions/basic_nack.rb +0 -33
- data/examples/guides/extensions/connection_blocked.rb +0 -35
- data/examples/guides/extensions/consumer_cancellation_notification.rb +0 -39
- data/examples/guides/extensions/dead_letter_exchange.rb +0 -32
- data/examples/guides/extensions/exchange_to_exchange_bindings.rb +0 -29
- data/examples/guides/extensions/per_message_ttl.rb +0 -36
- data/examples/guides/extensions/per_queue_message_ttl.rb +0 -36
- data/examples/guides/extensions/publisher_confirms.rb +0 -28
- data/examples/guides/extensions/queue_lease.rb +0 -26
- data/examples/guides/extensions/sender_selected_distribution.rb +0 -32
- data/examples/guides/getting_started/blabbr.rb +0 -27
- data/examples/guides/getting_started/hello_world.rb +0 -22
- data/examples/guides/getting_started/weathr.rb +0 -49
- data/examples/guides/queues/one_off_consumer.rb +0 -25
- data/examples/guides/queues/redeliveries.rb +0 -81
- data/profiling/basic_publish/with_4K_messages.rb +0 -33
- data/repl +0 -3
- data/spec/config/enabled_plugins +0 -1
- data/spec/config/rabbitmq.config +0 -19
- data/spec/higher_level_api/integration/basic_ack_spec.rb +0 -230
- data/spec/higher_level_api/integration/basic_cancel_spec.rb +0 -142
- data/spec/higher_level_api/integration/basic_consume_spec.rb +0 -349
- data/spec/higher_level_api/integration/basic_consume_with_objects_spec.rb +0 -54
- data/spec/higher_level_api/integration/basic_get_spec.rb +0 -80
- data/spec/higher_level_api/integration/basic_nack_spec.rb +0 -82
- data/spec/higher_level_api/integration/basic_publish_spec.rb +0 -74
- data/spec/higher_level_api/integration/basic_qos_spec.rb +0 -57
- data/spec/higher_level_api/integration/basic_reject_spec.rb +0 -152
- data/spec/higher_level_api/integration/basic_return_spec.rb +0 -33
- data/spec/higher_level_api/integration/channel_close_spec.rb +0 -25
- data/spec/higher_level_api/integration/channel_open_spec.rb +0 -57
- data/spec/higher_level_api/integration/connection_recovery_spec.rb +0 -471
- data/spec/higher_level_api/integration/connection_spec.rb +0 -559
- data/spec/higher_level_api/integration/connection_stop_spec.rb +0 -83
- data/spec/higher_level_api/integration/consumer_cancellation_notification_spec.rb +0 -128
- data/spec/higher_level_api/integration/dead_lettering_spec.rb +0 -75
- data/spec/higher_level_api/integration/exchange_bind_spec.rb +0 -31
- data/spec/higher_level_api/integration/exchange_declare_spec.rb +0 -237
- data/spec/higher_level_api/integration/exchange_delete_spec.rb +0 -105
- data/spec/higher_level_api/integration/exchange_unbind_spec.rb +0 -40
- data/spec/higher_level_api/integration/exclusive_queue_spec.rb +0 -28
- data/spec/higher_level_api/integration/heartbeat_spec.rb +0 -49
- data/spec/higher_level_api/integration/merry_go_round_spec.rb +0 -85
- data/spec/higher_level_api/integration/message_properties_access_spec.rb +0 -95
- data/spec/higher_level_api/integration/predeclared_exchanges_spec.rb +0 -24
- data/spec/higher_level_api/integration/publisher_confirms_spec.rb +0 -191
- data/spec/higher_level_api/integration/publishing_edge_cases_spec.rb +0 -87
- data/spec/higher_level_api/integration/queue_bind_spec.rb +0 -109
- data/spec/higher_level_api/integration/queue_declare_spec.rb +0 -221
- data/spec/higher_level_api/integration/queue_delete_spec.rb +0 -41
- data/spec/higher_level_api/integration/queue_purge_spec.rb +0 -30
- data/spec/higher_level_api/integration/queue_unbind_spec.rb +0 -54
- data/spec/higher_level_api/integration/read_only_consumer_spec.rb +0 -60
- data/spec/higher_level_api/integration/sender_selected_distribution_spec.rb +0 -36
- data/spec/higher_level_api/integration/tls_connection_spec.rb +0 -222
- data/spec/higher_level_api/integration/tx_commit_spec.rb +0 -21
- data/spec/higher_level_api/integration/tx_rollback_spec.rb +0 -21
- data/spec/higher_level_api/integration/with_channel_spec.rb +0 -25
- data/spec/issues/issue100_spec.rb +0 -42
- data/spec/issues/issue141_spec.rb +0 -43
- data/spec/issues/issue202_spec.rb +0 -15
- data/spec/issues/issue224_spec.rb +0 -40
- data/spec/issues/issue465_spec.rb +0 -32
- data/spec/issues/issue78_spec.rb +0 -72
- data/spec/issues/issue83_spec.rb +0 -30
- data/spec/issues/issue97_attachment.json +0 -1
- data/spec/issues/issue97_spec.rb +0 -175
- data/spec/lower_level_api/integration/basic_cancel_spec.rb +0 -83
- data/spec/lower_level_api/integration/basic_consume_spec.rb +0 -99
- data/spec/spec_helper.rb +0 -51
- data/spec/stress/channel_close_stress_spec.rb +0 -64
- data/spec/stress/channel_open_stress_spec.rb +0 -84
- data/spec/stress/channel_open_stress_with_single_threaded_connection_spec.rb +0 -28
- data/spec/stress/concurrent_consumers_stress_spec.rb +0 -71
- data/spec/stress/concurrent_publishers_stress_spec.rb +0 -54
- data/spec/stress/connection_open_close_spec.rb +0 -52
- data/spec/stress/long_running_consumer_spec.rb +0 -84
- data/spec/tls/ca_certificate.pem +0 -29
- data/spec/tls/ca_key.pem +0 -52
- data/spec/tls/client_certificate.pem +0 -29
- data/spec/tls/client_key.pem +0 -51
- data/spec/tls/generate-server-cert.sh +0 -8
- data/spec/tls/server-openssl.cnf +0 -10
- data/spec/tls/server.csr +0 -16
- data/spec/tls/server_certificate.pem +0 -29
- data/spec/tls/server_key.pem +0 -51
- data/spec/unit/bunny_spec.rb +0 -15
- data/spec/unit/concurrent/atomic_fixnum_spec.rb +0 -35
- data/spec/unit/concurrent/condition_spec.rb +0 -82
- data/spec/unit/concurrent/linked_continuation_queue_spec.rb +0 -35
- data/spec/unit/concurrent/synchronized_sorted_set_spec.rb +0 -73
- data/spec/unit/exchange_recovery_spec.rb +0 -39
- data/spec/unit/version_delivery_tag_spec.rb +0 -28
data/spec/issues/issue97_spec.rb
DELETED
@@ -1,175 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe "Message framing implementation" do
|
4
|
-
before :all do
|
5
|
-
@connection = Bunny.new(username: "bunny_gem",
|
6
|
-
password: "bunny_password",
|
7
|
-
vhost: "bunny_testbed",
|
8
|
-
port: ENV.fetch("RABBITMQ_PORT", 5672))
|
9
|
-
@connection.start
|
10
|
-
end
|
11
|
-
|
12
|
-
after :all do
|
13
|
-
@connection.close if @connection.open?
|
14
|
-
end
|
15
|
-
|
16
|
-
|
17
|
-
unless ENV["CI"]
|
18
|
-
context "with payload ~ 248K in size including non-ASCII characters" do
|
19
|
-
it "successfully frames the message" do
|
20
|
-
ch = @connection.create_channel
|
21
|
-
|
22
|
-
q = ch.queue("", exclusive: true)
|
23
|
-
x = ch.default_exchange
|
24
|
-
|
25
|
-
body = IO.read("spec/issues/issue97_attachment.json")
|
26
|
-
x.publish(body, routing_key: q.name, persistent: true)
|
27
|
-
|
28
|
-
sleep(1)
|
29
|
-
expect(q.message_count).to eq 1
|
30
|
-
|
31
|
-
q.purge
|
32
|
-
ch.close
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
|
38
|
-
context "with payload of several MBs in size" do
|
39
|
-
it "successfully frames the message" do
|
40
|
-
ch = @connection.create_channel
|
41
|
-
|
42
|
-
q = ch.queue("", exclusive: true)
|
43
|
-
x = ch.default_exchange
|
44
|
-
|
45
|
-
as = ("a" * (1024 * 1024 * 4 + 2823777))
|
46
|
-
x.publish(as, routing_key: q.name, persistent: true)
|
47
|
-
|
48
|
-
sleep(1)
|
49
|
-
expect(q.message_count).to eq 1
|
50
|
-
|
51
|
-
_, _, payload = q.pop
|
52
|
-
expect(payload.bytesize).to eq as.bytesize
|
53
|
-
|
54
|
-
ch.close
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
context "with empty message body" do
|
61
|
-
it "successfully publishes the message" do
|
62
|
-
ch = @connection.create_channel
|
63
|
-
|
64
|
-
q = ch.queue("", exclusive: true)
|
65
|
-
x = ch.default_exchange
|
66
|
-
|
67
|
-
x.publish("", routing_key: q.name, persistent: true)
|
68
|
-
|
69
|
-
sleep(1)
|
70
|
-
expect(q.message_count).to eq 1
|
71
|
-
|
72
|
-
envelope, headers, payload = q.pop
|
73
|
-
|
74
|
-
expect(payload).to eq ""
|
75
|
-
|
76
|
-
expect(headers[:content_type]).to eq "application/octet-stream"
|
77
|
-
expect(headers[:delivery_mode]).to eq 2
|
78
|
-
expect(headers[:priority]).to eq 0
|
79
|
-
|
80
|
-
ch.close
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
|
85
|
-
context "with payload being 2 bytes less than 128K bytes in size" do
|
86
|
-
it "successfully frames the message" do
|
87
|
-
ch = @connection.create_channel
|
88
|
-
|
89
|
-
q = ch.queue("", exclusive: true)
|
90
|
-
x = ch.default_exchange
|
91
|
-
|
92
|
-
as = "a" * (1024 * 128 - 2)
|
93
|
-
x.publish(as, routing_key: q.name, persistent: true)
|
94
|
-
|
95
|
-
sleep(1)
|
96
|
-
expect(q.message_count).to eq 1
|
97
|
-
|
98
|
-
q.purge
|
99
|
-
ch.close
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
context "with payload being 1 byte less than 128K bytes in size" do
|
104
|
-
it "successfully frames the message" do
|
105
|
-
ch = @connection.create_channel
|
106
|
-
|
107
|
-
q = ch.queue("", exclusive: true)
|
108
|
-
x = ch.default_exchange
|
109
|
-
|
110
|
-
as = "a" * (1024 * 128 - 1)
|
111
|
-
x.publish(as, routing_key: q.name, persistent: true)
|
112
|
-
|
113
|
-
sleep(1)
|
114
|
-
expect(q.message_count).to eq 1
|
115
|
-
|
116
|
-
q.purge
|
117
|
-
ch.close
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
context "with payload being exactly 128K bytes in size" do
|
122
|
-
it "successfully frames the message" do
|
123
|
-
ch = @connection.create_channel
|
124
|
-
|
125
|
-
q = ch.queue("", exclusive: true)
|
126
|
-
x = ch.default_exchange
|
127
|
-
|
128
|
-
as = "a" * (1024 * 128)
|
129
|
-
x.publish(as, routing_key: q.name, persistent: true)
|
130
|
-
|
131
|
-
sleep(1)
|
132
|
-
expect(q.message_count).to eq 1
|
133
|
-
|
134
|
-
q.purge
|
135
|
-
ch.close
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
|
140
|
-
context "with payload being 1 byte greater than 128K bytes in size" do
|
141
|
-
it "successfully frames the message" do
|
142
|
-
ch = @connection.create_channel
|
143
|
-
|
144
|
-
q = ch.queue("", exclusive: true)
|
145
|
-
x = ch.default_exchange
|
146
|
-
|
147
|
-
as = "a" * (1024 * 128 + 1)
|
148
|
-
x.publish(as, routing_key: q.name, persistent: true)
|
149
|
-
|
150
|
-
sleep(1)
|
151
|
-
expect(q.message_count).to eq 1
|
152
|
-
|
153
|
-
q.purge
|
154
|
-
ch.close
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
context "with payload being 2 bytes greater than 128K bytes in size" do
|
159
|
-
it "successfully frames the message" do
|
160
|
-
ch = @connection.create_channel
|
161
|
-
|
162
|
-
q = ch.queue("", exclusive: true)
|
163
|
-
x = ch.default_exchange
|
164
|
-
|
165
|
-
as = "a" * (1024 * 128 + 2)
|
166
|
-
x.publish(as, routing_key: q.name, persistent: true)
|
167
|
-
|
168
|
-
sleep(1)
|
169
|
-
expect(q.message_count).to eq 1
|
170
|
-
|
171
|
-
q.purge
|
172
|
-
ch.close
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
@@ -1,83 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe Bunny::Channel, "#basic_cancel" do
|
4
|
-
before(:all) do
|
5
|
-
@connection = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed")
|
6
|
-
@connection.start
|
7
|
-
end
|
8
|
-
|
9
|
-
after :all do
|
10
|
-
@connection.close if @connection.open?
|
11
|
-
end
|
12
|
-
|
13
|
-
let(:queue_name) { "bunny.queues.#{rand}" }
|
14
|
-
|
15
|
-
it "returns basic.cancel-ok" do
|
16
|
-
ch = @connection.create_channel
|
17
|
-
q = ch.queue("", :exclusive => true)
|
18
|
-
|
19
|
-
consume_ok = ch.basic_consume(q, "")
|
20
|
-
cancel_ok = ch.basic_cancel(consume_ok.consumer_tag)
|
21
|
-
|
22
|
-
expect(cancel_ok).to be_instance_of AMQ::Protocol::Basic::CancelOk
|
23
|
-
expect(cancel_ok.consumer_tag).to eq consume_ok.consumer_tag
|
24
|
-
|
25
|
-
ch.close
|
26
|
-
end
|
27
|
-
|
28
|
-
context "when the given consumer tag is valid" do
|
29
|
-
let(:queue_name) { "bunny.basic.cancel.queue#{rand}" }
|
30
|
-
|
31
|
-
it "cancels the consumer" do
|
32
|
-
delivered_data = []
|
33
|
-
|
34
|
-
t = Thread.new do
|
35
|
-
ch = @connection.create_channel
|
36
|
-
q = ch.queue(queue_name, :auto_delete => true, :durable => false)
|
37
|
-
consume_ok = ch.basic_consume(q, "", true, false) do |_, _, payload|
|
38
|
-
delivered_data << payload
|
39
|
-
end
|
40
|
-
|
41
|
-
expect(consume_ok.consumer_tag).not_to be_nil
|
42
|
-
cancel_ok = ch.basic_cancel(consume_ok.consumer_tag)
|
43
|
-
expect(cancel_ok.consumer_tag).to eq consume_ok.consumer_tag
|
44
|
-
|
45
|
-
ch.close
|
46
|
-
end
|
47
|
-
t.abort_on_exception = true
|
48
|
-
sleep 0.5
|
49
|
-
|
50
|
-
ch = @connection.create_channel
|
51
|
-
ch.default_exchange.publish("", :routing_key => queue_name)
|
52
|
-
|
53
|
-
sleep 0.7
|
54
|
-
expect(delivered_data).to be_empty
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
context "when the given consumer tag is invalid (was never registered)" do
|
59
|
-
it "DOES NOT cause a channel error" do
|
60
|
-
ch = @connection.create_channel
|
61
|
-
|
62
|
-
# RabbitMQ 3.1 does not raise an exception w/ unknown consumer tag. MK.
|
63
|
-
ch.basic_cancel("878798s7df89#{rand}#{Time.now.to_i}")
|
64
|
-
|
65
|
-
ch.close
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
context "when the given consumer tag belongs to a different channel" do
|
70
|
-
it "DOES NOT cause a channel error" do
|
71
|
-
ch1 = @connection.create_channel
|
72
|
-
ch2 = @connection.create_channel
|
73
|
-
|
74
|
-
q = ch1.queue("", :exclusive => true)
|
75
|
-
cons = q.subscribe do |_, _, _|
|
76
|
-
end
|
77
|
-
ch2.basic_cancel(cons.consumer_tag)
|
78
|
-
|
79
|
-
ch1.close
|
80
|
-
ch2.close
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
@@ -1,99 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe Bunny::Channel, "#basic_consume" do
|
4
|
-
before(:all) do
|
5
|
-
@connection = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed")
|
6
|
-
@connection.start
|
7
|
-
end
|
8
|
-
|
9
|
-
after :all do
|
10
|
-
@connection.close if @connection.open?
|
11
|
-
end
|
12
|
-
|
13
|
-
it "returns basic.consume-ok when it is received" do
|
14
|
-
ch = @connection.create_channel
|
15
|
-
q = ch.queue("", :exclusive => true)
|
16
|
-
|
17
|
-
consume_ok = ch.basic_consume(q)
|
18
|
-
expect(consume_ok).to be_instance_of AMQ::Protocol::Basic::ConsumeOk
|
19
|
-
expect(consume_ok.consumer_tag).not_to be_nil
|
20
|
-
|
21
|
-
ch.close
|
22
|
-
end
|
23
|
-
|
24
|
-
it "carries server-generated consumer tag with basic.consume-ok" do
|
25
|
-
ch = @connection.create_channel
|
26
|
-
q = ch.queue("", :exclusive => true)
|
27
|
-
|
28
|
-
consume_ok = ch.basic_consume(q, "")
|
29
|
-
expect(consume_ok.consumer_tag).to match /amq\.ctag.*/
|
30
|
-
|
31
|
-
ch.close
|
32
|
-
end
|
33
|
-
|
34
|
-
context "with automatic acknowledgement mode" do
|
35
|
-
let(:queue_name) { "bunny.basic_consume#{rand}" }
|
36
|
-
|
37
|
-
it "causes messages to be automatically removed from the queue after delivery" do
|
38
|
-
delivered_keys = []
|
39
|
-
delivered_data = []
|
40
|
-
|
41
|
-
t = Thread.new do
|
42
|
-
ch = @connection.create_channel
|
43
|
-
q = ch.queue(queue_name, :auto_delete => true, :durable => false)
|
44
|
-
ch.basic_consume(q, "", true, false) do |delivery_info, properties, payload|
|
45
|
-
delivered_keys << delivery_info.routing_key
|
46
|
-
delivered_data << payload
|
47
|
-
end
|
48
|
-
end
|
49
|
-
t.abort_on_exception = true
|
50
|
-
sleep 0.5
|
51
|
-
|
52
|
-
ch = @connection.create_channel
|
53
|
-
x = ch.default_exchange
|
54
|
-
x.publish("hello", :routing_key => queue_name)
|
55
|
-
|
56
|
-
sleep 0.7
|
57
|
-
expect(delivered_keys).to include queue_name
|
58
|
-
expect(delivered_data).to include "hello"
|
59
|
-
|
60
|
-
expect(ch.queue(queue_name, :auto_delete => true, :durable => false).message_count).to eq 0
|
61
|
-
|
62
|
-
ch.close
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
context "with manual acknowledgement mode" do
|
67
|
-
let(:queue_name) { "bunny.basic_consume#{rand}" }
|
68
|
-
|
69
|
-
it "waits for an explicit acknowledgement" do
|
70
|
-
delivered_keys = []
|
71
|
-
delivered_data = []
|
72
|
-
|
73
|
-
t = Thread.new do
|
74
|
-
ch = @connection.create_channel
|
75
|
-
q = ch.queue(queue_name, :auto_delete => true, :durable => false)
|
76
|
-
ch.basic_consume(q, "", false, false) do |delivery_info, properties, payload|
|
77
|
-
delivered_keys << delivery_info.routing_key
|
78
|
-
delivered_data << payload
|
79
|
-
|
80
|
-
ch.close
|
81
|
-
end
|
82
|
-
end
|
83
|
-
t.abort_on_exception = true
|
84
|
-
sleep 0.5
|
85
|
-
|
86
|
-
ch = @connection.create_channel
|
87
|
-
x = ch.default_exchange
|
88
|
-
x.publish("hello", :routing_key => queue_name)
|
89
|
-
|
90
|
-
sleep 0.7
|
91
|
-
expect(delivered_keys).to include queue_name
|
92
|
-
expect(delivered_data).to include "hello"
|
93
|
-
|
94
|
-
expect(ch.queue(queue_name, :auto_delete => true, :durable => false).message_count).to eq 0
|
95
|
-
|
96
|
-
ch.close
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8; mode: ruby -*-
|
2
|
-
|
3
|
-
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
4
|
-
|
5
|
-
require 'bundler'
|
6
|
-
Bundler.setup(:default, :test)
|
7
|
-
|
8
|
-
|
9
|
-
require "effin_utf8"
|
10
|
-
require "bunny"
|
11
|
-
require "rabbitmq/http/client"
|
12
|
-
|
13
|
-
|
14
|
-
require "amq/protocol/version"
|
15
|
-
puts "Using Ruby #{RUBY_VERSION}, amq-protocol #{AMQ::Protocol::VERSION}"
|
16
|
-
|
17
|
-
module RabbitMQ
|
18
|
-
module Control
|
19
|
-
|
20
|
-
RABBITMQ_NODENAME = ENV['RABBITMQ_NODENAME'] || 'rabbit'
|
21
|
-
|
22
|
-
def rabbitmq_pid
|
23
|
-
$1.to_i if `rabbitmqctl -n #{RABBITMQ_NODENAME} status` =~ /\{pid,(\d+)\}/
|
24
|
-
end
|
25
|
-
|
26
|
-
def start_rabbitmq(delay = 1.0)
|
27
|
-
# this is Homebrew-specific :(
|
28
|
-
`RABBITMQ_NODENAME=#{RABBITMQ_NODENAME} rabbitmq-server > /dev/null 2>&1 &`; sleep(delay)
|
29
|
-
end
|
30
|
-
|
31
|
-
def stop_rabbitmq(pid = rabbitmq_pid, delay = 1.0)
|
32
|
-
`rabbitmqctl -n #{RABBITMQ_NODENAME} stop`; sleep(delay)
|
33
|
-
end
|
34
|
-
|
35
|
-
def kill_rabbitmq(pid = rabbitmq_pid, delay = 1.0)
|
36
|
-
# tango is down, tango is down!
|
37
|
-
Process.kill("KILL", pid); sleep(delay)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
|
43
|
-
module PlatformDetection
|
44
|
-
def mri?
|
45
|
-
!defined?(RUBY_ENGINE) || (defined?(RUBY_ENGINE) && ("ruby" == RUBY_ENGINE))
|
46
|
-
end
|
47
|
-
|
48
|
-
def rubinius?
|
49
|
-
defined?(RUBY_ENGINE) && (RUBY_ENGINE == 'rbx')
|
50
|
-
end
|
51
|
-
end
|
@@ -1,64 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe "Rapidly closing lots of temporary channels" do
|
4
|
-
before :all do
|
5
|
-
@connection = Bunny.new(automatic_recovery: false).tap do |c|
|
6
|
-
c.start
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
after :all do
|
11
|
-
@connection.close
|
12
|
-
end
|
13
|
-
|
14
|
-
100.times do |i|
|
15
|
-
context "in a multi-threaded scenario A (take #{i})" do
|
16
|
-
let(:n) { 20 }
|
17
|
-
|
18
|
-
it "works correctly" do
|
19
|
-
ts = []
|
20
|
-
|
21
|
-
n.times do
|
22
|
-
t = Thread.new do
|
23
|
-
@connection.with_channel do |ch1|
|
24
|
-
q = ch1.queue("", exclusive: true)
|
25
|
-
q.delete
|
26
|
-
ch1.close
|
27
|
-
end
|
28
|
-
|
29
|
-
ch2 = @connection.create_channel
|
30
|
-
ch2.close
|
31
|
-
end
|
32
|
-
t.abort_on_exception = true
|
33
|
-
ts << t
|
34
|
-
end
|
35
|
-
|
36
|
-
ts.each { |t| t.join }
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
100.times do |i|
|
42
|
-
context "in a multi-threaded scenario B (take #{i})" do
|
43
|
-
let(:n) { 20 }
|
44
|
-
|
45
|
-
it "works correctly" do
|
46
|
-
ts = []
|
47
|
-
|
48
|
-
n.times do
|
49
|
-
t = Thread.new do
|
50
|
-
3.times do
|
51
|
-
@connection.with_channel do |ch|
|
52
|
-
x = ch.topic('bunny.stress.topics.t2', durable: false)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
t.abort_on_exception = true
|
57
|
-
ts << t
|
58
|
-
end
|
59
|
-
|
60
|
-
ts.each { |t| t.join }
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
@@ -1,84 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe "Rapidly opening and closing lots of channels" do
|
4
|
-
before :all do
|
5
|
-
@connection = Bunny.new(automatic_recovery: false).tap do |c|
|
6
|
-
c.start
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
after :all do
|
11
|
-
@connection.close
|
12
|
-
end
|
13
|
-
|
14
|
-
context "in a single-threaded scenario" do
|
15
|
-
let(:n) { 500 }
|
16
|
-
|
17
|
-
it "works correctly" do
|
18
|
-
xs = Array.new(n) { @connection.create_channel }
|
19
|
-
puts "Opened #{n} channels"
|
20
|
-
|
21
|
-
expect(xs.size).to eq n
|
22
|
-
xs.each do |ch|
|
23
|
-
ch.close
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
100.times do |i|
|
29
|
-
context "in a multi-threaded scenario A (take #{i})" do
|
30
|
-
# actually, on MRI values greater than ~100 will eventually cause write
|
31
|
-
# operations to fail with a timeout (1 second is not enough)
|
32
|
-
# which will cause recovery to re-acquire @channel_mutex in Session.
|
33
|
-
# Because Ruby's mutexes are not re-entrant, it will raise a ThreadError.
|
34
|
-
#
|
35
|
-
# But this already demonstrates that within these platform constraints,
|
36
|
-
# Bunny is safe to use in such scenarios.
|
37
|
-
let(:n) { 20 }
|
38
|
-
|
39
|
-
it "works correctly" do
|
40
|
-
ts = []
|
41
|
-
|
42
|
-
n.times do
|
43
|
-
t = Thread.new do
|
44
|
-
ch1 = @connection.create_channel
|
45
|
-
q = ch1.queue("", exclusive: true)
|
46
|
-
q.delete
|
47
|
-
ch1.close
|
48
|
-
|
49
|
-
ch2 = @connection.create_channel
|
50
|
-
ch2.close
|
51
|
-
end
|
52
|
-
t.abort_on_exception = true
|
53
|
-
ts << t
|
54
|
-
end
|
55
|
-
|
56
|
-
ts.each { |t| t.join }
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
100.times do |i|
|
62
|
-
context "in a multi-threaded scenario B (take #{i})" do
|
63
|
-
let(:n) { 20 }
|
64
|
-
|
65
|
-
it "works correctly" do
|
66
|
-
ts = []
|
67
|
-
|
68
|
-
n.times do
|
69
|
-
t = Thread.new do
|
70
|
-
3.times do
|
71
|
-
ch = @connection.create_channel
|
72
|
-
x = ch.topic('bunny.stress.topics.t2', durable: false)
|
73
|
-
ch.close
|
74
|
-
end
|
75
|
-
end
|
76
|
-
t.abort_on_exception = true
|
77
|
-
ts << t
|
78
|
-
end
|
79
|
-
|
80
|
-
ts.each { |t| t.join }
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
unless ENV["CI"]
|
4
|
-
describe "Rapidly opening and closing lots of channels on a non-threaded connection" do
|
5
|
-
before :all do
|
6
|
-
@connection = Bunny.new(username: "bunny_gem", password: "bunny_password", vhost: "bunny_testbed",
|
7
|
-
automatic_recovery: false, threaded: false)
|
8
|
-
@connection.start
|
9
|
-
end
|
10
|
-
|
11
|
-
after :all do
|
12
|
-
@connection.close
|
13
|
-
end
|
14
|
-
|
15
|
-
context "in a single-threaded scenario" do
|
16
|
-
let(:n) { 500 }
|
17
|
-
|
18
|
-
it "works correctly" do
|
19
|
-
xs = Array.new(n) { @connection.create_channel }
|
20
|
-
|
21
|
-
expect(xs.size).to eq n
|
22
|
-
xs.each do |ch|
|
23
|
-
ch.close
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
@@ -1,71 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
require "spec_helper"
|
3
|
-
|
4
|
-
unless ENV["CI"]
|
5
|
-
describe "Concurrent consumers sharing a connection" do
|
6
|
-
before :all do
|
7
|
-
@connection = Bunny.new(username: "bunny_gem", password: "bunny_password", vhost: "bunny_testbed",
|
8
|
-
automatic_recovery: false, continuation_timeout: 45000)
|
9
|
-
@connection.start
|
10
|
-
end
|
11
|
-
|
12
|
-
after :all do
|
13
|
-
@connection.close
|
14
|
-
end
|
15
|
-
|
16
|
-
def any_not_drained?(qs)
|
17
|
-
qs.any? { |q| !q.message_count.zero? }
|
18
|
-
end
|
19
|
-
|
20
|
-
context "when publishing thousands of messages over 128K in size" do
|
21
|
-
let(:colors) { ["red", "blue", "white"] }
|
22
|
-
|
23
|
-
let(:n) { 16 }
|
24
|
-
let(:m) { 5000 }
|
25
|
-
|
26
|
-
it "successfully drain all queues" do
|
27
|
-
ch0 = @connection.create_channel
|
28
|
-
ch0.confirm_select
|
29
|
-
body = "абвг"
|
30
|
-
x = ch0.topic("bunny.stress.concurrent.consumers.topic", durable: true)
|
31
|
-
|
32
|
-
chs = {}
|
33
|
-
n.times do |i|
|
34
|
-
chs[i] = @connection.create_channel
|
35
|
-
end
|
36
|
-
qs = []
|
37
|
-
|
38
|
-
n.times do |i|
|
39
|
-
t = Thread.new do
|
40
|
-
cht = chs[i]
|
41
|
-
|
42
|
-
q = cht.queue("", exclusive: true)
|
43
|
-
q.bind(x.name, routing_key: colors.sample).subscribe do |delivery_info, meta, payload|
|
44
|
-
# no-op
|
45
|
-
end
|
46
|
-
qs << q
|
47
|
-
end
|
48
|
-
t.abort_on_exception = true
|
49
|
-
end
|
50
|
-
|
51
|
-
sleep 1.0
|
52
|
-
|
53
|
-
5.times do |i|
|
54
|
-
m.times do
|
55
|
-
x.publish(body, routing_key: colors.sample)
|
56
|
-
end
|
57
|
-
puts "Published #{(i + 1) * m} messages..."
|
58
|
-
ch0.wait_for_confirms
|
59
|
-
end
|
60
|
-
|
61
|
-
while any_not_drained?(qs)
|
62
|
-
sleep 1.0
|
63
|
-
end
|
64
|
-
puts "Drained all queues, winding down..."
|
65
|
-
|
66
|
-
ch0.close
|
67
|
-
chs.each { |_, ch| ch.close }
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
@@ -1,54 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
require "spec_helper"
|
3
|
-
|
4
|
-
unless ENV["CI"]
|
5
|
-
describe "Concurrent publishers sharing a connection" do
|
6
|
-
before :all do
|
7
|
-
@connection = Bunny.new(username: "bunny_gem", password: "bunny_password",
|
8
|
-
vhost: "bunny_testbed", automatically_recover: false)
|
9
|
-
@connection.start
|
10
|
-
end
|
11
|
-
|
12
|
-
after :all do
|
13
|
-
@connection.close
|
14
|
-
end
|
15
|
-
|
16
|
-
let(:concurrency) { 24 }
|
17
|
-
let(:messages) { 5_000 }
|
18
|
-
|
19
|
-
it "successfully finish publishing" do
|
20
|
-
body = "сообщение"
|
21
|
-
|
22
|
-
chs = {}
|
23
|
-
concurrency.times do |i|
|
24
|
-
ch = @connection.create_channel
|
25
|
-
ch.confirm_select
|
26
|
-
chs[i] = ch
|
27
|
-
end
|
28
|
-
|
29
|
-
ts = []
|
30
|
-
|
31
|
-
concurrency.times do |i|
|
32
|
-
t = Thread.new do
|
33
|
-
cht = chs[i]
|
34
|
-
x = cht.default_exchange
|
35
|
-
|
36
|
-
messages.times do
|
37
|
-
x.publish(body)
|
38
|
-
end
|
39
|
-
puts "Published #{messages} messages..."
|
40
|
-
cht.wait_for_confirms
|
41
|
-
end
|
42
|
-
t.abort_on_exception = true
|
43
|
-
|
44
|
-
ts << t
|
45
|
-
end
|
46
|
-
|
47
|
-
ts.each do |t|
|
48
|
-
t.join
|
49
|
-
end
|
50
|
-
|
51
|
-
chs.each { |_, ch| ch.close }
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|