bmabey-rosetta_queue 0.2.0 → 0.3.3

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.
Files changed (59) hide show
  1. data/History.txt +6 -3
  2. data/README.rdoc +1 -193
  3. data/Rakefile +7 -1
  4. data/cucumber.yml +1 -1
  5. data/examples/sample_amqp_consumer.rb +13 -3
  6. data/examples/sample_amqp_fanout_consumer.rb +6 -3
  7. data/examples/sample_amqp_fanout_producer.rb +3 -2
  8. data/examples/sample_amqp_producer.rb +2 -1
  9. data/features/filtering.feature +13 -13
  10. data/features/messaging.feature +28 -20
  11. data/features/step_definitions/common_messaging_steps.rb +54 -17
  12. data/features/step_definitions/filtering_steps.rb +2 -2
  13. data/features/step_definitions/point_to_point_steps.rb +19 -9
  14. data/features/step_definitions/publish_subscribe_steps.rb +22 -8
  15. data/features/support/env.rb +2 -0
  16. data/features/support/sample_consumers.rb +6 -6
  17. data/lib/rosetta_queue.rb +1 -0
  18. data/lib/rosetta_queue/adapter.rb +6 -6
  19. data/lib/rosetta_queue/adapters/amqp.rb +6 -3
  20. data/lib/rosetta_queue/adapters/amqp_evented.rb +22 -22
  21. data/lib/rosetta_queue/adapters/amqp_synch.rb +42 -36
  22. data/lib/rosetta_queue/adapters/base.rb +3 -3
  23. data/lib/rosetta_queue/adapters/beanstalk.rb +5 -5
  24. data/lib/rosetta_queue/adapters/fake.rb +5 -5
  25. data/lib/rosetta_queue/adapters/null.rb +9 -9
  26. data/lib/rosetta_queue/adapters/stomp.rb +25 -12
  27. data/lib/rosetta_queue/base.rb +2 -2
  28. data/lib/rosetta_queue/consumer.rb +4 -4
  29. data/lib/rosetta_queue/consumer_managers/base.rb +8 -6
  30. data/lib/rosetta_queue/consumer_managers/evented.rb +5 -5
  31. data/lib/rosetta_queue/consumer_managers/threaded.rb +4 -4
  32. data/lib/rosetta_queue/core_ext/string.rb +3 -3
  33. data/lib/rosetta_queue/core_ext/time.rb +20 -0
  34. data/lib/rosetta_queue/destinations.rb +6 -6
  35. data/lib/rosetta_queue/filters.rb +8 -8
  36. data/lib/rosetta_queue/logger.rb +2 -2
  37. data/lib/rosetta_queue/message_handler.rb +10 -4
  38. data/lib/rosetta_queue/producer.rb +2 -2
  39. data/lib/rosetta_queue/spec_helpers/hash.rb +3 -3
  40. data/lib/rosetta_queue/spec_helpers/helpers.rb +8 -8
  41. data/lib/rosetta_queue/spec_helpers/publishing_matchers.rb +26 -26
  42. data/spec/rosetta_queue/adapter_spec.rb +27 -27
  43. data/spec/rosetta_queue/adapters/amqp_synchronous_spec.rb +21 -1
  44. data/spec/rosetta_queue/adapters/beanstalk_spec.rb +3 -3
  45. data/spec/rosetta_queue/adapters/fake_spec.rb +6 -6
  46. data/spec/rosetta_queue/adapters/null_spec.rb +5 -5
  47. data/spec/rosetta_queue/adapters/shared_adapter_behavior.rb +4 -4
  48. data/spec/rosetta_queue/adapters/shared_fanout_behavior.rb +1 -1
  49. data/spec/rosetta_queue/adapters/stomp_spec.rb +39 -18
  50. data/spec/rosetta_queue/consumer_managers/evented_spec.rb +6 -6
  51. data/spec/rosetta_queue/consumer_managers/shared_manager_behavior.rb +3 -3
  52. data/spec/rosetta_queue/consumer_managers/threaded_spec.rb +5 -5
  53. data/spec/rosetta_queue/consumer_spec.rb +13 -13
  54. data/spec/rosetta_queue/core_ext/string_spec.rb +3 -3
  55. data/spec/rosetta_queue/destinations_spec.rb +8 -8
  56. data/spec/rosetta_queue/filters_spec.rb +16 -16
  57. data/spec/rosetta_queue/producer_spec.rb +15 -15
  58. data/spec/rosetta_queue/shared_messaging_behavior.rb +6 -6
  59. metadata +3 -2
