euston-rabbitmq 1.0.1-java → 1.0.2-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.
Files changed (46) hide show
  1. data/Gemfile +2 -0
  2. data/Rakefile +0 -21
  3. data/euston-rabbitmq.gemspec +26 -38
  4. data/lib/euston-rabbitmq/{bindings → euston}/command_handler_binder.rb +2 -2
  5. data/lib/euston-rabbitmq/{errors.rb → euston/errors.rb} +1 -1
  6. data/lib/euston-rabbitmq/{bindings → euston}/event_handler_binder.rb +4 -4
  7. data/lib/euston-rabbitmq/{exchanges.rb → euston/exchanges.rb} +1 -1
  8. data/lib/euston-rabbitmq/{bindings → euston}/handler_binder.rb +2 -1
  9. data/lib/euston-rabbitmq/{queues.rb → euston/queues.rb} +1 -1
  10. data/lib/euston-rabbitmq/{subscriptions/retriable_subscription.rb → euston/retrying_subscription.rb} +17 -16
  11. data/lib/euston-rabbitmq/rabbitmq_client/queue.rb +70 -0
  12. data/lib/euston-rabbitmq/rabbitmq_client/reactive_message.rb +15 -0
  13. data/lib/euston-rabbitmq/{constant_loader.rb → reflection/constant_loader.rb} +0 -0
  14. data/lib/euston-rabbitmq/{handler_finder.rb → reflection/handler_finder.rb} +0 -0
  15. data/lib/euston-rabbitmq/{handler_reference.rb → reflection/handler_reference.rb} +0 -0
  16. data/lib/euston-rabbitmq/version.rb +1 -1
  17. data/lib/euston-rabbitmq.rb +8 -22
  18. data/spec/euston/command_handler_binder_spec.rb +24 -0
  19. data/spec/euston/event_handler_binder_spec.rb +36 -0
  20. data/spec/euston/exchanges_spec.rb +27 -0
  21. data/spec/euston/queues_spec.rb +24 -0
  22. data/spec/euston/retrying_subscription_spec.rb +74 -0
  23. data/spec/rabbitmq_client/queue_spec.rb +69 -0
  24. data/spec/{constant_loader_spec.rb → reflection/constant_loader_spec.rb} +3 -1
  25. data/spec/{handler_finder_spec.rb → reflection/handler_finder_spec.rb} +3 -1
  26. data/spec/spec_helper.rb +19 -52
  27. data/spec/support/filters.rb +10 -0
  28. data/spec/support/queue_subscription_thread_harness.rb +29 -0
  29. data/spec/support/rabbitmqadmin.rb +74 -0
  30. metadata +60 -76
  31. data/Gemfile.lock +0 -76
  32. data/lib/euston-rabbitmq/command_handlers/retry_failed_message.rb +0 -29
  33. data/lib/euston-rabbitmq/event_handlers/message_failure.rb +0 -27
  34. data/lib/euston-rabbitmq/message_buffer.rb +0 -67
  35. data/lib/euston-rabbitmq/message_logger.rb +0 -50
  36. data/lib/euston-rabbitmq/queue.rb +0 -30
  37. data/lib/euston-rabbitmq/read_model/failed_message.rb +0 -36
  38. data/lib/euston-rabbitmq/read_model/message_buffer.rb +0 -57
  39. data/lib/euston-rabbitmq/read_model/message_log.rb +0 -37
  40. data/spec/command_buffer_spec.rb +0 -69
  41. data/spec/event_buffer_spec.rb +0 -69
  42. data/spec/exchange_declaration_spec.rb +0 -28
  43. data/spec/message_failure_spec.rb +0 -77
  44. data/spec/mt_safe_queue_subscription_spec.rb +0 -72
  45. data/spec/safe_queue_subscription_spec.rb +0 -50
  46. data/spec/support/factories.rb +0 -18
data/Gemfile CHANGED
@@ -1,2 +1,4 @@
1
1
  source :rubygems
2
2
  gemspec
3
+
4
+ gem 'safely', :git => 'https://github.com/leemhenson/safely.git', :branch => 'override_strategies'
data/Rakefile CHANGED
@@ -78,27 +78,6 @@ RSpec::Core::RakeTask.new(:spec) do |t|
78
78
  t.rspec_opts = default_rspec_opts
79
79
  end
