euston-daemons 1.0.4-java → 1.1.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. data/Gemfile +3 -1
  2. data/Rakefile +2 -3
  3. data/euston-daemons.gemspec +61 -26
  4. data/lib/euston-daemons/command_processor_daemon/config/environment.rb +27 -18
  5. data/lib/euston-daemons/command_processor_daemon/lib/clients/command_handler.rb +37 -0
  6. data/lib/euston-daemons/command_processor_daemon/lib/command_handlers/retry_failed_message.rb +35 -0
  7. data/lib/euston-daemons/command_processor_daemon/lib/daemon.rb +11 -32
  8. data/lib/euston-daemons/command_processor_daemon/lib/mongo_models/failed_message.rb +34 -0
  9. data/lib/euston-daemons/command_processor_daemon/rake_task.rb +15 -13
  10. data/lib/euston-daemons/euston/daemon.rb +93 -0
  11. data/lib/euston-daemons/euston/daemon_client.rb +24 -0
  12. data/lib/euston-daemons/euston/daemon_component.rb +65 -0
  13. data/lib/euston-daemons/euston/daemon_environment.rb +54 -0
  14. data/lib/euston-daemons/event_processor_daemon/config/environment.rb +27 -16
  15. data/lib/euston-daemons/event_processor_daemon/lib/clients/event_handler.rb +42 -0
  16. data/lib/euston-daemons/event_processor_daemon/lib/daemon.rb +13 -60
  17. data/lib/euston-daemons/event_processor_daemon/lib/event_handlers/message_failure.rb +27 -0
  18. data/lib/euston-daemons/event_processor_daemon/rake_task.rb +18 -16
  19. data/lib/euston-daemons/message_buffer_daemon/config/environment.rb +39 -25
  20. data/lib/euston-daemons/message_buffer_daemon/lib/clients/command_buffer_cleanup.rb +9 -0
  21. data/lib/euston-daemons/message_buffer_daemon/lib/clients/command_buffer_publisher.rb +9 -0
  22. data/lib/euston-daemons/message_buffer_daemon/lib/clients/command_logger.rb +9 -0
  23. data/lib/euston-daemons/message_buffer_daemon/lib/clients/euston_exchange_accessors.rb +15 -0
  24. data/lib/euston-daemons/message_buffer_daemon/lib/clients/event_buffer_cleanup.rb +9 -0
  25. data/lib/euston-daemons/message_buffer_daemon/lib/clients/event_buffer_publisher.rb +9 -0
  26. data/lib/euston-daemons/message_buffer_daemon/lib/clients/event_logger.rb +9 -0
  27. data/lib/euston-daemons/message_buffer_daemon/lib/clients/event_store_dispatcher.rb +25 -0
  28. data/lib/euston-daemons/message_buffer_daemon/lib/clients/message_buffer_cleanup.rb +52 -0
  29. data/lib/euston-daemons/message_buffer_daemon/lib/clients/message_buffer_publisher.rb +37 -0
  30. data/lib/euston-daemons/message_buffer_daemon/lib/clients/message_logger.rb +45 -0
  31. data/lib/euston-daemons/message_buffer_daemon/lib/clients/mongo_model_accessors.rb +21 -0
  32. data/lib/euston-daemons/message_buffer_daemon/lib/daemon.rb +11 -42
  33. data/lib/euston-daemons/message_buffer_daemon/lib/mongo_models/command_buffer.rb +11 -0
  34. data/lib/euston-daemons/message_buffer_daemon/lib/mongo_models/command_log.rb +11 -0
  35. data/lib/euston-daemons/message_buffer_daemon/lib/mongo_models/event_buffer.rb +11 -0
  36. data/lib/euston-daemons/message_buffer_daemon/lib/mongo_models/event_log.rb +11 -0
  37. data/lib/euston-daemons/message_buffer_daemon/lib/mongo_models/message_buffer.rb +57 -0
  38. data/lib/euston-daemons/message_buffer_daemon/lib/{read_model → mongo_models}/message_log.rb +4 -11
  39. data/lib/euston-daemons/message_buffer_daemon/rake_task.rb +13 -11
  40. data/lib/euston-daemons/rake_task.rb +41 -65
  41. data/lib/euston-daemons/rake_tasks.rb +5 -5
  42. data/lib/euston-daemons/snapshot_daemon/lib/clients/snapshotter.rb +43 -0
  43. data/lib/euston-daemons/version.rb +1 -1
  44. data/lib/euston-daemons.rb +6 -1
  45. data/sample/Rakefile +63 -0
  46. data/sample/amqp_config.yml +14 -0
  47. data/sample/command_handlers.rb +17 -0
  48. data/sample/command_processor_daemon_config.yml +9 -0
  49. data/sample/event_handlers.rb +21 -0
  50. data/sample/event_processor_daemon_config.yml +8 -0
  51. data/sample/message_buffer_daemon_config.yml +8 -0
  52. data/sample/mongoid_config.yml +13 -0
  53. data/sample/pids/.placeholder +0 -0
  54. data/spec/daemons/command_buffer_publisher_spec.rb +110 -0
  55. data/spec/daemons/command_handler_spec.rb +48 -0
  56. data/spec/daemons/event_handler_spec.rb +55 -0
  57. data/spec/daemons/snapshot_client_spec.rb +98 -0
  58. data/spec/spec_helper.rb +77 -0
  59. data/spec/support/factories/commands.rb +16 -0
  60. data/spec/support/factories/commit.rb +7 -0
  61. data/spec/support/factories/event_message.rb +12 -0
  62. data/spec/support/factories/events.rb +8 -0
  63. data/spec/support/filters.rb +14 -0
  64. data/spec/support/sample_model/commands.rb +14 -0
  65. data/spec/support/sample_model/counter.rb +36 -0
  66. data/spec/support/sample_model/counter2.rb +46 -0
  67. data/spec/support/stub_retrying_subscription.rb +9 -0
  68. metadata +134 -67
  69. data/lib/euston-daemons/command_processor_daemon/lib/components/command_handler_component.rb +0 -56
  70. data/lib/euston-daemons/command_processor_daemon/lib/settings.rb +0 -22
  71. data/lib/euston-daemons/event_processor_daemon/lib/components/event_handler_component.rb +0 -58
  72. data/lib/euston-daemons/event_processor_daemon/lib/settings.rb +0 -26
  73. data/lib/euston-daemons/framework/basic_component.rb +0 -33
  74. data/lib/euston-daemons/framework/channel_thread.rb +0 -22
  75. data/lib/euston-daemons/framework/component_shutdown.rb +0 -22
  76. data/lib/euston-daemons/framework/daemon.rb +0 -27
  77. data/lib/euston-daemons/framework/handler_bindings_component.rb +0 -56
  78. data/lib/euston-daemons/framework/queue.rb +0 -71
  79. data/lib/euston-daemons/message_buffer_daemon/lib/components/buffer_component.rb +0 -73
  80. data/lib/euston-daemons/message_buffer_daemon/lib/components/event_store_component.rb +0 -52
  81. data/lib/euston-daemons/message_buffer_daemon/lib/message_logger.rb +0 -54
  82. data/lib/euston-daemons/message_buffer_daemon/lib/publisher.rb +0 -56
  83. data/lib/euston-daemons/message_buffer_daemon/lib/settings.rb +0 -14
  84. data/lib/euston-daemons/message_buffer_daemon/lib/subscriber.rb +0 -60
