brightbox-warren 0.5 → 0.7

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,2 +1,4 @@
1
+ v0.7. Added adapters
2
+ v0.6. Added config file
1
3
  v0.5. Added filters
2
4
  v0.3. Initial release
@@ -1,6 +1,6 @@
1
- Released under the MIT Licence
1
+ Released under the MIT License
2
2
 
3
- Copyright (c) 2008 Brightbox Systems Ltd
3
+ Copyright (c) 2008 Brightbox Systems Ltd
4
4
 
5
5
  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:
6
6
 
@@ -8,4 +8,4 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of
8
8
 
9
9
  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.
10
10
 
11
- See http://www.brightbox.co.uk/ for contact details.
11
+ See http://www.brightbox.co.uk/ for contact details.
data/Manifest CHANGED
@@ -2,24 +2,28 @@ CHANGELOG
2
2
  examples/authed/receiver.rb
3
3
  examples/authed/secret.rb
4
4
  examples/authed/sender.rb
5
- examples/simple/mass_sender.rb
6
- examples/simple/receiver.rb
7
- examples/simple/sender.rb
5
+ examples/simple/amqp_mass_sender.rb
6
+ examples/simple/amqp_receiver.rb
7
+ examples/simple/amqp_sender.rb
8
+ examples/simple/bunny_receiver.rb
9
+ examples/simple/bunny_sender.rb
10
+ lib/warren/adapters/amqp_adapter.rb
11
+ lib/warren/adapters/bunny_adapter.rb
8
12
  lib/warren/connection.rb
13
+ lib/warren/filters/shared_secret.rb
14
+ lib/warren/filters/yaml.rb
9
15
  lib/warren/message_filter.rb
10
- lib/warren/message_filters/shared_secret.rb
11
- lib/warren/message_filters/yaml.rb
12
16
  lib/warren/queue.rb
13
17
  lib/warren.rb
14
- LICENCE
18
+ LICENSE
15
19
  Manifest
16
20
  Rakefile
17
21
  readme.rdoc
18
- spec/hash_extend.rb
19
22
  spec/spec.opts
20
23
  spec/spec_helper.rb
21
24
  spec/warren/connection_spec.rb
22
- spec/warren/message_filter_spec.rb
23
25
  spec/warren/queue_spec.rb
26
+ spec/warren/warren_spec.rb
24
27
  tasks/rdoc.rake
25
28
  tasks/rspec.rake
29
+ warren.gemspec
data/Rakefile CHANGED
@@ -2,13 +2,13 @@ require 'rubygems'
2
2
  require 'rake'
3
3
 
4
4
  # Load in external rakefiles
5
- Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each do | rake_file |
5
+ Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each do | rake_file |
6
6
  load rake_file
7
7
  end
8
8
 
9
9
  # Gem stuff
10
10
  require 'echoe'
11
- Echoe.new('warren') do | gem |
11
+ Echoe.new('warren') do | gem |
12
12
  gem.author = ["Caius Durling", "David Smalley"]
13
13
  gem.email = 'support@brightbox.co.uk'
14
14
  gem.summary = 'Library for pushing messages onto and off RabbitMQ queues'
@@ -1,5 +1,7 @@
1
1
  require "rubygems"
2
2
  require File.expand_path(File.dirname(__FILE__) + "/../../lib/warren")
3
+ require File.expand_path(File.dirname(__FILE__) + "/../../lib/warren/adapters/amqp_adapter")
4
+ require File.expand_path(File.dirname(__FILE__) + "/../../lib/warren/filters/shared_secret")
3
5
 
4
6
  Signal.trap("INT") { AMQP.stop { EM.stop } }
5
7
  Signal.trap("TERM") { AMQP.stop { EM.stop } }
@@ -9,7 +11,7 @@ q = "main"
9
11
  puts "Listening to the #{q} queue."
10
12
 
11
13
  # Setup the connection directly this time
12
- Warren::Queue.connection = {:user => "caius", :pass => "caius", :vhost => "/"}
14
+ Warren::Queue.connection = {"development" => {:user => "caius", :pass => "caius", :vhost => "/"}}
13
15
 
14
16
  # Set the secret key
15
17
  require File.expand_path(File.dirname(__FILE__) + "/secret")
@@ -1,16 +1,18 @@
1
1
  require "rubygems"
2
2
  require File.expand_path(File.dirname(__FILE__) + "/../../lib/warren")
