euston-rabbitmq 1.0.0-java → 1.0.1-java
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.
- data/Gemfile.lock +5 -32
- data/euston-rabbitmq.gemspec +10 -7
- data/lib/euston-rabbitmq/bindings/command_handler_binder.rb +24 -0
- data/lib/euston-rabbitmq/bindings/event_handler_binder.rb +32 -0
- data/lib/euston-rabbitmq/bindings/handler_binder.rb +25 -0
- data/lib/euston-rabbitmq/constant_loader.rb +26 -0
- data/lib/euston-rabbitmq/handler_finder.rb +57 -0
- data/lib/euston-rabbitmq/handler_reference.rb +11 -0
- data/lib/euston-rabbitmq/message_buffer.rb +1 -2
- data/lib/euston-rabbitmq/read_model/message_buffer.rb +7 -2
- data/lib/euston-rabbitmq/{handler_bindings.rb → subscriptions/retriable_subscription.rb} +22 -41
- data/lib/euston-rabbitmq/version.rb +1 -1
- data/lib/euston-rabbitmq.rb +3 -1
- data/spec/constant_loader_spec.rb +38 -0
- data/spec/handler_finder_spec.rb +48 -0
- metadata +42 -37
- data/lib/euston-rabbitmq/buffered_message_dispatcher.rb +0 -48
- data/lib/euston-rabbitmq/command_handler_bindings.rb +0 -30
- data/lib/euston-rabbitmq/event_handler_binding.rb +0 -114
- data/lib/euston-rabbitmq/event_handler_bindings.rb +0 -30
- data/lib/euston-rabbitmq/event_store_dispatcher.rb +0 -45
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
|
-
|
|
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)
|
data/euston-rabbitmq.gemspec
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Gem::Specification.new do |s|
|
|
2
2
|
s.name = 'euston-rabbitmq'
|
|
3
|
-
s.version = '1.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/
|
|
19
|
-
lib/euston-rabbitmq/
|
|
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/
|
|
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
|
|
@@ -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' =>
|
|
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
|
|
4
|
-
include
|
|
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
|
-
@
|
|
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
|
-
|
|
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
|
-
|
|
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 = @
|
|
95
|
-
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
|
data/lib/euston-rabbitmq.rb
CHANGED
|
@@ -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.
|
|
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-
|
|
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: &
|
|
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: *
|
|
24
|
+
requirement: *2158
|
|
24
25
|
prerelease: false
|
|
25
26
|
type: :runtime
|
|
26
27
|
- !ruby/object:Gem::Dependency
|
|
27
28
|
name: euston
|
|
28
|
-
version_requirements: &
|
|
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: *
|
|
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: &
|
|
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: *
|
|
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: &
|
|
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: *
|
|
57
|
+
requirement: *2208
|
|
57
58
|
prerelease: false
|
|
58
59
|
type: :runtime
|
|
59
60
|
- !ruby/object:Gem::Dependency
|
|
60
61
|
name: hollywood
|
|
61
|
-
version_requirements: &
|
|
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: *
|
|
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: &
|
|
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: *
|
|
79
|
+
requirement: *2240
|
|
79
80
|
prerelease: false
|
|
80
81
|
type: :runtime
|
|
81
82
|
- !ruby/object:Gem::Dependency
|
|
82
83
|
name: robustthread
|
|
83
|
-
version_requirements: &
|
|
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: *
|
|
90
|
+
requirement: *2256
|
|
90
91
|
prerelease: false
|
|
91
92
|
type: :runtime
|
|
92
93
|
- !ruby/object:Gem::Dependency
|
|
93
94
|
name: safely
|
|
94
|
-
version_requirements: &
|
|
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: *
|
|
101
|
+
requirement: *2272
|
|
101
102
|
prerelease: false
|
|
102
103
|
type: :runtime
|
|
103
104
|
- !ruby/object:Gem::Dependency
|
|
104
105
|
name: jmongo
|
|
105
|
-
version_requirements: &
|
|
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: *
|
|
112
|
+
requirement: *2288
|
|
112
113
|
prerelease: false
|
|
113
114
|
type: :runtime
|
|
114
115
|
- !ruby/object:Gem::Dependency
|
|
115
116
|
name: jessica
|
|
116
|
-
version_requirements: &
|
|
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: *
|
|
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: &
|
|
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: *
|
|
134
|
+
requirement: *2320
|
|
134
135
|
prerelease: false
|
|
135
136
|
type: :development
|
|
136
137
|
- !ruby/object:Gem::Dependency
|
|
137
138
|
name: faker
|
|
138
|
-
version_requirements: &
|
|
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: *
|
|
145
|
+
requirement: *2338
|
|
145
146
|
prerelease: false
|
|
146
147
|
type: :development
|
|
147
148
|
- !ruby/object:Gem::Dependency
|
|
148
149
|
name: fuubar
|
|
149
|
-
version_requirements: &
|
|
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: *
|
|
156
|
+
requirement: *2354
|
|
156
157
|
prerelease: false
|
|
157
158
|
type: :development
|
|
158
159
|
- !ruby/object:Gem::Dependency
|
|
159
160
|
name: rspec
|
|
160
|
-
version_requirements: &
|
|
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: *
|
|
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/
|
|
183
|
-
- lib/euston-rabbitmq/
|
|
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/
|
|
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.
|
|
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
|