data/Gemfile CHANGED
@@ -1,4 +1,6 @@
1
1
  source :rubygems
2
2
  gemspec
3
3
 
4
- gem 'mongoid', :git => 'https://github.com/guyboertje/mongoid.git'
4
+ gem 'cranky', :git => 'https://github.com/leemhenson/cranky.git', :branch => 'hashes'
5
+ gem 'ffaker', :git => 'https://github.com/leemhenson/ffaker.git', :branch => 'countries'
6
+ gem 'safely', :git => 'https://github.com/leemhenson/safely.git', :branch => 'override_strategies'
data/Rakefile CHANGED
@@ -71,11 +71,10 @@ end
71
71
  #
72
72
  #############################################################################
73
73
 
74
- default_rspec_opts = %w[--colour --format Fuubar]
75
-
76
74
  desc "Run all examples"
77
75
  RSpec::Core::RakeTask.new(:spec) do |t|
78
- t.rspec_opts = default_rspec_opts
76
+ t.rspec_opts = ['-r ./spec/spec_helper.rb', '--colour', '--format Fuubar']
77
+ t.pattern = 'spec/**/*_spec.rb'
79
78
  end
80
79
 
81
80
  #############################################################################
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'euston-daemons'
3
- s.version = '1.0.4'
3
+ s.version = '1.1.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']
@@ -16,34 +16,68 @@ Gem::Specification.new do |s|
16
16
  euston-daemons.gemspec
