bmabey-rosetta_queue 0.2.0 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
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