onstomp 1.0.0pre1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. data/README.md +1 -1
  2. data/Rakefile +8 -0
  3. data/examples/openuri.rb +36 -0
  4. data/lib/onstomp.rb +4 -0
  5. data/lib/onstomp/client.rb +6 -5
  6. data/lib/onstomp/components.rb +0 -1
  7. data/lib/onstomp/components/frame_headers.rb +35 -38
  8. data/lib/onstomp/components/threaded_processor.rb +13 -0
  9. data/lib/onstomp/connections/base.rb +15 -8
  10. data/lib/onstomp/connections/stomp_1.rb +0 -6
  11. data/lib/onstomp/connections/stomp_1_0.rb +8 -0
  12. data/lib/onstomp/connections/stomp_1_1.rb +8 -0
  13. data/lib/onstomp/failover.rb +16 -0
  14. data/lib/onstomp/failover/buffers.rb +8 -0
  15. data/lib/onstomp/failover/buffers/written.rb +91 -0
  16. data/lib/onstomp/failover/client.rb +127 -0
  17. data/lib/onstomp/failover/failover_configurable.rb +63 -0
  18. data/lib/onstomp/failover/failover_events.rb +96 -0
  19. data/lib/onstomp/failover/new_with_failover.rb +20 -0
  20. data/lib/onstomp/failover/pools.rb +8 -0
  21. data/lib/onstomp/failover/pools/base.rb +39 -0
  22. data/lib/onstomp/failover/pools/round_robin.rb +17 -0
  23. data/lib/onstomp/failover/uri.rb +34 -0
  24. data/lib/onstomp/interfaces/client_configurable.rb +2 -6
  25. data/lib/onstomp/interfaces/client_events.rb +4 -0
  26. data/lib/onstomp/interfaces/connection_events.rb +3 -3
  27. data/lib/onstomp/interfaces/event_manager.rb +8 -0
  28. data/lib/onstomp/interfaces/uri_configurable.rb +7 -7
  29. data/lib/onstomp/open-uri.rb +37 -0
  30. data/lib/onstomp/open-uri/client_extensions.rb +88 -0
  31. data/lib/onstomp/open-uri/message_queue.rb +38 -0
  32. data/lib/onstomp/version.rb +1 -1
  33. data/spec/onstomp/client_spec.rb +1 -4
  34. data/spec/onstomp/components/frame_headers_spec.rb +2 -5
  35. data/spec/onstomp/connections/stomp_1_0_spec.rb +22 -0
  36. data/spec/onstomp/connections/stomp_1_1_spec.rb +22 -0
  37. data/spec/onstomp/connections/stomp_1_spec.rb +2 -19
  38. data/spec/onstomp/connections_spec.rb +4 -0
  39. data/spec/onstomp/failover/buffers/written_spec.rb +8 -0
  40. data/spec/onstomp/failover/client_spec.rb +38 -0
  41. data/spec/onstomp/failover/failover_events_spec.rb +75 -0
  42. data/spec/onstomp/failover/new_with_failover_spec.rb +16 -0
  43. data/spec/onstomp/failover/pools/base_spec.rb +54 -0
  44. data/spec/onstomp/failover/pools/round_robin_spec.rb +27 -0
  45. data/spec/onstomp/failover/uri_spec.rb +21 -0
  46. data/spec/onstomp/full_stacks/failover_spec.rb +55 -0
  47. data/spec/onstomp/full_stacks/onstomp_spec.rb +15 -0
  48. data/spec/onstomp/full_stacks/open-uri_spec.rb +40 -0
  49. data/spec/onstomp/full_stacks/ssl/README +6 -0
  50. data/spec/onstomp/full_stacks/ssl/broker_cert.csr +17 -0
  51. data/spec/onstomp/full_stacks/ssl/broker_cert.pem +72 -0
  52. data/spec/onstomp/full_stacks/ssl/broker_key.pem +27 -0
  53. data/spec/onstomp/full_stacks/ssl/client_cert.csr +17 -0
  54. data/spec/onstomp/full_stacks/ssl/client_cert.pem +72 -0
  55. data/spec/onstomp/full_stacks/ssl/client_key.pem +27 -0
  56. data/spec/onstomp/full_stacks/ssl/demoCA/cacert.pem +17 -0
  57. data/spec/onstomp/full_stacks/ssl/demoCA/index.txt +2 -0
  58. data/spec/onstomp/full_stacks/ssl/demoCA/index.txt.attr +1 -0
  59. data/spec/onstomp/full_stacks/ssl/demoCA/index.txt.attr.old +1 -0
  60. data/spec/onstomp/full_stacks/ssl/demoCA/index.txt.old +1 -0
  61. data/spec/onstomp/full_stacks/ssl/demoCA/newcerts/01.pem +72 -0
  62. data/spec/onstomp/full_stacks/ssl/demoCA/newcerts/02.pem +72 -0
  63. data/spec/onstomp/full_stacks/ssl/demoCA/private/cakey.pem +17 -0
  64. data/spec/onstomp/full_stacks/ssl/demoCA/serial +1 -0
  65. data/spec/onstomp/full_stacks/ssl/demoCA/serial.old +1 -0
  66. data/spec/onstomp/full_stacks/test_broker.rb +251 -0
  67. data/spec/onstomp/interfaces/connection_events_spec.rb +3 -1
  68. data/spec/onstomp/open-uri/client_extensions_spec.rb +113 -0
  69. data/spec/onstomp/open-uri/message_queue_spec.rb +29 -0
  70. data/spec/onstomp/open-uri_spec.rb +43 -0
  71. data/spec/spec_helper.rb +2 -0
  72. data/yard_extensions.rb +5 -1
  73. metadata +82 -8
  74. data/lib/onstomp/components/nil_processor.rb +0 -20
  75. data/spec/onstomp/components/nil_processor_spec.rb +0 -32