17
17
  lib/euston-daemons.rb
18
18
  lib/euston-daemons/command_processor_daemon/config/environment.rb
19
- lib/euston-daemons/command_processor_daemon/lib/components/command_handler_component.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
20
21
  lib/euston-daemons/command_processor_daemon/lib/daemon.rb
21
- lib/euston-daemons/command_processor_daemon/lib/settings.rb
22
+ lib/euston-daemons/command_processor_daemon/lib/mongo_models/failed_message.rb
22
23
  lib/euston-daemons/command_processor_daemon/rake_task.rb
24
+ lib/euston-daemons/euston/daemon.rb
25
+ lib/euston-daemons/euston/daemon_client.rb
26
+ lib/euston-daemons/euston/daemon_component.rb
27
+ lib/euston-daemons/euston/daemon_environment.rb
23
28
  lib/euston-daemons/event_processor_daemon/config/environment.rb
24
- lib/euston-daemons/event_processor_daemon/lib/components/event_handler_component.rb
29
+ lib/euston-daemons/event_processor_daemon/lib/clients/event_handler.rb
25
30
  lib/euston-daemons/event_processor_daemon/lib/daemon.rb
26
- lib/euston-daemons/event_processor_daemon/lib/settings.rb
31
+ lib/euston-daemons/event_processor_daemon/lib/event_handlers/message_failure.rb
27
32
  lib/euston-daemons/event_processor_daemon/rake_task.rb
28
- lib/euston-daemons/framework/basic_component.rb
29
- lib/euston-daemons/framework/channel_thread.rb
30
- lib/euston-daemons/framework/component_shutdown.rb
31
- lib/euston-daemons/framework/daemon.rb
32
- lib/euston-daemons/framework/handler_bindings_component.rb
33
- lib/euston-daemons/framework/queue.rb
34
33
  lib/euston-daemons/message_buffer_daemon/config/environment.rb
35
- lib/euston-daemons/message_buffer_daemon/lib/components/buffer_component.rb
36
- lib/euston-daemons/message_buffer_daemon/lib/components/event_store_component.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
37
46
  lib/euston-daemons/message_buffer_daemon/lib/daemon.rb
38
- lib/euston-daemons/message_buffer_daemon/lib/message_logger.rb
39
- lib/euston-daemons/message_buffer_daemon/lib/publisher.rb
40
- lib/euston-daemons/message_buffer_daemon/lib/read_model/message_log.rb
41
- lib/euston-daemons/message_buffer_daemon/lib/settings.rb
42
- lib/euston-daemons/message_buffer_daemon/lib/subscriber.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
43
53
  lib/euston-daemons/message_buffer_daemon/rake_task.rb
