euston-rabbitmq 1.0.0-java → 1.0.1-java

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,16 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- euston-rabbitmq (1.0.0)
4
+ euston-rabbitmq (1.0.0-java)
5
5
  activesupport (~> 3.0.0)
6
- amqp (~> 0.8.0)
7
- bson_ext (~> 1.3.1)
8
6
  euston (~> 1.0.0)
9
7
  euston-eventstore (~> 1.0.0)
10
- eventmachine (~> 0.12.10)
11
8
  hash-keys (~> 1.0.0)
12
9
  hollywood (~> 1.0.0)
13
- mongo (~> 1.3.1)
10
+ jessica (~> 1.0.0)
11
+ jmongo (~> 1.0.0)
14
12
  require_all (~> 1.2.0)
15
13
  robustthread (~> 0.5.2)
16
14
  safely (~> 0.3.0)
@@ -19,31 +17,12 @@ GEM
19
17
  remote: http://rubygems.org/
20
18
  specs:
21
19
  activesupport (3.0.10)
22
- amq-client (0.8.3)
23
- amq-protocol (>= 0.8.0)
24
- eventmachine
25
- amq-protocol (0.8.1)
26
- amqp (0.8.0)
27
- amq-client (~> 0.8.3)
28
- amq-protocol (~> 0.8.0)
29
- eventmachine
30
20
  awesome_print (0.4.0)
31
- bson (1.3.1)
32
- bson (1.3.1-java)
33
- bson_ext (1.3.1)
34
21
  diff-lcs (1.1.3)
35
22
  euston (1.0.0)
36
23
  activesupport (~> 3.0.9)
37
24
  euston-eventstore (~> 1.0.0)
38
25
  require_all (~> 1.2.0)
39
- euston-eventstore (1.0.4)
40
- activesupport (~> 3.0.9)
41
- bson_ext (~> 1.3.1)
42
- hash-keys (~> 1.0.0)
43
- json (~> 1.5.0)
44
- mongo (~> 1.3.1)
45
- require_all (~> 1.2.0)
46
- uuid (~> 2.3.0)
47
26
  euston-eventstore (1.0.4-java)
48
27
  activesupport (~> 3.0.9)
49
28
  hash-keys (~> 1.0.0)
@@ -51,9 +30,6 @@ GEM
51
30
  json-jruby (~> 1.5.0)
52
31
  require_all (~> 1.2.0)
53
32
  uuid (~> 2.3.0)
54
- evented-spec (0.9.0)
55
- eventmachine (0.12.10)
56
- eventmachine (0.12.10-java)
57
33
  faker (1.0.0)
58
34
  i18n (~> 0.4)
59
35
  fuubar (0.0.6)
@@ -63,16 +39,15 @@ GEM
63
39
  hash-keys (1.0.0)
64
40
  hollywood (1.0.0)
65
41
  i18n (0.6.0)
42
+ jessica (1.0.2-java)
43
+ require_all (~> 1.2.0)
66
44
  jmongo (1.0.3)
67
45
  require_all (~> 1.2)
68
- json (1.5.0)
69
46
  json (1.5.0-java)
70
47
  json-jruby (1.5.0-java)
71
48
  json (= 1.5.0)
72
49
  macaddr (1.4.0)
73
50
  systemu (~> 2.2.0)
74
- mongo (1.3.1)
75
- bson (>= 1.3.1)
76
51
  require_all (1.2.0)
77
52
  robustthread (0.5.2)
78
53
  rspec (2.6.0)
@@ -92,12 +67,10 @@ GEM
92
67
 
93
68
  PLATFORMS
94
69
  java
95
- ruby
96
70
 
97
71
  DEPENDENCIES
98
72
  awesome_print (~> 0.4.0)
99
73
  euston-rabbitmq!
100
- evented-spec (~> 0.9.0)
101
74
  faker (~> 1.0.0)
102
75
  fuubar (~> 0.0.0)
103
76
  rspec (~> 2.6.0)
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'euston-rabbitmq'
3
- s.version = '1.0.0'
3
+ s.version = '1.0.1'
4
4
  s.platform = RUBY_PLATFORM.to_s == 'java' ? 'java' : Gem::Platform::RUBY
5
5
  s.authors = ['Lee Henson', 'Guy Boertje']
6
6
  s.email = ['lee.m.henson@gmail.com', 'guyboertje@gmail.com']
@@ -15,16 +15,16 @@ Gem::Specification.new do |s|
15
15
  Rakefile
16
16
  euston-rabbitmq.gemspec
17
17
  lib/euston-rabbitmq.rb
18
- lib/euston-rabbitmq/buffered_message_dispatcher.rb
19
- lib/euston-rabbitmq/command_handler_bindings.rb
18
+ lib/euston-rabbitmq/bindings/command_handler_binder.rb
19
+ lib/euston-rabbitmq/bindings/event_handler_binder.rb
20
+ lib/euston-rabbitmq/bindings/handler_binder.rb
20
21
  lib/euston-rabbitmq/command_handlers/retry_failed_message.rb