@@ -32,6 +32,13 @@ module OnStomp::Interfaces::EventManager
32
32
 
33
33
  # Mixin to allow includers to define custom event methods
34
34
  module ClassMethods
35
+ # A convenient way to get a list of all of the event methods a class
36
+ # has defined for itself. Returns an array of event method names as symbols.
37
+ # @return [Array<Symbol>]
38
+ def event_methods
39
+ @event_methods ||= []
40
+ end
41
+
35
42
  # Creates a convenience method for binding callbacks to the given
36
43
  # event name.
37
44
  # @param [Symbol] name
@@ -44,6 +51,7 @@ module OnStomp::Interfaces::EventManager
44
51
  #
45
52
  # example_obj.do_event { |arg1, arg2| ... }
46
53
  def create_event_method name
54
+ event_methods << name
47
55
  module_eval "def #{name}(&block); bind_event(:#{name}, block); end"
48
56
  end
49
57
 
@@ -29,7 +29,7 @@ module OnStomp::Interfaces::UriConfigurable
29
29
  def attr_configurable *args, &block
30
30
  opts = args.last.is_a?(Hash) ? args.pop : {}
31
31
  args.each do |attr_name|
32
- __init_config_attribute__ attr_name, opts
32
+ init_config_attribute attr_name, opts
33
33
  attr_reader attr_name
34
34
  define_method :"#{attr_name}=" do |v|
35
35
  instance_variable_set(:"@#{attr_name}", (block ? block.call(v) : v))
@@ -44,7 +44,7 @@ module OnStomp::Interfaces::UriConfigurable
44
44
  # created by this method are assigned an +Array+, only the first element
45
45
  # will be used as their value.
46
46
  def attr_configurable_single *args, &block
47
- trans = __attr_configurable_wrap__ lambda { |v| v.is_a?(Array) ? v.first : v }, block
47
+ trans = attr_configurable_wrap lambda { |v| v.is_a?(Array) ? v.first : v }, block
48
48
  attr_configurable(*args, &trans)