@@ -7,36 +7,36 @@
7
7
 
8
8
  module RosettaQueue
9
9
  class Filters
10
-
10
+
11
11
  class << self
12
-
12
+
13
13
  def define
14
14
  yield self
15
15
  end
16
-
16
+
17
17
  def reset
18
18
  @receiving = nil
19
19
  @sending = nil
20
20
  end
21
-
21
+
22
22
  def receiving(&receiving_filter)
23
23
  @receiving = receiving_filter
24
24
  end
25
-
25
+
26
26
  def sending(&sending_filter)
27
27
  @sending = sending_filter
28
28
  end
29
-
29
+
30
30
  def process_sending(message)
31
31
  return message unless @sending
32
32
  @sending.call(message)
33
33
  end
34
-
34
+
35
35
  def process_receiving(message)
36
36
  return message unless @receiving
37
37
  @receiving.call(message)
38
38
  end
39
-
39
+
40
40
  end
41
41
  end
42
42
  end
@@ -6,7 +6,7 @@ module RosettaQueue
6
6
  def self.logger=(new_logger)
7
7
  @logger = new_logger
8
8
  end
9
-
9
+
10
10
  def self.logger
11
11
  return @logger if @logger
12
12
  raise MissingLogger, "No logger has been set for RosettaQueue. Please define one with RosettaQueue.logger=."
@@ -19,7 +19,7 @@ module RosettaQueue
19
19
  class Logger < ::Logger
20
20
 
21
21
  def format_message(severity, timestamp, progname, msg)
22
- "[#{timestamp.to_formatted_s(:db)}] #{severity} #{msg}\n"
22
+ "[#{timestamp.to_formatted_s(:db)}] #{severity} -- : #{msg}\n"
23
23
  end
24
24
 
25
25
  end
@@ -1,6 +1,6 @@
1
1
  module RosettaQueue
2
2
  module MessageHandler
3
-
3
+
4
4
  module ClassMethods
5
5
 
6
6
  attr_reader :destination, :options_hash
@@ -17,17 +17,23 @@ module RosettaQueue
17
17
  @destination = destination
18
18
  end
19
19
  end
20
-
20
+
21
21
  def self.included(receiver)
22
22
  receiver.extend(ClassMethods)
23
+ attr_accessor :adapter_proxy
23
24
 
24
25
  def destination
25
- self.class.destination
26
+ self.class.destination
26
27
  end
27
-
28
+
28
29
  def options_hash
29
30
  self.class.options_hash
30
31
  end
32
+
33
+ def ack
34
+ adapter_proxy.ack unless adapter_proxy.nil?
35
+ end
36
+
31
37
  end
32
38
  end
33
39
  end
@@ -1,12 +1,12 @@
1
1
  module RosettaQueue
2
-
2
+
3
3
  class Producer < Base
4
4
  include MessageHandler
5
5
 
6
6
  def self.publish(destination, message, options = {})
7
7
  RosettaQueue::Adapter.instance.send_message(Destinations.lookup(destination), Filters.process_sending(message), options)
8
8
 
9
- rescue Exception=>e
9
+ rescue Exception => e
10
10
  RosettaQueue.logger.error("Caught exception in Consumer.publish: #{$!}\n" + e.backtrace.join("\n\t"))
11
11
  end
12
12
 
@@ -1,7 +1,7 @@
1
1
  class Hash
2
2
  # To be used in conjuction with rspec's predicate matcher.