44
54
  lib/euston-daemons/rake_task.rb
45
55
  lib/euston-daemons/rake_tasks.rb
56
+ lib/euston-daemons/snapshot_daemon/lib/clients/snapshotter.rb
46
57
  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
71
+ spec/spec_helper.rb
72
+ spec/support/factories/commands.rb
73
+ spec/support/factories/commit.rb
74
+ spec/support/factories/event_message.rb
75
+ spec/support/factories/events.rb
76
+ spec/support/filters.rb
77
+ spec/support/sample_model/commands.rb
78
+ spec/support/sample_model/counter.rb
79
+ spec/support/sample_model/counter2.rb
80
+ spec/support/stub_retrying_subscription.rb
47
81
  ]
48
82
  # = MANIFEST =
49
83
 
@@ -53,21 +87,22 @@ Gem::Specification.new do |s|
53
87
  s.add_dependency 'activemodel', '~> 3.0.0'
54
88
  s.add_dependency 'activesupport', '~> 3.0.0'
55
89
  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'
56
93
  s.add_dependency 'hollywood', '~> 1.0.0'
57
94
  s.add_dependency 'i18n', '~> 0.5.0'
58
- s.add_dependency 'require_all', '~> 1.2.0'
59
95
  s.add_dependency 'safely', '~> 0.3.0'
60
96
 
61
97
  if RUBY_PLATFORM.to_s == 'java'
62
- s.add_dependency 'euston-rabbitmq', '~> 1.0.0'
63
98
  s.add_dependency 'jessica', '~> 1.0.0'
64
- s.add_dependency 'jmongo', '~> 1.0.0'
99
+ s.add_dependency 'jmongo', '~> 1.1.0'
65
100
  end
66
101
 
67
- s.add_dependency 'euston', '~> 1.0.0'
68
- s.add_dependency 'euston-eventstore', '~> 1.0.0'
69
- s.add_dependency 'mongoid-glue', '~> 1.0.0'
70
- # s.add_dependency 'mongoid'
71
-
102
+ s.add_development_dependency 'awesome_print', '~> 0.4.0'
103
+ s.add_development_dependency 'cranky', '~> 0.2.0'
104
+ s.add_development_dependency 'ffaker', '~> 1.8.0'
105
+ s.add_development_dependency 'fuubar', '~> 0.0.0'
106
+ s.add_development_dependency 'rabbitmqadmin-cli', '~> 1.0.2'
72
107
  s.add_development_dependency 'rspec', '~> 2.6.0'
73
108
  end
@@ -1,25 +1,34 @@
1
1
  require 'jessica'
2
- require 'euston'
3
- require 'euston-eventstore'
4
2
  require 'euston-rabbitmq'
5
- require_rel '../lib'
6
3
 
7
- Safely::Strategy::Log.logger = EUSTON_LOG
8
- AMQP.settings.merge! ErbYaml.read(AMQP_CONFIG_PATH, EUSTON_ENV)
9
- Euston::CommandProcessorDaemon::Settings.configure ErbYaml.read(DAEMON_CONFIG_PATH, EUSTON_ENV)
4
+ require 'euston-daemons/command_processor_daemon/lib/mongo_models/failed_message'
5
+ require 'euston-daemons/command_processor_daemon/lib/command_handlers/retry_failed_message'
6
+ require 'euston-daemons/command_processor_daemon/lib/clients/command_handler'
7
+ require 'euston-daemons/command_processor_daemon/lib/daemon'
10
8
 
11
- hash = ErbYaml.read(MONGOID_CONFIG_PATH, EUSTON_ENV)
9
+ module Euston
10
+ module CommandProcessorDaemon
11
+ class DaemonEnvironment < Euston::DaemonEnvironment
12
+ class << self
13
+ attr_accessor :command_handler_namespaces, :client_instances
14
+ end
12
15
 
