euston-daemons 1.1.0-java → 1.2.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. data/Gemfile +1 -0
  2. data/euston-daemons.gemspec +27 -52
  3. data/lib/euston-daemons/euston/daemon.rb +7 -1
  4. data/lib/euston-daemons/euston/daemon_component.rb +9 -49
  5. data/lib/euston-daemons/euston/daemon_component_host.rb +66 -0
  6. data/lib/euston-daemons/euston/daemon_environment.rb +10 -5
  7. data/lib/euston-daemons/euston/exceptions.rb +9 -0
  8. data/lib/euston-daemons/euston/stopwatch.rb +15 -0
  9. data/lib/euston-daemons/pipeline/config/environment.rb +74 -0
  10. data/lib/euston-daemons/pipeline/lib/command_logger/component.rb +54 -0
  11. data/lib/euston-daemons/pipeline/lib/command_logger/log.rb +31 -0
  12. data/lib/euston-daemons/pipeline/lib/command_processor/component.rb +50 -0
  13. data/lib/euston-daemons/pipeline/lib/command_processor/default_handlers/retry_failed_message.rb +34 -0
  14. data/lib/euston-daemons/pipeline/lib/command_processor/failed_message.rb +36 -0
  15. data/lib/euston-daemons/pipeline/lib/daemon.rb +77 -0
  16. data/lib/euston-daemons/pipeline/lib/event_processor/component.rb +67 -0
  17. data/lib/euston-daemons/pipeline/lib/event_processor/default_handlers/message_failure.rb +30 -0
  18. data/lib/euston-daemons/pipeline/lib/event_store_dispatcher/component.rb +68 -0
  19. data/lib/euston-daemons/pipeline/lib/message_buffer/buffer.rb +85 -0
  20. data/lib/euston-daemons/pipeline/lib/message_buffer/component.rb +59 -0
  21. data/lib/euston-daemons/pipeline/lib/snapshotter/component.rb +48 -0
  22. data/lib/euston-daemons/pipeline/rake_task.rb +45 -0
  23. data/lib/euston-daemons/rake_task.rb +40 -19
  24. data/lib/euston-daemons/rake_tasks.rb +1 -3
  25. data/lib/euston-daemons/version.rb +1 -1
  26. data/lib/euston-daemons.rb +3 -1
  27. data/spec/daemons/{command_handler_spec.rb → command_processor_spec.rb} +3 -3
  28. data/spec/daemons/{event_handler_spec.rb → event_processor_spec.rb} +2 -2
  29. data/spec/daemons/{command_buffer_publisher_spec.rb → message_buffer_spec.rb} +19 -23
  30. data/spec/daemons/{snapshot_client_spec.rb → snapshotter_spec.rb} +3 -5
  31. data/spec/spec_helper.rb +23 -9
  32. data/spec/support/filters.rb +4 -5
  33. metadata +73 -88
  34. data/lib/euston-daemons/command_processor_daemon/config/environment.rb +0 -34
  35. data/lib/euston-daemons/command_processor_daemon/lib/clients/command_handler.rb +0 -37
  36. data/lib/euston-daemons/command_processor_daemon/lib/command_handlers/retry_failed_message.rb +0 -35
  37. data/lib/euston-daemons/command_processor_daemon/lib/daemon.rb +0 -22
  38. data/lib/euston-daemons/command_processor_daemon/lib/mongo_models/failed_message.rb +0 -34
  39. data/lib/euston-daemons/command_processor_daemon/rake_task.rb +0 -36
  40. data/lib/euston-daemons/euston/daemon_client.rb +0 -24
  41. data/lib/euston-daemons/event_processor_daemon/config/environment.rb +0 -36
  42. data/lib/euston-daemons/event_processor_daemon/lib/clients/event_handler.rb +0 -42
  43. data/lib/euston-daemons/event_processor_daemon/lib/daemon.rb +0 -24
  44. data/lib/euston-daemons/event_processor_daemon/lib/event_handlers/message_failure.rb +0 -27
  45. data/lib/euston-daemons/event_processor_daemon/rake_task.rb +0 -39
  46. data/lib/euston-daemons/message_buffer_daemon/config/environment.rb +0 -42
  47. data/lib/euston-daemons/message_buffer_daemon/lib/clients/command_buffer_cleanup.rb +0 -9
  48. data/lib/euston-daemons/message_buffer_daemon/lib/clients/command_buffer_publisher.rb +0 -9
  49. data/lib/euston-daemons/message_buffer_daemon/lib/clients/command_logger.rb +0 -9
  50. data/lib/euston-daemons/message_buffer_daemon/lib/clients/euston_exchange_accessors.rb +0 -15
  51. data/lib/euston-daemons/message_buffer_daemon/lib/clients/event_buffer_cleanup.rb +0 -9
  52. data/lib/euston-daemons/message_buffer_daemon/lib/clients/event_buffer_publisher.rb +0 -9
  53. data/lib/euston-daemons/message_buffer_daemon/lib/clients/event_logger.rb +0 -9
  54. data/lib/euston-daemons/message_buffer_daemon/lib/clients/event_store_dispatcher.rb +0 -25
  55. data/lib/euston-daemons/message_buffer_daemon/lib/clients/message_buffer_cleanup.rb +0 -52
  56. data/lib/euston-daemons/message_buffer_daemon/lib/clients/message_buffer_publisher.rb +0 -37
  57. data/lib/euston-daemons/message_buffer_daemon/lib/clients/message_logger.rb +0 -45
  58. data/lib/euston-daemons/message_buffer_daemon/lib/clients/mongo_model_accessors.rb +0 -21
  59. data/lib/euston-daemons/message_buffer_daemon/lib/daemon.rb +0 -17
  60. data/lib/euston-daemons/message_buffer_daemon/lib/mongo_models/command_buffer.rb +0 -11
  61. data/lib/euston-daemons/message_buffer_daemon/lib/mongo_models/command_log.rb +0 -11
  62. data/lib/euston-daemons/message_buffer_daemon/lib/mongo_models/event_buffer.rb +0 -11
  63. data/lib/euston-daemons/message_buffer_daemon/lib/mongo_models/event_log.rb +0 -11
  64. data/lib/euston-daemons/message_buffer_daemon/lib/mongo_models/message_buffer.rb +0 -57
  65. data/lib/euston-daemons/message_buffer_daemon/lib/mongo_models/message_log.rb +0 -29
  66. data/lib/euston-daemons/message_buffer_daemon/rake_task.rb +0 -32
  67. data/lib/euston-daemons/snapshot_daemon/lib/clients/snapshotter.rb +0 -43
  68. data/sample/Rakefile +0 -63
  69. data/sample/amqp_config.yml +0 -14
  70. data/sample/command_handlers.rb +0 -17
  71. data/sample/command_processor_daemon_config.yml +0 -9
  72. data/sample/event_handlers.rb +0 -21
  73. data/sample/event_processor_daemon_config.yml +0 -8
  74. data/sample/message_buffer_daemon_config.yml +0 -8
  75. data/sample/mongoid_config.yml +0 -13
  76. data/sample/pids/.placeholder +0 -0