3
3
  #
4
- # For example, in story/feature or a functional spec you could say:
4
+ # For example, in story/feature or a functional spec you could say:
5
5
  #
6
6
  # expected_message = {'name' => 'Advertiser'}
7
7
  # expected_message.should be_published_to(:advertiser_create)
@@ -13,9 +13,9 @@ class Hash
13
13
  rescue Timeout::Error
14
14
  raise "#{destination} should have received a message but did not NOTE: make sure there are no other processes which are polling messages"
15
15
  end
16
-
16
+
17
17
  # calling should == is kinda wierd, I know.. but in order to get a decent error message it is needed
18
18
  received_message.should == self
19
19
  end
20
-
20
+
21
21
  end
@@ -4,18 +4,18 @@ module RosettaQueue
4
4
  # World {|world| world.extend RosettaQueue::SpecHelpers }
5
5
  module SpecHelpers
6
6
  require 'open-uri'
7
-
8
- # *Currently* only works with ActiveMQ being used as gateway.
7
+
8
+ # *Currently* only works with ActiveMQ being used as gateway.
9
9
  # This will clear the queues defined in the RosettaQueue::Destinations mapping.
10
10
  # TODO: Figure out a better spot for this to allow for other gateways...
11
11
  def clear_queues
12
- RosettaQueue::Destinations.queue_names.each do |name|
12
+ RosettaQueue::Destinations.queue_names.each do |name|
13
13
  queue = name.gsub('/queue/','')
14
14
  open("http://127.0.0.1:8161/admin/deleteDestination.action?JMSDestination=#{queue}&JMSDestinationType=queue")
15
15
  end
16
16
  end
17
-
18
- # Publishes a given hash as json to the specified destination.
17
+
18
+ # Publishes a given hash as json to the specified destination.
19
19
  # Example:
20
20
  # publish_message(expected_message, :to => :client_status, :options => {...})
21
21
  # The :options will be passed to the publisher and are optional.
@@ -23,14 +23,14 @@ module RosettaQueue
23
23
  options[:options] ||= {:persistent => false}
24
24
  RosettaQueue::Producer.publish(options[:to], message, options[:options])
25
25
  end
26
-
26
+
27
27
  # Consumes the first message on queue of consumer that is passed in and uses the consumer to handle it.
28
28
  # Example:
29
29
  # consume_once_with ClientStatusConsumer
30
30
  def consume_once_with(consumer)
31
31
  consumer.new.on_message(RosettaQueue::Consumer.receive(consumer.destination))
32
32
  end
33
-
33
+
34
34
  # Consumes the first message on queue and returns it.
35
35
  # Example:
36
36
  # message = consume_once :foo_queue
@@ -42,6 +42,6 @@ module RosettaQueue
42
42
  sleep 1
43
43
  Messaging::Consumer.receive(destination, :persistent => false).to_hash_from_json
44
44
  end
45
-
45
+
46
46
  end
47
47
  end
@@ -1,6 +1,6 @@
1
1
  module RosettaQueue
2
2
  module Matchers
3
-
3
+
4
4
  class PublishAMessageTo
5
5
 
6
6
  def initialize(expected_queue_name, options=nil)
@@ -10,14 +10,14 @@ module RosettaQueue
10
10
  @expected_queue = expected_queue_name.is_a?(Symbol) ? RosettaQueue::Destinations.lookup(expected_queue_name) : expected_queue_name
11
11
  end
12
12
 
13
- def matches?(lambda_to_run)
13
+ def matches?(lambda_to_run)
14
14
  #given
15
15
  RosettaQueue::Adapter.stub!(:instance).and_return(fake_adapter = RosettaQueue::Gateway::FakeAdapter.new)
16
16
  #when
17
17
  lambda_to_run.call
18
18
  #then
19
- @actual_queues = fake_adapter.queues
20
- @number_of_messages_published = @actual_queues.select{ |q| q == @expected_queue}.size
19
+ @actual_queues = fake_adapter.queues
20
+ @number_of_messages_published = @actual_queues.select{ |q| q == @expected_queue}.size
21
21
  @number_of_messages_published == @how_many_messages_expected