13
- event_connection = Mongo::Connection.new hash[:host], hash[:port], :safe => hash[:safe] #, :logger => EUSTON_LOG
14
- read_connection = Mongo::Connection.new hash[:host], hash[:port], :safe => hash[:safe] #, :logger => EUSTON_LOG
16
+ def initialize data
17
+ @logger = data[:logger]
18
+ @amqp_config = ErbYaml.read data[:amqp_config_path], data[:environment]
19
+ @daemon_config = ErbYaml.read data[:daemon_config_path], data[:environment]
20
+ @mongoid_config = ErbYaml.read data[:mongoid_config_path], data[:environment]
15
21
 
16
- Euston::RabbitMq.event_store_mongodb = Mongo::DB.new(hash[:event_store_database], event_connection)
17
- Euston::RabbitMq.read_model_mongodb = Mongo::DB.new(hash[:read_model_database], read_connection)
22
+ self.class.client_instances = @daemon_config[:client_instances]
23
+ self.class.command_handler_namespaces = data[:command_handler_namespaces]
24
+ end
18
25
 
19
- Euston::EventStore::Persistence::Mongodb::Config.instance.logger = EUSTON_LOG
20
- Euston::EventStore::Persistence::Mongodb::Config.instance.database = Euston::CommandProcessorDaemon::Settings.mongo_db_name
21
-
22
- Euston::RabbitMq.event_store = Euston::EventStore::Persistence::Mongodb::MongoPersistenceFactory.build
23
- Euston::RabbitMq.event_store.init
24
-
25
- Euston::Repository.event_store = Euston::EventStore::OptimisticEventStore.new Euston::RabbitMq.event_store
26
+ def setup
27
+ setup_safely @daemon_config[:hoptoad_key]
28
+ setup_amqp @amqp_config
29
+ setup_mongo @mongoid_config
30
+ setup_euston @mongoid_config[:event_store_database]
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,37 @@
1
+ module Euston
2
+ module CommandProcessorDaemon
3
+ class CommandHandler < Euston::DaemonClient
4
+ def initialize channel, handlers, logger
5
+ @channel = channel
6
+ @channel.prefetch 1
7
+ @handlers = handlers
8
+ @log = logger
9
+ end
10
+
11
+ private
12
+
13
+ def next_iteration
14
+ message_received = Proc.new do |message|
15
+ command_headers = CommandHeaders.from_hash(message[:headers]).freeze
16
+ command_body = message[:body].freeze
17
+
18
+ handler_type = command_headers.type.to_s.camelize.to_sym
19
+ handler_method_name = "__version__#{command_headers.version}"
20
+ reference = @handlers.find { |reference| reference.name == handler_type }
21
+
22
+ if reference.nil?
23
+ @log.debug "Delivering command #{command_headers} to command bus"
24
+ Euston::CommandBus.publish command_headers, command_body
25
+ else
26
+ @log.debug "Delivering command #{command_headers} to #{reference.name}.#{handler_method_name}"
27
+ reference.handler.new.send handler_method_name, command_headers, command_body
28
+ end
29
+ end
30
+
31
+ Euston::RabbitMq::RetryingSubscription.new(@channel, :command_handlers, @log)
32
+ .when(:message_received => message_received)
33
+ .subscribe
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,35 @@
1
+ module Euston
2
+ module CommandProcessorDaemon
3
+ module CommandHandlers
4
+ class RetryFailedMessage
5
+ include Euston::CommandHandler
6
+
7
+ version 1 do |headers, command|
8
+ model = MongoModel::FailedMessage.new DaemonEnvironment.event_store_mongodb
9
+ message = model.get_by_id command[:id]
10
+
11
+ unless message.nil?
12
+ routing_key = message['routing_key']
13
+ exchange = routing_key.split('.').first
14
+
15
+ headers = message['headers'].merge(:id => command[:id],
16
+ :type => message['type'],
17
+ :version => message['version'] )
18
+
19
+ if exchange == 'commands'
20
+ buffer = MessageBufferDaemon::MongoModel::CommandBuffer
21
+ elsif exchange == 'events'
22
+ buffer = MessageBufferDaemon::MongoModel::EventBuffer
23
+ end
24
+
25
+ buffer = buffer.new DaemonEnvironment.event_store_mongodb
26
+ buffer.push :headers => headers,
27
+ :body => message['body']
28
+
29
+ model.remove_by_id command[:id]
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,42 +1,21 @@
1
1
  module Euston