data/Gemfile CHANGED
@@ -4,3 +4,4 @@ gemspec
4
4
  gem 'cranky', :git => 'https://github.com/leemhenson/cranky.git', :branch => 'hashes'
5
5
  gem 'ffaker', :git => 'https://github.com/leemhenson/ffaker.git', :branch => 'countries'
6
6
  gem 'safely', :git => 'https://github.com/leemhenson/safely.git', :branch => 'override_strategies'
7
+ gem 'hot_bunnies', :git => 'https://github.com/ruby-amqp/hot_bunnies.git'
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'euston-daemons'
3
- s.version = '1.1.0'
3
+ s.version = '1.2.0'
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,59 +15,33 @@ Gem::Specification.new do |s|
15
15
  Rakefile
16
16
  euston-daemons.gemspec
17
17
  lib/euston-daemons.rb
18
- lib/euston-daemons/command_processor_daemon/config/environment.rb
19
- lib/euston-daemons/command_processor_daemon/lib/clients/command_handler.rb
20
- lib/euston-daemons/command_processor_daemon/lib/command_handlers/retry_failed_message.rb
21
- lib/euston-daemons/command_processor_daemon/lib/daemon.rb
22
- lib/euston-daemons/command_processor_daemon/lib/mongo_models/failed_message.rb
23
- lib/euston-daemons/command_processor_daemon/rake_task.rb
24
18
  lib/euston-daemons/euston/daemon.rb