22
+ lib/euston-rabbitmq/constant_loader.rb
21
23
  lib/euston-rabbitmq/errors.rb
22
- lib/euston-rabbitmq/event_handler_binding.rb
23
- lib/euston-rabbitmq/event_handler_bindings.rb
24
24
  lib/euston-rabbitmq/event_handlers/message_failure.rb
25
- lib/euston-rabbitmq/event_store_dispatcher.rb
26
25
  lib/euston-rabbitmq/exchanges.rb
27
- lib/euston-rabbitmq/handler_bindings.rb
26
+ lib/euston-rabbitmq/handler_finder.rb
27
+ lib/euston-rabbitmq/handler_reference.rb
28
28
  lib/euston-rabbitmq/message_buffer.rb
29
29
  lib/euston-rabbitmq/message_logger.rb
30
30
  lib/euston-rabbitmq/queue.rb
@@ -32,10 +32,13 @@ Gem::Specification.new do |s|
32
32
  lib/euston-rabbitmq/read_model/failed_message.rb
33
33
  lib/euston-rabbitmq/read_model/message_buffer.rb
34
34
  lib/euston-rabbitmq/read_model/message_log.rb
35
+ lib/euston-rabbitmq/subscriptions/retriable_subscription.rb
35
36
  lib/euston-rabbitmq/version.rb
36
37
  spec/command_buffer_spec.rb
38
+ spec/constant_loader_spec.rb
37
39
  spec/event_buffer_spec.rb
38
40
  spec/exchange_declaration_spec.rb
41
+ spec/handler_finder_spec.rb
39
42
  spec/message_failure_spec.rb
40
43
  spec/mt_safe_queue_subscription_spec.rb
41
44
  spec/safe_queue_subscription_spec.rb
@@ -0,0 +1,24 @@
1
+ module Euston
2
+ module RabbitMq
3
+ class CommandHandlerBinder < HandlerBinder
4
+ private
5
+
6
+ def ensure_bindings_exist_for_reference channel, reference
7
+ queue_name = :command_handlers
8
+ queue = get_command_handler_queue channel, queue_name
9
+
10
+ routing_key = "commands.#{reference.name.to_s.underscore}"
11
+
12
+ EUSTON_LOG.debug "Ensuring routing key exists for queue #{queue_name}: #{routing_key}"
13
+
14
+ exchange = get_exchange channel, :commands
15
+ queue.bind exchange, :routing_key => routing_key
16
+ end
17
+
18
+ def get_command_handler_queue channel, queue_name
19
+ EUSTON_LOG.debug "Ensuring command handler queue exists: #{queue_name}" if @command_handler_queue.nil?
20
+ @command_handler_queue ||= get_queue channel, queue_name
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,32 @@
1
+ module Euston
2
+ module RabbitMq
3
+ class EventHandlerBinder < HandlerBinder
4
+ private
5
+
6
+ def ensure_bindings_exist_for_reference channel, reference
7
+ queue_name = reference.name.to_s.underscore
8
+
9
+ EUSTON_LOG.debug "Ensuring event handler queue exists: #{queue_name}"
10
+
11
+ queue = get_queue channel, queue_name
12
+
13
+ prefix = '__event_handler__'
14
+
15
+ methods = reference.handler.public_instance_methods(false)
16
+ methods = methods.select { |method| method.to_s.start_with? prefix }
17
+ methods = methods.map { |method| method.to_s[prefix.length, method.to_s.length - prefix.length] }
18
+ methods = methods.map { |method| method.split('__').first }
19
+
20
+ exchange = get_exchange channel, :events
21
+
22
+ methods.uniq.each do |method|
23
+ routing_key = "events.#{method}"
24
+
25
+ EUSTON_LOG.debug "Ensuring routing key exists for queue #{queue_name}: #{routing_key}"
26
+
27
+ queue.bind exchange, :routing_key => routing_key
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,25 @@
1
+ module Euston
2
+ module RabbitMq
3
+ class HandlerBinder
4
+ include Euston::RabbitMq::Queues
5
+ include Euston::RabbitMq::Exchanges
6
+
7
+ def initialize references
8
+ @references = references
9
+ end
10
+
11
+ def ensure_bindings_exist
12
+ begin
13
+ channel = AMQP::Channel.new
14
+ channel.prefetch 1
15
+
16
+ @references.each do |reference|
17
+ ensure_bindings_exist_for_reference channel, reference
18
+ end
19
+ ensure
20
+ channel.disconnect unless channel.nil?
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,26 @@
1
+ module Euston
2
+ module RabbitMq
3
+ class ConstantLoader
4
+ include Hollywood
5
+
6
+ def load string
7
+ namespace = Object
8
+ found = true
9
+
10
+ string.split('::').each do |segment|
11
+ if found && namespace.const_defined?(segment)
12
+ namespace = namespace.const_get segment.to_sym
13
+ else
14
+ found = false
15
+ end
16
+ end
17
+
18
+ if found
19
+ callback :hit, namespace
20
+ else
21
+ callback :miss, string
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,57 @@
1
+ module Euston
2
+ module RabbitMq
3
+ class HandlerFinder
4
+ def initialize required_mixins = []
5
+ @namespaces = []
6
+ @constant_loader = ConstantLoader.new.when(:hit => method(:store_found_constant), :miss => method(:log_failed_lookup))
7
+ @required_mixins = required_mixins
8
+ end
9
+
10
+ attr_reader :namespaces
11
+
12
+ def find
13
+ filter_namespaces_list
14
+ map_namespaces_to_references
15
+ end
16
+
17
+ private
18
+
19
+ def filter_namespaces_list
20
+ @namespaces = @namespaces.map do |namespace|
21
+ @current_constant = nil
22
+
23
+ if namespace.is_a? Module
24
+ @current_constant = namespace
25
+ else
26
+ namespace = namespace.to_s
27
+ @constant_loader.load namespace
28
+ end
29
+
30
+ @current_constant
31
+ end.uniq.to_a - [nil]
32
+ end
33
+
34
+ def log_failed_lookup string
35
+ EUSTON_LOG.warn "Couldn't find handler namespace: #{string}" if Object.const_defined?('EUSTON_LOG')
36
+ end
37
+
38
+ def map_namespaces_to_references
39
+ references = []
40
+
41
+ @namespaces.each do |namespace|
42
+ references.push *(namespace.constants.map do |constant|
43
+ reference = HandlerReference.new namespace, namespace.const_get(constant), constant
44
+ reference = nil unless @required_mixins.all? { |mixin| reference.handler.included_modules.include? mixin }
45
+ reference
46
+ end.to_a - [nil])
47
+ end
48
+
49
+ references
50
+ end
51
+
52
+ def store_found_constant constant
53
+ @current_constant = constant if constant.is_a?(Module)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,11 @@
1
+ module Euston
2
+ module RabbitMq
3
+ class HandlerReference
4
+ def initialize namespace, handler, name
5
+ @namespace, @handler, @name = namespace, handler, name
6
+ end
7
+
8
+ attr_reader :namespace, :handler, :name
9
+ end
10
+ end
11
+ end
@@ -16,7 +16,6 @@ module Euston
16
16
  include Hollywood