2
2
  module CommandProcessorDaemon
3
- class Daemon
4
- include Euston::Daemon
3
+ class Daemon < Euston::Daemon
4
+ private
5
5
 
6
- attr_reader :clients, :queue #,:ctx
6
+ def pre_registration_setup
7
+ handler_finder = Euston::RabbitMq::HandlerFinder.new [Euston::CommandHandler]
8
+ handler_finder.namespaces.push Euston::CommandProcessorDaemon::CommandHandlers, *DaemonEnvironment.command_handler_namespaces
9
+ @handlers = handler_finder.find
7
10
 
8
- def initialize #(ctx)
9
- @queue = Queue.new
10
- # @ctx = ctx
11
- @clients = {}
12
-
13
- Settings.client_instances.times do |i|
14
- @clients["command_component_#{i.succ}"] = CommandHandlerComponent.new self
15
- end
11
+ binder = Euston::RabbitMq::CommandHandlerBinder.new @handlers
12
+ binder.ensure_bindings_exist
16
13
  end
17
14
 
18
- def run
19
- @clients.each do |name, component|
20
- sleep 0.25
21
- EUSTON_LOG.debug "Starting component: #{name}"
22
- component.start
23
- end
24
-
25
- EUSTON_LOG.debug "Components started"
26
-
27
- @clients.each do |name, component|
28
- EUSTON_LOG.debug("Thread state of #{name}: #{component.thread_state}")
15
+ def register_components
16
+ (1..DaemonEnvironment.client_instances).each do |i|
17
+ register_component "command_handler_#{i}".to_sym, CommandHandler.new(AMQP::Channel.new, @handlers, @log)
29
18
  end
30
-
31
- @queue.pop #<-------- stops here until interrupted
32
-
33
- @clients.each do |name, component|
34
- EUSTON_LOG.debug "Stopping component: #{name}"
35
- component.stop
36
- end
37
-
38
- report_shutdown_reasons
39
- EUSTON_LOG.debug "Components stopped"
40
19
  end
41
20
  end
42
21
  end
@@ -0,0 +1,34 @@
1
+ module Euston
2
+ module CommandProcessorDaemon
3
+ module MongoModel
4
+ class FailedMessage
5
+ def initialize mongodb
6
+ name = 'failed_messages'
7
+ mongodb.create_collection name unless mongodb.collection_names.include? name
8
+
9
+ @collection = mongodb.collection name
10
+ @collection.ensure_index [ ['failure_timestamp', Mongo::ASCENDING] ], :unique => false, :name => 'failed_messages_failure_timestamp_index'
11
+ end
12
+
13
+ def get_by_id id
14
+ @collection.find_one({ '_id' => id })
15
+ end
16
+
17
+ def find_all
18
+ @collection.find({}, { :sort => [ 'failure_timestamp', Mongo::DESCENDING ] })
19
+ end
20
+
21
+ def log_failure failure
22
+ failure.recursive_stringify_keys!
23
+ failure['_id'] = failure.delete 'message_id'
24
+
25
+ @collection.save(failure, :safe => { :fsync => true })
26
+ end
27
+
28
+ def remove_by_id id
29
+ @collection.remove({ '_id' => id }, :safe => { :fsync => true })
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -2,9 +2,9 @@ module Euston
2
2
  class CommandProcessorRakeTask < Euston::Daemons::RakeTask