3
+ require File.expand_path(File.dirname(__FILE__) + "/../../lib/warren/adapters/amqp_adapter")
4
+ require File.expand_path(File.dirname(__FILE__) + "/../../lib/warren/filters/shared_secret")
3
5
 
4
6
  Signal.trap("INT") { exit! }
5
7
  Signal.trap("TERM") { exit! }
6
8
 
7
9
  # Setup our own connection before generating the queue object
8
- conn = Warren::Connection.new(
10
+ conn = Warren::Connection.new("development" => {
9
11
  :user => "caius",
10
12
  :pass => "caius",
11
13
  :vhost => "/",
12
14
  :default_queue => "main"
13
- )
15
+ })
14
16
  # Set the connection for the queue
15
17
  Warren::Queue.connection = conn
16
18
  # Generate some data to send
@@ -0,0 +1,18 @@
1
+ require "rubygems"
2
+ require File.expand_path(File.dirname(__FILE__) + "/../../lib/warren")
3
+ # Next line is the only one you need to change to use a different adapter
4
+ require File.expand_path(File.dirname(__FILE__) + "/../../lib/warren/adapters/amqp_adapter")
5
+
6
+ Signal.trap("INT") { AMQP.stop { EM.stop } }
7
+ Signal.trap("TERM") { AMQP.stop { EM.stop } }
8
+
9
+ # Listen to the main queue
10
+ q = "main"
11
+ puts "Listening to the #{q} queue."
12
+
13
+ Warren::Queue.connection = {"development" => {:user => "caius", :pass => "caius", :vhost => "/"}}
14
+
15
+ # And attach a block for new messages to fire
16
+ Warren::Queue.subscribe(q) do |msg|
17
+ p [Time.now, msg]
18
+ end
@@ -1,16 +1,18 @@
1
1
  require "rubygems"
2
- require File.expand_path(File.dirname(__FILE__) + "/../lib/warren")
2
+ require File.expand_path(File.dirname(__FILE__) + "/../../lib/warren")
3
+ # Next line is the only one you need to change to use a different adapter
4
+ require File.expand_path(File.dirname(__FILE__) + "/../../lib/warren/adapters/amqp_adapter")
3
5
 
4
6
  Signal.trap("INT") { exit! }
5
7
  Signal.trap("TERM") { exit! }
6
8
 
7
9
  # Setup our own connection before generating the queue object
8
- conn = Warren::Connection.new(
10
+ conn = Warren::Connection.new("development" => {
9
11
  :user => "caius",
10
12
  :pass => "caius",
11
13
  :vhost => "/",
12
14
  :default_queue => "main"
13
- )
15
+ })
14
16
  # Set the connection for the queue
15
17
  Warren::Queue.connection = conn
16
18
  # Generate some data to send
@@ -26,8 +28,9 @@ data = {
26
28
  }
27
29
  ]
28
30
  }
31
+
29
32
  # Push a message onto the queue
30
33
  p Warren::Queue.publish(:default, data )
31
34
 
32
35
  # And then push a message onto the queue, returning "foo"
33
- p Warren::Queue.publish(:default, data) { "foo" }
36
+ # p Warren::Queue.publish(:default, data) { "foo" }
@@ -0,0 +1,18 @@
1
+ require "rubygems"
2
+ require File.expand_path(File.dirname(__FILE__) + "/../../lib/warren")
3
+ # Next line is the only one you need to change to use a different adapter
4
+ require File.expand_path(File.dirname(__FILE__) + "/../../lib/warren/adapters/bunny_adapter")
5
+
6
+ Signal.trap("INT") { exit! }
7
+ Signal.trap("TERM") { exit! }
8
+
9
+ # Listen to the main queue
10
+ q = "main"
11
+ puts "Listening to the #{q} queue."
12
+
13
+ Warren::Queue.connection = {"development" => {:user => "caius", :pass => "caius", :vhost => "/"}}
14
+
15
+ # And attach a block for new messages to fire
16
+ Warren::Queue.subscribe(q) do |msg|
17
+ p [Time.now, msg]
18
+ end
@@ -0,0 +1,36 @@
1
+ require "rubygems"
2
+ require File.expand_path(File.dirname(__FILE__) + "/../../lib/warren")
3
+ # Next line is the only one you need to change to use a different adapter
4
+ require File.expand_path(File.dirname(__FILE__) + "/../../lib/warren/adapters/bunny_adapter")
5
+
6
+ Signal.trap("INT") { exit! }
7
+ Signal.trap("TERM") { exit! }
8
+
9
+ # Setup our own connection before generating the queue object
10
+ conn = Warren::Connection.new("development" => {
11
+ :user => "caius",
12
+ :pass => "caius",
13
+ :vhost => "/",
14
+ :default_queue => "main"
15
+ })
16
+ # Set the connection for the queue
17
+ Warren::Queue.connection = conn
18
+ # Generate some data to send
19
+ data = {
20
+ :people => [
21
+ :fred => {
22
+ :age => 25,
23
+ :location => "Leeds"
24
+ },
25
+ :george => {
26
+ :age => 32,
27
+ :location => "London"
28
+ }
29
+ ]
30
+ }
31
+
32
+ # Push a message onto the queue
33
+ p Warren::Queue.publish(:default, data )
34
+
35
+ # And then push a message onto the queue, returning "foo"
36
+ # p Warren::Queue.publish(:default, data) { "foo" }
data/lib/warren.rb CHANGED
@@ -1,24 +1,23 @@
1
1
  require "yaml"