80
80
 
81
- desc "Resets the testing vhost in rabbitmq"
82
- task :reset_rabbitmq do
83
- vhosts = `rabbitmqctl list_vhosts`.split("\n")
84
- vhosts = trim_array_ends vhosts
85
- vhost = '/euston-rabbitmq-test'
86
-
87
- puts `rabbitmqctl delete_vhost #{vhost}` if vhosts.include? vhost
88
- puts `rabbitmqctl add_vhost #{vhost}`
89
-
90
- users = `rabbitmqctl list_users`.split("\n")
91
- users = trim_array_ends users
92
- users = users.map { |u| u.split("\t").shift }
93
-
94
- user, password = 'euston-rabbitmq-tester', 'password'
95
-
96
- puts `rabbitmqctl delete_user #{user}` if users.include? user
97
- puts `rabbitmqctl add_user #{user} #{password}`
98
- puts `rabbitmqctl set_permissions -p #{vhost} #{user} ".*" ".*" ".*"`
99
- puts `rabbitmqctl set_permissions -p #{vhost} guest ".*" ".*" ".*"` if users.include? 'guest'
100
- end
101
-
102
81
  #############################################################################
103
82
  #
104
83
  # Packaging tasks
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'euston-rabbitmq'
3
- s.version = '1.0.1'
3
+ s.version = '1.0.2'
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']
@@ -11,39 +11,34 @@ Gem::Specification.new do |s|
11
11
  # = MANIFEST =
12
12
  s.files = %w[
13
13
  Gemfile
14
- Gemfile.lock
15
14
  Rakefile
16
15
  euston-rabbitmq.gemspec
17
16
  lib/euston-rabbitmq.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
21
- lib/euston-rabbitmq/command_handlers/retry_failed_message.rb
22
- lib/euston-rabbitmq/constant_loader.rb
23
- lib/euston-rabbitmq/errors.rb
24
- lib/euston-rabbitmq/event_handlers/message_failure.rb
25
- lib/euston-rabbitmq/exchanges.rb
26
- lib/euston-rabbitmq/handler_finder.rb
27
- lib/euston-rabbitmq/handler_reference.rb
28
- lib/euston-rabbitmq/message_buffer.rb
29
- lib/euston-rabbitmq/message_logger.rb
30
- lib/euston-rabbitmq/queue.rb
31
- lib/euston-rabbitmq/queues.rb
32
- lib/euston-rabbitmq/read_model/failed_message.rb
33
- lib/euston-rabbitmq/read_model/message_buffer.rb
34
- lib/euston-rabbitmq/read_model/message_log.rb
35
- lib/euston-rabbitmq/subscriptions/retriable_subscription.rb
17
+ lib/euston-rabbitmq/euston/command_handler_binder.rb
18
+ lib/euston-rabbitmq/euston/errors.rb
19
+ lib/euston-rabbitmq/euston/event_handler_binder.rb
20
+ lib/euston-rabbitmq/euston/exchanges.rb
21
+ lib/euston-rabbitmq/euston/handler_binder.rb
22
+ lib/euston-rabbitmq/euston/queues.rb
23
+ lib/euston-rabbitmq/euston/retrying_subscription.rb
24
+ lib/euston-rabbitmq/rabbitmq_client/queue.rb
25
+ lib/euston-rabbitmq/rabbitmq_client/reactive_message.rb
26
+ lib/euston-rabbitmq/reflection/constant_loader.rb
27
+ lib/euston-rabbitmq/reflection/handler_finder.rb
28
+ lib/euston-rabbitmq/reflection/handler_reference.rb
36
29
  lib/euston-rabbitmq/version.rb
37
- spec/command_buffer_spec.rb
38
- spec/constant_loader_spec.rb
39
- spec/event_buffer_spec.rb
40
- spec/exchange_declaration_spec.rb
41
- spec/handler_finder_spec.rb
42
- spec/message_failure_spec.rb
43
- spec/mt_safe_queue_subscription_spec.rb
44
- spec/safe_queue_subscription_spec.rb
30
+ spec/euston/command_handler_binder_spec.rb
31
+ spec/euston/event_handler_binder_spec.rb
32
+ spec/euston/exchanges_spec.rb
33
+ spec/euston/queues_spec.rb
34
+ spec/euston/retrying_subscription_spec.rb
35
+ spec/rabbitmq_client/queue_spec.rb
36
+ spec/reflection/constant_loader_spec.rb
37
+ spec/reflection/handler_finder_spec.rb
45
38
  spec/spec_helper.rb
46
- spec/support/factories.rb
39
+ spec/support/filters.rb
40
+ spec/support/queue_subscription_thread_harness.rb
41
+ spec/support/rabbitmqadmin.rb
47
42
  ]