17
17
 
18
18
  def initialize channel, exchange_name
19
-
20
19
  @channel = channel
21
20
  @exchange = get_exchange channel, exchange_name
22
21
  @read_model = Euston::RabbitMq::ReadModel::MessageBuffer.send exchange_name
@@ -65,4 +64,4 @@ module Euston
65
64
  end
66
65
  end
67
66
  end
68
- end
67
+ end
@@ -27,6 +27,11 @@ module Euston
27
27
  'json' => ::ActiveSupport::JSON.encode(message) }, :safe => { :fsync => true })
28
28
  end
29
29
 
30
+ def find_next_message
31
+ query = { 'next_attempt' => { '$lte' => Time.now.to_f } }
32
+ @collection.find_one(query)
33
+ end
34
+
30
35
  def find_due_messages
31
36
  query = { 'next_attempt' => { '$lte' => Time.now.to_f } }
32
37
  order = [ 'next_attempt', Mongo::ASCENDING ]
@@ -40,7 +45,7 @@ module Euston
40
45
 
41
46
  def set_next_attempt message
42
47
  @collection.update({ '_id' => message['_id'] },
43
- { '$set' => { 'next_attempt' => message['next_attempt'] + 10 } }, :safe => { :fsync => true })
48
+ { '$set' => { 'next_attempt' => Time.now.to_f + 10 } }, :safe => { :fsync => true })
44
49
  end
45
50
 
46
51
  def remove_published_message id
@@ -49,4 +54,4 @@ module Euston
49
54
  end
50
55
  end
51
56
  end
52
- end
57
+ end
@@ -1,47 +1,16 @@
1
1
  module Euston
2
2
  module RabbitMq
3
- class HandlerBindings
4
- include Euston::RabbitMq::Exchanges
3
+ class RetriableSubscription
4
+ include Hollywood
5
5
  include Euston::RabbitMq::Queues
6
+ include Euston::RabbitMq::Exchanges
6
7
 
7
- def initialize channel
8
+ def initialize channel, queue_name
8
9
  @channel = channel
9
- @exchanges = { :commands => get_exchange(@channel, :commands),
10
- :events => get_exchange(@channel, :events) }
11
- @namespaces = []
12
- end
13
-
14
- def add_namespace namespace
15
- @namespaces << namespace
16
- end
17
-
18
- def namespaced_handler_types
19
- ret = []
20
- @namespaces.each do |namespace|
21
- namespace.constants.each do |handler_type|
22
- ret << [namespace, handler_type]
23
- end
24
- end
25
- ret
26
- end
27
-
28
- def finalize_bindings
29
- namespaced_handler_types.each do |namespace, handler_type|
30
- bind_handler handler_type
31
- end
10
+ @queue_name = queue_name
32
11
  end
33
12
 
