cwyckoff-rosetta_queue 0.1.4 → 0.2.0

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.
data/Rakefile CHANGED
@@ -18,8 +18,8 @@ begin
18
18
  s.name = "rosetta_queue"
19
19
  s.rubyforge_project = "rosetta-queue"
20
20
  s.summary = %Q{Messaging gateway API with adapters for many messaging systems available in Ruby.}
21
- s.email = "cbwyckoff@gmail.com"
22
- s.homepage = "http://github.com/cwyckoff/rosetta_queue"
21
+ s.email = "ben@benmabey.com"
22
+ s.homepage = "http://github.com/bmabey/rosetta_queue"
23
23
  s.description = %Q{Messaging gateway API with adapters for many messaging systems available in Ruby. Messaging systems can be easily switched out with a small configuration change. Code for testing on the object and application level is also provided.}
24
24
  s.extra_rdoc_files = ["README.rdoc", "MIT-LICENSE.txt"]
25
25
  s.files = FileList["[A-Z]*.*", "{bin,generators,lib,features,spec}/**/*", "Rakefile", "cucumber.yml"]
@@ -15,6 +15,7 @@ module RosettaQueue
15
15
  end
16
16
 
17
17
  def type=(adapter_prefix)
18
+ require "rosetta_queue/adapters/amqp_base" if adapter_prefix =~ /amqp/
18
19
  require "rosetta_queue/adapters/#{adapter_prefix}"
19
20
  @adapter_class = RosettaQueue::Gateway.const_get("#{adapter_prefix.to_s.classify}Adapter")
20
21
 