25
- lib/euston-daemons/euston/daemon_client.rb
26
19
  lib/euston-daemons/euston/daemon_component.rb
20
+ lib/euston-daemons/euston/daemon_component_host.rb
27
21
  lib/euston-daemons/euston/daemon_environment.rb
28
- lib/euston-daemons/event_processor_daemon/config/environment.rb
29
- lib/euston-daemons/event_processor_daemon/lib/clients/event_handler.rb
30
- lib/euston-daemons/event_processor_daemon/lib/daemon.rb
31
- lib/euston-daemons/event_processor_daemon/lib/event_handlers/message_failure.rb
32
- lib/euston-daemons/event_processor_daemon/rake_task.rb
33
- lib/euston-daemons/message_buffer_daemon/config/environment.rb
34
- lib/euston-daemons/message_buffer_daemon/lib/clients/command_buffer_cleanup.rb
35
- lib/euston-daemons/message_buffer_daemon/lib/clients/command_buffer_publisher.rb
36
- lib/euston-daemons/message_buffer_daemon/lib/clients/command_logger.rb
37
- lib/euston-daemons/message_buffer_daemon/lib/clients/euston_exchange_accessors.rb
38
- lib/euston-daemons/message_buffer_daemon/lib/clients/event_buffer_cleanup.rb
39
- lib/euston-daemons/message_buffer_daemon/lib/clients/event_buffer_publisher.rb
40
- lib/euston-daemons/message_buffer_daemon/lib/clients/event_logger.rb
41
- lib/euston-daemons/message_buffer_daemon/lib/clients/event_store_dispatcher.rb
42
- lib/euston-daemons/message_buffer_daemon/lib/clients/message_buffer_cleanup.rb
43
- lib/euston-daemons/message_buffer_daemon/lib/clients/message_buffer_publisher.rb
44
- lib/euston-daemons/message_buffer_daemon/lib/clients/message_logger.rb
45
- lib/euston-daemons/message_buffer_daemon/lib/clients/mongo_model_accessors.rb
46
- lib/euston-daemons/message_buffer_daemon/lib/daemon.rb
47
- lib/euston-daemons/message_buffer_daemon/lib/mongo_models/command_buffer.rb
48
- lib/euston-daemons/message_buffer_daemon/lib/mongo_models/command_log.rb
49
- lib/euston-daemons/message_buffer_daemon/lib/mongo_models/event_buffer.rb
50
- lib/euston-daemons/message_buffer_daemon/lib/mongo_models/event_log.rb
51
- lib/euston-daemons/message_buffer_daemon/lib/mongo_models/message_buffer.rb
52
- lib/euston-daemons/message_buffer_daemon/lib/mongo_models/message_log.rb
53
- lib/euston-daemons/message_buffer_daemon/rake_task.rb
22
+ lib/euston-daemons/euston/exceptions.rb
23
+ lib/euston-daemons/euston/stopwatch.rb
24
+ lib/euston-daemons/pipeline/config/environment.rb
25
+ lib/euston-daemons/pipeline/lib/command_logger/component.rb
26
+ lib/euston-daemons/pipeline/lib/command_logger/log.rb
27
+ lib/euston-daemons/pipeline/lib/command_processor/component.rb
28
+ lib/euston-daemons/pipeline/lib/command_processor/default_handlers/retry_failed_message.rb
29
+ lib/euston-daemons/pipeline/lib/command_processor/failed_message.rb
30
+ lib/euston-daemons/pipeline/lib/daemon.rb
31
+ lib/euston-daemons/pipeline/lib/event_processor/component.rb
32
+ lib/euston-daemons/pipeline/lib/event_processor/default_handlers/message_failure.rb
33
+ lib/euston-daemons/pipeline/lib/event_store_dispatcher/component.rb
34
+ lib/euston-daemons/pipeline/lib/message_buffer/buffer.rb
35
+ lib/euston-daemons/pipeline/lib/message_buffer/component.rb
36
+ lib/euston-daemons/pipeline/lib/snapshotter/component.rb
37
+ lib/euston-daemons/pipeline/rake_task.rb
54
38
  lib/euston-daemons/rake_task.rb
