bunny 0.10.0 → 0.10.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.
- checksums.yaml +4 -4
- data/.travis.yml +4 -1
- data/ChangeLog.md +10 -0
- data/README.md +5 -5
- data/benchmarks/mutex_and_monitor.rb +42 -0
- data/lib/bunny/exceptions.rb +4 -1
- data/lib/bunny/reader_loop.rb +13 -1
- data/lib/bunny/session.rb +13 -2
- data/lib/bunny/version.rb +1 -1
- data/spec/higher_level_api/integration/basic_cancel_spec.rb +1 -1
- data/spec/higher_level_api/integration/basic_consume_spec.rb +1 -1
- data/spec/higher_level_api/integration/basic_nack_spec.rb +1 -1
- data/spec/higher_level_api/integration/basic_publish_spec.rb +1 -1
- data/spec/higher_level_api/integration/basic_qos_spec.rb +5 -8
- data/spec/higher_level_api/integration/basic_reject_spec.rb +16 -17
- data/spec/higher_level_api/integration/basic_return_spec.rb +1 -1
- data/spec/higher_level_api/integration/channel_close_spec.rb +6 -10
- data/spec/higher_level_api/integration/channel_flow_spec.rb +6 -9
- data/spec/higher_level_api/integration/channel_open_spec.rb +11 -20
- data/spec/higher_level_api/integration/confirm_select_spec.rb +1 -1
- data/spec/higher_level_api/integration/connection_spec.rb +1 -1
- data/spec/higher_level_api/integration/consistent_hash_exchange_spec.rb +1 -1
- data/spec/higher_level_api/integration/consumer_cancellation_notification_spec.rb +1 -1
- data/spec/higher_level_api/integration/dead_lettering_spec.rb +1 -1
- data/spec/higher_level_api/integration/exchange_bind_spec.rb +1 -1
- data/spec/higher_level_api/integration/exchange_declare_spec.rb +1 -1
- data/spec/higher_level_api/integration/exchange_delete_spec.rb +1 -1
- data/spec/higher_level_api/integration/exchange_unbind_spec.rb +1 -1
- data/spec/higher_level_api/integration/merry_go_round_spec.rb +1 -1
- data/spec/higher_level_api/integration/message_properties_access_spec.rb +1 -1
- data/spec/higher_level_api/integration/predeclared_exchanges_spec.rb +1 -1
- data/spec/higher_level_api/integration/publishing_edge_cases_spec.rb +1 -1
- data/spec/higher_level_api/integration/queue_declare_spec.rb +1 -1
- data/spec/higher_level_api/integration/queue_delete_spec.rb +2 -2
- data/spec/higher_level_api/integration/queue_purge_spec.rb +1 -1
- data/spec/higher_level_api/integration/queue_unbind_spec.rb +2 -2
- data/spec/higher_level_api/integration/read_only_consumer_spec.rb +1 -1
- data/spec/higher_level_api/integration/sender_selected_distribution_spec.rb +2 -2
- data/spec/higher_level_api/integration/tls_connection_spec.rb +2 -2
- data/spec/higher_level_api/integration/tx_commit_spec.rb +1 -1
- data/spec/higher_level_api/integration/tx_rollback_spec.rb +1 -1
- data/spec/stress/connection_open_close_spec.rb +11 -2
- data/spec/unit/concurrent/condition_spec.rb +53 -46
- data/spec/unit/concurrent/synchronized_sorted_set_spec.rb +48 -9
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d3e5ee2f2801f1420033324361e8fe9768a48e7e
|
4
|
+
data.tar.gz: b1f35041c2d32444ab5290301cbab613c4d63abd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 35622fd832fd559a594c7eb1bbb46576f1831d34c4bb2a1b9e4ee86e58500afa39e179785388aba9ca3a9311665f193b06d96b10429be7bc33dd6d54f98de706
|
7
|
+
data.tar.gz: 9f39c1e15d01f1a09f617a411f7d157028e2efe4cb4eb905564f73a08ff956e2fbbfdb0cb71cb9087aca7b0f3c0082fee348dc9ba41764876d857f2a14fdf7a2
|
data/.travis.yml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
bundler_args: --without development
|
2
2
|
before_script: "./bin/ci/before_build.sh"
|
3
|
-
script: "bundle exec rspec -
|
3
|
+
script: "bundle exec rspec -cfs spec"
|
4
4
|
rvm:
|
5
5
|
- "2.0"
|
6
6
|
- "1.9.3"
|
@@ -15,3 +15,6 @@ branches:
|
|
15
15
|
only:
|
16
16
|
- master
|
17
17
|
- 0.9.x-stable
|
18
|
+
matrix:
|
19
|
+
allow_failures:
|
20
|
+
- rvm: rbx-19mode
|
data/ChangeLog.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
## Changes between Bunny 0.10.0 and 0.10.1
|
2
|
+
|
3
|
+
### Fix Abnormally Slow Bunny::Connection#close on JRuby
|
4
|
+
|
5
|
+
`Bunny::Connection#close` on JRuby sometimes could enter a waiting
|
6
|
+
state [on a native NIO/kqueue method] that lasted up to over 10 seconds.
|
7
|
+
|
8
|
+
This severely affected test suite run times.
|
9
|
+
|
10
|
+
|
1
11
|
## Changes between Bunny 0.9.0 and 0.10.0
|
2
12
|
|
3
13
|
This release has one minor **breaking API change**.
|
data/README.md
CHANGED
@@ -79,7 +79,7 @@ backwards compatible as possible but within reason.
|
|
79
79
|
|
80
80
|
### With Rubygems
|
81
81
|
|
82
|
-
To install Bunny
|
82
|
+
To install Bunny with RubyGems:
|
83
83
|
|
84
84
|
```
|
85
85
|
gem install bunny
|
@@ -87,17 +87,17 @@ gem install bunny
|
|
87
87
|
|
88
88
|
### Bundler Dependency
|
89
89
|
|
90
|
-
To use Bunny
|
90
|
+
To use Bunny in a project managed with Bundler:
|
91
91
|
|
92
92
|
``` ruby
|
93
|
-
gem "bunny", ">= 0.
|
93
|
+
gem "bunny", ">= 0.10.0"
|
94
94
|
```
|
95
95
|
|
96
96
|
|
97
|
-
## Quick Start
|
97
|
+
## Quick Start
|
98
98
|
|
99
99
|
Below is a small snippet that demonstrates how to publish
|
100
|
-
and synchronously consume ("pull API") messages with Bunny
|
100
|
+
and synchronously consume ("pull API") messages with Bunny.
|
101
101
|
|
102
102
|
For a 15 minute tutorial using more practical examples, see [Getting Started with RabbitMQ and Ruby using Bunny](http://rubybunny.info/articles/getting_started.html).
|
103
103
|
|
@@ -0,0 +1,42 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require "rubygems"
|
5
|
+
require "set"
|
6
|
+
require "thread"
|
7
|
+
require "benchmark"
|
8
|
+
require "monitor"
|
9
|
+
|
10
|
+
puts
|
11
|
+
puts "-" * 80
|
12
|
+
puts "Benchmarking on #{RUBY_DESCRIPTION}"
|
13
|
+
|
14
|
+
n = 2_000_000
|
15
|
+
mx = Mutex.new
|
16
|
+
mt = Monitor.new
|
17
|
+
|
18
|
+
# warm up the JIT, etc
|
19
|
+
puts "Doing a warmup run..."
|
20
|
+
n.times do |i|
|
21
|
+
mx.synchronize { 1 }
|
22
|
+
mt.synchronize { 1 }
|
23
|
+
end
|
24
|
+
|
25
|
+
t1 = Benchmark.realtime do
|
26
|
+
n.times do |i|
|
27
|
+
mx.synchronize { 1 }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
r1 = (n.to_f/t1.to_f)
|
31
|
+
|
32
|
+
t2 = Benchmark.realtime do
|
33
|
+
n.times do |i|
|
34
|
+
mt.synchronize { 1 }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
r2 = (n.to_f/t2.to_f)
|
38
|
+
|
39
|
+
puts "Mutex#synchronize, rate: #{(r1 / 1000).round(2)} KGHz"
|
40
|
+
puts "Monitor#synchronize, rate: #{(r2 / 1000).round(2)} KGHz"
|
41
|
+
puts
|
42
|
+
puts "-" * 80
|
data/lib/bunny/exceptions.rb
CHANGED
@@ -55,7 +55,7 @@ module Bunny
|
|
55
55
|
when Exception then
|
56
56
|
e.message
|
57
57
|
end
|
58
|
-
super("Could not
|
58
|
+
super("Could not establish TCP connection to #{hostname}:#{port}: #{m}")
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
@@ -70,6 +70,9 @@ module Bunny
|
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
+
class ShutdownSignal < Exception
|
74
|
+
end
|
75
|
+
|
73
76
|
# Raised when RabbitMQ closes TCP connection before finishing connection
|
74
77
|
# sequence properly. This typically indicates an authentication issue.
|
75
78
|
class PossibleAuthenticationFailureError < Exception
|
data/lib/bunny/reader_loop.rb
CHANGED
@@ -19,7 +19,6 @@ module Bunny
|
|
19
19
|
|
20
20
|
def start
|
21
21
|
@thread = Thread.new(&method(:run_loop))
|
22
|
-
@thread.abort_on_exception = true
|
23
22
|
end
|
24
23
|
|
25
24
|
def resume
|
@@ -33,8 +32,10 @@ module Bunny
|
|
33
32
|
break if @stopping || @network_is_down
|
34
33
|
run_once
|
35
34
|
rescue Errno::EBADF => ebadf
|
35
|
+
break if @stopping
|
36
36
|
# ignored, happens when we loop after the transport has already been closed
|
37
37
|
rescue AMQ::Protocol::EmptyResponseError, IOError, SystemCallError => e
|
38
|
+
break if @stopping
|
38
39
|
log_exception(e)
|
39
40
|
|
40
41
|
@network_is_down = true
|
@@ -44,7 +45,10 @@ module Bunny
|
|
44
45
|
else
|
45
46
|
@session_thread.raise(Bunny::NetworkFailure.new("detected a network failure: #{e.message}", e))
|
46
47
|
end
|
48
|
+
rescue ShutdownSignal => _
|
49
|
+
break
|
47
50
|
rescue Exception => e
|
51
|
+
break if @stopping
|
48
52
|
log_exception(e)
|
49
53
|
|
50
54
|
@network_is_down = true
|
@@ -86,6 +90,14 @@ module Bunny
|
|
86
90
|
@stopped
|
87
91
|
end
|
88
92
|
|
93
|
+
def raise(e)
|
94
|
+
@thread.raise(e)
|
95
|
+
end
|
96
|
+
|
97
|
+
def join
|
98
|
+
@thread.join
|
99
|
+
end
|
100
|
+
|
89
101
|
def kill
|
90
102
|
@thread.kill
|
91
103
|
@thread.join
|
data/lib/bunny/session.rb
CHANGED
@@ -269,7 +269,9 @@ module Bunny
|
|
269
269
|
self.close_connection(true)
|
270
270
|
end
|
271
271
|
|
272
|
+
# puts "before maybe_shutdown_reader_loop"
|
272
273
|
maybe_shutdown_reader_loop
|
274
|
+
# puts "after maybe_shutdown_reader_loop"
|
273
275
|
close_transport
|
274
276
|
|
275
277
|
@status = :closed
|
@@ -626,10 +628,19 @@ module Bunny
|
|
626
628
|
def maybe_shutdown_reader_loop
|
627
629
|
if @reader_loop
|
628
630
|
@reader_loop.stop
|
629
|
-
# We don't need to kill the loop but
|
630
631
|
# this is the easiest way to wait until the loop
|
631
632
|
# is guaranteed to have terminated
|
632
|
-
@reader_loop.
|
633
|
+
@reader_loop.raise(ShutdownSignal)
|
634
|
+
# joining the thread here may take forever
|
635
|
+
# on JRuby because sun.nio.ch.KQueueArrayWrapper#kevent0 is
|
636
|
+
# a native method that cannot be (easily) interrupted.
|
637
|
+
# So we use this ugly hack or else our test suite takes forever
|
638
|
+
# to run on JRuby (a new connection is opened/closed per example). MK.
|
639
|
+
if RUBY_ENGINE == "jruby"
|
640
|
+
sleep 0.075
|
641
|
+
else
|
642
|
+
@reader_loop.join
|
643
|
+
end
|
633
644
|
end
|
634
645
|
|
635
646
|
@reader_loop = nil
|
data/lib/bunny/version.rb
CHANGED
@@ -7,25 +7,22 @@ describe Bunny::Channel, "#prefetch" do
|
|
7
7
|
c
|
8
8
|
end
|
9
9
|
|
10
|
-
after :
|
10
|
+
after :each do
|
11
11
|
connection.close
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
subject do
|
16
|
-
connection.create_channel
|
17
|
-
end
|
18
|
-
|
19
14
|
context "with a positive integer" do
|
20
15
|
it "sets that prefetch level via basic.qos" do
|
21
|
-
|
16
|
+
ch = connection.create_channel
|
17
|
+
ch.prefetch(10).should be_instance_of(AMQ::Protocol::Basic::QosOk)
|
22
18
|
end
|
23
19
|
end
|
24
20
|
|
25
21
|
context "with a negative integer" do
|
26
22
|
it "raises an ArgumentError" do
|
23
|
+
ch = connection.create_channel
|
27
24
|
expect {
|
28
|
-
|
25
|
+
ch.prefetch(-2)
|
29
26
|
}.to raise_error(ArgumentError)
|
30
27
|
end
|
31
28
|
end
|
@@ -7,65 +7,64 @@ describe Bunny::Channel, "#reject" do
|
|
7
7
|
c
|
8
8
|
end
|
9
9
|
|
10
|
-
after :
|
10
|
+
after :each do
|
11
11
|
connection.close if connection.open?
|
12
12
|
end
|
13
13
|
|
14
|
-
subject do
|
15
|
-
connection.create_channel
|
16
|
-
end
|
17
|
-
|
18
14
|
context "with requeue = true" do
|
19
15
|
it "requeues a message" do
|
20
|
-
|
21
|
-
|
16
|
+
ch = connection.create_channel
|
17
|
+
q = ch.queue("bunny.basic.reject.manual-acks", :exclusive => true)
|
18
|
+
x = ch.default_exchange
|
22
19
|
|
23
20
|
x.publish("bunneth", :routing_key => q.name)
|
24
21
|
sleep(0.5)
|
25
22
|
q.message_count.should == 1
|
26
23
|
delivery_info, _, _ = q.pop(:ack => true)
|
27
24
|
|
28
|
-
|
25
|
+
ch.reject(delivery_info.delivery_tag, true)
|
29
26
|
sleep(0.5)
|
30
27
|
q.message_count.should == 1
|
31
28
|
|
32
|
-
|
29
|
+
ch.close
|
33
30
|
end
|
34
31
|
end
|
35
32
|
|
36
33
|
context "with requeue = false" do
|
37
34
|
it "rejects a message" do
|
38
|
-
|
39
|
-
|
35
|
+
ch = connection.create_channel
|
36
|
+
q = ch.queue("bunny.basic.reject.with-requeue-false", :exclusive => true)
|
37
|
+
x = ch.default_exchange
|
40
38
|
|
41
39
|
x.publish("bunneth", :routing_key => q.name)
|
42
40
|
sleep(0.5)
|
43
41
|
q.message_count.should == 1
|
44
42
|
delivery_info, _, _ = q.pop(:ack => true)
|
45
43
|
|
46
|
-
|
44
|
+
ch.reject(delivery_info.delivery_tag, false)
|
47
45
|
sleep(0.5)
|
48
46
|
q.message_count.should == 0
|
49
47
|
|
50
|
-
|
48
|
+
ch.close
|
51
49
|
end
|
52
50
|
end
|
53
51
|
|
54
52
|
|
55
53
|
context "with an invalid (random) delivery tag" do
|
56
54
|
it "causes a channel-level error" do
|
57
|
-
|
58
|
-
|
55
|
+
ch = connection.create_channel
|
56
|
+
q = ch.queue("bunny.basic.reject.unknown-delivery-tag", :exclusive => true)
|
57
|
+
x = ch.default_exchange
|
59
58
|
|
60
59
|
x.publish("bunneth", :routing_key => q.name)
|
61
60
|
sleep(0.25)
|
62
61
|
q.message_count.should == 1
|
63
62
|
_, _, content = q.pop(:ack => true)
|
64
63
|
|
65
|
-
|
64
|
+
ch.on_error do |ch, channel_close|
|
66
65
|
@channel_close = channel_close
|
67
66
|
end
|
68
|
-
|
67
|
+
ch.reject(82, true)
|
69
68
|
|
70
69
|
sleep 0.5
|
71
70
|
|
@@ -7,21 +7,17 @@ describe Bunny::Channel, "when closed" do
|
|
7
7
|
c
|
8
8
|
end
|
9
9
|
|
10
|
-
after :
|
10
|
+
after :each do
|
11
11
|
connection.close
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
subject do
|
16
|
-
connection.create_channel
|
17
|
-
end
|
18
|
-
|
19
14
|
it "releases the id" do
|
20
|
-
|
15
|
+
ch = connection.create_channel
|
16
|
+
n = ch.number
|
21
17
|
|
22
|
-
|
23
|
-
|
24
|
-
|
18
|
+
ch.should be_open
|
19
|
+
ch.close
|
20
|
+
ch.should be_closed
|
25
21
|
|
26
22
|
# a new channel with the same id can be created
|
27
23
|
connection.create_channel(n)
|
@@ -7,18 +7,15 @@ describe Bunny::Channel, "#flow" do
|
|
7
7
|
c
|
8
8
|
end
|
9
9
|
|
10
|
-
after :
|
10
|
+
after :each do
|
11
11
|
connection.close
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
subject do
|
16
|
-
connection.create_channel
|
17
|
-
end
|
18
|
-
|
19
14
|
it "is supported" do
|
20
|
-
|
21
|
-
|
22
|
-
|
15
|
+
ch = connection.create_channel
|
16
|
+
|
17
|
+
ch.flow(true).should be_instance_of(AMQ::Protocol::Channel::FlowOk)
|
18
|
+
ch.flow(false).should be_instance_of(AMQ::Protocol::Channel::FlowOk)
|
19
|
+
ch.flow(true).should be_instance_of(AMQ::Protocol::Channel::FlowOk)
|
23
20
|
end
|
24
21
|
end
|
@@ -7,51 +7,42 @@ describe Bunny::Channel, "when opened" do
|
|
7
7
|
c
|
8
8
|
end
|
9
9
|
|
10
|
-
after :
|
10
|
+
after :each do
|
11
11
|
connection.close
|
12
12
|
end
|
13
13
|
|
14
14
|
context "without explicitly provided id" do
|
15
|
-
subject do
|
16
|
-
connection.create_channel
|
17
|
-
end
|
18
|
-
|
19
15
|
it "gets an allocated id and is successfully opened" do
|
20
16
|
connection.should be_connected
|
21
|
-
|
17
|
+
ch = connection.create_channel
|
18
|
+
ch.should be_open
|
22
19
|
|
23
|
-
|
20
|
+
ch.id.should be > 0
|
24
21
|
end
|
25
22
|
end
|
26
23
|
|
27
24
|
|
28
25
|
context "with explicitly provided id" do
|
29
|
-
subject do
|
30
|
-
connection.create_channel(767)
|
31
|
-
end
|
32
|
-
|
33
26
|
it "uses that id and is successfully opened" do
|
27
|
+
ch = connection.create_channel(767)
|
34
28
|
connection.should be_connected
|
35
|
-
|
29
|
+
ch.should be_open
|
36
30
|
|
37
|
-
|
31
|
+
ch.id.should == 767
|
38
32
|
end
|
39
33
|
end
|
40
34
|
|
41
35
|
|
42
36
|
|
43
37
|
context "with explicitly provided id that is already taken" do
|
44
|
-
subject do
|
45
|
-
connection.create_channel(767)
|
46
|
-
end
|
47
|
-
|
48
38
|
it "reuses the channel that is already opened" do
|
39
|
+
ch = connection.create_channel(767)
|
49
40
|
connection.should be_connected
|
50
|
-
|
41
|
+
ch.should be_open
|
51
42
|
|
52
|
-
|
43
|
+
ch.id.should == 767
|
53
44
|
|
54
|
-
connection.create_channel(767).should ==
|
45
|
+
connection.create_channel(767).should == ch
|
55
46
|
end
|
56
47
|
end
|
57
48
|
end
|
@@ -7,7 +7,7 @@ describe Bunny::Queue, "#delete" do
|
|
7
7
|
c
|
8
8
|
end
|
9
9
|
|
10
|
-
after :
|
10
|
+
after :each do
|
11
11
|
connection.close
|
12
12
|
end
|
13
13
|
|
@@ -22,7 +22,7 @@ describe Bunny::Queue, "#delete" do
|
|
22
22
|
expect {
|
23
23
|
q.delete
|
24
24
|
}.to raise_error(Bunny::NotFound)
|
25
|
-
|
25
|
+
|
26
26
|
ch.queues.size.should == 0
|
27
27
|
end
|
28
28
|
end
|
@@ -7,7 +7,7 @@ describe Bunny::Queue, "bound to an exchange" do
|
|
7
7
|
c
|
8
8
|
end
|
9
9
|
|
10
|
-
after :
|
10
|
+
after :each do
|
11
11
|
connection.close
|
12
12
|
end
|
13
13
|
|
@@ -37,7 +37,7 @@ describe Bunny::Queue, "NOT bound to an exchange" do
|
|
37
37
|
c
|
38
38
|
end
|
39
39
|
|
40
|
-
after :
|
40
|
+
after :each do
|
41
41
|
connection.close
|
42
42
|
end
|
43
43
|
|
@@ -7,7 +7,7 @@ describe "Sender-selected distribution" do
|
|
7
7
|
c
|
8
8
|
end
|
9
9
|
|
10
|
-
after :
|
10
|
+
after :each do
|
11
11
|
connection.close if connection.open?
|
12
12
|
end
|
13
13
|
|
@@ -23,7 +23,7 @@ describe "Sender-selected distribution" do
|
|
23
23
|
n.times do |i|
|
24
24
|
x.publish("Message #{i}", :routing_key => "one", :headers => {"CC" => ["two", "three"]})
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
sleep 0.5
|
28
28
|
|
29
29
|
q1.message_count.should == n
|
@@ -1,8 +1,17 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
unless RUBY_ENGINE == "jruby"
|
3
|
+
unless RUBY_ENGINE == "jruby" && !ENV["FORCE_JRUBY_RUN"]
|
4
4
|
describe Bunny::Session do
|
5
|
-
|
5
|
+
# creating thousands of connections means creating
|
6
|
+
# twice as many threads and this won't fly with the JVM
|
7
|
+
# in CI containers. MK.
|
8
|
+
n = if RUBY_ENGINE == "jruby"
|
9
|
+
250
|
10
|
+
else
|
11
|
+
2500
|
12
|
+
end
|
13
|
+
|
14
|
+
n.times do |i|
|
6
15
|
it "can be closed (take #{i})" do
|
7
16
|
c = Bunny.new(:automatically_recover => false)
|
8
17
|
c.start
|
@@ -2,73 +2,80 @@ require "spec_helper"
|
|
2
2
|
require "bunny/concurrent/condition"
|
3
3
|
|
4
4
|
describe Bunny::Concurrent::Condition do
|
5
|
+
|
5
6
|
describe "#wait" do
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
100.times do |i|
|
8
|
+
it "blocks current thread until notified (take #{i})" do
|
9
|
+
condition = described_class.new
|
10
|
+
xs = []
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
+
t = Thread.new do
|
13
|
+
xs << :notified
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
sleep 0.25
|
16
|
+
condition.notify
|
17
|
+
end
|
18
|
+
t.abort_on_exception = true
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
+
condition.wait
|
21
|
+
xs.should == [:notified]
|
22
|
+
end
|
20
23
|
end
|
21
24
|
end
|
22
25
|
|
23
26
|
describe "#notify" do
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
27
|
+
100.times do |i|
|
28
|
+
it "notifies a single thread waiting on the latch (take #{i})" do
|
29
|
+
mutex = Mutex.new
|
30
|
+
condition = described_class.new
|
31
|
+
xs = []
|
28
32
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
33
|
+
t1 = Thread.new do
|
34
|
+
condition.wait
|
35
|
+
mutex.synchronize { xs << :notified1 }
|
36
|
+
end
|
37
|
+
t1.abort_on_exception = true
|
34
38
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
39
|
+
t2 = Thread.new do
|
40
|
+
condition.wait
|
41
|
+
mutex.synchronize { xs << :notified2 }
|
42
|
+
end
|
43
|
+
t2.abort_on_exception = true
|
40
44
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
+
sleep 0.25
|
46
|
+
condition.notify
|
47
|
+
sleep 0.5
|
48
|
+
xs.should satisfy { |ys| ys.size == 1 && (ys.include?(:notified1) || ys.include?(:notified2)) }
|
49
|
+
end
|
45
50
|
end
|
46
51
|
end
|
47
52
|
|
48
53
|
describe "#notify_all" do
|
49
|
-
let(:n) {
|
54
|
+
let(:n) { 30 }
|
50
55
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
56
|
+
100.times do |i|
|
57
|
+
it "notifies all the threads waiting on the latch (take #{i})" do
|
58
|
+
mutex = Mutex.new
|
59
|
+
condition = described_class.new
|
60
|
+
@xs = []
|
55
61
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
62
|
+
n.times do |i|
|
63
|
+
t = Thread.new do
|
64
|
+
condition.wait
|
65
|
+
mutex.synchronize { @xs << "notified#{i + 1}".to_sym }
|
66
|
+
end
|
67
|
+
t.abort_on_exception = true
|
60
68
|
end
|
61
|
-
t.abort_on_exception = true
|
62
|
-
end
|
63
69
|
|
64
|
-
|
65
|
-
|
66
|
-
|
70
|
+
sleep 0.5
|
71
|
+
condition.notify_all
|
72
|
+
sleep 0.5
|
67
73
|
|
68
|
-
|
69
|
-
|
74
|
+
n.times do |i|
|
75
|
+
item = "notified#{i + 1}".to_sym
|
70
76
|
|
71
|
-
|
77
|
+
@xs.should include(item)
|
78
|
+
end
|
72
79
|
end
|
73
80
|
end
|
74
81
|
end
|
@@ -1,34 +1,73 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
require "bunny/concurrent/synchronized_sorted_set"
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
unless ENV["CI"]
|
5
|
+
describe Bunny::Concurrent::SynchronizedSortedSet do
|
6
|
+
50.times do |i|
|
7
|
+
it "provides the same API as SortedSet for key operations (take #{i})" do
|
8
|
+
s = described_class.new
|
9
|
+
s.length.should == 0
|
8
10
|
|
9
|
-
10.times do
|
10
|
-
Thread.new do
|
11
11
|
s << 1
|
12
|
+
s.length.should == 1
|
12
13
|
s << 1
|
14
|
+
s.length.should == 1
|
13
15
|
s << 2
|
16
|
+
s.length.should == 2
|
14
17
|
s << 3
|
18
|
+
s.length.should == 3
|
15
19
|
s << 4
|
20
|
+
s.length.should == 4
|
16
21
|
s << 4
|
17
22
|
s << 4
|
18
23
|
s << 4
|
24
|
+
s.length.should == 4
|
19
25
|
s << 5
|
26
|
+
s.length.should == 5
|
20
27
|
s << 5
|
21
28
|
s << 5
|
22
29
|
s << 5
|
30
|
+
s.length.should == 5
|
23
31
|
s << 6
|
32
|
+
s.length.should == 6
|
24
33
|
s << 7
|
34
|
+
s.length.should == 7
|
25
35
|
s << 8
|
36
|
+
s.length.should == 8
|
26
37
|
s.delete 8
|
38
|
+
s.length.should == 7
|
27
39
|
s.delete_if { |i| i == 1 }
|
40
|
+
s.length.should == 6
|
28
41
|
end
|
29
|
-
|
30
|
-
|
42
|
+
it "synchronizes common operations needed by Bunny (take #{i})" do
|
43
|
+
s = described_class.new
|
44
|
+
s.length.should == 0
|
45
|
+
|
46
|
+
10.times do
|
47
|
+
Thread.new do
|
48
|
+
s << 1
|
49
|
+
s << 1
|
50
|
+
s << 2
|
51
|
+
s << 3
|
52
|
+
s << 4
|
53
|
+
s << 4
|
54
|
+
s << 4
|
55
|
+
s << 4
|
56
|
+
s << 5
|
57
|
+
s << 5
|
58
|
+
s << 5
|
59
|
+
s << 5
|
60
|
+
s << 6
|
61
|
+
s << 7
|
62
|
+
s << 8
|
63
|
+
s.delete 8
|
64
|
+
s.delete_if { |i| i == 1 }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
sleep 0.5
|
31
68
|
|
32
|
-
|
69
|
+
s.length.should == 6
|
70
|
+
end
|
71
|
+
end
|
33
72
|
end
|
34
73
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bunny
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.10.
|
4
|
+
version: 0.10.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Duncan
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2013-08-
|
15
|
+
date: 2013-08-07 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: amq-protocol
|
@@ -54,6 +54,7 @@ files:
|
|
54
54
|
- benchmarks/basic_publish/with_4K_messages.rb
|
55
55
|
- benchmarks/basic_publish/with_64K_messages.rb
|
56
56
|
- benchmarks/channel_open.rb
|
57
|
+
- benchmarks/mutex_and_monitor.rb
|
57
58
|
- benchmarks/queue_declare.rb
|
58
59
|
- benchmarks/queue_declare_and_bind.rb
|
59
60
|
- benchmarks/queue_declare_bind_and_delete.rb
|