49
49
  end
50
50
 
@@ -55,7 +55,7 @@ module OnStomp::Interfaces::UriConfigurable
55
55
  # created by this method will be treated as though they were created
56
56
  # with {#attr_configurable_single} and will also be converted into Strings.
57
57
  def attr_configurable_str *args, &block
58
- trans = __attr_configurable_wrap__ lambda { |v| v.to_s }, block
58
+ trans = attr_configurable_wrap lambda { |v| v.to_s }, block
59
59
  attr_configurable_single(*args, &trans)
60
60
  end
61
61
 
@@ -66,7 +66,7 @@ module OnStomp::Interfaces::UriConfigurable
66
66
  # created by this method are assigned a value that is not an +Array+, the
67
67
  # value will be wrapped in an array.
68
68
  def attr_configurable_arr *args, &block
69
- trans = __attr_configurable_wrap__ lambda { |v| Array(v) }, block
69
+ trans = attr_configurable_wrap lambda { |v| Array(v) }, block
70
70
  attr_configurable(*args, &trans)
71
71
  end
72
72
 
@@ -78,12 +78,12 @@ module OnStomp::Interfaces::UriConfigurable
78
78
  # with {#attr_configurable_single} and will also be converted into Class
79
79
  # or Module objects.
80
80
  def attr_configurable_class *args, &block
81
- trans = __attr_configurable_wrap__ lambda { |v| OnStomp.constantize(v) }, block
81
+ trans = attr_configurable_wrap lambda { |v| OnStomp.constantize(v) }, block
82
82
  attr_configurable_single(*args, &trans)
83
83
  end
84
84
 
85
85
  private
86
- def __attr_configurable_wrap__(trans, block)
86
+ def attr_configurable_wrap(trans, block)
87
87
  if block
88
88
  lambda { |v| block.call(trans.call(v)) }
89
89
  else
@@ -91,7 +91,7 @@ module OnStomp::Interfaces::UriConfigurable
91
91
  end
92
92
  end
93
93
 
94
- def __init_config_attribute__(name, opts)
94
+ def init_config_attribute(name, opts)
95
95
  unless respond_to?(:config_attributes)
96
96
  class << self
97
97
  def config_attributes