55
39
  lib/euston-daemons/rake_tasks.rb
56
- lib/euston-daemons/snapshot_daemon/lib/clients/snapshotter.rb
57
40
  lib/euston-daemons/version.rb
58
- sample/Rakefile
59
- sample/amqp_config.yml
60
- sample/command_handlers.rb
61
- sample/command_processor_daemon_config.yml
62
- sample/event_handlers.rb
63
- sample/event_processor_daemon_config.yml
64
- sample/message_buffer_daemon_config.yml
65
- sample/mongoid_config.yml
66
- sample/pids/.placeholder
67
- spec/daemons/command_buffer_publisher_spec.rb
68
- spec/daemons/command_handler_spec.rb
69
- spec/daemons/event_handler_spec.rb
70
- spec/daemons/snapshot_client_spec.rb
41
+ spec/daemons/command_processor_spec.rb
42
+ spec/daemons/event_processor_spec.rb
43
+ spec/daemons/message_buffer_spec.rb
44
+ spec/daemons/snapshotter_spec.rb
71
45
  spec/spec_helper.rb
72
46
  spec/support/factories/commands.rb
73
47
  spec/support/factories/commit.rb
@@ -87,15 +61,16 @@ Gem::Specification.new do |s|
87
61
  s.add_dependency 'activemodel', '~> 3.0.0'
88
62
  s.add_dependency 'activesupport', '~> 3.0.0'
89
63
  s.add_dependency 'erb-yaml', '~> 1.0.0'
90
- s.add_dependency 'euston', '~> 1.1.0'
91
- s.add_dependency 'euston-eventstore', '~> 1.1.0'
92
- s.add_dependency 'euston-rabbitmq', '~> 1.1.0'
64
+ s.add_dependency 'euston', '~> 1.2.0'
65
+ s.add_dependency 'euston-eventstore', '~> 1.2.0'
66
+ s.add_dependency 'euston-rabbitmq', '~> 1.2.0'
93
67
  s.add_dependency 'hollywood', '~> 1.0.0'
94
68
  s.add_dependency 'i18n', '~> 0.5.0'
69
+ s.add_dependency 'macaddr', '~> 1.4.0'
95
70
  s.add_dependency 'safely', '~> 0.3.0'
96
71
 
97
72
  if RUBY_PLATFORM.to_s == 'java'
98
- s.add_dependency 'jessica', '~> 1.0.0'
73
+ s.add_dependency 'hot_bunnies', '~> 1.3.0.pre1'
99
74
  s.add_dependency 'jmongo', '~> 1.1.0'
100
75
  end
101
76
 
@@ -16,6 +16,7 @@ module Euston
16
16
  start_components
17
17
  wait_for_shutdown_event
18
18
  stop_components
19
+ post_shutdown_cleanup
19
20
  report_shutdown_reasons
20
21
  end
21
22
 
@@ -26,10 +27,15 @@ module Euston
26
27
  end
27
28
 
28
29
  def register_component name, klass
29
- component = Euston::DaemonComponent.new @log, name, klass, self
30
+ component = Euston::DaemonComponentHost.new @log, name, klass, self
30
31
  component.when(:fatal_error_in_component => method(:shutdown))
31
32
 
32
33
  @components << component
34
+ component
35
+ end
36
+
37
+ def post_shutdown_cleanup
38
+ # virtual
33
39
  end