22
22
  end
23
23
 
@@ -32,7 +32,7 @@ module RosettaQueue
32
32
  def description
33
33
  "publish #{message_plural} to the '#{@expected_queue_name}' queue"
34
34
  end
35
-
35
+
36
36
  private
37
37
  def message_plural
38
38
  @how_many_messages_expected == 1 ? "a message" : "#{@how_many_messages_expected} messages"
@@ -42,16 +42,16 @@ module RosettaQueue
42
42
  def publish_a_message_to(expected_queue)
43
43
  PublishAMessageTo.new(expected_queue)
44
44
  end
45
-
45
+
46
46
  alias :publish_message_to :publish_a_message_to
47
-
47
+
48
48
  def publish_messages_to(expected_queue, options)
49
49
  PublishAMessageTo.new(expected_queue, options)
50
50
  end
51
-
51
+
52
52
  class PublishMessageMatcher
53
-
54
-
53
+
54
+
55
55
  def matches?(lambda_to_run)
56
56
  #given
57
57
  RosettaQueue::Adapter.stub!(:instance).and_return(fake_adapter = RosettaQueue::Gateway::FakeAdapter.new)
@@ -61,30 +61,30 @@ module RosettaQueue
61
61
  message = fake_adapter.messages_sent_to(@expected_queue).first || ''
62
62
  @actual_message = message
63
63
  end
64
-
64
+
65
65
  protected
66
66
  def extract_options(options)
67
- if (expected_queue_name = options[:to])
67
+ if (expected_queue_name = options[:to])
68
68
  @expected_queue = expected_queue_name.is_a?(Symbol) ? RosettaQueue::Destinations.lookup(expected_queue_name) : expected_queue_name
69
69
  end
70
70
  end
71
71
  end
72
-
72
+
73
73
  class PublishMessageWith < PublishMessageMatcher
74
-
74
+
75
75
  def initialize(message_subset, options)
76
76
  @message_subset = message_subset
77
77
  extract_options(options)
78
78
  end
79
79
 
80
- def matches?(lambda_to_run)
80
+ def matches?(lambda_to_run)
81
81
  super
82
82
  Spec::Mocks::ArgumentConstraints::HashIncludingConstraint.new(@message_subset) == @actual_message
83
83
  end
84
84
 
85
85
  def failure_message
86
86
  if @actual_message.blank?
87
- "expected #{@message_subset.inspect} to be contained in a message but no message was published"
87
+ "expected #{@message_subset.inspect} to be contained in a message but no message was published"
88
88
  else
89
89
  "expected #{@message_subset.inspect} to be contained in the message: #{@actual_message.inspect}"
90
90
  end
@@ -97,29 +97,29 @@ module RosettaQueue
97
97
  def description
98
98
  "publish a message with #{@message_subset.inspect}"
99
99
  end
100
-
100
+
101
101
  end
102
-
102
+
103
103
  def publish_message_with(message_subset, options={})
104
104
  PublishMessageWith.new(message_subset, options)
105
105
  end
106
-
107
-
106
+
107
+
108
108
  class PublishMessage < PublishMessageMatcher
109
-
109
+
110
110
  def initialize(expected_message, options)
111
111
  @expected_message = expected_message
112
112
  extract_options(options)
113
113
  end
114
114
 
115
- def matches?(lambda_to_run)
115
+ def matches?(lambda_to_run)
116
116
  super
117
117
  @actual_message == @expected_message
118
118
  end
119
119
 
120
120
  def failure_message
121
121
  if @actual_message.blank?
122
- "expected #{@expected_message.inspect} to be published but no message was"
122
+ "expected #{@expected_message.inspect} to be published but no message was"
123
123
  else
124
124
  "expected #{@expected_message.inspect} to be published but the following was instead: #{@actual_message.inspect}"
125
125
  end
