forked from Vericity/bunny_burrow
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Phillip Koebbe
committed
Jun 16, 2016
1 parent
6fb5d1d
commit 8e624c4
Showing
24 changed files
with
1,182 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/.bundle/ | ||
/.yardoc | ||
/Gemfile.lock | ||
/_yardoc/ | ||
/coverage/ | ||
/doc/ | ||
/pkg/ | ||
/spec/reports/ | ||
/tmp/ | ||
*.bundle | ||
*.so | ||
*.o | ||
*.a | ||
mkmf.log | ||
vendor/bundle | ||
.ruby-version |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
language: ruby | ||
rvm: | ||
- 2.2.0 | ||
before_install: gem install bundler -v 1.11.2 | ||
install: bundle install --path vendor/bundle | ||
script: bundle exec rspec |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
source 'https://rubygems.org' | ||
|
||
gemspec |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
The MIT License (MIT) | ||
|
||
Copyright (c) 2016 Fidelity Life Association | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,135 @@ | ||
bunny_burrow | ||
# BunnyBurrow | ||
|
||
BunnyBurrow is a simple approach to RPC over RabbitMQ via the Bunny gem. | ||
A 'server' application listens on one ore more queues on a topic exchange | ||
while a 'client' publishes to a single queue on the same exchange. | ||
BunnyBurrow will do all of the dirty work of establishing a connection to | ||
RabbitMQ, opening the channel, ensuring the exchange and queue(s) exist, | ||
and sending the payloads back and forth. All you have to do is decide what | ||
to do on each end. BunnyBurrow even cleans up after itself so there aren't | ||
a bunch of queues and connections left laying around after they are no | ||
longer needed. | ||
|
||
Why 'burrow'? | ||
|
||
burrow (noun) | ||
1. a hole or tunnel dug by a small animal, especially a rabbit, as a dwelling. | ||
synonyms: hole, tunnel, warren, dugout | ||
|
||
burrow (verb) | ||
1. (of an animal) make a hole or tunnel, especially to use as a dwelling. | ||
synonyms: tunnel, dig (out), excavate, grub, mine, bore, channel | ||
|
||
The idea that _a_ burrow is a tunnel (or channel) and _to_ burrow is to | ||
make a tunnel (or channel) seemed to fit very nicely with what the gem does. | ||
Well, that and 'bunny_rpc' was already taken ;) | ||
|
||
## Installation | ||
|
||
Add this line to your application's Gemfile: | ||
|
||
```ruby | ||
gem 'bunny_burrow' | ||
``` | ||
|
||
And then execute: | ||
|
||
$ bundle | ||
|
||
Or install it yourself as: | ||
|
||
$ gem install bunny_burrow | ||
|
||
## Usage | ||
|
||
There are templates you can use to get started quickly (or just see how | ||
BunnyBurrow is used) in the `templates` directory of the repository. But a | ||
very simple server can be made with | ||
|
||
```ruby | ||
require 'bunny_burrow' | ||
|
||
rpc_server = BunnyBurrow::Server.new do |server| | ||
server.rabbitmq_url = 'amqp://user:pass@server[:port]/vhost' | ||
server.rabbitmq_exchange = 'bunny_exchange' | ||
server.logger = Logger.new(STDOUT) | ||
end | ||
|
||
rpc_server.subscribe('some.routing.key') do |payload, response| | ||
response[:data] = do_something_with(payload) | ||
|
||
# return the response | ||
response | ||
end | ||
|
||
# can subscribe to multiple queues | ||
rpc_server.subscribe('some.other.routing.key') do |payload, response| | ||
response[:data] = do_something_else_with(payload) | ||
|
||
# return the response | ||
response | ||
end | ||
|
||
# tell the server to keep the process alive so it can receive messages | ||
rpc_server.wait | ||
|
||
# at some later point, stop waiting and close connections | ||
rpc_server.shutdown | ||
``` | ||
|
||
A client is equally as easy to implement: | ||
|
||
```ruby | ||
require 'bunny_burrow' | ||
|
||
rpc_client = BunnyBurrow::Client.new do |client| | ||
client.rabbitmq_url = 'amqp://user:pass@server[:port]/vhost' | ||
client.rabbitmq_exchange = 'bunny_exchange' | ||
client.logger = Logger.new(STDOUT) | ||
end | ||
|
||
payload = { question: 'the thing you want' } | ||
|
||
# the rpc_client will wait for a response from the server | ||
# (this _is_ RPC, after all ;) ) | ||
result = rpc_client.publish(payload, 'some.routing.key') | ||
puts result | ||
|
||
# some time later, close connections | ||
rpc_client.shutdown | ||
``` | ||
|
||
Using the templates is also easy: | ||
|
||
``` | ||
$ cd /path/to/development/work | ||
$ git init my_rpc_server | ||
$ cd my_rpc_server | ||
$ cp /path/to/bunny_burrow/repo/templates/Gemfile . | ||
$ cp -R /path/to/bunny_burrow/repo/templates/server/* . | ||
$ grep -r your_project . | cut -d : -f 1 | xargs sed -i '' 's/your_project/my_rpc_server/' | ||
$ grep -r YourProject . | cut -d : -f 1 | xargs sed -i '' 's/YourProject/MyRPCServer/' | ||
$ mv lib/your_project lib/my_rpc_server | ||
``` | ||
|
||
Edit the Gemfile as appropriate, then | ||
|
||
``` | ||
$ bundle install [--path vendor/bundle] | ||
$ git add . | ||
$ git commit -m 'Initial commit.' | ||
``` | ||
|
||
## Development | ||
|
||
After checking out the repo, run `bundle install [--path vendor/bundle]` to install dependencies. | ||
Then, run `bundle exec rspec` to run the tests. | ||
|
||
## Contributing | ||
|
||
Bug reports and pull requests are welcome on GitHub at https://github.com/vericity/bunny_burrow. | ||
|
||
## License | ||
|
||
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT). | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
require "bundler/gem_tasks" | ||
require "rspec/core/rake_task" | ||
|
||
RSpec::Core::RakeTask.new(:spec) | ||
|
||
task :default => :spec |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# coding: utf-8 | ||
lib = File.expand_path('lib', __dir__) | ||
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) | ||
require 'bunny_burrow/version' | ||
|
||
Gem::Specification.new do |spec| | ||
spec.name = 'bunny_burrow' | ||
spec.version = BunnyBurrow::VERSION | ||
spec.authors = ['Fidelity Life Association'] | ||
|
||
spec.summary = 'RPC over RabbitMQ based on Bunny.' | ||
spec.description = spec.summary | ||
spec.license = 'MIT' | ||
|
||
spec.files = ['lib/bunny_burrow.rb'] | ||
spec.require_paths = ['lib'] | ||
|
||
spec.add_development_dependency 'bundler', '~> 1.11' | ||
spec.add_development_dependency 'pry' | ||
spec.add_development_dependency 'pry-nav' | ||
spec.add_development_dependency 'rake', '~> 10.0' | ||
spec.add_development_dependency 'rspec', '~> 3.0' | ||
spec.add_development_dependency 'simplecov', '~> 0.11.2' | ||
spec.add_development_dependency 'simplecov-rcov', '~> 0.2.3' | ||
|
||
spec.add_runtime_dependency 'bunny', '~> 2.3.1' | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
require 'bunny_burrow/version' | ||
require 'bunny_burrow/client' | ||
require 'bunny_burrow/server' | ||
|
||
module BunnyBurrow | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
require 'bunny' | ||
require 'json' | ||
require 'thread' | ||
|
||
module BunnyBurrow | ||
STATUS_OK = 'ok' | ||
STATUS_CLIENT_ERROR = 'client_error' | ||
STATUS_SERVER_ERROR = 'server_error' | ||
|
||
class Base | ||
attr_accessor :rabbitmq_url, :rabbitmq_exchange, :logger, :log_prefix | ||
attr_writer :timeout, :log_request, :log_response | ||
|
||
def initialize | ||
yield self if block_given? | ||
end | ||
|
||
def timeout | ||
@timeout ||= 60 | ||
end | ||
|
||
def log_request? | ||
@log_request ||= false | ||
end | ||
|
||
def log_response? | ||
@log_response ||= false | ||
end | ||
|
||
def shutdown | ||
log 'Shutting down' | ||
channel.close | ||
connection.close | ||
end | ||
|
||
private | ||
|
||
def connection | ||
unless @connection | ||
@connection = Bunny.new(rabbitmq_url) | ||
@connection.start | ||
end | ||
|
||
@connection | ||
end | ||
|
||
def channel | ||
@channel ||= connection.create_channel | ||
end | ||
|
||
def default_exchange | ||
@default_exchange ||= channel.default_exchange | ||
end | ||
|
||
def topic_exchange | ||
@topic_exchange ||= channel.topic(rabbitmq_exchange, durable: true) | ||
end | ||
|
||
def lock | ||
@lock ||= Mutex.new | ||
end | ||
|
||
def condition | ||
@condition ||= ConditionVariable.new | ||
end | ||
|
||
def log(message, level: :info) | ||
prefix = log_prefix || 'BunnyBurrow' | ||
message = "#{prefix}: #{message}" | ||
logger.send(level, message) if logger | ||
end | ||
end | ||
end | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
require_relative 'base' | ||
|
||
module BunnyBurrow | ||
class Client < Base | ||
def publish(payload, routing_key) | ||
result = nil | ||
|
||
details = { | ||
routing_key: routing_key, | ||
reply_to: reply_to | ||
} | ||
details[:request] = payload if log_request? | ||
log "Publishing #{details}" | ||
|
||
begin | ||
options = { | ||
routing_key: routing_key, | ||
reply_to: reply_to.name, | ||
persistence: false | ||
} | ||
|
||
topic_exchange.publish(payload.to_json, options) | ||
|
||
Timeout.timeout(timeout) do | ||
reply_to.subscribe do |_, _, payload| | ||
details[:response] = payload if log_response? | ||
log "Receiving #{details}" | ||
result = payload | ||
lock.synchronize { condition.signal } | ||
end | ||
|
||
lock.synchronize { condition.wait(lock) } | ||
end | ||
rescue Timeout::Error => e | ||
log "Timeout #{details}", level: :error | ||
result = e.message | ||
end | ||
|
||
result | ||
rescue => e | ||
log e.message, level: :error | ||
end | ||
|
||
private | ||
|
||
def reply_to | ||
# when creating a queue, a blank name indicates we want the AMPQ broker | ||
# to generate a unique name for us. Also note that this queue will be on | ||
# the default exchange | ||
@reply_to ||= channel.queue('', exclusive: true, auto_delete: true) | ||
end | ||
end | ||
end |
Oops, something went wrong.