34
40
 
35
41
  def register_components
@@ -1,65 +1,25 @@
1
1
  module Euston
2
2
  class DaemonComponent
3
3
  include Hollywood
4
+ include Daemons::Exceptions
4
5
 
5
- def initialize logger, name, client, owner
6
- @log, @name, @client, @owner = logger, name, client, owner
7
- end
8
-
9
- attr_reader :name
10
-
11
- def start
12
- @thread = Thread.new do
13
- while_thread_is_running do
14
- begin
15
- @client.run
16
- rescue => e
17
- Thread.current[:exception] = e
18
- end
19
-
20
- report_exceptions
21
- end
22
- end
6
+ def run
7
+ next_iteration unless stopped
23
8
  end
24
9
 
25
10
  def stop
26
- @client.stop
27
- @thread[:stop] = true
28
- end
29
-
30
- def thread_state
31
- @thread.status
11
+ @stopped = true
12
+ @channel.close unless @channel.nil? || !@channel.respond_to?(:close)
32
13
  end
33
14
 
34
15
  private
35
16
 
36
- def report_exceptions
37
- exception = Thread.current[:exception]
38
-
39
- unless exception.nil? || exception.to_s =~ /clean channel shutdown/
40
- if exception.respond_to? :cause # its a serious (Java?) exception
41
- Thread.current[:stop] = true
42
- callback :fatal_error_in_component, exception
43
- else
44
- Safely.report! exception
45
- end
46
- end
47
- end
48
-
49
- def thread_is_stopping?
50
- Thread.current[:stop]
17
+ def next_iteration
18
+ # abstract
51
19
  end
52
20
 
53
- def wait_time
54
- @wait_time ||= 0.2
55
- end
56
-
57
- def while_thread_is_running
58
- until thread_is_stopping? do
59
- yield
60
-
61
- sleep wait_time
62
- end
21
+ def stopped
22
+ @stopped ||= false
63
23
  end
64
24
  end
65
25
  end
@@ -0,0 +1,66 @@
1
+ module Euston
2
+ class DaemonComponentHost
3
+ include Hollywood
4
+ include Daemons::Exceptions
5
+
6
+ def initialize logger, name, client, owner
7
+ @log, @name, @client, @owner = logger, name, client, owner
8
+ end
9
+
10
+ attr_reader :name
11
+ attr_writer :wait_time
12
+
13
+ def start
14
+ @thread = Thread.new do
15
+ while_thread_is_running do
16
+ begin
17
+ @client.run
18
+ rescue => e
19
+ Thread.current[:exception] = e
20
+ end
21
+
22
+ report_exceptions
23
+ end
24
+ end
25
+ end
26
+
27
+ def stop
28
+ @client.stop
29
+ @thread[:stop] = true
30
+ end
31
+
32
+ def thread_state
33
+ @thread.status
34
+ end
35
+
36
+ private
37
+
38
+ def report_exceptions
39
+ exception = Thread.current[:exception]
40
+ return if exception.nil? || ignorable_exception?(exception)
41
+
42
+ if exception.respond_to? :cause # its a serious (Java?) exception
43
+ Thread.current[:stop] = true
44
+ callback :fatal_error_in_component, exception
45
+ else
46
+ Safely.report! exception
47
+ end
48
+ end
49
+
50
+ def thread_is_stopping?
51
+ Thread.current[:stop]
52
+ end
53
+
54
+ def wait_time
55
+ @wait_time ||= 0.2
56
+ end
57
+
58
+ def while_thread_is_running
59
+ until thread_is_stopping? do
60
+ yield
61
+
62
+ sleep wait_time
63
+ end
64
+ end
65
+ end
66
+ end
@@ -11,7 +11,11 @@ module Euston
11
11
  private
12
12
 
13
13
  def setup_amqp config
14
- AMQP.settings.merge! config
14
+ class << self.class
15
+ attr_accessor :amqp_connection
16
+ end
17
+
18
+ self.class.amqp_connection = HotBunnies.connect config
15
19
  end
16
20
 
