bunny 0.10.0 → 0.10.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|