3
3
  attr_accessor :amqp_config_path, :command_handler_namespaces, :daemon_config_path, :mongoid_config_path
4
4
 
5
- def initialize
5
+ def initialize environment
6
6
  @command_handler_namespaces = []
7
- super(:command_processor_daemon)
7
+ super environment, :command_processor_daemon
8
8
  end
9
9
 
10
10
  def before_creating_task
@@ -12,23 +12,25 @@ module Euston
12
12
  @daemon_class = 'Euston::CommandProcessorDaemon::Daemon'
13
13
  end
14
14
 
15
- def initialize_paths
16
- EUSTON_LOG.debug "AMQP config path: #{@amqp_config_path}"
17
- Object.const_set :AMQP_CONFIG_PATH, @amqp_config_path
15
+ def initialize_settings
16
+ @logger.debug "AMQP config path: #{@amqp_config_path}"
17
+ @data[:amqp_config_path] = @amqp_config_path
18
18
 
19
- EUSTON_LOG.debug "Command handler namespaces: #{@command_handler_namespaces}"
20
- Object.const_set :COMMAND_HANDLER_NAMESPACES, @command_handler_namespaces
19
+ @logger.debug "Command handler namespaces: #{@command_handler_namespaces}"
20
+ @data[:command_handler_namespaces] = @command_handler_namespaces
21
21
 
22
- EUSTON_LOG.debug "Daemon config path: #{@daemon_config_path}"
23
- Object.const_set :DAEMON_CONFIG_PATH, @daemon_config_path
22
+ @logger.debug "Daemon config path: #{@daemon_config_path}"
23
+ @data[:daemon_config_path] = @daemon_config_path
24
24
 
25
- EUSTON_LOG.debug "Mongoid config path: #{@mongoid_config_path}"
26
- Object.const_set :MONGOID_CONFIG_PATH, @mongoid_config_path
25
+ @logger.debug "Mongoid config path: #{@mongoid_config_path}"
26
+ @data[:mongoid_config_path] = @mongoid_config_path
27
27
  end
28
28
 
29
29
  def load_environment
30
- EUSTON_LOG.debug "Loading environment"
31
- require_rel 'config/environment.rb'
30
+ @logger.debug "Loading environment"
31
+ require 'euston-daemons/command_processor_daemon/config/environment'
32
+
33
+ Euston::CommandProcessorDaemon::DaemonEnvironment.new(@data).setup
32
34
  end
33
35
  end
34
36
  end