2
- require "rubygems"
3
- require "mq"
4
2
 
5
- #
3
+ #
6
4
  # Library for pushing messages onto RabbitMQ queues,
7
5
  # and receiving them at the other end.
8
- #
6
+ #
9
7
  # It handles authentication + filtering messages with custom
10
8
  # classes if needed.
11
- #
9
+ #
12
10
  # Start with Warren::Queue for details and see also
13
11
  # examples/
14
- #
12
+ #
15
13
  module Warren
16
- @@foo = ""
17
14
  end
18
15
 
19
- WARREN_ROOT = File.expand_path(File.join(File.dirname(__FILE__), ".."))
16
+ WARREN_ENV = (defined?(RAILS_ENV) ? RAILS_ENV : "development") unless defined?(WARREN_ENV)
17
+ WARREN_ROOT = File.dirname($0)
18
+ WARREN_LIB_ROOT = File.expand_path(File.join(File.dirname(__FILE__), ".."))
20
19
 
21
20
  # Require everything in the lib folder
22
- Dir["#{WARREN_ROOT}/lib/warren/**/*.rb"].each do |file|
21
+ Dir["#{WARREN_LIB_ROOT}/lib/warren/*.rb"].each do |file|
23
22
  require file
24
23
  end
@@ -0,0 +1,87 @@
1
+ require "rubygems"
2
+ require "mq"
3
+
4
+ class Warren::Queue::AMQPAdapter < Warren::Queue
5
+
6
+ #
7
+ # Checks the connection details are correct for this adapter
8
+ #
9
+ def self.check_connection_details opts
10
+ # Check they've passed in the stuff without a default on it
11
+ unless opts.has_key?(:user) && opts.has_key?(:pass) && opts.has_key?(:vhost)
12
+ raise Warren::Connection::InvalidConnectionDetails, "Missing a username, password or vhost."
13
+ end
14
+ true
15
+ end
16
+
17
+ #
18
+ # Returns the default queue name or returns InvalidConnectionDetails
19
+ # if no default queue is defined
20
+ #
21
+ def self.queue_name
22
+ unless self.connection.options.has_key?(:default_queue)
23
+ raise Warren::Connection::InvalidConnectionDetails, "Missing a default queue name."
24
+ end
25
+ self.connection.options[:default_queue]
26
+ end
27
+
28
+ #
29
+ # Sends a message to a queue. If successfully sent it returns
30
+ # true, unless callback block is passed (see below)
31
+ #
32
+ # Warren::Queue.publish(:queue_name, {:foo => "name"})
33
+ #
34
+ # Can also pass a block which is fired after the message
35
+ # is sent. If a block is passed, then the return value of the block
36
+ # is returned from this method.
37
+ #
38
+ # Warren::Queue.publish(:queue_name, {:foo => "name"}) { puts "foo" }
39
+ #
40
+ def self.publish queue_name, payload, &blk
41
+ queue_name = self.queue_name if queue_name == :default
42
+ # Create a message object if it isn't one already
43
+ msg = Warren::MessageFilter.pack(payload)
44
+
45
+ do_connect(true, blk) do
46
+ queue = MQ::Queue.new(MQ.new, queue_name)
47
+ queue.publish msg.to_s
48
+ end
49
+
50
+ end
51
+
52
+ #
53
+ # Subscribes to a queue and runs the block
54
+ # for each message received
55
+ #
56
+ # Warren::Queue.subscribe("example") {|msg| puts msg }
57
+ #
58
+ # Expects a block and raises NoBlockGiven if no block is given.
59
+ #
60
+ def self.subscribe queue_name, &block
61
+ raise NoBlockGiven unless block_given?
62
+ queue_name = self.queue_name if queue_name == :default
63
+ # todo: check if its a valid queue?
64
+ do_connect(false) do
65
+ queue = MQ::Queue.new(MQ.new, queue_name)
66
+ queue.subscribe do |msg|
67
+ msg = Warren::MessageFilter.unpack(msg)
68
+ block.call(msg)
69
+ end
70
+ end
71
+ end
72
+
73
+ private
74
+
75
+ #
76
+ # Connects and does the stuff its told to!
77
+ #
78
+ def self.do_connect should_stop = true, callback = nil, &block
79
+ AMQP.start(self.connection.options) do
80
+ block.call
81
+ AMQP.stop { EM.stop_event_loop } if should_stop
82
+ end
83
+ # Returns the block return value or true
84
+ callback.nil? ? true : callback.call
85
+ end
86
+
87
+ end
@@ -0,0 +1,97 @@
1
+ require "rubygems"
2
+ require "bunny"
3
+
4
+ class Warren::Queue::BunnyAdapter < Warren::Queue
5
+
6
+ #
7
+ # Checks the connection details are correct for this adapter
8
+ #
9
+ def self.check_connection_details opts
10
+ # Check they've passed in the stuff without a default on it
11
+ unless opts.has_key?(:user) && opts.has_key?(:pass) && opts.has_key?(:vhost)
12
+ raise Warren::Connection::InvalidConnectionDetails, "Missing a username, password or vhost."
13
+ end
14
+ true
15
+ end
16
+
17
+ #
18
+ # Returns the default queue name or returns InvalidConnectionDetails
19
+ # if no default queue is defined
20
+ #
21
+ def self.queue_name
22
+ unless self.connection.options.has_key?(:default_queue)
23
+ raise Warren::Connection::InvalidConnectionDetails, "Missing a default queue name."
24
+ end
25
+ self.connection.options[:default_queue]
26
+ end
27
+
28
+ #
29
+ # Sends a message to a queue. If successfully sent it returns
30
+ # true, unless callback block is passed (see below)
31
+ #
32
+ # Warren::Queue.publish(:queue_name, {:foo => "name"})
33
+ #
34
+ # Can also pass a block which is fired after the message
35
+ # is sent. If a block is passed, then the return value of the block
36
+ # is returned from this method.
37
+ #
38
+ # Warren::Queue.publish(:queue_name, {:foo => "name"}) { puts "foo" }
39
+ #
40
+ def self.publish queue_name, payload, &blk
41
+ queue_name = self.queue_name if queue_name == :default
42
+ # Create a message object if it isn't one already
43
+ msg = Warren::MessageFilter.pack(payload)
44
+
45
+ do_connect(queue_name, blk) do |queue|
46
+ queue.publish msg.to_s
47
+ end
48
+
49
+ end
50
+
51
+ #
52
+ # Subscribes to a queue and runs the block
53
+ # for each message received
54
+ #
55
+ # Warren::Queue.subscribe("example") {|msg| puts msg }
56
+ #
57
+ # Expects a block and raises NoBlockGiven if no block is given.
58
+ #
59
+ def self.subscribe queue_name, &block
60
+ raise NoBlockGiven unless block_given?
61
+ queue_name = self.queue_name if queue_name == :default
62
+ # todo: check if its a valid queue?
63
+ do_connect(queue_name) do |queue|
64
+ msg = queue.pop
65
+ return if msg == :queue_empty
66
+ block.call(Warren::MessageFilter.unpack(msg))
67
+ end
68
+ end
69
+
70
+ private
71
+
72
+ #
73
+ # Connects and does the stuff its told to!
74
+ #
75
+ def self.do_connect queue_name, callback = nil, &block
76
+ # Open a connection
77
+ b = Bunny.new(connection_details)
78
+ b.start
79
+ # Create the queue
80
+ q = b.queue(queue_name)
81
+ # Run the code on the queue
82
+ block.call(q)
83
+ # And stop
84
+ b.stop
85
+ # Returns the block return value or true
86
+ callback.nil? ? true : callback.call
87
+ end
88
+
89
+ def self.connection_details
90
+ {
91
+ :user => self.connection.options[:user],
92
+ :pass => self.connection.options[:pass],
93
+ :vhost => self.connection.options[:vhost]
94
+ }
95
+ end
96
+
97
+ end