34
- protected
35
-
36
- def bind_handler handler_type
37
- # virtual
38
- end
39
-
40
- def find_namespaces_containing_handler_type handler_type
41
- @namespaces.select { |namespace| namespace.const_defined? handler_type }
42
- end
43
-
44
- def attach_queue_hook_listeners queue
13
+ def attach_queue_hook_listeners
45
14
  queue.when(:message_decode_failed => method(:log_decode_failure),
46
15
  :message_failed => method(:handle_failure),
47
16
  :message_received => method(:call_handler))
@@ -49,8 +18,10 @@ module Euston
49
18
  queue.safe_subscribe
50
19
  end
51
20
 
21
+ private
22
+
52
23
  def call_handler(message)
53
- # abstract
24
+ callback :message_received, message
54
25
  end
55
26
 
56
27
  def create_message_failed_message error, failed_message, amqp_header
@@ -80,19 +51,25 @@ module Euston
80
51
 
81
52
  begin
82
53
  if failures == 3
54
+ debug_message = "Message failed, out of retries"
55
+
83
56
  message.delete :failures
84
57
  message = create_message_failed_message error, message, amqp_header
85
58
 
86
59
  options = { :key => 'events.message_failed' }
87
60
  exchange = :events
88
61
  else
62
+ debug_message = "Message failed, retrying"
63
+
89
64
  options = { :key => amqp_header.method.routing_key }
90
65
  exchange = amqp_header.method.routing_key.split('.').first.to_sym
91
66
  end
92
67
 
93
68
  options = default_publish_options.merge options
94
- exchange = @exchanges[exchange]
95
- message = ::ActiveSupport::JSON.encode message
69
+ exchange = get_exchange @channel, exchange
70
+ message = ActiveSupport::JSON.encode message
71
+
72
+ EUSTON_LOG.debug "#{debug_message}: #{message}"
96
73
 
97
74
  exchange.publish message, options
98
75
 
@@ -110,6 +87,10 @@ module Euston
110
87
 
111
88
  Safely.report! err
112
89
  end
90
+
91
+ def queue
92
+ @queue ||= get_queue @channel, @queue_name
93
+ end
113
94
  end
114
95
  end
115
- end
96
+ end
@@ -1,5 +1,5 @@
1
1
  module Euston
2
2
  module RabbitMq
3
- VERSION = "1.0.0"
3
+ VERSION = "1.0.1"
4
4
  end
5
5
  end
@@ -17,7 +17,9 @@ require 'hollywood'
17
17
  require 'euston'
18
18
  require 'euston-eventstore'
19
19
 
20
- require_rel 'euston-rabbitmq'
20
+ require_rel 'euston-rabbitmq/exchanges.rb'
21
+ require_rel 'euston-rabbitmq/queues.rb'
22
+ require_rel 'euston-rabbitmq/**/*.rb'
21
23
 
22
24
  module Euston
23
25
  module RabbitMq
@@ -0,0 +1,38 @@
1
+ require File.expand_path('../spec_helper.rb', __FILE__)
2
+
3
+ module ConstantLoaderTesting
4
+ module SubNamespace
5
+ class Foobar
6
+ end
7
+ end
8
+ end
9
+
10
+ describe 'constant loader' do
11
+ let(:loader) { Euston::RabbitMq::ConstantLoader.new }
12
+ let(:outcome) { { :hit => nil, :miss => nil} }
13
+
14
+ before { loader.when(:hit => ->(constant) { outcome[:hit] = constant }, :miss => ->{ outcome[:miss] = true }) }
15
+
16
+ subject do
17
+ loader.load constant_string
18
+ outcome
19
+ end
20
+
21
+ context 'with a valid constant string' do
22
+ let(:constant_string) { 'ConstantLoaderTesting::SubNamespace::Foobar' }
23
+
24
+ its([:hit]) { should == ConstantLoaderTesting::SubNamespace::Foobar }
25
+ end
26
+
27
+ context 'with a totally invalid constant string' do
28
+ let(:constant_string) { 'Something::Entirely::Made::Up' }
29
+
30
+ its([:miss]) { should == true }
31
+ end
32
+
33
+ context 'with a partially invalid constant string' do
34
+ let(:constant_string) { 'ConstantLoaderTesting::Missing' }
35
+
36
+ its([:miss]) { should == true }
37
+ end
38
+ end
@@ -0,0 +1,48 @@
1
+ require File.expand_path('../spec_helper.rb', __FILE__)
2
+
3
+ module HandlerFinderTesting
4
+ module EmptyNamespace; end
5
+ module SuperSpecialMixin; end
6
+
7
+ module NonEmptyNamespace
8
+ class Handler1; end
9
+ class Handler2; end
10
+
11
+ class Handler3
12
+ include HandlerFinderTesting::SuperSpecialMixin
13
+ end
14
+ end
15
+ end
16
+
17
+ describe 'handler finder' do
18
+ let(:required_mixins) { [] }
19
+ let(:finder) { Euston::RabbitMq::HandlerFinder.new required_mixins }
20
+
21
+ before { finder.namespaces.push *namespaces }
22
+ subject { finder.find }
23
+
24
+ context 'no namespaces are provided' do
25
+ let(:namespaces) { [] }
26
+
27
+ it { should be_empty }
28
+ end
29
+
30
+ context 'a namespace is provided which contains no classes' do
31
+ let(:namespaces) { [HandlerFinderTesting::EmptyNamespace] }
32
+
33
+ it { should be_empty }
34
+ end
35
+
36
+ context 'a namespace is provided with contains some classes' do
37
+ let(:namespaces) { [HandlerFinderTesting::EmptyNamespace, 'HandlerFinderTesting::NonEmptyNamespace'] }
38
+
39
+ it { should have(3).items }
40
+ end
41
+
42
+ context 'a specific mixin is required on each handler' do
43
+ let(:required_mixins) { [HandlerFinderTesting::SuperSpecialMixin] }
44
+ let(:namespaces) { [HandlerFinderTesting::EmptyNamespace, 'HandlerFinderTesting::NonEmptyNamespace'] }
45
+
46
+ it { should have(1).items }
47
+ end
48
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: euston-rabbitmq
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 1.0.0
5
+ version: 1.0.1
6
6
  platform: java