17
21
  def setup_euston event_store_database_name
@@ -29,14 +33,15 @@ module Euston
29
33
  end
30
34
 
31
35
  def setup_mongo config
32
- connection = Mongo::Connection.new config[:host], config[:port], :safe => config[:safe], :logger => @logger
36
+ # logger arg will not work until jmongo forwards it correctly
37
+ connection = Mongo::Connection.from_uri config[:uri], :logger => @logger
33
38
 
34
39
  class << self.class
35
- attr_accessor :event_store_mongodb, :read_model_mongodb
40
+ attr_accessor :event_store_mongodb, :projections_mongodb
36
41
  end
37
42
 
38
- self.class.event_store_mongodb = Mongo::DB.new config[:event_store_database], connection
39
- self.class.read_model_mongodb = Mongo::DB.new config[:read_model_database], connection
43
+ self.class.event_store_mongodb = Mongo::DB.new config[:event_store_database], connection
44
+ self.class.projections_mongodb = Mongo::DB.new config[:projections_database], connection
40
45
  end
41
46
 
42
47
  def setup_safely hoptoad_key
@@ -0,0 +1,9 @@
1
+ module Euston
2
+ module Daemons
3
+ module Exceptions
4
+ def ignorable_exception? exception
5
+ exception.to_s =~ /clean channel shutdown|clean connection shutdown/
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,15 @@
1
+ module Euston
2
+ class Stopwatch
3
+ include Hollywood
4
+
5
+ def time decimal_places = 3, &block
6
+ start = Time.now.to_f
7
+ result = yield block
8
+ finish = Time.now.to_f
9
+ elapsed = finish - start
10
+ elapsed = elapsed.round(decimal_places) unless decimal_places.nil?
11
+ callback :finished, elapsed
12
+ result
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,74 @@
1
+ require 'i18n'
2
+ require 'hot_bunnies'
3
+ require 'macaddr'
4
+ require 'euston-rabbitmq'
5
+
6
+ require 'euston-daemons/pipeline/lib/command_processor/failed_message'
7
+ require 'euston-daemons/pipeline/lib/command_processor/default_handlers/retry_failed_message'
8
+ require 'euston-daemons/pipeline/lib/command_processor/component'
9
+ require 'euston-daemons/pipeline/lib/command_logger/log'
10
+ require 'euston-daemons/pipeline/lib/command_logger/component'
11
+ require 'euston-daemons/pipeline/lib/event_processor/default_handlers/message_failure'
12
+ require 'euston-daemons/pipeline/lib/event_processor/component'
13
+ require 'euston-daemons/pipeline/lib/event_store_dispatcher/component'
14
+ require 'euston-daemons/pipeline/lib/message_buffer/buffer'
15
+ require 'euston-daemons/pipeline/lib/message_buffer/component'
16
+ require 'euston-daemons/pipeline/lib/snapshotter/component'
17
+ require 'euston-daemons/pipeline/lib/daemon'
18
+
19
+ module Euston
20
+ module Daemons
21
+ module Pipeline
22
+ class DaemonEnvironment < Euston::DaemonEnvironment
23
+ class << self
24
+ attr_accessor :command_processors,
25
+ :command_handler_namespaces,
26
+ :command_loggers,
27
+ :event_handler_namespaces,
28
+ :event_processors,
29
+ :event_store_dispatchers,
30
+ :event_store_dispatcher_wait_time,
31
+ :message_buffers,
32
+ :message_buffer_wait_time,
33
+ :snapshotters,
34
+ :snapshotter_wait_time,
35
+ :snapshot_threshold
36
+ end
37
+
38
+ def initialize data
39
+ @logger = data[:logger]
40
+ @daemon_config = data[:daemon_config]
41
+ @i18n_locales_path = @daemon_config[:i18n_locales_path]
42
+
43
+ @amqp_config = ErbYaml.read data[:amqp_config_path], data[:environment]
44
+ @mongo_config = ErbYaml.read data[:mongo_config_path], data[:environment]
45
+
46
+ self.class.command_handler_namespaces = data[:command_handler_namespaces]
47
+ self.class.event_handler_namespaces = data[:event_handler_namespaces]
48
+
49
+ self.class.command_processors = @daemon_config[:command_processors].to_i
50
+ self.class.command_loggers = @daemon_config[:command_loggers].to_i
51
+ self.class.event_processors = @daemon_config[:event_processors].to_i
52
+ self.class.event_store_dispatchers = @daemon_config[:event_store_dispatchers].to_i
53
+ self.class.event_store_dispatcher_wait_time = @daemon_config[:event_store_dispatcher_wait_time].to_f
54
+ self.class.message_buffers = @daemon_config[:message_buffers].to_i
55
+ self.class.message_buffer_wait_time = @daemon_config[:message_buffer_wait_time].to_f
56
+ self.class.snapshotters = @daemon_config[:snapshotters].to_i
57
+ self.class.snapshotter_wait_time = @daemon_config[:snapshotter_wait_time].to_f
58
+ self.class.snapshot_threshold = @daemon_config[:snapshot_threshold].to_i
59
+ end
60
+
61
+ def setup
62
+ setup_safely @daemon_config[:hoptoad_key]
63
+ setup_amqp @amqp_config
64
+ setup_mongo @mongo_config
65
+ setup_euston @mongo_config[:event_store_database]
66
+
67
+ I18n.load_path += Dir[@i18n_locales_path] unless @i18n_locales_path.nil?
68
+
69
+ self.class
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,54 @@
1
+ module Euston
2
+ module Daemons
3
+ module Pipeline
4
+ module CommandLogger
5
+ class Component < Euston::DaemonComponent
6
+ extend RabbitMq::Exchanges
7
+ extend RabbitMq::Queues
8
+
9
+ def initialize channel, id = 1, logger = Euston::NullLogger.instance
10
+ @id = id
11
+ @log = logger
12
+ @channel = channel
13
+ @channel.prefetch = 1
14
+ @command_log = Log.new DaemonEnvironment.event_store_mongodb
15
+ @exchange = self.class.get_exchange channel, :commands
16
+ @queue = self.class.get_queue channel, @command_log.name
17
+ @queue.bind @exchange, :routing_key => "#{@exchange.name}.#"
18
+
19
+ @queue.when(:message_decode_failed => method(:log_failure),
20
+ :message_failed => method(:message_failed),
21
+ :message_received => method(:write_message_to_log))
22
+
23
+ @consumer = @queue.consumer
24
+ end
25
+
26
+ private
27
+
28
+ def log_failure message, error
29
+ return if ignorable_exception? error
30
+
31
+ text = "Command logger #{@id} failed.\n [Error] #{error.message}\n [Payload] #{message}"
32
+ err = Euston::RabbitMq::MessageDecodeFailedError.new text
33
+ err.set_backtrace error.backtrace
34
+
35
+ Safely.report! err
36
+ end
37
+
38
+ def message_failed message, error, reactive_message
39
+ log_failure message, error
40
+ reactive_message.ack
41
+ end
42
+
43
+ def next_iteration
44
+ @queue.safe_subscribe_with_timeout @consumer
45
+ end
46
+
47
+ def write_message_to_log message
48
+ @command_log.write_command message
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,31 @@
1
+ module Euston
2
+ module Daemons
3
+ module Pipeline
4
+ module CommandLogger
5
+ class Log
6
+ def initialize mongodb
7
+ @name = 'command_log'
8
+ mongodb.create_collection @name unless mongodb.collection_names.include? @name
9
+
10
+ @collection = mongodb.collection @name
11
+ end
12
+
13
+ attr_reader :name
14
+
15
+ def write_command command
16
+ timestamp = Time.now.to_f
17
+
18
+ doc = { '_id' => command[:headers][:id],
19
+ 'type' => command[:headers][:type],
20
+ 'version' => command[:headers][:version],
21
+ 'timestamp' => timestamp,
22
+ 'timestamp_for_humans' => Time.at(timestamp),
23
+ 'json' => ActiveSupport::JSON.encode(command) }
24
+
25
+ @collection.insert doc
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,50 @@
1
+ module Euston
2
+ module Daemons
3
+ module Pipeline
4
+ module CommandProcessor
5
+ class Component < Euston::DaemonComponent
6
+ include Euston::CommandHandlerPrivateMethodNames
7
+
8
+ def initialize channel, handlers, id = 1, logger = Euston::NullLogger.instance
9
+ @channel = channel
10
+ @channel.prefetch = 1
11
+ @handlers = handlers
12
+ @id = id
13
+ @log = logger
14
+ @process_method = method(:process_message)
15
+ @stopwatch = Stopwatch.new.when(:finished => method(:log_elapsed_time))
16
+ end
17
+
18
+ private
19
+
20
+ def next_iteration
21
+ Euston::RabbitMq::RetryingSubscription.new(@channel, :command_handlers, @log)
22
+ .when(:message_received => @process_method)
23
+ .subscribe
24
+ end
25
+
26
+ def process_message message
27
+ @stopwatch.time do
28
+ command_headers = CommandHeaders.from_hash(message[:headers]).freeze
29
+ command_body = message[:body].freeze
30
+
31
+ handler_type = command_headers.type.to_s.camelize.to_sym
32
+ reference = @handlers.find { |reference| reference.name == handler_type }
33
+
34
+ if reference.nil?
35
+ Euston::CommandBus.publish command_headers, command_body, @log
36
+ else
37
+ handler_method_name = self.class.command_handler_method_name command_headers.version
38
+ reference.handler.new.send handler_method_name, command_headers, command_body
39
+ end
40
+ end
41
+ end
42
+
43
+ def log_elapsed_time elapsed_time
44
+ @log.debug "Command handler client #{@id} processed a message in #{elapsed_time} sec(s)"
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,34 @@
1
+ module Euston
2
+ module Daemons
3
+ module Pipeline
4
+ module CommandProcessor
5
+ module DefaultHandlers
6
+ class RetryFailedMessage
7
+ include Euston::CommandHandler
8
+
9
+ version 1 do |headers, command|
10
+ failed_messages = FailedMessage.new DaemonEnvironment.event_store_mongodb
11
+ message = failed_messages.get_by_id command[:id]
12
+
13
+ unless message.nil?
14
+ routing_key = message['routing_key']
15
+ exchange = routing_key.split('.').first
16
+
17
+ headers = message['headers'].merge(:id => command[:id],
18
+ :type => message['type'],
19
+ :version => message['version'] )
20
+
21
+ retry_message = { :headers => headers, :body => message['body'] }
22
+
23
+ buffer = MessageBuffer::Buffer.new DaemonEnvironment.event_store_mongodb
24
+ buffer.enqueue exchange, retry_message
25
+
26
+ failed_messages.remove_by_id command[:id]
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,36 @@
1
+ module Euston
2
+ module Daemons
3
+ module Pipeline
4
+ module CommandProcessor
5
+ class FailedMessage
6
+ def initialize mongodb
7
+ name = 'failed_messages'
8
+ mongodb.create_collection name unless mongodb.collection_names.include? name
9
+
10
+ @collection = mongodb.collection name
11
+ @collection.ensure_index [ ['failure_timestamp', Mongo::ASCENDING] ], :unique => false, :name => 'failed_messages_failure_timestamp_index'
12
+ end
13
+
14
+ def get_by_id id
15
+ @collection.find_one({ '_id' => id })
16
+ end
17
+
18
+ def find_all
19
+ @collection.find({}, { :sort => [ 'failure_timestamp', Mongo::DESCENDING ] })
20
+ end
21
+
22
+ def log_failure failure
23
+ failure.recursive_stringify_keys!
24
+ failure['_id'] = failure.delete 'message_id'
25
+
26
+ @collection.save(failure, :safe => { :fsync => true })
27
+ end
28
+
29
+ def remove_by_id id
30
+ @collection.remove({ '_id' => id }, :safe => { :fsync => true })
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end