@@ -0,0 +1,123 @@
1
+ require 'mq'
2
+
3
+ module RosettaQueue
4
+ module Gateway
5
+
6
+ class AmqpAdapter < AmqpBaseAdapter
7
+
8
+ def exchange_strategy_for(destination, options)
9
+ case destination
10
+ when /fanout/
11
+ @exchange ||= AmqpExchangeStrategies::FanoutExchange.new(@adapter_settings, options)
12
+ when /queue/
13
+ @exchange ||= AmqpExchangeStrategies::DirectExchange.new(@adapter_settings, options)
14
+ else
15
+ @exchange ||= AmqpExchangeStrategies::DirectExchange.new(@adapter_settings, options)
16
+ end
17
+ end
18
+ end
19
+
20
+ module AmqpExchangeStrategies
21
+
22
+ class BaseExchange
23
+
24
+ def initialize(adapter_settings, options={})
25
+ @adapter_settings, @options = adapter_settings, options
26
+ end
27
+
28
+ def publish(destination, message)
29
+ unless EM.reactor_running?
30
+ EM.run do
31
+ publish_message(destination, message)
32
+ EM.add_timer(1) { EM.stop_event_loop }
33
+ end
34
+ else
35
+ publish_message(destination, message)
36
+ end
37
+ end
38
+
39
+ protected
40
+
41
+ def channel
42
+ @channel ||= MQ.new(conn)
43
+ end
44
+
45
+ def conn
46
+ vhost = @adapter_settings[:opts][:vhost] || "/"
47
+ @conn ||= AMQP.connect(:user => @adapter_settings[:user],
48
+ :pass => @adapter_settings[:password],
49
+ :host => @adapter_settings[:host],
50
+ :vhost => vhost)
51
+ end
52
+
53
+ def publish_message(dest, msg)
54
+ RosettaQueue.logger.info("Publishing to #{dest} :: #{msg}")
55
+ channel.queue(dest).publish(msg, @options)
56
+ channel.queue(dest).unsubscribe
57
+ end
58
+ end
59
+
60
+
61
+ class DirectExchange < BaseExchange
62
+
63
+ def receive(destination, message_handler)
64
+ channel.queue(destination).subscribe(@options) do |msg|
65
+ RosettaQueue.logger.info("Receiving from #{destination} :: #{msg}")
66
+ message_handler.on_message(Filters.process_receiving(msg))
67
+ end
68
+ end
69
+
70
+ def receive_once(destination)
71
+ EM.run do
72
+ channel.queue(destination).pop(@options) do |msg|
73
+ RosettaQueue.logger.info("Receiving from #{destination} :: #{msg}")
74
+ yield Filters.process_receiving(msg)
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+
81
+ class FanoutExchange < BaseExchange
82
+
83
+ def receive(destination, message_handler)
84
+ queue = channel.queue("queue_#{self.object_id}")
85
+ exchange = channel.fanout(fanout_name_for(destination))
86
+
87
+ queue.bind(exchange).subscribe(@options) do |msg|
88
+ RosettaQueue.logger.info("Receiving from #{destination} :: #{msg}")
89
+ message_handler.on_message(Filters.process_receiving(msg))
90
+ end
91
+ end
92
+
93
+ def receive_once(destination)
94
+ EM.run do
95
+ queue = channel.queue("queue_#{self.object_id}")
96
+ exchange = channel.fanout(fanout_name_for(destination))
97
+
98
+ queue.bind(exchange).pop(@options) do |msg|
99
+ RosettaQueue.logger.info("Receiving from #{destination} :: #{msg}")
100
+ yield Filters.process_receiving(msg)
101
+ end
102
+ end
103
+ end
104
+
105
+ protected
106
+
107
+ def publish_message(dest, msg)
108
+ exchange = channel.fanout(fanout_name_for(dest))
109
+ exchange.publish(msg, @options)
110
+ RosettaQueue.logger.info("Publishing to fanout #{dest} :: #{msg}")
111
+ end
112
+
113
+ private
114
+
115
+ def fanout_name_for(destination)
116
+ fanout_name = destination.gsub(/(topic|fanout)\/(.*)/, '\2')
117
+ raise "Unable to discover fanout exchange. Cannot bind queue to exchange!" unless fanout_name
118
+ fanout_name
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,36 @@
1
+ module RosettaQueue
2
+ module Gateway
3
+
4
+ class AmqpBaseAdapter < BaseAdapter
5
+
6
+ def initialize(adapter_settings = {})
7
+ raise AdapterException, "Missing adapter settings" if adapter_settings.empty?
8
+ @adapter_settings = adapter_settings
9
+ end
10
+
11
+ def delete(destination, opts={})
12
+ exchange_strategy_for(destination, opts).delete(destination)
13
+ end
14
+
15
+ def disconnect(message_handler); end
16
+
17
+ def receive_once(destination, opts={})
18
+ exchange_strategy_for(destination, opts).receive_once(destination) do |msg|
19
+ return msg
20
+ end
21
+ end
22
+
23
+ def receive_with(message_handler)
24
+ options = options_for(message_handler)
25
+ destination = destination_for(message_handler)
26
+ exchange_strategy_for(destination, options).receive(destination, message_handler)
27
+ end
28
+
29
+ def send_message(destination, message, options=nil)
30
+ exchange_strategy_for(destination, options).publish(destination, message)
31
+ end
32
+
33
+ def unsubscribe; end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,100 @@
1
+ require 'carrot'
2
+
3
+ module RosettaQueue
4
+ module Gateway
5
+
6
+ class AmqpCarrotAdapter < AmqpBaseAdapter
7
+
8
+ def exchange_strategy_for(destination, options)
9
+ case destination
10
+ when /fanout/
11
+ @exchange ||= CarrotExchangeStrategies::FanoutExchange.new(@adapter_settings, options)
12
+ when /queue/
13
+ @exchange ||= CarrotExchangeStrategies::DirectExchange.new(@adapter_settings, options)
14
+ else
15
+ @exchange ||= CarrotExchangeStrategies::DirectExchange.new(@adapter_settings, options)
16
+ end
17
+ end
18
+
19
+ end
20
+
21
+ module CarrotExchangeStrategies
22
+
23
+ class BaseExchange
24
+
25
+ def initialize(adapter_settings, options={})
26
+ @adapter_settings, @options = adapter_settings, options
27
+ end
28
+
29
+ def delete(destination)
30
+ conn.queue(destination).delete(@options)
31
+ end
32
+
33
+ protected
34
+ def conn
35
+ vhost = @adapter_settings[:opts][:vhost] || "/"
36
+ @conn ||= Carrot.new(:user => @adapter_settings[:user],
37
+ :pass => @adapter_settings[:password],
38
+ :host => @adapter_settings[:host],
39
+ :vhost => vhost)
40
+ end
41
+ end
42
+
43
+ class DirectExchange < BaseExchange
44
+
45
+ def publish(destination, message, options={})
46
+ RosettaQueue.logger.info("Publishing to #{destination} :: #{message}")
47
+ conn.queue(destination).publish(message, options)
48
+ end
49
+
50
+ def receive(destination, message_handler)
51
+ conn.queue(destination).subscribe(@options) do |msg|
52
+ RosettaQueue.logger.info("Receiving from #{destination} :: #{msg}")
53
+ message_handler.on_message(Filters.process_receiving(msg))
54
+ end
55
+ end
56
+
57
+ def receive_once(destination)
58
+ msg = conn.queue(destination).pop(@options)
59
+ RosettaQueue.logger.info("Receiving from #{destination} :: #{msg}")
60
+ yield Filters.process_receiving(msg)
61
+ end
62
+ end
63
+
64
+ class FanoutExchange < BaseExchange
65
+
66
+ def fanout_name_for(destination)
67
+ fanout_name = destination.gsub(/fanout\/(.*)/, '\1')
68
+ raise "Unable to discover fanout exchange. Cannot bind queue to exchange!" unless fanout_name
69
+ fanout_name
70
+ end
71
+
72
+ def receive_once(destination)
73
+ queue = conn.queue("queue_#{self.object_id}")
74
+ exchange = conn.fanout(fanout_name_for(destination))
75
+
76
+ msg = queue.bind(exchange).pop(@options)
77
+ RosettaQueue.logger.info("Receiving from #{destination} :: #{msg}")
78
+ yield Filters.process_receiving(msg)
79
+ end
80
+
81
+ def publish(destination, message, options={})
82
+ exchange = conn.fanout(fanout_name_for(destination))
83
+ exchange.publish(message, @options)
84
+ RosettaQueue.logger.info("Publishing to fanout #{destination} :: #{message}")
85
+ end
86
+
87
+ def receive(destination, message_handler)
88
+ queue = conn.queue("queue_#{self.object_id}")
89
+ exchange = conn.fanout(fanout_name_for(destination))
90
+
91
+ msg = queue.bind(exchange).subscribe(@options) do |msg|
92
+
93
+ RosettaQueue.logger.info("Receiving from #{destination} :: #{msg}")
94
+ message_handler.on_message(Filters.process_receiving(msg))
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -24,4 +24,4 @@ module RosettaQueue
24
24
 