7
7
  authors:
8
8
  - Lee Henson
@@ -10,160 +10,161 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2011-09-16 00:00:00.000000000Z
13
+ date: 2011-09-20 00:00:00.000000000 +01:00
14
+ default_executable:
14
15
  dependencies:
15
16
  - !ruby/object:Gem::Dependency
16
17
  name: activesupport
17
- version_requirements: &2058 !ruby/object:Gem::Requirement
18
+ version_requirements: &2158 !ruby/object:Gem::Requirement
18
19
  requirements:
19
20
  - - ~>
20
21
  - !ruby/object:Gem::Version
21
22
  version: 3.0.0
22
23
  none: false
23
- requirement: *2058
24
+ requirement: *2158
24
25
  prerelease: false
25
26
  type: :runtime
26
27
  - !ruby/object:Gem::Dependency
27
28
  name: euston
28
- version_requirements: &2076 !ruby/object:Gem::Requirement
29
+ version_requirements: &2176 !ruby/object:Gem::Requirement
29
30
  requirements:
30
31
  - - ~>
31
32
  - !ruby/object:Gem::Version
32
33
  version: 1.0.0
33
34
  none: false
34
- requirement: *2076
35
+ requirement: *2176
35
36
  prerelease: false
36
37
  type: :runtime
37
38
  - !ruby/object:Gem::Dependency
38
39
  name: euston-eventstore
39
- version_requirements: &2092 !ruby/object:Gem::Requirement
40
+ version_requirements: &2192 !ruby/object:Gem::Requirement
40
41
  requirements:
41
42
  - - ~>
42
43
  - !ruby/object:Gem::Version
43
44
  version: 1.0.0
44
45
  none: false
45
- requirement: *2092
46
+ requirement: *2192
46
47
  prerelease: false
47
48
  type: :runtime
48
49
  - !ruby/object:Gem::Dependency
49
50
  name: hash-keys
50
- version_requirements: &2108 !ruby/object:Gem::Requirement
51
+ version_requirements: &2208 !ruby/object:Gem::Requirement
51
52
  requirements:
52
53
  - - ~>
53
54
  - !ruby/object:Gem::Version
54
55
  version: 1.0.0
55
56
  none: false
56
- requirement: *2108
57
+ requirement: *2208
57
58
  prerelease: false
58
59
  type: :runtime
59
60
  - !ruby/object:Gem::Dependency
60
61
  name: hollywood
61
- version_requirements: &2124 !ruby/object:Gem::Requirement
62
+ version_requirements: &2224 !ruby/object:Gem::Requirement
62
63
  requirements:
63
64
  - - ~>
64
65
  - !ruby/object:Gem::Version
65
66
  version: 1.0.0
66
67
  none: false
67
- requirement: *2124
68
+ requirement: *2224
68
69
  prerelease: false
69
70
  type: :runtime
70
71
  - !ruby/object:Gem::Dependency
71
72
  name: require_all
72
- version_requirements: &2140 !ruby/object:Gem::Requirement
73
+ version_requirements: &2240 !ruby/object:Gem::Requirement
73
74
  requirements:
74
75
  - - ~>
75
76
  - !ruby/object:Gem::Version
76
77
  version: 1.2.0
77
78
  none: false
78
- requirement: *2140
79
+ requirement: *2240
79
80
  prerelease: false
80
81
  type: :runtime
81
82
  - !ruby/object:Gem::Dependency
82
83
  name: robustthread
83
- version_requirements: &2156 !ruby/object:Gem::Requirement
84
+ version_requirements: &2256 !ruby/object:Gem::Requirement
84
85
  requirements:
85
86
  - - ~>
86
87
  - !ruby/object:Gem::Version
87
88
  version: 0.5.2
88
89
  none: false
89
- requirement: *2156
90
+ requirement: *2256
90
91
  prerelease: false
91
92
  type: :runtime
92
93
  - !ruby/object:Gem::Dependency
93
94
  name: safely
94
- version_requirements: &2172 !ruby/object:Gem::Requirement
95
+ version_requirements: &2272 !ruby/object:Gem::Requirement
95
96
  requirements:
96
97
  - - ~>