@@ -0,0 +1,37 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'open-uri'
3
+
4
+ class OnStomp::Components::URI::STOMP
5
+ # Creates a new {OnStomp::Client}, extends it with
6
+ # {OnStomp::OpenURI::ClientExtensions} and either returns it directly or
7
+ # connects it, yields it to a given block and the disconnects it.
8
+ # @param [arg1, arg2, ...] args additional arguments to pass to {OnStomp::Client#initialize}
9
+ # @yield [client] block to evaluate within a connected client
10
+ # @yieldparam [OnStomp::Client] client
11
+ # @return [OnStomp::Client]
12
+ def open(*args)
13
+ client = OnStomp::Client.new(self, *args)
14
+ client.extend OnStomp::OpenURI::ClientExtensions
15
+ client.auto_destination = self.path
16
+ if block_given?
17
+ begin
18
+ client.connect
19
+ yield client
20
+ ensure
21
+ client.disconnect
22
+ end
23
+ end
24
+ client
25
+ end
26
+ end
27
+
28
+ # Namespace for OnStomp open-uri extensions.
29
+ module OnStomp::OpenURI
30
+ # Raised if a client's
31
+ # {OnStomp::OpenURI::ClientExtensions#auto_destination auto_destination} has
32
+ # not been properly set.
33
+ class UnusableDestinationError < OnStomp::OnStompError; end
34
+ end
35
+
36
+ require 'onstomp/open-uri/message_queue'
37
+ require 'onstomp/open-uri/client_extensions'
@@ -0,0 +1,88 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ # Mixin of extensions added to {OnStomp::Client clients} when they are
4
+ # created by opening a stomp:// URI.
5
+ module OnStomp::OpenURI::ClientExtensions
6
+ attr_reader :auto_destination, :openuri_message_queue
7
+
8
+ # Aliases {#send_with_openuri} as +send+
9
+ def self.extended inst
10
+ inst.instance_eval do
11
+ alias :send_without_openuri :send
12
+ alias :send :send_with_openuri
13
+ alias :puts :send
14
+ end
15
+ end
16
+
17
+ # Adds the ability for clients to generate SEND frames without specifying
18
+ # a destination by using {#auto_destination} instead.
19
+ # @return [OnStomp::Components::Frame] SEND frame
20
+ def send_with_openuri *args, &block
21
+ headers = args.last.is_a?(Hash) ? args.pop : {}
22
+ dest, body = args
23
+ if body.nil?
24
+ body, dest = dest, verified_auto_destination
25
+ end
26
+ send_without_openuri dest, body, headers, &block
27
+ end
28
+
29
+ # Creates a subscription to {#auto_destination} and yields each MESSAGE frame
30
+ # read from the subscription to the supplied block. If no block is provided
31
+ # an enumerator is returned.
32
+ # @yield [m] block to call for each MESSAGE frame
33
+ # @yieldparam [OnStomp::Components::Frame] m
34
+ # @return [Enumerator,self]
35
+ def each(&block)
36
+ if block
37
+ subscribe_to_auto_destination
38
+ loop do
39
+ yield openuri_message_queue.shift
40
+ end
41
+ else
42
+ OnStomp::ENUMERATOR_KLASS.new(self)
43
+ end
44
+ end
45
+
46
+ # Returns +n+ frames read from the subscription. If +n+ is ommited,
47
+ # the next frame is returned, otherwise an array of the next +n+ frames
48
+ # is returned.
49
+ # @see #each
50
+ # @param [Fixnum,nil] n
51
+ # @return [OnStomp::Components::Frame,Array<OnStomp::Components::Frame>]
52
+ def first(n=nil)
53
+ to_recv = n || 1
54
+ received = []
55
+ each do |m|
56
+ received << m
57
+ break if received.size == to_recv
58
+ end
59
+ n ? received : received.first
60
+ end
61
+ alias :take :first
62
+ alias :gets :first
63
+
64
+ # Assigns the auto destination. When a stomp:// URI is opened, this
65
+ # will initially be set to the +path+ of the URI.
66
+ # @param [String] dest
67
+ # @return [String,nil]
68
+ def auto_destination= dest
69
+ @auto_destination = (dest == '/') ? nil : dest
70
+ end
71
+
72
+ private
73
+ def subscribe_to_auto_destination
74
+ unless @subscribe
75
+ @openuri_message_queue = OnStomp::OpenURI::MessageQueue.new
76
+ @subscribe = subscribe(verified_auto_destination) do |m|
77
+ openuri_message_queue << m
78
+ end
79
+ end
80
+ end
81
+
82
+ def verified_auto_destination
83
+ if auto_destination.nil? || auto_destination.empty?
84
+ raise OnStomp::OpenURI::UnusableDestinationError
85
+ end
86
+ auto_destination
87
+ end
88
+ end
@@ -0,0 +1,38 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ # A simple synchronized message queue used to handle yielding MESSAGE frames
4
+ # to {OnStomp::OpenURI::ClientExtensions#each} blocks.
5
+ class OnStomp::OpenURI::MessageQueue
6
+ def initialize
7
+ @queue = []
8
+ @queue.extend MonitorMixin
9
+ @empty_check = @queue.new_cond
10
+ end
11
+
12
+ # Waits until the queue contains at least one element, then takes it out
13
+ # and returns it.
14
+ def shift
15
+ take_from_queue :shift
16
+ end
17
+
18
+ # Puts a new object into the queue.
19
+ def push msg
20
+ put_in_queue :push, msg
21
+ end
22
+ alias :<< :push
23
+
24
+ private
25
+ def put_in_queue meth, msg
26
+ @queue.synchronize do
27
+ @queue.send meth, msg
28
+ @empty_check.signal
29
+ end
30
+ end
31
+
32
+ def take_from_queue meth
33
+ @queue.synchronize do
34
+ @empty_check.wait_while { @queue.empty? }
35
+ @queue.send meth
36
+ end
37
+ end
38
+ end
@@ -9,5 +9,5 @@ module OnStomp
9
9
  # Patch version
