rosetta_queue 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +38 -0
- data/MIT-LICENSE.txt +19 -0
- data/README.rdoc +11 -0
- data/Rakefile +39 -0
- data/VERSION.yml +4 -0
- data/cucumber.yml +1 -0
- data/examples/sample_amqp_consumer.rb +45 -0
- data/examples/sample_amqp_fanout_consumer.rb +52 -0
- data/examples/sample_amqp_fanout_producer.rb +18 -0
- data/examples/sample_amqp_producer.rb +16 -0
- data/features/filtering.feature +31 -0
- data/features/messaging.feature +48 -0
- data/features/step_definitions/common_messaging_steps.rb +82 -0
- data/features/step_definitions/filtering_steps.rb +17 -0
- data/features/step_definitions/point_to_point_steps.rb +22 -0
- data/features/step_definitions/publish_subscribe_steps.rb +25 -0
- data/features/support/env.rb +25 -0
- data/features/support/sample_consumers.rb +29 -0
- data/lib/rosetta_queue.rb +23 -0
- data/lib/rosetta_queue/adapter.rb +39 -0
- data/lib/rosetta_queue/adapters/amqp.rb +48 -0
- data/lib/rosetta_queue/adapters/amqp_evented.rb +132 -0
- data/lib/rosetta_queue/adapters/amqp_synch.rb +123 -0
- data/lib/rosetta_queue/adapters/base.rb +27 -0
- data/lib/rosetta_queue/adapters/beanstalk.rb +56 -0
- data/lib/rosetta_queue/adapters/fake.rb +26 -0
- data/lib/rosetta_queue/adapters/null.rb +57 -0
- data/lib/rosetta_queue/adapters/stomp.rb +88 -0
- data/lib/rosetta_queue/base.rb +15 -0
- data/lib/rosetta_queue/consumer.rb +30 -0
- data/lib/rosetta_queue/consumer_managers/base.rb +24 -0
- data/lib/rosetta_queue/consumer_managers/evented.rb +43 -0
- data/lib/rosetta_queue/consumer_managers/threaded.rb +94 -0
- data/lib/rosetta_queue/core_ext/string.rb +22 -0
- data/lib/rosetta_queue/core_ext/time.rb +20 -0
- data/lib/rosetta_queue/destinations.rb +33 -0
- data/lib/rosetta_queue/exception_handler.rb +105 -0
- data/lib/rosetta_queue/exceptions.rb +10 -0
- data/lib/rosetta_queue/filters.rb +58 -0
- data/lib/rosetta_queue/logger.rb +27 -0
- data/lib/rosetta_queue/message_handler.rb +52 -0
- data/lib/rosetta_queue/producer.rb +21 -0
- data/lib/rosetta_queue/spec_helpers.rb +5 -0
- data/lib/rosetta_queue/spec_helpers/hash.rb +21 -0
- data/lib/rosetta_queue/spec_helpers/helpers.rb +47 -0
- data/lib/rosetta_queue/spec_helpers/publishing_matchers.rb +144 -0
- data/spec/rosetta_queue/adapter_spec.rb +101 -0
- data/spec/rosetta_queue/adapters/amqp_synchronous_spec.rb +277 -0
- data/spec/rosetta_queue/adapters/beanstalk_spec.rb +47 -0
- data/spec/rosetta_queue/adapters/fake_spec.rb +72 -0
- data/spec/rosetta_queue/adapters/null_spec.rb +31 -0
- data/spec/rosetta_queue/adapters/shared_adapter_behavior.rb +38 -0
- data/spec/rosetta_queue/adapters/shared_fanout_behavior.rb +20 -0
- data/spec/rosetta_queue/adapters/stomp_spec.rb +126 -0
- data/spec/rosetta_queue/consumer_managers/evented_spec.rb +56 -0
- data/spec/rosetta_queue/consumer_managers/shared_manager_behavior.rb +26 -0
- data/spec/rosetta_queue/consumer_managers/threaded_spec.rb +51 -0
- data/spec/rosetta_queue/consumer_spec.rb +99 -0
- data/spec/rosetta_queue/core_ext/string_spec.rb +15 -0
- data/spec/rosetta_queue/destinations_spec.rb +34 -0
- data/spec/rosetta_queue/exception_handler_spec.rb +106 -0
- data/spec/rosetta_queue/filters_spec.rb +57 -0
- data/spec/rosetta_queue/message_handler_spec.rb +47 -0
- data/spec/rosetta_queue/producer_spec.rb +77 -0
- data/spec/rosetta_queue/shared_messaging_behavior.rb +21 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +47 -0
- metadata +142 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
Given /^a consumer is listening to queue '(.*)'$/ do |queue|
|
2
|
+
klass = eval_consumer_class(queue)
|
3
|
+
@thread = Thread.new do
|
4
|
+
cons = klass.new
|
5
|
+
case @adapter_type
|
6
|
+
when /evented/
|
7
|
+
EM.run do
|
8
|
+
RosettaQueue::Consumer.new(cons).receive
|
9
|
+
end
|
10
|
+
else
|
11
|
+
RosettaQueue::Consumer.new(cons).receive
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
Then /^the message should be consumed from '(.*)'$/ do |queue|
|
17
|
+
sleep 1
|
18
|
+
file_path = "#{CONSUMER_LOG_DIR}/point-to-point.log"
|
19
|
+
# sleep 1 unless File.exists?(file_path)
|
20
|
+
File.readlines(file_path).last.should =~ /Hello World! from #{queue.capitalize}Consumer/
|
21
|
+
@thread.kill
|
22
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
Given /^multiple consumers are listening to queue '(.*)'$/ do |queue|
|
2
|
+
@managers = []
|
3
|
+
Thread.new do
|
4
|
+
@managers << RosettaQueue::ThreadedManager.create do |m|
|
5
|
+
m.add(eval_consumer_class(queue, "fooconsumer.log", "FooConsumer").new)
|
6
|
+
m.start
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
Thread.new do
|
11
|
+
@managers << RosettaQueue::ThreadedManager.create do |m|
|
12
|
+
m.add(eval_consumer_class(queue, "barconsumer.log", "BarConsumer").new)
|
13
|
+
m.start
|
14
|
+
end
|
15
|
+
end
|
16
|
+
sleep 5
|
17
|
+
end
|
18
|
+
|
19
|
+
Then /^multiple messages should be consumed from '(\w+)'$/ do |queue|
|
20
|
+
["FooConsumer", "BarConsumer"].each do |class_name, value|
|
21
|
+
file_path = "#{CONSUMER_LOG_DIR}/#{class_name.downcase}.log"
|
22
|
+
File.readlines(file_path).last.should =~ /Hello World! from #{class_name}/
|
23
|
+
end
|
24
|
+
@managers.each {|m| m.stop_threads }
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
$:.unshift(File.dirname(__FILE__) + '/../../lib')
|
3
|
+
require 'rosetta_queue'
|
4
|
+
require 'rosetta_queue/spec_helpers'
|
5
|
+
require 'spec/expectations'
|
6
|
+
require 'rosetta_queue/spec_helpers'
|
7
|
+
|
8
|
+
CONSUMER_LOG_DIR = File.expand_path(File.dirname(__FILE__) + "/../support/tmp")
|
9
|
+
|
10
|
+
begin
|
11
|
+
RosettaQueue.logger = RosettaQueue::Logger.new(File.join(File.dirname(__FILE__), '../../../log', 'rosetta_queue.log'))
|
12
|
+
rescue Errno::ENOENT
|
13
|
+
Kernel.warn "No log directory setup at the root of rosetta_queue. Using the null logger instead."
|
14
|
+
class NullLogger
|
15
|
+
def info(*args); end
|
16
|
+
def debug(*args); end
|
17
|
+
def fatal(*args); end
|
18
|
+
def error(*args); end
|
19
|
+
def warn(*args); end
|
20
|
+
end
|
21
|
+
|
22
|
+
RosettaQueue.logger = NullLogger.new
|
23
|
+
end
|
24
|
+
|
25
|
+
World(RosettaQueue::SpecHelpers)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/env.rb')
|
2
|
+
|
3
|
+
class SampleConsumer
|
4
|
+
include ::RosettaQueue::MessageHandler
|
5
|
+
subscribes_to :foo
|
6
|
+
options :durable => true
|
7
|
+
|
8
|
+
attr_reader :msg
|
9
|
+
|
10
|
+
def on_message(msg)
|
11
|
+
@msg = msg
|
12
|
+
puts "MESSAGE #{msg}"
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
class SampleConsumerTwo
|
19
|
+
include ::RosettaQueue::MessageHandler
|
20
|
+
subscribes_to :foo
|
21
|
+
options :durable => true
|
22
|
+
|
23
|
+
attr_reader :msg
|
24
|
+
|
25
|
+
def on_message(msg)
|
26
|
+
@msg = msg
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__)))
|
2
|
+
|
3
|
+
require('rosetta_queue/core_ext/string') unless defined? ActiveSupport
|
4
|
+
require('rosetta_queue/core_ext/time') unless defined? ActiveSupport
|
5
|
+
|
6
|
+
require 'rosetta_queue/adapter'
|
7
|
+
require 'rosetta_queue/base'
|
8
|
+
require 'rosetta_queue/consumer'
|
9
|
+
require 'rosetta_queue/destinations'
|
10
|
+
require 'rosetta_queue/exceptions'
|
11
|
+
require 'rosetta_queue/filters'
|
12
|
+
require 'rosetta_queue/logger'
|
13
|
+
require 'rosetta_queue/message_handler'
|
14
|
+
require 'rosetta_queue/exception_handler'
|
15
|
+
require 'rosetta_queue/producer'
|
16
|
+
require 'rosetta_queue/consumer_managers/base'
|
17
|
+
require 'rosetta_queue/consumer_managers/threaded'
|
18
|
+
|
19
|
+
if defined?(Rails)
|
20
|
+
RosettaQueue.logger = RosettaQueue::Logger.new(File.join(Rails.root, 'log', 'rosetta_queue.log'))
|
21
|
+
require('rosetta_queue/spec_helpers') if Rails.env == "test"
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'rosetta_queue/adapters/base'
|
2
|
+
|
3
|
+
module RosettaQueue
|
4
|
+
class Adapter
|
5
|
+
|
6
|
+
class << self
|
7
|
+
attr_writer :user, :password, :host, :port, :options
|
8
|
+
|
9
|
+
def define
|
10
|
+
yield self
|
11
|
+
end
|
12
|
+
|
13
|
+
def reset
|
14
|
+
@user, @password, @host, @port, @options, @adapter_class = nil, nil, nil, nil, nil, nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def type=(adapter_prefix)
|
18
|
+
require "rosetta_queue/adapters/#{adapter_prefix}"
|
19
|
+
@adapter_class = RosettaQueue::Gateway.const_get("#{adapter_prefix.to_s.classify}Adapter")
|
20
|
+
|
21
|
+
rescue LoadError
|
22
|
+
raise AdapterException, "Adapter type '#{adapter_prefix}' does not match existing adapters!"
|
23
|
+
end
|
24
|
+
|
25
|
+
def instance
|
26
|
+
raise AdapterException, "Adapter type was never defined!" unless @adapter_class
|
27
|
+
@adapter_class.new({:user => @user, :password => @password, :host => @host, :port => @port, :opts => opts})
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def opts
|
33
|
+
raise AdapterException, "Adapter options should be a hash" unless @options.nil? || @options.is_a?(Hash)
|
34
|
+
@options ||= {}
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module RosettaQueue
|
2
|
+
module Gateway
|
3
|
+
|
4
|
+
module Fanout
|
5
|
+
def fanout_name_for(destination)
|
6
|
+
fanout_name = destination.gsub(/(topic|fanout)\/(.*)/, '\2')
|
7
|
+
raise AdapterException, "Unable to discover fanout exchange. Cannot bind queue to exchange!" unless fanout_name
|
8
|
+
fanout_name
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Amqp < BaseAdapter
|
13
|
+
|
14
|
+
def initialize(adapter_settings = {})
|
15
|
+
raise AdapterException, "Missing adapter settings" if adapter_settings.empty?
|
16
|
+
@adapter_settings = adapter_settings
|
17
|
+
end
|
18
|
+
|
19
|
+
def delete(destination, opts={})
|
20
|
+
exchange_strategy_for(destination, opts).delete(destination)
|
21
|
+
end
|
22
|
+
|
23
|
+
def disconnect(message_handler)
|
24
|
+
destination = destination_for(message_handler)
|
25
|
+
exchange_strategy_for(destination).unsubscribe
|
26
|
+
end
|
27
|
+
|
28
|
+
def receive_once(destination, opts={})
|
29
|
+
exchange_strategy_for(destination, opts).receive_once(destination) do |msg|
|
30
|
+
return msg
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def receive_with(message_handler)
|
35
|
+
options = options_for(message_handler)
|
36
|
+
destination = destination_for(message_handler)
|
37
|
+
exchange_strategy_for(destination, options).receive(destination, message_handler)
|
38
|
+
end
|
39
|
+
|
40
|
+
def send_message(destination, message, options=nil)
|
41
|
+
exchange_strategy_for(destination, options).publish(destination, message)
|
42
|
+
end
|
43
|
+
|
44
|
+
def unsubscribe; end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
require 'mq'
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + "/amqp.rb")
|
4
|
+
|
5
|
+
module RosettaQueue
|
6
|
+
module Gateway
|
7
|
+
|
8
|
+
class AmqpEventedAdapter < Amqp
|
9
|
+
private
|
10
|
+
|
11
|
+
def exchange_strategy_for(destination, options)
|
12
|
+
case destination
|
13
|
+
when /^fanout\./
|
14
|
+
@exchange ||= EventedExchange::FanoutExchange.new(@adapter_settings, options)
|
15
|
+
when /^topic\./
|
16
|
+
raise "Sorry. RosettaQueue can not process AMQP topics yet"
|
17
|
+
when /^queue\./
|
18
|
+
@exchange ||= EventedExchange::DirectExchange.new(@adapter_settings, options)
|
19
|
+
else
|
20
|
+
@exchange ||= EventedExchange::DirectExchange.new(@adapter_settings, options)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
module EventedExchange
|
26
|
+
|
27
|
+
class BaseExchange
|
28
|
+
|
29
|
+
def initialize(adapter_settings, options={})
|
30
|
+
@adapter_settings, @options = adapter_settings, options
|
31
|
+
end
|
32
|
+
|
33
|
+
def delete(destination)
|
34
|
+
conn.queue(destination).delete(@options)
|
35
|
+
end
|
36
|
+
|
37
|
+
protected
|
38
|
+
|
39
|
+
def channel
|
40
|
+
@channel ||= MQ.new(conn)
|
41
|
+
end
|
42
|
+
|
43
|
+
def conn
|
44
|
+
vhost = @adapter_settings[:opts][:vhost] || "/"
|
45
|
+
@conn ||= AMQP.connect(:user => @adapter_settings[:user],
|
46
|
+
:pass => @adapter_settings[:password],
|
47
|
+
:host => @adapter_settings[:host],
|
48
|
+
:vhost => vhost)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
class DirectExchange < BaseExchange
|
54
|
+
|
55
|
+
def publish(destination, message, options={})
|
56
|
+
raise AdapterException, "Messages need to be published in an EventMachine run block (e.g., EM.run { RosettaQueue::Producer.publish(:foo, msg) } " unless EM.reactor_running?
|
57
|
+
|
58
|
+
queue = channel.queue(destination, options)
|
59
|
+
queue.publish(message, options)
|
60
|
+
RosettaQueue.logger.info("Publishing to #{destination} :: #{message}")
|
61
|
+
queue.unsubscribe
|
62
|
+
end
|
63
|
+
|
64
|
+
def receive(destination, message_handler)
|
65
|
+
raise AdapterException, "Consumers need to run in an EventMachine 'run' block. Try wrapping them inside the evented consumer manager." unless EM.reactor_running?
|
66
|
+
|
67
|
+
queue = channel.queue(destination, @options)
|
68
|
+
ack = @options[:ack]
|
69
|
+
queue.subscribe(@options) do |header, msg|
|
70
|
+
RosettaQueue.logger.info("Receiving from #{destination} :: #{msg}")
|
71
|
+
message_handler.handle_message(msg)
|
72
|
+
header.ack if ack
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def receive_once(destination, options={})
|
77
|
+
raise AdapterException, "Consumers need to run in an EventMachine 'run' block. (e.g., EM.run { RosettaQueue::Consumer.receive }" unless EM.reactor_running?
|
78
|
+
|
79
|
+
queue = channel.queue(destination, @options)
|
80
|
+
ack = @options[:ack]
|
81
|
+
queue.pop(@options) do |header, msg|
|
82
|
+
RosettaQueue.logger.info("Receiving from #{destination} :: #{msg}")
|
83
|
+
header.ack if ack
|
84
|
+
yield Filters.process_receiving(msg)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
class FanoutExchange < BaseExchange
|
91
|
+
include Fanout
|
92
|
+
|
93
|
+
def publish(dest, msg, opts)
|
94
|
+
raise AdapterException, "Messages need to be published in an EventMachine run block (e.g., EM.run { RosettaQueue::Producer.publish(:foo, msg) } " unless EM.reactor_running?
|
95
|
+
|
96
|
+
exchange = channel.fanout(fanout_name_for(dest), opts)
|
97
|
+
exchange.publish(msg, opts)
|
98
|
+
RosettaQueue.logger.info("Publishing to fanout #{dest} :: #{msg}")
|
99
|
+
end
|
100
|
+
|
101
|
+
def receive(destination, message_handler)
|
102
|
+
raise AdapterException, "Consumers need to run in an EventMachine 'run' block. Try wrapping them inside the evented consumer manager." unless EM.reactor_running?
|
103
|
+
|
104
|
+
queue = channel.queue("queue_#{self.object_id}")
|
105
|
+
exchange = channel.fanout(fanout_name_for(destination), @options)
|
106
|
+
ack = @options[:ack]
|
107
|
+
|
108
|
+
queue.bind(exchange).subscribe(@options) do |header, msg|
|
109
|
+
RosettaQueue.logger.info("Receiving from #{destination} :: #{msg}")
|
110
|
+
message_handler.handle_message(msg)
|
111
|
+
header.ack if ack
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def receive_once(destination, opts={})
|
116
|
+
raise AdapterException, "Consumers need to run in an EventMachine 'run' block. (e.g., EM.run { RosettaQueue::Consumer.receive }" unless EM.reactor_running?
|
117
|
+
|
118
|
+
queue = channel.queue("queue_#{self.object_id}")
|
119
|
+
exchange = channel.fanout(fanout_name_for(destination), opts)
|
120
|
+
ack = @options[:ack]
|
121
|
+
|
122
|
+
queue.bind(exchange).pop(opts) do |header, msg|
|
123
|
+
RosettaQueue.logger.info("Receiving from #{destination} :: #{msg}")
|
124
|
+
header.ack if ack
|
125
|
+
yield Filters.process_receiving(msg)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'bunny'
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + "/amqp.rb")
|
3
|
+
|
4
|
+
module RosettaQueue
|
5
|
+
module Gateway
|
6
|
+
|
7
|
+
# This AMQP adapter utilizes the synchronous AMPQ client 'Bunny'
|
8
|
+
# by celldee (http://github.com/celldee/bunny)
|
9
|
+
class AmqpSynchAdapter < Amqp
|
10
|
+
private
|
11
|
+
|
12
|
+
def exchange_strategy_for(destination, options={})
|
13
|
+
case destination
|
14
|
+
when /^fanout\./
|
15
|
+
@exchange ||= SynchExchange::FanoutExchange.new(@adapter_settings, options)
|
16
|
+
when /^topic\./
|
17
|
+
raise "Sorry. RosettaQueue can not process AMQP topics yet"
|
18
|
+
when /^queue\./
|
19
|
+
@exchange ||= SynchExchange::DirectExchange.new(@adapter_settings, options)
|
20
|
+
else
|
21
|
+
@exchange ||= SynchExchange::DirectExchange.new(@adapter_settings, options)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module SynchExchange
|
27
|
+
|
28
|
+
class BaseExchange
|
29
|
+
|
30
|
+
def initialize(adapter_settings, options={})
|
31
|
+
@adapter_settings, @options = adapter_settings, options
|
32
|
+
end
|
33
|
+
|
34
|
+
def delete(destination, options={})
|
35
|
+
conn.queue(destination).delete(options)
|
36
|
+
end
|
37
|
+
|
38
|
+
def unsubscribe
|
39
|
+
@queue.unsubscribe
|
40
|
+
conn.stop
|
41
|
+
end
|
42
|
+
|
43
|
+
protected
|
44
|
+
|
45
|
+
def conn
|
46
|
+
vhost = @adapter_settings[:opts][:vhost] || "/"
|
47
|
+
@conn ||= Bunny.new( :user => @adapter_settings[:user],
|
48
|
+
:pass => @adapter_settings[:password],
|
49
|
+
:host => @adapter_settings[:host],
|
50
|
+
:vhost => vhost)
|
51
|
+
@conn.start unless @conn.status == :connected
|
52
|
+
@conn
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
class DirectExchange < BaseExchange
|
58
|
+
|
59
|
+
def publish(destination, message, options={})
|
60
|
+
RosettaQueue.logger.info("Publishing to #{destination} :: #{message}")
|
61
|
+
queue = conn.queue(destination, options)
|
62
|
+
queue.publish(message, options)
|
63
|
+
conn.stop
|
64
|
+
end
|
65
|
+
|
66
|
+
def receive(destination, message_handler)
|
67
|
+
ack = @options[:ack]
|
68
|
+
@queue = conn.queue(destination, @options)
|
69
|
+
@queue.subscribe(@options) do |msg|
|
70
|
+
RosettaQueue.logger.info("Receiving from #{destination} :: #{msg}")
|
71
|
+
message_handler.handle_message(msg)
|
72
|
+
@queue.ack if ack
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def receive_once(destination, options = {})
|
77
|
+
ack = options[:ack]
|
78
|
+
@queue = conn.queue(destination, options)
|
79
|
+
msg = @queue.pop(options)
|
80
|
+
RosettaQueue.logger.info("Receiving from #{destination} :: #{msg}")
|
81
|
+
@queue.ack if ack
|
82
|
+
yield Filters.process_receiving(msg)
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
class FanoutExchange < BaseExchange
|
88
|
+
include Fanout
|
89
|
+
|
90
|
+
def publish(destination, message, options={})
|
91
|
+
exchange = conn.exchange(fanout_name_for(destination), options.merge({:type => :fanout}))
|
92
|
+
exchange.publish(message, options)
|
93
|
+
RosettaQueue.logger.info("Publishing to fanout #{destination} :: #{message}")
|
94
|
+
end
|
95
|
+
|
96
|
+
def receive(destination, message_handler)
|
97
|
+
ack = @options[:ack]
|
98
|
+
@queue = conn.queue("queue_#{self.object_id}", @options)
|
99
|
+
exchange = conn.exchange(fanout_name_for(destination), @options.merge({:type => :fanout}))
|
100
|
+
@queue.bind(exchange)
|
101
|
+
@queue.subscribe(@options) do |msg|
|
102
|
+
RosettaQueue.logger.info("Receiving from #{destination} :: #{msg}")
|
103
|
+
message_handler.handle_message(msg)
|
104
|
+
@queue.ack if ack
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def receive_once(destination, options={})
|
109
|
+
ack = options[:ack]
|
110
|
+
@queue = conn.queue("queue_#{self.object_id}", options)
|
111
|
+
exchange = conn.exchange(fanout_name_for(destination), options.merge({:type => :fanout}))
|
112
|
+
@queue.bind(exchange)
|
113
|
+
msg = @queue.pop(options)
|
114
|
+
RosettaQueue.logger.info("Receiving from #{destination} :: #{msg}")
|
115
|
+
@queue.ack if ack
|
116
|
+
yield Filters.process_receiving(msg)
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|