97
98
  - !ruby/object:Gem::Version
98
99
  version: 0.3.0
99
100
  none: false
100
- requirement: *2172
101
+ requirement: *2272
101
102
  prerelease: false
102
103
  type: :runtime
103
104
  - !ruby/object:Gem::Dependency
104
105
  name: jmongo
105
- version_requirements: &2188 !ruby/object:Gem::Requirement
106
+ version_requirements: &2288 !ruby/object:Gem::Requirement
106
107
  requirements:
107
108
  - - ~>
108
109
  - !ruby/object:Gem::Version
109
110
  version: 1.0.0
110
111
  none: false
111
- requirement: *2188
112
+ requirement: *2288
112
113
  prerelease: false
113
114
  type: :runtime
114
115
  - !ruby/object:Gem::Dependency
115
116
  name: jessica
116
- version_requirements: &2204 !ruby/object:Gem::Requirement
117
+ version_requirements: &2304 !ruby/object:Gem::Requirement
117
118
  requirements:
118
119
  - - ~>
119
120
  - !ruby/object:Gem::Version
120
121
  version: 1.0.0
121
122
  none: false
122
- requirement: *2204
123
+ requirement: *2304
123
124
  prerelease: false
124
125
  type: :runtime
125
126
  - !ruby/object:Gem::Dependency
126
127
  name: awesome_print
127
- version_requirements: &2220 !ruby/object:Gem::Requirement
128
+ version_requirements: &2320 !ruby/object:Gem::Requirement
128
129
  requirements:
129
130
  - - ~>
130
131
  - !ruby/object:Gem::Version
131
132
  version: 0.4.0
132
133
  none: false
133
- requirement: *2220
134
+ requirement: *2320
134
135
  prerelease: false
135
136
  type: :development
136
137
  - !ruby/object:Gem::Dependency
137
138
  name: faker
138
- version_requirements: &2238 !ruby/object:Gem::Requirement
139
+ version_requirements: &2338 !ruby/object:Gem::Requirement
139
140
  requirements:
140
141
  - - ~>
141
142
  - !ruby/object:Gem::Version
142
143
  version: 1.0.0
143
144
  none: false
144
- requirement: *2238
145
+ requirement: *2338
145
146
  prerelease: false
146
147
  type: :development
147
148
  - !ruby/object:Gem::Dependency
148
149
  name: fuubar
149
- version_requirements: &2254 !ruby/object:Gem::Requirement
150
+ version_requirements: &2354 !ruby/object:Gem::Requirement
150
151
  requirements:
151
152
  - - ~>
152
153
  - !ruby/object:Gem::Version
153
154
  version: 0.0.0
154
155
  none: false
155
- requirement: *2254
156
+ requirement: *2354
156
157
  prerelease: false
157
158
  type: :development
158
159
  - !ruby/object:Gem::Dependency
159
160
  name: rspec
160
- version_requirements: &2270 !ruby/object:Gem::Requirement
161
+ version_requirements: &2370 !ruby/object:Gem::Requirement
161
162
  requirements:
162
163
  - - ~>
163
164
  - !ruby/object:Gem::Version
164
165
  version: 2.6.0
165
166
  none: false
166
- requirement: *2270
167
+ requirement: *2370
167
168
  prerelease: false
168
169
  type: :development
169
170
  description: JRuby RabbitMq bindings
@@ -179,16 +180,16 @@ files:
179
180
  - Rakefile
180
181
  - euston-rabbitmq.gemspec
181
182
  - lib/euston-rabbitmq.rb
182
- - lib/euston-rabbitmq/buffered_message_dispatcher.rb
183
- - lib/euston-rabbitmq/command_handler_bindings.rb
183
+ - lib/euston-rabbitmq/bindings/command_handler_binder.rb
184
+ - lib/euston-rabbitmq/bindings/event_handler_binder.rb
185
+ - lib/euston-rabbitmq/bindings/handler_binder.rb
184
186
  - lib/euston-rabbitmq/command_handlers/retry_failed_message.rb
187
+ - lib/euston-rabbitmq/constant_loader.rb
185
188
  - lib/euston-rabbitmq/errors.rb
186
- - lib/euston-rabbitmq/event_handler_binding.rb
187
- - lib/euston-rabbitmq/event_handler_bindings.rb
188
189
  - lib/euston-rabbitmq/event_handlers/message_failure.rb
189
- - lib/euston-rabbitmq/event_store_dispatcher.rb
190
190
  - lib/euston-rabbitmq/exchanges.rb
191
- - lib/euston-rabbitmq/handler_bindings.rb
191
+ - lib/euston-rabbitmq/handler_finder.rb
192
+ - lib/euston-rabbitmq/handler_reference.rb
192
193
  - lib/euston-rabbitmq/message_buffer.rb
193
194
  - lib/euston-rabbitmq/message_logger.rb
194
195
  - lib/euston-rabbitmq/queue.rb
@@ -196,15 +197,19 @@ files:
196
197
  - lib/euston-rabbitmq/read_model/failed_message.rb
197
198
  - lib/euston-rabbitmq/read_model/message_buffer.rb
