bunny 0.9.0.rc1 → 0.9.0.rc2
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/.ruby-version +1 -1
- data/ChangeLog.md +95 -2
- data/README.md +81 -26
- data/bunny.gemspec +2 -2
- data/lib/bunny/channel.rb +7 -3
- data/lib/bunny/consumer_work_pool.rb +11 -3
- data/lib/bunny/queue.rb +0 -48
- data/lib/bunny/session.rb +3 -8
- data/lib/bunny/transport.rb +37 -11
- data/lib/bunny/version.rb +1 -1
- data/spec/higher_level_api/integration/basic_consume_spec.rb +50 -1
- data/spec/higher_level_api/integration/basic_get_spec.rb +2 -36
- data/spec/higher_level_api/integration/connection_spec.rb +33 -24
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 23f16e1a514fe184d1460364e3a04247ddedf75d
|
|
4
|
+
data.tar.gz: a9e0dbba16677d8671a2e20ead8a0b5aa120b9ac
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ede8a080ddae75c6011790a72fa0cb1d21e13e227cba2e4ab3fc35fc5e8b99649601595061ae4f178b3c965487f91ba75944a22fdf86bc51d144e2cf61ca8839
|
|
7
|
+
data.tar.gz: 7988d768033079976e984ec930684d195df9ee7dd54e83520149134eed080cec31cbecf83ed4f906e1bcdfbc14b7b90d22445cd0a697826d8b031fe3200d560c
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.0@
|
|
1
|
+
2.0@rabbitmq
|
data/ChangeLog.md
CHANGED
|
@@ -1,7 +1,93 @@
|
|
|
1
|
-
## Changes between Bunny 0.9.0.
|
|
1
|
+
## Changes between Bunny 0.9.0.rc1 and 0.9.0.rc2
|
|
2
|
+
|
|
3
|
+
### Channel Now Properly Restarts Consumer Pool
|
|
4
|
+
|
|
5
|
+
In a case when all consumers are cancelled, `Bunny::Channel`
|
|
6
|
+
will shut down its consumer delivery thread pool.
|
|
7
|
+
|
|
8
|
+
It will also now mark the pool as not running so that it can be
|
|
9
|
+
started again successfully if new consumers are registered later.
|
|
10
|
+
|
|
11
|
+
GH issue: #133.
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Bunny::Queue#pop_waiting is Removed
|
|
15
|
+
|
|
16
|
+
A little bit of background: on MRI, the method raised `ThreadErrors`
|
|
17
|
+
reliably. On JRuby, we used a different [internal] queue implementation
|
|
18
|
+
from JDK so it wasn't an issue.
|
|
19
|
+
|
|
20
|
+
`Timeout.timeout` uses `Thread#kill` and `Thread#join`, both of which
|
|
21
|
+
eventually attempt to acquire a mutex used by Queue#pop, which Bunny
|
|
22
|
+
currently uses for continuations. The mutex is already has an owner
|
|
23
|
+
and so a ThreadError is raised.
|
|
24
|
+
|
|
25
|
+
This is not a problem on JRuby because there we don't use Ruby's
|
|
26
|
+
Timeout and Queue and instead rely on a JDK concurrency primitive
|
|
27
|
+
which provides "poll with a timeout".
|
|
28
|
+
|
|
29
|
+
[The issue with `Thread#kill` and `Thread#raise`](http://blog.headius.com/2008/02/ruby-threadraise-threadkill-timeoutrb.html)
|
|
30
|
+
has been first investigated and blogged about by Ruby implementers
|
|
31
|
+
in 2008.
|
|
32
|
+
|
|
33
|
+
Finding a workaround will probably take a bit of time and may involve
|
|
34
|
+
reimplementing standard library and core classes.
|
|
35
|
+
|
|
36
|
+
We don't want this issue to block Bunny 0.9 release. Neither we want
|
|
37
|
+
to ship a broken feature. So as a result, we will drop
|
|
38
|
+
Bunny::Queue#pop_waiting since it cannot be reliably implemented in a
|
|
39
|
+
reasonable amount of time on MRI.
|
|
40
|
+
|
|
41
|
+
Per issue #131.
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
### More Flexible SSLContext Configuration
|
|
45
|
+
|
|
46
|
+
Bunny will now upgrade connection to SSL in `Bunny::Session#start`,
|
|
47
|
+
so it is possible to fine tune SSLContext and socket settings
|
|
48
|
+
before that:
|
|
49
|
+
|
|
50
|
+
``` ruby
|
|
51
|
+
require "bunny"
|
|
52
|
+
|
|
53
|
+
conn = Bunny.new(:tls => true,
|
|
54
|
+
:tls_cert => "examples/tls/client_cert.pem",
|
|
55
|
+
:tls_key => "examples/tls/client_key.pem",
|
|
56
|
+
:tls_ca_certificates => ["./examples/tls/cacert.pem"])
|
|
57
|
+
|
|
58
|
+
puts conn.transport.socket.inspect
|
|
59
|
+
puts conn.transport.tls_context.inspect
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
This also means that `Bunny.new` will now open the socket. Previously
|
|
63
|
+
it was only done when `Bunny::Session#start` was invoked.
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
## Changes between Bunny 0.9.0.pre13 and 0.9.0.rc1
|
|
67
|
+
|
|
68
|
+
### TLS Support
|
|
69
|
+
|
|
70
|
+
Bunny 0.9 finally supports TLS. There are 3 new options `Bunny.new` takes:
|
|
71
|
+
|
|
72
|
+
* `:tls` which, when set to `true`, will set SSL context up and switch to TLS port (5671)
|
|
73
|
+
* `:tls_cert` which is a string path to the client certificate (public key) in PEM format
|
|
74
|
+
* `:tls_key` which is a string path to the client key (private key) in PEM format
|
|
75
|
+
* `:tls_ca_certificates` which is an array of string paths to CA certificates in PEM format
|
|
76
|
+
|
|
77
|
+
An example:
|
|
78
|
+
|
|
79
|
+
``` ruby
|
|
80
|
+
conn = Bunny.new(:tls => true,
|
|
81
|
+
:tls_cert => "examples/tls/client_cert.pem",
|
|
82
|
+
:tls_key => "examples/tls/client_key.pem",
|
|
83
|
+
:tls_ca_certificates => ["./examples/tls/cacert.pem"])
|
|
84
|
+
```
|
|
85
|
+
|
|
2
86
|
|
|
3
87
|
### Bunny::Queue#pop_waiting
|
|
4
88
|
|
|
89
|
+
**This function was removed in v0.9.0.rc2**
|
|
90
|
+
|
|
5
91
|
`Bunny::Queue#pop_waiting` is a new function that mimics `Bunny::Queue#pop`
|
|
6
92
|
but will wait until a message is available. It uses a `:timeout` option and will
|
|
7
93
|
raise an exception if the timeout is hit:
|
|
@@ -20,6 +106,13 @@ q.pop_waiting(:timeout => 0.5)
|
|
|
20
106
|
This method only makes sense for collecting Request/Reply ("RPC") replies.
|
|
21
107
|
|
|
22
108
|
|
|
109
|
+
### Bunny::InvalidCommand is now Bunny::CommandInvalid
|
|
110
|
+
|
|
111
|
+
`Bunny::InvalidCommand` is now `Bunny::CommandInvalid` (follows
|
|
112
|
+
the exception class naming convention based on response status
|
|
113
|
+
name).
|
|
114
|
+
|
|
115
|
+
|
|
23
116
|
|
|
24
117
|
## Changes between Bunny 0.9.0.pre12 and 0.9.0.pre13
|
|
25
118
|
|
|
@@ -533,7 +626,7 @@ It makes more sense for beginners that way.
|
|
|
533
626
|
|
|
534
627
|
`Bunny::Queue#subscribe` support the new `:block` option
|
|
535
628
|
(a boolean).
|
|
536
|
-
|
|
629
|
+
|
|
537
630
|
It controls whether the current thread will be blocked
|
|
538
631
|
by `Bunny::Queue#subscribe`.
|
|
539
632
|
|
data/README.md
CHANGED
|
@@ -1,13 +1,56 @@
|
|
|
1
1
|
# Bunny, a Ruby RabbitMQ Client
|
|
2
2
|
|
|
3
|
-
Bunny is a synchronous RabbitMQ client that focuses on ease of use.
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Bunny is a synchronous RabbitMQ client that focuses on ease of use. It
|
|
4
|
+
is feature complete, supports all RabbitMQ 3.0 features and does not
|
|
5
|
+
have any heavyweight dependencies.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
## I Know What RabbitMQ and Bunny are, How Do I Get Started?
|
|
9
|
+
|
|
10
|
+
[Right here](http://rubybunny.info/articles/getting_started.html)!
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## What is Bunny Good For?
|
|
14
|
+
|
|
15
|
+
One can use amqp gem to make Ruby applications interoperate with other
|
|
16
|
+
applications (both Ruby and not). Complexity and size may vary from
|
|
17
|
+
simple work queues to complex multi-stage data processing workflows that involve
|
|
18
|
+
many applications built with all kinds of technologies.
|
|
19
|
+
|
|
20
|
+
Specific examples:
|
|
21
|
+
|
|
22
|
+
* Events collectors, metrics & analytics applications can aggregate events produced by various applications
|
|
23
|
+
(Web and not) in the company network.
|
|
24
|
+
|
|
25
|
+
* A Web application may route messages to a Java app that works
|
|
26
|
+
with SMS delivery gateways.
|
|
27
|
+
|
|
28
|
+
* MMO games can use flexible routing RabbitMQ provides to propagate event notifications to players and locations.
|
|
29
|
+
|
|
30
|
+
* Price updates from public markets or other sources can be distributed between interested parties, from trading systems to points of sale in a specific geographic region.
|
|
31
|
+
|
|
32
|
+
* Content aggregators may update full-text search and geospatial search indexes
|
|
33
|
+
by delegating actual indexing work to other applications over RabbitMQ.
|
|
34
|
+
|
|
35
|
+
* Companies may provide streaming/push APIs to their customers, partners
|
|
36
|
+
or just general public.
|
|
37
|
+
|
|
38
|
+
* Continuous integration systems can distribute builds between multiple machines with various hardware and software
|
|
39
|
+
configurations using advanced routing features of RabbitMQ.
|
|
40
|
+
|
|
41
|
+
* An application that watches updates from a real-time stream (be it markets data
|
|
42
|
+
or Twitter stream) can propagate updates to interested parties, including
|
|
43
|
+
Web applications that display that information in the real time.
|
|
44
|
+
|
|
6
45
|
|
|
7
46
|
|
|
8
47
|
## Supported Ruby Versions
|
|
9
48
|
|
|
10
|
-
Bunny 0.9 and more recent versions support
|
|
49
|
+
Bunny 0.9 and more recent versions support
|
|
50
|
+
|
|
51
|
+
* CRuby 1.9.3, 1.9.2, 2.0.0, and 1.8.7
|
|
52
|
+
* JRuby 1.7+
|
|
53
|
+
* Rubinius 2.0+
|
|
11
54
|
|
|
12
55
|
|
|
13
56
|
## Supported RabbitMQ Versions
|
|
@@ -16,13 +59,20 @@ Bunny `0.8.x` and later versions only support RabbitMQ 2.x and 3.x.
|
|
|
16
59
|
Bunny `0.7.x` and earlier versions support RabbitMQ 1.x and 2.x.
|
|
17
60
|
|
|
18
61
|
|
|
19
|
-
##
|
|
62
|
+
## Project Maturity
|
|
20
63
|
|
|
21
|
-
Bunny is a
|
|
22
|
-
|
|
23
|
-
|
|
64
|
+
Bunny is a pretty old (started circa late 2008) library that, before version 0.9, **a lot** of missing functionality. Version 0.9
|
|
65
|
+
can be considered to be "second birthday" for Bunny as it was rewritten from scratch. Key objectives
|
|
66
|
+
for 0.9 are
|
|
24
67
|
|
|
25
|
-
|
|
68
|
+
* Be feature complete, support all RabbitMQ 3.x features
|
|
69
|
+
* Eliminate limitations Bunny used to have with earlier versions
|
|
70
|
+
* Be [well documented](http://rubybunny.info)
|
|
71
|
+
* Make use of concurrency and, if the runtime provides it, parallelism
|
|
72
|
+
* Reuse code with amqp gem and possibly other clients where it makes sense
|
|
73
|
+
|
|
74
|
+
We (the maintainers) make our best to keep the new version as
|
|
75
|
+
backwards compatible as possible but within reason.
|
|
26
76
|
|
|
27
77
|
|
|
28
78
|
## Installation & Bundler Dependency
|
|
@@ -33,12 +83,12 @@ To install Bunny 0.9.x with RubyGems:
|
|
|
33
83
|
gem install bunny --pre
|
|
34
84
|
```
|
|
35
85
|
|
|
36
|
-
the most recent 0.9.x version is `0.9.0.
|
|
86
|
+
the most recent 0.9.x version is `0.9.0.rc1`.
|
|
37
87
|
|
|
38
88
|
To use Bunny 0.9.x in a project managed with Bundler:
|
|
39
89
|
|
|
40
90
|
``` ruby
|
|
41
|
-
gem "bunny", ">= 0.9.0.
|
|
91
|
+
gem "bunny", ">= 0.9.0.rc1" # optionally: , :git => "git://github.com/ruby-amqp/bunny.git", :branch => "master"
|
|
42
92
|
```
|
|
43
93
|
|
|
44
94
|
|
|
@@ -62,11 +112,8 @@ ch = conn.create_channel
|
|
|
62
112
|
# declare a queue
|
|
63
113
|
q = ch.queue("test1")
|
|
64
114
|
|
|
65
|
-
# default
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
# publish a message to the exchange which then gets routed to the queue
|
|
69
|
-
e.publish("Hello, everybody!", :routing_key => 'test1')
|
|
115
|
+
# publish a message to the default exchange which then gets routed to this queue
|
|
116
|
+
q.publish("Hello, everybody!")
|
|
70
117
|
|
|
71
118
|
# fetch a message from the queue
|
|
72
119
|
delivery_info, metadata, payload = q.pop
|
|
@@ -86,7 +133,17 @@ For a 15 minute tutorial using more practical examples, see [Getting Started wit
|
|
|
86
133
|
|
|
87
134
|
### Guides
|
|
88
135
|
|
|
89
|
-
Other documentation guides are available at [rubybunny.info](http://rubybunny.info)
|
|
136
|
+
Other documentation guides are available at [rubybunny.info](http://rubybunny.info):
|
|
137
|
+
|
|
138
|
+
* [Queues and Consumers](http://rubybunny.info/articles/queues.html)
|
|
139
|
+
* [Exchanges and Publishers](http://rubybunny.info/articles/exchanges.html)
|
|
140
|
+
* [AMQP 0.9.1 Model Explained](http://www.rabbitmq.com/tutorials/amqp-concepts.html)
|
|
141
|
+
* [Connecting to RabbitMQ](http://rubybunny.info/articles/connecting.html)
|
|
142
|
+
* [Error Handling and Recovery](http://rubybunny.info/articles/error_handling.html)
|
|
143
|
+
* [TLS/SSL Support](http://rubybunny.info/articles/tls.html)
|
|
144
|
+
* [Bindings](http://rubybunny.info/articles/bindings.html)
|
|
145
|
+
* [Using RabbitMQ Extensions with Bunny](http://rubybunny.info/articles/extensions.html)
|
|
146
|
+
* [Durability and Related Matters](http://rubybunny.info/articles/durability.html)
|
|
90
147
|
|
|
91
148
|
### API Reference
|
|
92
149
|
|
|
@@ -110,6 +167,11 @@ For more immediate help, please join `#rabbitmq` on `irc.freenode.net`.
|
|
|
110
167
|
|
|
111
168
|
To subscribe for announcements of releases, important changes and so on, please follow [@rubyamqp](https://twitter.com/#!/rubyamqp) on Twitter.
|
|
112
169
|
|
|
170
|
+
More detailed announcements can be found in the blogs
|
|
171
|
+
|
|
172
|
+
* [RabbitMQ Ruby clients blog](http://blog.rubyrabbitmq.info)
|
|
173
|
+
* [Bunny Blog](http://bunnyamqp.wordpress.com)
|
|
174
|
+
|
|
113
175
|
|
|
114
176
|
### Reporting Issues
|
|
115
177
|
|
|
@@ -144,13 +206,6 @@ After that create a branch and make your changes on it. Once you are done with y
|
|
|
144
206
|
on GitHub.
|
|
145
207
|
|
|
146
208
|
|
|
209
|
+
## License
|
|
147
210
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
* [AMQP 0.9.1 model explained](http://www.rabbitmq.com/tutorials/amqp-concepts.html): introductory explanation of the AMQP v0.9.1 specification with particular reference to RabbitMQ.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
## Links
|
|
154
|
-
|
|
155
|
-
* [Source code](http://github.com/ruby-amqp/bunny)
|
|
156
|
-
* [Blog](http://bunnyamqp.wordpress.com)
|
|
211
|
+
Released under the MIT license.
|
data/bunny.gemspec
CHANGED
|
@@ -7,9 +7,9 @@ require File.expand_path("../lib/bunny/version", __FILE__)
|
|
|
7
7
|
Gem::Specification.new do |s|
|
|
8
8
|
s.name = "bunny"
|
|
9
9
|
s.version = Bunny::VERSION.dup
|
|
10
|
-
s.homepage = "http://
|
|
10
|
+
s.homepage = "http://rubybunny.info"
|
|
11
11
|
s.summary = "Popular easy to use Ruby client for RabbitMQ"
|
|
12
|
-
s.description = "
|
|
12
|
+
s.description = "Easy to use, feature complete Ruby client for RabbitMQ 2.0."
|
|
13
13
|
s.license = "MIT"
|
|
14
14
|
|
|
15
15
|
# Sorted alphabetically.
|
data/lib/bunny/channel.rb
CHANGED
|
@@ -1690,17 +1690,21 @@ module Bunny
|
|
|
1690
1690
|
# publishing). MK.
|
|
1691
1691
|
# @private
|
|
1692
1692
|
def maybe_start_consumer_work_pool!
|
|
1693
|
-
@work_pool
|
|
1693
|
+
if @work_pool && !@work_pool.running?
|
|
1694
|
+
@work_pool.start
|
|
1695
|
+
end
|
|
1694
1696
|
end
|
|
1695
1697
|
|
|
1696
1698
|
# @private
|
|
1697
1699
|
def maybe_pause_consumer_work_pool!
|
|
1698
|
-
@work_pool.pause if @work_pool && @work_pool.
|
|
1700
|
+
@work_pool.pause if @work_pool && @work_pool.running?
|
|
1699
1701
|
end
|
|
1700
1702
|
|
|
1701
1703
|
# @private
|
|
1702
1704
|
def maybe_kill_consumer_work_pool!
|
|
1703
|
-
|
|
1705
|
+
if @work_pool && @work_pool.running?
|
|
1706
|
+
@work_pool.kill
|
|
1707
|
+
end
|
|
1704
1708
|
end
|
|
1705
1709
|
|
|
1706
1710
|
# @private
|
|
@@ -31,14 +31,16 @@ module Bunny
|
|
|
31
31
|
@threads << t
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
-
@
|
|
34
|
+
@running = true
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
def
|
|
38
|
-
@
|
|
37
|
+
def running?
|
|
38
|
+
@running
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
def shutdown
|
|
42
|
+
@running = false
|
|
43
|
+
|
|
42
44
|
@size.times do
|
|
43
45
|
submit do |*args|
|
|
44
46
|
throw :terminate
|
|
@@ -51,14 +53,20 @@ module Bunny
|
|
|
51
53
|
end
|
|
52
54
|
|
|
53
55
|
def pause
|
|
56
|
+
@running = false
|
|
57
|
+
|
|
54
58
|
@threads.each { |t| t.stop }
|
|
55
59
|
end
|
|
56
60
|
|
|
57
61
|
def resume
|
|
62
|
+
@running = true
|
|
63
|
+
|
|
58
64
|
@threads.each { |t| t.run }
|
|
59
65
|
end
|
|
60
66
|
|
|
61
67
|
def kill
|
|
68
|
+
@running = false
|
|
69
|
+
|
|
62
70
|
@threads.each { |t| t.kill }
|
|
63
71
|
end
|
|
64
72
|
|
data/lib/bunny/queue.rb
CHANGED
|
@@ -256,54 +256,6 @@ module Bunny
|
|
|
256
256
|
end
|
|
257
257
|
end
|
|
258
258
|
|
|
259
|
-
# @param [Hash] opts Options
|
|
260
|
-
#
|
|
261
|
-
# @option opts [Boolean] :ack (false) Will the message be acknowledged manually?
|
|
262
|
-
# @option opts [Float] :timeout (1.0) Max amount of time, in seconds, to wait before raising an exception
|
|
263
|
-
#
|
|
264
|
-
# @return [Array] Triple of delivery info, message properties and message content.
|
|
265
|
-
# If the queue is empty, all three will be nils.
|
|
266
|
-
#
|
|
267
|
-
# @raises [Bunny::ClientException] When no message is available in the amount of time provided via the :timeout option
|
|
268
|
-
#
|
|
269
|
-
# @see http://rubybunny.info/articles/queues.html Queues and Consumers guide
|
|
270
|
-
# @see Bunny::Queue#subscribe
|
|
271
|
-
# @api public
|
|
272
|
-
#
|
|
273
|
-
# @example
|
|
274
|
-
# conn = Bunny.new
|
|
275
|
-
# conn.start
|
|
276
|
-
#
|
|
277
|
-
# ch = conn.create_channel
|
|
278
|
-
# q = ch.queue("test1")
|
|
279
|
-
# x = ch.default_exchange
|
|
280
|
-
# x.publish("Hello, everybody!", :routing_key => 'test1')
|
|
281
|
-
#
|
|
282
|
-
# delivery_info, properties, payload = q.pop_waiting(:timeout => 0.5)
|
|
283
|
-
#
|
|
284
|
-
# puts "This is the message: " + payload + "\n\n"
|
|
285
|
-
# conn.close
|
|
286
|
-
def pop_waiting(opts = {:ack => false, :timeout => 1.0}, &block)
|
|
287
|
-
delivery_info, properties, content = nil, nil, nil
|
|
288
|
-
|
|
289
|
-
Bunny::Timer.timeout(opts[:timeout], ClientTimeout) do
|
|
290
|
-
loop do
|
|
291
|
-
delivery_info, properties, content = @channel.basic_get(@name, opts)
|
|
292
|
-
|
|
293
|
-
if !content.nil?
|
|
294
|
-
break
|
|
295
|
-
end
|
|
296
|
-
end
|
|
297
|
-
end
|
|
298
|
-
|
|
299
|
-
if block
|
|
300
|
-
block.call(delivery_info, properties, content)
|
|
301
|
-
else
|
|
302
|
-
[delivery_info, properties, content]
|
|
303
|
-
end
|
|
304
|
-
end
|
|
305
|
-
alias get_waiting pop_waiting
|
|
306
|
-
|
|
307
259
|
|
|
308
260
|
# Publishes a message to the queue via default exchange. Takes the same arguments
|
|
309
261
|
# as {Bunny::Exchange#publish}
|
data/lib/bunny/session.rb
CHANGED
|
@@ -178,11 +178,7 @@ module Bunny
|
|
|
178
178
|
def configure_socket(&block)
|
|
179
179
|
raise ArgumentError, "No block provided!" if block.nil?
|
|
180
180
|
|
|
181
|
-
|
|
182
|
-
@transport.configure_socket(&block)
|
|
183
|
-
else
|
|
184
|
-
@socket_configurator = block
|
|
185
|
-
end
|
|
181
|
+
@transport.configure_socket(&block)
|
|
186
182
|
end
|
|
187
183
|
|
|
188
184
|
# Starts the connection process.
|
|
@@ -199,10 +195,9 @@ module Bunny
|
|
|
199
195
|
begin
|
|
200
196
|
# close existing transport if we have one,
|
|
201
197
|
# to not leak sockets
|
|
202
|
-
|
|
203
|
-
self.initialize_transport
|
|
198
|
+
@transport.maybe_initialize_socket
|
|
204
199
|
|
|
205
|
-
@transport.
|
|
200
|
+
@transport.post_initialize_socket
|
|
206
201
|
@transport.connect
|
|
207
202
|
|
|
208
203
|
if @socket_configurator
|
data/lib/bunny/transport.rb
CHANGED
|
@@ -49,6 +49,9 @@ module Bunny
|
|
|
49
49
|
@disconnect_timeout = @read_write_timeout || @connect_timeout
|
|
50
50
|
|
|
51
51
|
@writes_mutex = Mutex.new
|
|
52
|
+
|
|
53
|
+
maybe_initialize_socket
|
|
54
|
+
prepare_tls_context if @tls_enabled
|
|
52
55
|
end
|
|
53
56
|
|
|
54
57
|
|
|
@@ -71,15 +74,26 @@ module Bunny
|
|
|
71
74
|
if uses_ssl?
|
|
72
75
|
@socket.connect
|
|
73
76
|
@socket.post_connection_check(host) if uses_tls? && @verify_peer
|
|
77
|
+
|
|
78
|
+
@status = :connected
|
|
79
|
+
|
|
80
|
+
@socket
|
|
74
81
|
else
|
|
75
82
|
# no-op
|
|
76
83
|
end
|
|
77
84
|
end
|
|
78
85
|
|
|
86
|
+
def connected?
|
|
87
|
+
:not_connected == @status && open?
|
|
88
|
+
end
|
|
89
|
+
|
|
79
90
|
def configure_socket(&block)
|
|
80
|
-
block.call(@socket)
|
|
91
|
+
block.call(@socket) if @socket
|
|
81
92
|
end
|
|
82
93
|
|
|
94
|
+
def configure_tls_context(&block)
|
|
95
|
+
block.call(@tls_context) if @tls_context
|
|
96
|
+
end
|
|
83
97
|
|
|
84
98
|
# Writes data to the socket. If read/write timeout was specified, Bunny::ClientTimeout will be raised
|
|
85
99
|
# if the operation times out.
|
|
@@ -102,6 +116,7 @@ module Bunny
|
|
|
102
116
|
end
|
|
103
117
|
rescue SystemCallError, Bunny::ClientTimeout, Bunny::ConnectionError, IOError => e
|
|
104
118
|
close
|
|
119
|
+
@status = :not_connected
|
|
105
120
|
|
|
106
121
|
if @session.automatically_recover?
|
|
107
122
|
@session.handle_network_failure(e)
|
|
@@ -153,11 +168,11 @@ module Bunny
|
|
|
153
168
|
|
|
154
169
|
|
|
155
170
|
def close(reason = nil)
|
|
156
|
-
@socket.close if
|
|
171
|
+
@socket.close if open?
|
|
157
172
|
end
|
|
158
173
|
|
|
159
174
|
def open?
|
|
160
|
-
!@socket.closed?
|
|
175
|
+
@socket && !@socket.closed?
|
|
161
176
|
end
|
|
162
177
|
|
|
163
178
|
def closed?
|
|
@@ -224,17 +239,11 @@ module Bunny
|
|
|
224
239
|
|
|
225
240
|
def initialize_socket
|
|
226
241
|
begin
|
|
227
|
-
|
|
242
|
+
@socket = Bunny::Timer.timeout(@connect_timeout, ConnectionTimeout) do
|
|
228
243
|
Bunny::Socket.open(@host, @port,
|
|
229
244
|
:keepalive => @opts[:keepalive],
|
|
230
245
|
:socket_timeout => @connect_timeout)
|
|
231
246
|
end
|
|
232
|
-
|
|
233
|
-
@socket = if uses_tls?
|
|
234
|
-
wrap_in_tls_socket(s)
|
|
235
|
-
else
|
|
236
|
-
s
|
|
237
|
-
end
|
|
238
247
|
rescue StandardError, ConnectionTimeout => e
|
|
239
248
|
@status = :not_connected
|
|
240
249
|
raise Bunny::TCPConnectionFailed.new(e, self.hostname, self.port)
|
|
@@ -243,6 +252,18 @@ module Bunny
|
|
|
243
252
|
@socket
|
|
244
253
|
end
|
|
245
254
|
|
|
255
|
+
def maybe_initialize_socket
|
|
256
|
+
initialize_socket if !@socket || closed?
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def post_initialize_socket
|
|
260
|
+
@socket = if uses_tls?
|
|
261
|
+
wrap_in_tls_socket(@socket)
|
|
262
|
+
else
|
|
263
|
+
@socket
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
246
267
|
protected
|
|
247
268
|
|
|
248
269
|
def tls_enabled?(opts)
|
|
@@ -257,10 +278,15 @@ module Bunny
|
|
|
257
278
|
opts[:tls_key] || opts[:ssl_key] || opts[:tls_key_path] || opts[:ssl_key_path]
|
|
258
279
|
end
|
|
259
280
|
|
|
260
|
-
def
|
|
281
|
+
def prepare_tls_context
|
|
261
282
|
read_tls_keys!
|
|
262
283
|
|
|
263
284
|
@tls_context = initialize_tls_context(OpenSSL::SSL::SSLContext.new)
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def wrap_in_tls_socket(socket)
|
|
288
|
+
raise ArgumentError, "cannot wrap nil into TLS socket, @tls_context is nil. This is a Bunny bug." unless socket
|
|
289
|
+
raise "cannot wrap a socket into TLS socket, @tls_context is nil. This is a Bunny bug." unless @tls_context
|
|
264
290
|
|
|
265
291
|
s = Bunny::SSLSocket.new(socket, @tls_context)
|
|
266
292
|
s.sync_close = true
|
data/lib/bunny/version.rb
CHANGED
|
@@ -114,5 +114,54 @@ describe Bunny::Queue, "#subscribe" do
|
|
|
114
114
|
ch.close
|
|
115
115
|
end
|
|
116
116
|
end
|
|
117
|
+
end # 20.times
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
context "after consumer pool has already been shut down" do
|
|
121
|
+
let(:queue_name) { "bunny.basic_consume#{rand}" }
|
|
122
|
+
|
|
123
|
+
it "registers the consumer" do
|
|
124
|
+
delivered_keys = []
|
|
125
|
+
delivered_data = []
|
|
126
|
+
|
|
127
|
+
t = Thread.new do
|
|
128
|
+
ch = connection.create_channel
|
|
129
|
+
q = ch.queue(queue_name)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
c1 = q.subscribe(:exclusive => false, :manual_ack => false, :block => false) do |delivery_info, properties, payload|
|
|
134
|
+
end
|
|
135
|
+
c1.cancel
|
|
136
|
+
puts "Cancelled #{c1.consumer_tag}"
|
|
137
|
+
|
|
138
|
+
c2 = q.subscribe(:exclusive => false, :manual_ack => false, :block => false) do |delivery_info, properties, payload|
|
|
139
|
+
delivered_keys << delivery_info.routing_key
|
|
140
|
+
delivered_data << payload
|
|
141
|
+
end
|
|
142
|
+
c2.cancel
|
|
143
|
+
puts "Cancelled #{c2.consumer_tag}"
|
|
144
|
+
|
|
145
|
+
q.subscribe(:exclusive => false, :manual_ack => false, :block => true) do |delivery_info, properties, payload|
|
|
146
|
+
delivered_keys << delivery_info.routing_key
|
|
147
|
+
delivered_data << payload
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
t.abort_on_exception = true
|
|
151
|
+
sleep 0.5
|
|
152
|
+
|
|
153
|
+
ch = connection.create_channel
|
|
154
|
+
x = ch.default_exchange
|
|
155
|
+
x.publish("hello", :routing_key => queue_name)
|
|
156
|
+
|
|
157
|
+
sleep 0.7
|
|
158
|
+
delivered_keys.should include(queue_name)
|
|
159
|
+
delivered_data.should include("hello")
|
|
160
|
+
|
|
161
|
+
ch.queue(queue_name).message_count.should == 0
|
|
162
|
+
|
|
163
|
+
ch.close
|
|
164
|
+
end
|
|
117
165
|
end
|
|
118
|
-
|
|
166
|
+
|
|
167
|
+
end # describe
|
|
@@ -2,7 +2,8 @@ require "spec_helper"
|
|
|
2
2
|
|
|
3
3
|
describe Bunny::Queue, "#pop" do
|
|
4
4
|
let(:connection) do
|
|
5
|
-
c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed"
|
|
5
|
+
c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed",
|
|
6
|
+
:automatically_recover => false)
|
|
6
7
|
c.start
|
|
7
8
|
c
|
|
8
9
|
end
|
|
@@ -30,25 +31,6 @@ describe Bunny::Queue, "#pop" do
|
|
|
30
31
|
end
|
|
31
32
|
|
|
32
33
|
|
|
33
|
-
context "with all defaults and a timeout that is never hit" do
|
|
34
|
-
it "fetches a messages which is automatically acknowledged" do
|
|
35
|
-
ch = connection.create_channel
|
|
36
|
-
|
|
37
|
-
q = ch.queue("", :exclusive => true)
|
|
38
|
-
x = ch.default_exchange
|
|
39
|
-
|
|
40
|
-
x.publish("xyzzy", :routing_key => q.name)
|
|
41
|
-
|
|
42
|
-
sleep(0.5)
|
|
43
|
-
delivery_info, properties, content = q.pop_waiting(:timeout => 1.0)
|
|
44
|
-
content.should == "xyzzy"
|
|
45
|
-
q.message_count.should == 0
|
|
46
|
-
|
|
47
|
-
ch.close
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
|
|
52
34
|
context "with an empty queue" do
|
|
53
35
|
it "returns an empty response" do
|
|
54
36
|
ch = connection.create_channel
|
|
@@ -63,20 +45,4 @@ describe Bunny::Queue, "#pop" do
|
|
|
63
45
|
ch.close
|
|
64
46
|
end
|
|
65
47
|
end
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
context "with an empty queue and a timeout" do
|
|
69
|
-
it "raises an exception" do
|
|
70
|
-
ch = connection.create_channel
|
|
71
|
-
|
|
72
|
-
q = ch.queue("", :exclusive => true)
|
|
73
|
-
q.purge
|
|
74
|
-
|
|
75
|
-
lambda {
|
|
76
|
-
_, _, content = q.pop_waiting(:timeout => 0.5)
|
|
77
|
-
}.should raise_error(Timeout::Error)
|
|
78
|
-
|
|
79
|
-
ch.close
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
48
|
end
|
|
@@ -153,27 +153,37 @@ describe Bunny::Session do
|
|
|
153
153
|
end
|
|
154
154
|
end
|
|
155
155
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
subject
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
156
|
+
unless ENV["CI"]
|
|
157
|
+
context "initialized with :ssl => true" do
|
|
158
|
+
let(:subject) do
|
|
159
|
+
described_class.new(:user => "bunny_gem",
|
|
160
|
+
:password => "bunny_password",
|
|
161
|
+
:vhost => "bunny_testbed",
|
|
162
|
+
:ssl => true,
|
|
163
|
+
:ssl_cert => "spec/tls/client_cert.pem",
|
|
164
|
+
:ssl_key => "spec/tls/client_key.pem",
|
|
165
|
+
:ssl_ca_certificates => ["./spec/tls/cacert.pem"])
|
|
166
|
+
end
|
|
167
167
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
168
|
+
it "uses TLS port" do
|
|
169
|
+
subject.port.should == tls_port
|
|
170
|
+
end
|
|
171
171
|
end
|
|
172
172
|
|
|
173
|
-
|
|
173
|
+
context "initialized with :tls => true" do
|
|
174
|
+
let(:subject) do
|
|
175
|
+
described_class.new(:user => "bunny_gem",
|
|
176
|
+
:password => "bunny_password",
|
|
177
|
+
:vhost => "bunny_testbed",
|
|
178
|
+
:tls => true,
|
|
179
|
+
:tls_cert => "spec/tls/client_cert.pem",
|
|
180
|
+
:tls_key => "spec/tls/client_key.pem",
|
|
181
|
+
:tls_ca_certificates => ["./spec/tls/cacert.pem"])
|
|
182
|
+
end
|
|
174
183
|
|
|
175
|
-
|
|
176
|
-
|
|
184
|
+
it "uses TLS port" do
|
|
185
|
+
subject.port.should == tls_port
|
|
186
|
+
end
|
|
177
187
|
end
|
|
178
188
|
end
|
|
179
189
|
|
|
@@ -346,19 +356,17 @@ describe Bunny::Session do
|
|
|
346
356
|
|
|
347
357
|
|
|
348
358
|
context "initialized with a disconnected host" do
|
|
349
|
-
subject do
|
|
350
|
-
described_class.new(:port => 38000)
|
|
351
|
-
end
|
|
352
|
-
|
|
353
359
|
it "fails to connect" do
|
|
354
360
|
lambda do
|
|
355
|
-
|
|
361
|
+
c = described_class.new(:port => 38000)
|
|
362
|
+
c.start
|
|
356
363
|
end.should raise_error(Bunny::TCPConnectionFailed)
|
|
357
364
|
end
|
|
358
365
|
|
|
359
366
|
it "is not connected" do
|
|
360
367
|
begin
|
|
361
|
-
|
|
368
|
+
c = described_class.new(:port => 38000)
|
|
369
|
+
c.start
|
|
362
370
|
rescue Bunny::TCPConnectionFailed => e
|
|
363
371
|
true
|
|
364
372
|
end
|
|
@@ -368,7 +376,8 @@ describe Bunny::Session do
|
|
|
368
376
|
|
|
369
377
|
it "is not open" do
|
|
370
378
|
begin
|
|
371
|
-
|
|
379
|
+
c = described_class.new(:port => 38000)
|
|
380
|
+
c.start
|
|
372
381
|
rescue Bunny::TCPConnectionFailed => e
|
|
373
382
|
true
|
|
374
383
|
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.9.0.
|
|
4
|
+
version: 0.9.0.rc2
|
|
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-06-
|
|
15
|
+
date: 2013-06-27 00:00:00.000000000 Z
|
|
16
16
|
dependencies:
|
|
17
17
|
- !ruby/object:Gem::Dependency
|
|
18
18
|
name: amq-protocol
|
|
@@ -28,7 +28,7 @@ dependencies:
|
|
|
28
28
|
- - '>='
|
|
29
29
|
- !ruby/object:Gem::Version
|
|
30
30
|
version: 1.6.0
|
|
31
|
-
description:
|
|
31
|
+
description: Easy to use, feature complete Ruby client for RabbitMQ 2.0.
|
|
32
32
|
email:
|
|
33
33
|
- celldee@gmail.com
|
|
34
34
|
- eric@5stops.com
|
|
@@ -178,7 +178,7 @@ files:
|
|
|
178
178
|
- spec/unit/concurrent/condition_spec.rb
|
|
179
179
|
- spec/unit/concurrent/linked_continuation_queue_spec.rb
|
|
180
180
|
- spec/unit/transport_spec.rb
|
|
181
|
-
homepage: http://
|
|
181
|
+
homepage: http://rubybunny.info
|
|
182
182
|
licenses:
|
|
183
183
|
- MIT
|
|
184
184
|
metadata: {}
|