48
43
  # = MANIFEST =
49
44
 
@@ -51,27 +46,20 @@ Gem::Specification.new do |s|
51
46
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
52
47
 
53
48
  s.add_dependency 'activesupport', '~> 3.0.0'
54
- s.add_dependency 'euston', '~> 1.0.0'
49
+ s.add_dependency 'euston', '~> 1.0.1'
55
50
  s.add_dependency 'euston-eventstore', '~> 1.0.0'
56
51
  s.add_dependency 'hash-keys', '~> 1.0.0'
57
52
  s.add_dependency 'hollywood', '~> 1.0.0'
53
+ s.add_dependency 'i18n', '~> 0.6.0'
58
54
  s.add_dependency 'require_all', '~> 1.2.0'
59
55
  s.add_dependency 'robustthread', '~> 0.5.2'
60
56
  s.add_dependency 'safely', '~> 0.3.0'
61
57
 
62
58
  if RUBY_PLATFORM.to_s == 'java'
63
- s.add_dependency 'jmongo', '~> 1.0.0'
64
59
  s.add_dependency 'jessica', '~> 1.0.0'
65
- else
66
- s.add_dependency 'amqp', '~> 0.8.0'
67
- s.add_dependency 'bson_ext', '~> 1.3.1'
68
- s.add_dependency 'eventmachine', '~> 0.12.10'
69
- s.add_dependency 'mongo', '~> 1.3.1'
70
- s.add_development_dependency 'evented-spec', '~> 0.9.0'
71
60
  end
72
61
 
73
62
  s.add_development_dependency 'awesome_print', '~> 0.4.0'
74
- s.add_development_dependency 'faker', '~> 1.0.0'
75
63
  s.add_development_dependency 'fuubar', '~> 0.0.0'
76
64
  s.add_development_dependency 'rspec', '~> 2.6.0'
77
65
  end
@@ -9,14 +9,14 @@ module Euston
9
9
 
10
10
  routing_key = "commands.#{reference.name.to_s.underscore}"
11
11
 
12
- EUSTON_LOG.debug "Ensuring routing key exists for queue #{queue_name}: #{routing_key}"
12
+ @log.debug "Ensuring routing key exists for queue #{queue_name}: #{routing_key}"
13
13
 
14
14
  exchange = get_exchange channel, :commands
15
15
  queue.bind exchange, :routing_key => routing_key
16
16
  end
17
17
 
18
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?
19
+ @log.debug "Ensuring command handler queue exists: #{queue_name}" if @command_handler_queue.nil?
20
20
  @command_handler_queue ||= get_queue channel, queue_name
21
21
  end
22
22
  end
@@ -2,4 +2,4 @@ module Euston
2
2
  module RabbitMq
3
3
  class MessageDecodeFailedError < StandardError; end
4
4
  end
5
- end
5
+ end
@@ -6,7 +6,7 @@ module Euston
6
6
  def ensure_bindings_exist_for_reference channel, reference
7
7
  queue_name = reference.name.to_s.underscore
8
8
 
9
- EUSTON_LOG.debug "Ensuring event handler queue exists: #{queue_name}"
9
+ @log.debug "Ensuring event handler queue exists: #{queue_name}"
10
10
 
11
11
  queue = get_queue channel, queue_name
12
12
 
@@ -14,15 +14,15 @@ module Euston
14
14
 
15
15
  methods = reference.handler.public_instance_methods(false)
16
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 }
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
19
 
20
20
  exchange = get_exchange channel, :events
21
21
 
22
22
  methods.uniq.each do |method|
23
23
  routing_key = "events.#{method}"
24
24
 
25
- EUSTON_LOG.debug "Ensuring routing key exists for queue #{queue_name}: #{routing_key}"
25
+ @log.debug "Ensuring routing key exists for queue #{queue_name}: #{routing_key}"
26
26
 