25
25
  end
26
26
  end
27
- end
27
+ end
@@ -5,14 +5,14 @@ module RosettaQueue
5
5
  RosettaQueue::Adapter.instance.receive_once(Destinations.lookup(destination), options)
6
6
 
7
7
  rescue Exception=>e
8
- RosettaQueue.logger.error("Caught exception in Consumer.receive: #{$!}\n" + e.backtrace.join("\n\t"))
8
+ RosettaQueue.logger.error("Caught exception in Consumer#receive: #{$!}\n" + e.backtrace.join("\n\t"))
9
9
  end
10
10
 
11
11
  def self.delete(destination, options={})
12
12
  RosettaQueue::Adapter.instance.delete(Destinations.lookup(destination), options)
13
13
 
14
14
  rescue Exception=>e
15
- RosettaQueue.logger.error("Caught exception in Consumer.delete: #{$!}\n" + e.backtrace.join("\n\t"))
15
+ RosettaQueue.logger.error("Caught exception in Consumer#delete: #{$!}\n" + e.backtrace.join("\n\t"))
16
16
  end
17
17
 
18
18
  def initialize(message_handler)
@@ -19,4 +19,4 @@ module RosettaQueue
19
19
  end
20
20
 
21
21
  end
22
- end
22
+ end
@@ -7,8 +7,16 @@ module RosettaQueue
7
7
  RosettaQueue::Adapter.instance.send_message(Destinations.lookup(destination), Filters.process_sending(message), options)
8
8
 
9
9
  rescue Exception=>e
10
- RosettaQueue.logger.error("Caught exception in Consumer.publish: #{$!}\n" + e.backtrace.join("\n\t"))
10
+ RosettaQueue.logger.error("Caught exception in Consumer#receive: #{$!}\n" + e.backtrace.join("\n\t"))
11
11
  end
12
12
 
13
+ # def publish(message)
14
+ # begin
15
+ # connection.send_message(publish_destination, message, options)
16
+ # rescue Exception=>e
17
+ # RosettaQueue.logger.error("Caught exception in Producer#publish: #{$!}\n" + e.backtrace.join("\n\t"))
18
+ # end
19
+ # end
20
+
13
21
  end
14
- end
22
+ end
@@ -1,6 +1,6 @@
1
1
  module RosettaQueue
2
2
  # Adds helpful methods when doing application level testing.
3
- # If you are using cucumber just include it in your World in the env.rb file:
3
+ # If you are using cucumber just include it in your Wolrd in the env.rb file:
4
4
  # World {|world| world.extend RosettaQueue::SpecHelpers }
5
5
  module SpecHelpers
6
6
  require 'open-uri'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cwyckoff-rosetta_queue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Mabey
@@ -31,7 +31,9 @@ files:
31
31
  - lib/rosetta_queue
32
32
  - lib/rosetta_queue/adapter.rb
33
33
  - lib/rosetta_queue/adapters
34
- - lib/rosetta_queue/adapters/amqp_bunny.rb
34
+ - lib/rosetta_queue/adapters/amqp_base.rb
35
+ - lib/rosetta_queue/adapters/amqp.rb
36
+ - lib/rosetta_queue/adapters/amqp_carrot.rb
35
37
  - lib/rosetta_queue/adapters/base.rb
36
38
  - lib/rosetta_queue/adapters/fake.rb
37
39
  - lib/rosetta_queue/adapters/null.rb