198
199
  - lib/euston-rabbitmq/read_model/message_log.rb
200
+ - lib/euston-rabbitmq/subscriptions/retriable_subscription.rb
199
201
  - lib/euston-rabbitmq/version.rb
200
202
  - spec/command_buffer_spec.rb
203
+ - spec/constant_loader_spec.rb
201
204
  - spec/event_buffer_spec.rb
202
205
  - spec/exchange_declaration_spec.rb
206
+ - spec/handler_finder_spec.rb
203
207
  - spec/message_failure_spec.rb
204
208
  - spec/mt_safe_queue_subscription_spec.rb
205
209
  - spec/safe_queue_subscription_spec.rb
206
210
  - spec/spec_helper.rb
207
211
  - spec/support/factories.rb
212
+ has_rdoc: true
208
213
  homepage: http://github.com/leemhenson/euston-rabbitmq
209
214
  licenses: []
210
215
  post_install_message:
@@ -225,7 +230,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
225
230
  none: false
226
231
  requirements: []
227
232
  rubyforge_project:
228
- rubygems_version: 1.8.9
233
+ rubygems_version: 1.5.1
229
234
  signing_key:
230
235
  specification_version: 3
231
236
  summary: RabbitMq bindings for Euston.
@@ -1,48 +0,0 @@
1
- module Euston
2
- module RabbitMq
3
- class BufferedMessageDispatcher
4
- class << self
5
- def command_dispatcher channel
6
- @command_dispatcher ||= BufferedMessageDispatcher.new(Euston::RabbitMq::MessageBuffer.commands_buffer channel)
7
- end
8
-
9
- def event_dispatcher channel
10
- @event_dispatcher ||= BufferedMessageDispatcher.new(Euston::RabbitMq::MessageBuffer.events_buffer channel)
11
- end
12
- end
13
-
14
- include Euston::RabbitMq::Exchanges
15
-
16
- def initialize buffer
17
- @buffer = buffer
18
- @buffer.when(:no_messages_were_due) { @sleep = true }
19
- end
20
-
21
- attr_writer :wait_time
22
-
23
- def wait_time
24
- @wait_time ||= 1
25
- end
26
-
27
- def stop
28
- @stop = true
29
- end
30
-
31
- def start
32
- @stop = false
33
-
34
- dispatch_loop = Proc.new do
35
- @sleep = false
36
-
37
- begin
38
- @buffer.dispatch_due_messages
39
- end while !@sleep
40
-
41
- EM.add_timer(wait_time) { dispatch_loop.call } unless @stop
42
- end
43
-
44
- EM.add_timer(wait_time) { dispatch_loop.call }
45
- end
46
- end
47
- end
48
- end
@@ -1,30 +0,0 @@
1
- module Euston
2
- module RabbitMq
3
- class CommandHandlerBindings < HandlerBindings
4
- def finalize_bindings
5
- super
6
- attach_queue_hook_listeners queue
7
- end
8
-
9
- protected
10
-
11
- def bind_handler handler_type
12
- queue.bind @exchanges[:commands], :routing_key => "commands.#{handler_type.to_s.underscore}"
13
- end
14
-
15
- def call_handler message
16
- command_headers = CommandHeaders.from_hash(message[:headers]).freeze
17
- command_body = message[:body].freeze
18
- handler_type = command_headers.type.to_s.camelize.to_sym
19
- find_namespaces_containing_handler_type(handler_type).each do |namespace|
20
- handler = namespace.const_get handler_type
21
- handler.new.send "__version__#{command_headers.version}", command_headers, command_body
22
- end
23
- end
24
-
25
- def queue
26
- @queue ||= get_queue @channel, :command_handlers
27
- end
28
- end
29
- end
30
- end
@@ -1,114 +0,0 @@
1
- module Euston
2
- module RabbitMq
3
- class EventHandlerBinding
4
- include Euston::RabbitMq::Queues
5
- include Euston::RabbitMq::Exchanges
6
-
7
- PREFIX = '__event_handler__'
8
-
9
- def initialize(channel, namespace, handler_type)
10
- @channel, @namespace, @handler_type = channel, namespace, handler_type
11
-
12
- name = @handler_type.to_s.underscore
13
- @queue = get_queue(@channel, name)
14
- instance_variable_set "@#{name}".to_sym, @queue
15
- @handler_class = @namespace.const_get @handler_type
16
- @exchange = get_exchange(@channel, :events)
17
- end
18
-
19
- def bind
20
- bindable_methods.each do |method|
21
- @queue.bind @exchange, :routing_key => "events.#{method}"
22
- end
23
- self
24
- end
25
-
26
- def listen
27
- attach_queue_hook_listeners @queue
28
- end
29
-
30
- private
31
-
32
- def attach_queue_hook_listeners queue
33
- queue.when(:message_decode_failed => method(:log_decode_failure),
34
- :message_failed => method(:handle_failure),
35
- :message_received => method(:call_handler))
36
-
37
- queue.safe_subscribe
38
- end
39
-
40
- def call_handler(message)
41
- event_headers = EventHeaders.from_hash message[:headers]
42
- event_body = message[:body]
43
-
44
- @handler_class.new.send "#{PREFIX}#{event_headers.type}__#{event_headers.version}", event_headers.freeze, event_body.freeze
45
- end
46
-
47
- def bindable_methods
48
- methods = @handler_class.public_instance_methods(false)
49
- methods = methods.select { |method| method.to_s.start_with? PREFIX }
50
- methods = methods.map { |method| method.to_s[PREFIX.length, method.to_s.length - PREFIX.length] }
51
- methods = methods.map { |method| method.split('__').first }
52
- methods.uniq
53
- end
54
-
55
- def create_message_failed_message error, failed_message, amqp_header
56
- {
57
- :headers =>
58
- {
59
- :id => Euston.uuid.generate.to_s,
60
- :type => :message_failed,
61
- :version => 1,
62
- :timestamp => Time.now.to_f
63
- },
64
-
65
- :body =>
66
- {
67
- :message => failed_message,
68
- :routing_key => amqp_header.method.routing_key,
69
- :error => error.message,
70
- :backtrace => error.backtrace
71
- }
72
- }
73
- end
74
-
75
- def handle_failure message, error, amqp_header
76
- failures = message[:failures] || 0
77
- failures = failures + 1
78
- message[:failures] = failures
79
-
80
- begin
81
- if failures == 3
82
- message.delete :failures
83
- message = create_message_failed_message error, message, amqp_header
84
-
85
- options = { :key => 'events.message_failed' }
86
- exchange_ref = :events
87
- else
88
- options = { :key => amqp_header.method.routing_key }
89
- exchange_ref = amqp_header.method.routing_key.split('.').first.to_sym
90
- end
91
-
92
- options = default_publish_options.merge options
93
- exchange = get_exchange(@channel, exchange_ref)
94
- message = ::ActiveSupport::JSON.encode message
95
-
96
- exchange.publish message, options
97
-
98
- amqp_header.ack
99
- rescue StandardError => e
100
- amqp_header.reject :requeue => true
101
- raise e
102
- end
103
- end
104
-
105
- def log_decode_failure message, error
106
- text = "A handler queue subscription failed. [Error] #{error.message} [Payload] #{message}"
107
- err = Euston::RabbitMq::MessageDecodeFailedError.new text
108
- err.set_backtrace error.backtrace
109
-
110
- Safely.report! err
111
- end
112
- end
113
- end
114
- end
@@ -1,30 +0,0 @@
1
- module Euston
2
- module RabbitMq
3
- class EventHandlerBindings < HandlerBindings
4
- PREFIX = '__event_handler__'
5
-
6
- protected
7
-
8
- def bind_handler handler_type
9
- name = handler_type.to_s.underscore
10
- queue = get_queue @channel, name
11
- instance_variable_set "@#{name}".to_sym, queue
12
-
13
- namespace = find_namespaces_containing_handler_type(handler_type).first
14
- handler_class = namespace.const_get handler_type
15
- methods = handler_class.public_instance_methods(false)
16
- methods = methods.select { |method| method.to_s.start_with? PREFIX }
17
- methods = methods.map { |method| method.to_s[PREFIX.length, method.to_s.length - PREFIX.length] }
18
- methods = methods.map { |method| method.split('__').first }
19
- methods.uniq.each { |method| queue.bind @exchanges[:events], :routing_key => "events.#{method}" }
20
-
21
- attach_queue_hook_listeners queue do |message|
22
- event_headers = EventHeaders.from_hash message[:headers]
23
- event_body = message[:body]
24
-
25
- handler_class.new.send "#{PREFIX}#{event_headers.type}__#{event_headers.version}", event_headers.freeze, event_body.freeze
26
- end
27
- end
28
- end
29
- end
30
- end
@@ -1,45 +0,0 @@
1
- module Euston
2
- module RabbitMq
3
- class EventStoreDispatcher
4
- def initialize channel
5
- @channel = channel
6
- @event_buffer = Euston::RabbitMq::MessageBuffer.events_buffer channel
7
- @event_store = Euston::RabbitMq.event_store
8
- end
9
-
10
- attr_writer :wait_time
11
-
12
- def wait_time
13
- @wait_time ||= 1
14
- end
15
-
16
- def stop
17
- @stop = true
18
- end
19
-
20
- def start
21
- @stop = false
22
-
23
- dispatch_loop = Proc.new do
24
- begin
25
- begin
26
- commits = @event_store.get_undispatched_commits
27
-
28
- commits.each do |commit|
29
- commit.events.each { |event| @event_buffer.push event.to_hash }
30
-
31
- @event_store.mark_commit_as_dispatched commit
32
- end
33
- end while !commits.empty?
34
- rescue StandardError => e
35
- DaemonKit::logger.error "#{e}\n#{e.backtrace}"
36
- end
37
-
38
- EM.add_timer(wait_time) { dispatch_loop.call } unless @stop
39
- end
40
-
41
- EM.add_timer(wait_time) { dispatch_loop.call }
42
- end
43
- end
44
- end
45
- end