@@ -132,13 +132,13 @@ module RosettaQueue
132
132
  def description
133
133
  "publish the message: #{@expected_message.inspect}"
134
134
  end
135
-
135
+
136
136
  end
137
-
137
+
138
138
  def publish_message(exact_expected_message, options={})
139
139
  PublishMessage.new(exact_expected_message, options)
140
140
  end
141
-
141
+
142
142
  end
143
143
  end
144
144
 
@@ -1,14 +1,14 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper'
2
2
 
3
3
  module RosettaQueue
4
-
4
+
5
5
  describe Adapter do
6
6
 
7
7
  before(:each) do
8
8
  @stomp_adapter = mock("Gateway::StompAdapter")
9
9
  Adapter.reset
10
10
  end
11
-
11
+
12
12
  describe ".reset" do
13
13
  it "should clear all definitions" do
14
14
  Adapter.define { |a| a.type = "null" }
@@ -17,38 +17,38 @@ module RosettaQueue
17
17
  running { Adapter.instance }.should raise_error(AdapterException)
18
18
  end
19
19
  end
20
-
20
+
21
21
  describe ".type=" do
22
-
22
+
23
23
  it "should raise error when adapter does not exist" do
24
- running {
24
+ running {
25
25
  Adapter.define do |a|
26
26
  a.type = "foo"
27
27
  end
28
28
  }.should raise_error(AdapterException)
29
29
  end
30
-
30
+
31
31
  end
32
-
32
+
33
33
  describe "adapter not type set" do
34
34
  it "should raise an error when .instance is called" do
35
35
  # given
36
36
  Adapter.define { |a| }
37
37
  # then & when
38
- running { Adapter.instance }.should raise_error(AdapterException)
38
+ running { Adapter.instance }.should raise_error(AdapterException)
39
39
  end
40
40
  end
41
41
 
42
42
  describe "adapter type set" do
43
-
43
+
44
44
  before(:each) do
45
45
  Adapter.define { |a| a.type = "null" }
46
46
  end
47
-
47
+
48
48
  it "should return adapter instance" do
49
49
  Adapter.instance.class.should == RosettaQueue::Gateway::NullAdapter
50
50
  end
51
-
51
+
52
52
  end
53
53
 
54
54
  describe "adapter instantiation" do
@@ -61,41 +61,41 @@ module RosettaQueue
61
61
  a.port = "9000"
62
62
  a.type = "fake"
63
63
  end
64
- end
65
-
64
+ end
65
+
66
66
  def do_process
67
67
  Adapter.instance
68
68
  end
69
69
 
70
70
  it "should set opts as an empty has unless variable is set" do
71
- during_process {
71
+ during_process {
72
72
  RosettaQueue::Gateway::FakeAdapter.should_receive(:new).with({:user => "foo", :password => "bar", :host => "localhost", :port => "9000", :opts => {}})
73
73
  }
74
- end
74
+ end
75
75
 
76
76
  describe "when setting options" do
77
77
  before(:each) do
78
78
  Adapter.define { |a| a.options = {:vhost => "baz"} }
79
- end
80
-
79
+ end
80
+
81
81
  it "should map adapter_settings to a hash" do
82
- during_process {
82
+ during_process {
83
83
  RosettaQueue::Gateway::FakeAdapter.should_receive(:new).with({:user => "foo", :password => "bar", :host => "localhost", :port => "9000", :opts => {:vhost => "baz"}})
84
84
  }
85
- end
86
- end
85
+ end
86
+ end
87
87
 
88
88
  describe "setting options incorrectly (options should always be set as a Hash)" do
89
-
89
+
90
90
  before(:each) do
91
91
  Adapter.define { |a| a.options = "baz" }
92
- end
93
-
92
+ end
93
+
94
94
  it "should raise an adapter exception" do
95
95
  running { Adapter.instance }.should raise_error("Adapter options should be a hash")
96
- end
97
- end
98
-
99
- end
96
+ end
97
+ end
98
+
99
+ end
100
100
  end
101
101
  end