10
10
  PATCH = 0
11
11
  # Complete version
12
- VERSION = "#{MAJOR}.#{MINOR}.#{PATCH}pre1"
12
+ VERSION = "#{MAJOR}.#{MINOR}.#{PATCH}"
13
13
  end
@@ -124,6 +124,7 @@ module OnStomp
124
124
  client.stub(:processor => processor_class)
125
125
  end
126
126
  it "should call disconnect_without_flush and join the processor" do
127
+ processor.should_receive(:prepare_to_close)
127
128
  processor.should_receive(:join)
128
129
  client.should_receive(:disconnect_without_flush).with(headers).and_return(frame)
129
130
  client.disconnect_with_flush(headers).should == frame
@@ -235,10 +236,6 @@ module OnStomp
235
236
  client.processor = '::Module'
236
237
  client.processor.should == Module
237
238
  end
238
- it "should use the NilProcessor if set to nil" do
239
- client.processor = nil
240
- client.processor.should == OnStomp::Components::NilProcessor
241
- end
242
239
  end
243
240
 
244
241
  describe ".login" do
@@ -6,10 +6,7 @@ module OnStomp::Components
6
6
  let(:headers) {
7
7
  FrameHeaders.new
8
8
  }
9
- let(:enumerator_module) {
10
- RUBY_VERSION >= '1.9' ? Enumerator : Enumerable::Enumerator
11
- }
12
-
9
+
13
10
  describe ".initialize" do
14
11
  it "should create an empty set of headers" do
15
12
  FrameHeaders.new.names.should == []
@@ -133,7 +130,7 @@ module OnStomp::Components
133
130
  end
134
131
 
135
132
  it "should yield an enumerator if called without a block" do
136
- headers.each.should be_a_kind_of(enumerator_module)
133
+ headers.each.should be_a_kind_of(OnStomp::ENUMERATOR_KLASS)
137
134
  end
138
135
 
139
136
  it "should yield header names and values as pairs of strings" do
@@ -27,6 +27,28 @@ module OnStomp::Connections
27
27
  end
28
28
  end
29
29
 
30
+ describe ".subscribe_frame" do
31
+ it "should automatically generate an 'id' header if one is not supplied" do
32
+ frame = connection.subscribe_frame('/queue/test', :ack => 'client',
33
+ :destination => '/queue/not-test')
34
+ frame.should be_an_onstomp_frame('SUBSCRIBE', {:ack => 'client',
35
+ :destination => '/queue/test'}, nil)
36
+ frame.header?(:id).should be_true
37
+ end
38
+ it "should build a SUBSCRIBE frame" do
39
+ connection.subscribe_frame('/queue/test', :ack => 'auto',
40
+ :destination => '/queue/not-test', :id => 's-1234'
41
+ ).should be_an_onstomp_frame('SUBSCRIBE', {:ack => 'auto',
42
+ :destination => '/queue/test', :id => 's-1234'}, nil)
43
+ end
44
+ it "should set ack mode to auto if it is not set to client" do
45
+ connection.subscribe_frame('/queue/test', :ack => 'fudge!',
46
+ :destination => '/queue/not-test', :id => 's-1234'
47
+ ).should be_an_onstomp_frame('SUBSCRIBE', {:ack => 'auto',
48
+ :destination => '/queue/test', :id => 's-1234'}, nil)
49
+ end
50
+ end
51
+
30
52
  describe ".ack_frame" do