@@ -1,138 +0,0 @@
1
- require 'bunny'
2
-
3
- module RosettaQueue
4
- module Gateway
5
-
6
- # This AMQP adapter utilizes a forked version of the synchronous AMPQ client 'Bunny'
7
- # by bunny (http://github.com/celldee/bunny)
8
- class AmqpBunnyAdapter < BaseAdapter
9
-
10
- def initialize(adapter_settings = {})
11
- raise AdapterException, "Missing adapter settings" if adapter_settings.empty?
12
- @adapter_settings = adapter_settings
13
- end
14
-
15
- def delete(destination, opts={})
16
- exchange_strategy_for(destination, opts).delete(destination)
17
- end
18
-
19
- def disconnect(message_handler); end
20
-
21
- def receive_once(destination, opts={})
22
- exchange_strategy_for(destination, opts).receive_once(destination) do |msg|
23
- return msg
24
- end
25
- end
26
-
27
- def receive_with(message_handler)
28
- options = options_for(message_handler)
29
- destination = destination_for(message_handler)
30
- exchange_strategy_for(destination, options).receive(destination, message_handler)
31
- end
32
-
33
- def send_message(destination, message, options=nil)
34
- exchange_strategy_for(destination, options).publish(destination, message)
35
- end
36
-
37
- def unsubscribe; end
38
-
39
- private
40
-
41
- def exchange_strategy_for(destination, options)
42
- case destination
43
- when /^fanout\./
44
- @exchange ||= AmqpExchangeStrategies::FanoutExchange.new(@adapter_settings, options)
45
- when /^topic\./
46
- raise "Sorry. RosettaQueue can not process AMQP topics yet"
47
- when /^queue\./
48
- @exchange ||= AmqpExchangeStrategies::DirectExchange.new(@adapter_settings, options)
49
- else
50
- @exchange ||= AmqpExchangeStrategies::DirectExchange.new(@adapter_settings, options)
51
- end
52
- end
53
-
54
- end
55
-
56
- module AmqpExchangeStrategies
57
-
58
- class BaseExchange
59
-
60
- def initialize(adapter_settings, options={})
61
- @adapter_settings, @options = adapter_settings, options
62
- end
63
-
64
- def delete(destination)
65
- conn.queue(destination).delete(@options)
66
- end
67
-
68
- protected
69
-
70
- def conn
71
- vhost = @adapter_settings[:opts][:vhost] || "/"
72
- @conn ||= Bunny.new( :user => @adapter_settings[:user],
73
- :pass => @adapter_settings[:password],
74
- :host => @adapter_settings[:host],
75
- :vhost => vhost)
76
- @conn.start unless @conn.status == :connected
77
- @conn
78
- end
79
- end
80
-
81
- class DirectExchange < BaseExchange
82
-
83
- def publish(destination, message, options={})
84
- RosettaQueue.logger.info("Publishing to #{destination} :: #{message}")
85
- conn.queue(destination, options).publish(message, options)
86
- end
87
-
88
- def receive(destination, message_handler)
89
- conn.queue(destination, @options).subscribe(@options) do |msg|
90
- RosettaQueue.logger.info("Receiving from #{destination} :: #{msg}")
91
- message_handler.on_message(Filters.process_receiving(msg))
92
- end
93
- end
94
-
95
- def receive_once(destination, options={})
96
- msg = conn.queue(destination, options).pop(options)
97
- RosettaQueue.logger.info("Receiving from #{destination} :: #{msg}")
98
- yield Filters.process_receiving(msg)
99
- end
100
- end
101
-
102
- class FanoutExchange < BaseExchange
103
-
104
- def fanout_name_for(destination)
105
- fanout_name = destination.gsub(/fanout\/(.*)/, '\1')
106
- raise "Unable to discover fanout exchange. Cannot bind queue to exchange!" unless fanout_name
107
- fanout_name
108
- end
109
-
110
- def receive_once(destination, options={})
111
- queue = conn.queue("queue_#{self.object_id}", options)
112
- exchange = conn.fanout(fanout_name_for(destination), options)
113
-
114
- msg = queue.bind(exchange).pop(@options)
115
- RosettaQueue.logger.info("Receiving from #{destination} :: #{msg}")
116
- yield Filters.process_receiving(msg)
117
- end
118
-
119
- def publish(destination, message, options={})
120
- exchange = conn.fanout(fanout_name_for(destination), options)
121
- exchange.publish(message, options)
122
- RosettaQueue.logger.info("Publishing to fanout #{destination} :: #{message}")
123
- end
124
-
125
- def receive(destination, message_handler)
126
- queue = conn.queue("queue_#{self.object_id}", @options)
127
- exchange = conn.fanout(fanout_name_for(destination), @options)
128
-
129
- msg = queue.bind(exchange).subscribe(@options) do |msg|
130
-
131
- RosettaQueue.logger.info("Receiving from #{destination} :: #{msg}")
132
- message_handler.on_message(Filters.process_receiving(msg))
133
- end
134
- end
135
- end
136
- end
137
- end
138
- end