27
27
  queue.bind exchange, :routing_key => routing_key
28
28
  end
@@ -14,4 +14,4 @@ module Euston
14
14
  end
15
15
  end
16
16
  end
17
- end
17
+ end
@@ -4,8 +4,9 @@ module Euston
4
4
  include Euston::RabbitMq::Queues
5
5
  include Euston::RabbitMq::Exchanges
6
6
 
7
- def initialize references
7
+ def initialize references, logger = Euston::NullLogger.instance
8
8
  @references = references
9
+ @log = logger
9
10
  end
10
11
 
11
12
  def ensure_bindings_exist
@@ -10,4 +10,4 @@ module Euston
10
10
  end
11
11
  end
12
12
  end
13
- end
13
+ end
@@ -1,16 +1,17 @@
1
1
  module Euston
2
2
  module RabbitMq
3
- class RetriableSubscription
3
+ class RetryingSubscription
4
4
  include Hollywood
5
5
  include Euston::RabbitMq::Queues
6
6
  include Euston::RabbitMq::Exchanges
7
7
 
8
- def initialize channel, queue_name
8
+ def initialize channel, queue_name, logger = Euston::NullLogger.instance
9
9
  @channel = channel
10
10
  @queue_name = queue_name
11
+ @log = logger
11
12
  end
12
13
 
13
- def attach_queue_hook_listeners
14
+ def subscribe
14
15
  queue.when(:message_decode_failed => method(:log_decode_failure),
15
16
  :message_failed => method(:handle_failure),
16
17
  :message_received => method(:call_handler))
@@ -20,11 +21,11 @@ module Euston
20
21
 
21
22
  private
22
23
 
23
- def call_handler(message)
24
+ def call_handler message
24
25
  callback :message_received, message
25
26
  end
26
27
 