@@ -0,0 +1,93 @@
1
+ module Euston
2
+ class Daemon
3
+ def initialize data
4
+ @log = data[:logger]
5
+ @queue = Queue.new
6
+ @components = []
7
+ @errors = []
8
+ end
9
+
10
+ def run
11
+ Thread.abort_on_exception = true
12
+
13
+ pre_registration_setup
14
+ register_components
15
+ trap_exit_signals
16
+ start_components
17
+ wait_for_shutdown_event
18
+ stop_components
19
+ report_shutdown_reasons
20
+ end
21
+
22
+ private
23
+
24
+ def pre_registration_setup
25
+ # virtual
26
+ end
27
+
28
+ def register_component name, klass
29
+ component = Euston::DaemonComponent.new @log, name, klass, self
30
+ component.when(:fatal_error_in_component => method(:shutdown))
31
+
32
+ @components << component
33
+ end
34
+
35
+ def register_components
36
+ # virtual
37
+ end
38
+
39
+ def report_shutdown_reasons
40
+ sleep 0.25
41
+ reports = []
42
+
43
+ until @errors.empty? do
44
+ e = @errors.shift
45
+ next if e.nil?
46
+
47
+ case e
48
+ when NativeException
49
+ Safely.report! e.cause
50
+ else
51
+ Safely.report! e
52
+ end
53
+ end
54
+ end
55
+
56
+ def report_component_statuses
57
+ @components.each do |component|
58
+ @log.debug "Thread state of #{component.name}: #{component.thread_state}"
59
+ end
60
+ end
61
+
62
+ def start_components
63
+ @components.each do |component|
64
+ @log.debug "Starting component: #{component.name}"
65
+ component.start
66
+ sleep 0.350
67
+ end
68
+ end
69
+
70
+ def stop_components
71
+ @components.each do |component|
72
+ @log.debug "Stopping component: #{component.name}"
73
+ component.stop
74
+ end
75
+ end
76
+
77
+ def shutdown error
78
+ @errors.push error unless error.nil?
79
+ @queue.push "SHUTDOWN"
80
+ end
81
+
82
+ def trap_exit_signals
83
+ signals = %W(INT TERM) & Signal.list.keys
84
+ signals.each { |sig| sig.freeze }.freeze
85
+ signals.each { |sig| Signal.trap(sig) { @queue.push(sig) } }
86
+ end
87
+
88
+ def wait_for_shutdown_event
89
+ @log.debug "Awaiting shutdown event"
90
+ @queue.pop #<-------- stops here until interrupted
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,24 @@
1
+ module Euston
2
+ class DaemonClient
3
+ include Hollywood
4
+
5
+ def run
6
+ next_iteration unless stopped
7
+ end
8
+
9
+ def stop
10
+ @stopped = true
11
+ @channel.disconnect unless @channel.nil? || !@channel.respond_to?(:disconnect)
12
+ end
13
+
14
+ private
15
+
16
+ def next_iteration
17
+ # abstract
18
+ end
19
+
20
+ def stopped
21
+ @stopped ||= false
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,65 @@
1
+ module Euston
2
+ class DaemonComponent
3
+ include Hollywood
4
+
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
23
+ end
24
+
25
+ def stop
26
+ @client.stop
27
+ @thread[:stop] = true
28
+ end
29
+
30
+ def thread_state
31
+ @thread.status
32
+ end
33
+
34
+ private
35
+
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]
51
+ end
52
+
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
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,54 @@
1
+ module Euston
2
+ class DaemonEnvironment
3
+ def initialize data
4
+ @logger = data[:logger]
5
+ end
6
+
7
+ def setup
8
+ # abstract
9
+ end
10
+
11
+ private
12
+
13
+ def setup_amqp config
14
+ AMQP.settings.merge! config
15
+ end
16
+
17
+ def setup_euston event_store_database_name
18
+ Euston::EventStore::Persistence::Mongodb::Config.instance.logger = @logger
19
+ Euston::EventStore::Persistence::Mongodb::Config.instance.database = event_store_database_name
20
+
21
+ class << self.class
22
+ attr_accessor :event_store
23
+ end
24
+
25
+ self.class.event_store = Euston::EventStore::Persistence::Mongodb::MongoPersistenceFactory.build
26
+ self.class.event_store.init
27
+
28
+ Euston::Repository.event_store = Euston::EventStore::OptimisticEventStore.new self.class.event_store
29
+ end
30
+
31
+ def setup_mongo config
32
+ connection = Mongo::Connection.new config[:host], config[:port], :safe => config[:safe], :logger => @logger
33
+
34
+ class << self.class
35
+ attr_accessor :event_store_mongodb, :read_model_mongodb
36
+ end
37
+
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
40
+ end
41
+
42
+ def setup_safely hoptoad_key
43
+ safely_strategies = [ Safely::Strategy::Log ]
44
+
45
+ unless hoptoad_key.nil?
46
+ Safely::Strategy::Hoptoad.hoptoad_key = data[:environment]
47
+ safely_strategies << Safely::Strategy::Hoptoad
48
+ end
49
+
50
+ Safely::Strategy::Log.logger = @logger
51
+ Safely.configure { |config| config.strategies = safely_strategies }
52
+ end
53
+ end
54
+ end