31
53
  let(:message_frame) {
32
54
  OnStomp::Components::Frame.new('MESSAGE', :'message-id' => 'm-1234')
@@ -30,6 +30,28 @@ module OnStomp::Connections
30
30
  end
31
31
  end
32
32
 
33
+ describe ".subscribe_frame" do
34
+ it "should automatically generate an 'id' header if one is not supplied" do
35
+ frame = connection.subscribe_frame('/queue/test', :ack => 'client',
36
+ :destination => '/queue/not-test')
37
+ frame.should be_an_onstomp_frame('SUBSCRIBE', {:ack => 'client',
38
+ :destination => '/queue/test'}, nil)
39
+ frame.header?(:id).should be_true
40
+ end
41
+ it "should build a SUBSCRIBE frame" do
42
+ connection.subscribe_frame('/queue/test', :ack => 'client-individual',
43
+ :destination => '/queue/not-test', :id => 's-1234'
44
+ ).should be_an_onstomp_frame('SUBSCRIBE', {:ack => 'client-individual',
45
+ :destination => '/queue/test', :id => 's-1234'}, nil)
46
+ end
47
+ it "should set ack mode to auto if it is not set to client or client-individual" do
48
+ connection.subscribe_frame('/queue/test', :ack => 'fudge!',
49
+ :destination => '/queue/not-test', :id => 's-1234'
50
+ ).should be_an_onstomp_frame('SUBSCRIBE', {:ack => 'auto',
51
+ :destination => '/queue/test', :id => 's-1234'}, nil)
52
+ end
53
+ end
54
+
33
55
  describe ".ack_frame" do
34
56
  let(:message_frame) {
35
57
  OnStomp::Components::Frame.new('MESSAGE',
@@ -64,27 +64,10 @@ module OnStomp::Connections
64
64
  end
65
65
  end
66
66
 
67
- describe ".subscribe_frame" do
68
- it "should automatically generate an 'id' header if one is not supplied" do
69
- frame = connection.subscribe_frame('/queue/test', :ack => 'client',
70
- :destination => '/queue/not-test')
71
- frame.should be_an_onstomp_frame('SUBSCRIBE', {:ack => 'client',
72
- :destination => '/queue/test'}, nil)
73
- frame.header?(:id).should be_true
74
- end
75
- it "should build a SUBSCRIBE frame" do
76
- connection.subscribe_frame('/queue/test', :ack => 'auto',
77
- :destination => '/queue/not-test', :id => 's-1234'
78
- ).should be_an_onstomp_frame('SUBSCRIBE', {:ack => 'auto',
79
- :destination => '/queue/test', :id => 's-1234'}, nil)
80
- end
81
- end
82
-
83
67
  describe ".unsubscribe_frame" do
84
68
  it "should build an UNSUBSCRIBE frame from a SUBSCRIBE frame" do
85
- subscribe_frame = connection.subscribe_frame('/queue/test',
86
- :ack => 'auto',
87
- :destination => '/queue/not-test', :id => 's-1234')
69
+ subscribe_frame = OnStomp::Components::Frame.new('SUBSCRIBE',
70
+ :id => 's-1234', :ack => 'auto')
88
71
  unsubscribe_frame = connection.unsubscribe_frame(subscribe_frame,
89
72
  :header1 => 'value 1')
90
73
  unsubscribe_frame.should be_an_onstomp_frame('UNSUBSCRIBE',
@@ -63,6 +63,10 @@ module OnStomp
63
63
  Connections::PROTOCOL_VERSIONS['1.0'] = stomp_1_0_class
64
64
  Connections::PROTOCOL_VERSIONS['1.1'] = stomp_1_1_class
65
65
  end
66
+ after(:each) do
67
+ Connections::PROTOCOL_VERSIONS['1.0'] = Connections::Stomp_1_0
68
+ Connections::PROTOCOL_VERSIONS['1.1'] = Connections::Stomp_1_1
69
+ end
66
70
 
67
71
  describe "TCP connections" do
68
72
  before(:each) do
@@ -0,0 +1,8 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ module OnStomp::Failover::Buffers
5
+ describe Written, :failover => true do
6
+
7
+ end
8
+ end
@@ -0,0 +1,38 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ module OnStomp::Failover
5
+ describe Client, :failover => true do
6
+ let(:active_client) {
7
+ mock('active client')
8
+ }
9
+ let(:client) {
10
+ Client.new('failover:(stomp:///,stomp+ssl:///)').tap do |c|
11
+ c.stub(:active_client => active_client)
12
+ end
13
+ }
14
+ describe ".connected?" do
15
+ it "should be connected if it has an active client that's connected" do
16
+ active_client.stub(:connected? => true)
17
+ client.connected?.should be_true
18
+ end
19
+ it "should not be connected if it has an active client that's not connected" do
20
+ active_client.stub(:connected? => false)
21
+ client.connected?.should be_false
22
+ end
23
+ it "should not be connected if it has no active client" do
24
+ client.stub(:active_client => nil)
25
+ client.connected?.should be_false
26
+ end
27
+ end
28
+
29
+ describe ".transmit" do
30
+ it "should transmit on the active client if there is one" do
31
+ active_client.should_receive(:transmit).with('test', :coming => 'home')
32
+ client.transmit 'test', :coming => 'home'
33
+ client.stub(:active_client => nil)
34
+ client.transmit(mock('frame')).should be_nil
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,75 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ module OnStomp::Failover
5
+ describe FailoverEvents, :failover => true do
6
+ let(:events) {
7
+ mock('events', :active_client => nil).tap do |m|
8
+ m.extend FailoverEvents
9
+ end
10
+ }
11
+ let(:client1) {
12
+ mock('client 1', :connection => nil).tap do |m|
13
+ m.extend OnStomp::Interfaces::ClientEvents
14
+ end
15
+ }
16
+ let(:client2) {
17
+ mock('client 2', :connection => nil).tap do |m|
18
+ m.extend OnStomp::Interfaces::ClientEvents
19
+ end
20
+ }
21
+ let(:client_pool) {
22
+ [client1, client2]
23
+ }
24
+ describe "client events" do
25
+ before(:each) do
26
+ events.stub(:client_pool => client_pool)
27
+ end
28
+ OnStomp::Interfaces::ClientEvents.event_methods.each do |meth|
29
+ it "should bind #{meth} to each client" do
30
+ client_pool.each { |c| c.should_receive(meth) }
31
+ events.__send__(meth) { |*_| true }
32
+ end
33
+ it "should only invoke the event if the triggering client is active" do
34
+ triggered = false
35
+ events.__send__(meth) { |*_| triggered = true }
36
+ events.stub(:active_client => client2)
37
+ client1.trigger_event meth
38
+ triggered.should be_false
39
+ triggered = false
40
+ client2.trigger_event meth
41
+ triggered.should be_true
42
+ end
43
+ end
44
+
45
+ [:on_connection_established, :on_connection_died,
46
+ :on_connection_terminated, :on_connection_closed].each do |meth|
47
+ it "should bind #{meth} to each client" do
48
+ client_pool.each { |c| c.should_receive(meth) }
49
+ events.__send__(meth) { |*_| true }
50
+ end
51
+ end
52
+ end
53
+
54
+ describe "failover events" do
55
+ [:before, :after].each do |pref|
56
+ it "should have an event :#{pref}_failover_retry" do
57
+ triggered = false
58
+ events.send(:"#{pref}_failover_retry") { |*_| triggered = true }
59
+ events.trigger_failover_retry pref, 1
60
+ triggered.should be_true
61
+ end
62
+ end
63
+
64
+ [:connect_failure, :retries_exceeded,
65
+ :lost, :connected].each do |ev|
66
+ it "should have an event :on_failover_#{ev}" do
67
+ triggered = false
68
+ events.send(:"on_failover_#{ev}") { |*_| triggered = true }
69
+ events.trigger_failover_event ev, :on
70
+ triggered.should be_true
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end