27
- def create_message_failed_message error, failed_message, amqp_header
28
+ def create_message_failed_message error, failed_message, reactive_message
28
29
  {
29
30
  :headers =>
30
31
  {
@@ -37,14 +38,14 @@ module Euston
37
38
  :body =>
38
39
  {
39
40
  :message => failed_message,
40
- :routing_key => amqp_header.method.routing_key,
41
+ :routing_key => reactive_message.method.routing_key,
41
42
  :error => error.message,
42
43
  :backtrace => error.backtrace
43
44
  }
44
45
  }
45
46
  end
46
47
 
47
- def handle_failure message, error, amqp_header
48
+ def handle_failure message, error, reactive_message
48
49
  failures = message[:failures] || 0
49
50
  failures = failures + 1
50
51
  message[:failures] = failures
@@ -54,38 +55,38 @@ module Euston
54
55
  debug_message = "Message failed, out of retries"
55
56
 
56
57
  message.delete :failures
57
- message = create_message_failed_message error, message, amqp_header
58
+ message = create_message_failed_message error, message, reactive_message
58
59
 
59
60
  options = { :key => 'events.message_failed' }
60
61
  exchange = :events
61
62
  else
62
63
  debug_message = "Message failed, retrying"
63
64
 
64
- options = { :key => amqp_header.method.routing_key }
65
- exchange = amqp_header.method.routing_key.split('.').first.to_sym
65
+ options = { :key => reactive_message.method.routing_key }
66
+ exchange = reactive_message.method.routing_key.split('.').first.to_sym
66
67
  end
67
68
 
68
69
  options = default_publish_options.merge options
69
70
  exchange = get_exchange @channel, exchange
70
71
  message = ActiveSupport::JSON.encode message
71
72
 
72
- EUSTON_LOG.debug "#{debug_message}: #{message}"
73
+ @log.debug "#{debug_message}: #{message}"
73
74
 
74
75
  exchange.publish message, options
75
76
 
76
- amqp_header.ack
77
+ reactive_message.ack
77
78
  rescue StandardError => e
78
- amqp_header.reject :requeue => true
79
+ reactive_message.reject :requeue => true
79
80
  raise e
80
81
  end
81
82
  end
82
83
 
83
84
  def log_decode_failure message, error
84
85
  text = "A handler queue subscription failed. [Error] #{error.message} [Payload] #{message}"
85
- err = Euston::RabbitMq::MessageDecodeFailedError.new text
86
- err.set_backtrace error.backtrace
86
+ error = Euston::RabbitMq::MessageDecodeFailedError.new text
87
+ error.set_backtrace error.backtrace
87
88
 
88
- Safely.report! err
89
+ raise error
89
90
  end
90
91
 
91
92
  def queue
@@ -0,0 +1,70 @@
1
+ class RabbitMQClient
2
+ class Queue
3
+ include Hollywood
4
+
5
+ attr_writer :timeout
6
+
7
+ def delivery_timeout
8
+ @timeout ||= 500
9
+ end
10
+
11
+ def safe_subscribe
12
+ _consumer = self.consumer
13
+
14
+ until Thread.current[:stop] do
15
+ safe_subscribe_with_timeout(_consumer, self.delivery_timeout)
16
+ end
17
+ end
18
+
19
+ def safe_handle_message reactive_message
20
+ begin
21
+ message = parse_json reactive_message.body
22
+
23
+ begin
24
+ callback :message_received, message
25
+ reactive_message.ack!
26
+ rescue Euston::EventStore::ConcurrencyError
27
+ reactive_message.reject! true #requeue
28
+ rescue => e
29
+ callback :message_failed, message, e, reactive_message
30
+ Safely.report! e
31
+ end
32
+ rescue => e
33
+ callback :message_decode_failed, reactive_message.body, e
34
+ reactive_message.ack!
35
+ Safely.report! e
36
+ end
37
+ end
38
+
39
+ def consumer auto_ack = false
40
+ consumer = QueueingConsumer.new @channel
41
+ @channel.basic_consume @name, auto_ack, consumer
42
+ consumer
43
+ end
44
+
45
+ def safe_subscribe_with_timeout consumer, timeout = 500
46
+ loop do
47
+ delivery = nil
48
+ begin
49
+ delivery = consumer.next_delivery timeout
50
+ rescue NativeException => e
51
+ Thread.current[:exception] = e
52
+ break
53
+ end
54
+
55
+ break if delivery.nil?
56
+
57
+ reactive_message = ReactiveMessage.new @channel, delivery, String.from_java_bytes(delivery.get_body)
58
+ safe_handle_message reactive_message
59
+
60
+ @channel.basic_ack(delivery.envelope.delivery_tag, false) if reactive_message.should_acknowledge?
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ def parse_json json
67
+ JSON.parse json, :symbolize_names => true
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,15 @@
1
+ class RabbitMQClient
2
+ class ReactiveMessage
3
+ def reject opts = {}
4
+ self.reject!(opts.fetch :requeue, true)
5
+ end
6
+
7
+ def ack multiple = false
8
+ self.ack!
9
+ end
10
+
11
+ def method
12
+ self.envelope
13
+ end
14
+ end
15
+ end
@@ -1,5 +1,5 @@
1
1
  module Euston
2
2
  module RabbitMq
3
- VERSION = "1.0.1"
3
+ VERSION = "1.0.2"
4
4
  end
5
5
  end
@@ -1,30 +1,16 @@
1
- require 'require_all'
2
- require 'active_support/core_ext/hash/keys'
3
1
  require 'active_support/core_ext/string/inflections'
4
2
  require 'active_support/json'
5
3
  require 'active_support/ordered_hash'
6
- require 'robustthread'
7
-
8
- if RUBY_PLATFORM == 'java'
9
- require 'jessica'
10
- else
11
- require 'eventmachine'
12
- require 'amqp'
13
- end
14
-
15
4
  require 'hash-keys'
16
5
  require 'hollywood'
6
+ require 'i18n'
7
+ require 'jessica' if RUBY_PLATFORM == 'java'
8
+ require 'require_all'
9
+ require 'safely'
10
+
17
11
  require 'euston'
18
12
  require 'euston-eventstore'
19
13
 
20
- require_rel 'euston-rabbitmq/exchanges.rb'
21
- require_rel 'euston-rabbitmq/queues.rb'
22
- require_rel 'euston-rabbitmq/**/*.rb'
23
-
24
- module Euston
25
- module RabbitMq
26
- class << self
27
- attr_accessor :event_store, :event_store_mongodb, :read_model_mongodb
28
- end
29
- end
30
- end
14
+ require_rel 'euston-rabbitmq/reflection'
15
+ require_rel 'euston-rabbitmq/rabbitmq_client'
16
+ require_rel 'euston-rabbitmq/euston'