euston-daemons 1.0.5 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/Gemfile +4 -1
  2. data/Rakefile +2 -3
  3. data/euston-daemons.gemspec +50 -39
  4. data/lib/euston-daemons.rb +14 -1
  5. data/lib/euston-daemons/euston/daemon.rb +99 -0
  6. data/lib/euston-daemons/euston/daemon_component.rb +25 -0
  7. data/lib/euston-daemons/euston/daemon_component_host.rb +66 -0
  8. data/lib/euston-daemons/euston/daemon_environment.rb +59 -0
  9. data/lib/euston-daemons/euston/exceptions.rb +9 -0
  10. data/lib/euston-daemons/euston/stopwatch.rb +15 -0
  11. data/lib/euston-daemons/pipeline/config/environment.rb +78 -0
  12. data/lib/euston-daemons/pipeline/lib/command_logger/component.rb +54 -0
  13. data/lib/euston-daemons/pipeline/lib/command_logger/log.rb +31 -0
  14. data/lib/euston-daemons/pipeline/lib/command_processor/component.rb +50 -0
  15. data/lib/euston-daemons/pipeline/lib/command_processor/default_commands/retry_failed_message.rb +13 -0
  16. data/lib/euston-daemons/pipeline/lib/command_processor/default_handlers/retry_failed_message.rb +34 -0
  17. data/lib/euston-daemons/pipeline/lib/command_processor/failed_message.rb +36 -0
  18. data/lib/euston-daemons/pipeline/lib/daemon.rb +85 -0
  19. data/lib/euston-daemons/pipeline/lib/event_processor/component.rb +67 -0
  20. data/lib/euston-daemons/pipeline/lib/event_processor/default_handlers/message_failure.rb +30 -0
  21. data/lib/euston-daemons/pipeline/lib/event_store_dispatcher/component.rb +68 -0
  22. data/lib/euston-daemons/pipeline/lib/message_buffer/buffer.rb +85 -0
  23. data/lib/euston-daemons/pipeline/lib/message_buffer/component.rb +59 -0
  24. data/lib/euston-daemons/pipeline/lib/snapshotter/component.rb +48 -0
  25. data/lib/euston-daemons/pipeline/rake_task.rb +49 -0
  26. data/lib/euston-daemons/rake_task.rb +63 -66
  27. data/lib/euston-daemons/rake_tasks.rb +3 -5
  28. data/lib/euston-daemons/version.rb +1 -1
  29. data/spec/daemons/command_processor_spec.rb +48 -0
  30. data/spec/daemons/event_processor_spec.rb +55 -0
  31. data/spec/daemons/message_buffer_spec.rb +106 -0
  32. data/spec/daemons/snapshotter_spec.rb +96 -0
  33. data/spec/spec_helper.rb +91 -0
  34. data/spec/support/factories/commands.rb +16 -0
  35. data/spec/support/factories/commit.rb +7 -0
  36. data/spec/support/factories/event_message.rb +12 -0
  37. data/spec/support/factories/events.rb +8 -0
  38. data/spec/support/filters.rb +13 -0
  39. data/spec/support/sample_model/commands.rb +14 -0
  40. data/spec/support/sample_model/counter.rb +36 -0
  41. data/spec/support/sample_model/counter2.rb +46 -0
  42. data/spec/support/stub_retrying_subscription.rb +9 -0
  43. metadata +131 -67
  44. data/lib/euston-daemons/command_processor_daemon/config/environment.rb +0 -25
  45. data/lib/euston-daemons/command_processor_daemon/lib/components/command_handler_component.rb +0 -56
  46. data/lib/euston-daemons/command_processor_daemon/lib/daemon.rb +0 -43
  47. data/lib/euston-daemons/command_processor_daemon/lib/settings.rb +0 -22
  48. data/lib/euston-daemons/command_processor_daemon/rake_task.rb +0 -34
  49. data/lib/euston-daemons/event_processor_daemon/config/environment.rb +0 -25
  50. data/lib/euston-daemons/event_processor_daemon/lib/components/event_handler_component.rb +0 -58
  51. data/lib/euston-daemons/event_processor_daemon/lib/daemon.rb +0 -71
  52. data/lib/euston-daemons/event_processor_daemon/lib/settings.rb +0 -26
  53. data/lib/euston-daemons/event_processor_daemon/rake_task.rb +0 -37
  54. data/lib/euston-daemons/framework/basic_component.rb +0 -33
  55. data/lib/euston-daemons/framework/channel_thread.rb +0 -22
  56. data/lib/euston-daemons/framework/component_shutdown.rb +0 -22
  57. data/lib/euston-daemons/framework/daemon.rb +0 -27
  58. data/lib/euston-daemons/framework/handler_bindings_component.rb +0 -56
  59. data/lib/euston-daemons/framework/queue.rb +0 -71
  60. data/lib/euston-daemons/message_buffer_daemon/config/environment.rb +0 -28
  61. data/lib/euston-daemons/message_buffer_daemon/lib/components/buffer_component.rb +0 -73
  62. data/lib/euston-daemons/message_buffer_daemon/lib/components/event_store_component.rb +0 -52
  63. data/lib/euston-daemons/message_buffer_daemon/lib/daemon.rb +0 -48
  64. data/lib/euston-daemons/message_buffer_daemon/lib/message_logger.rb +0 -54
  65. data/lib/euston-daemons/message_buffer_daemon/lib/publisher.rb +0 -56
  66. data/lib/euston-daemons/message_buffer_daemon/lib/read_model/message_log.rb +0 -36
  67. data/lib/euston-daemons/message_buffer_daemon/lib/settings.rb +0 -14
  68. data/lib/euston-daemons/message_buffer_daemon/lib/subscriber.rb +0 -60
  69. data/lib/euston-daemons/message_buffer_daemon/rake_task.rb +0 -30
data/Gemfile CHANGED
@@ -1,4 +1,7 @@
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'
7
+ gem 'hot_bunnies', :git => 'https://github.com/ruby-amqp/hot_bunnies.git'
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.5'
3
+ s.version = '1.2.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,59 +15,70 @@ 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/components/command_handler_component.rb
20
- 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/rake_task.rb
23
- lib/euston-daemons/event_processor_daemon/config/environment.rb
24
- lib/euston-daemons/event_processor_daemon/lib/components/event_handler_component.rb
25
- lib/euston-daemons/event_processor_daemon/lib/daemon.rb
26
- lib/euston-daemons/event_processor_daemon/lib/settings.rb
27
- 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
- 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
37
- 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
43
- lib/euston-daemons/message_buffer_daemon/rake_task.rb
18
+ lib/euston-daemons/euston/daemon.rb
19
+ lib/euston-daemons/euston/daemon_component.rb
20
+ lib/euston-daemons/euston/daemon_component_host.rb
21
+ lib/euston-daemons/euston/daemon_environment.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_commands/retry_failed_message.rb
29
+ lib/euston-daemons/pipeline/lib/command_processor/default_handlers/retry_failed_message.rb
30
+ lib/euston-daemons/pipeline/lib/command_processor/failed_message.rb
31
+ lib/euston-daemons/pipeline/lib/daemon.rb
32
+ lib/euston-daemons/pipeline/lib/event_processor/component.rb
33
+ lib/euston-daemons/pipeline/lib/event_processor/default_handlers/message_failure.rb
34
+ lib/euston-daemons/pipeline/lib/event_store_dispatcher/component.rb
35
+ lib/euston-daemons/pipeline/lib/message_buffer/buffer.rb
36
+ lib/euston-daemons/pipeline/lib/message_buffer/component.rb
37
+ lib/euston-daemons/pipeline/lib/snapshotter/component.rb
38
+ lib/euston-daemons/pipeline/rake_task.rb
44
39
  lib/euston-daemons/rake_task.rb
45
40
  lib/euston-daemons/rake_tasks.rb
46
41
  lib/euston-daemons/version.rb
42
+ spec/daemons/command_processor_spec.rb
43
+ spec/daemons/event_processor_spec.rb
44
+ spec/daemons/message_buffer_spec.rb
45
+ spec/daemons/snapshotter_spec.rb
46
+ spec/spec_helper.rb
47
+ spec/support/factories/commands.rb
48
+ spec/support/factories/commit.rb
49
+ spec/support/factories/event_message.rb
50
+ spec/support/factories/events.rb
51
+ spec/support/filters.rb
52
+ spec/support/sample_model/commands.rb
53
+ spec/support/sample_model/counter.rb
54
+ spec/support/sample_model/counter2.rb
55
+ spec/support/stub_retrying_subscription.rb
47
56
  ]
48
57
  # = MANIFEST =
49
58
 
50
59
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
51
60
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
52
61
 
53
- s.add_dependency 'activemodel', '~> 3.0.0'
54
- s.add_dependency 'activesupport', '~> 3.0.0'
62
+ s.add_dependency 'activemodel', '>= 3.0.10'
63
+ s.add_dependency 'activesupport', '>= 3.0.10'
55
64
  s.add_dependency 'erb-yaml', '~> 1.0.0'
65
+ s.add_dependency 'euston', '~> 1.2.0'
66
+ s.add_dependency 'euston-eventstore', '~> 1.2.0'
67
+ s.add_dependency 'euston-rabbitmq', '~> 1.2.0'
56
68
  s.add_dependency 'hollywood', '~> 1.0.0'
57
- s.add_dependency 'i18n', '~> 0.5.0'
58
- s.add_dependency 'require_all', '~> 1.2.0'
69
+ s.add_dependency 'i18n', '>= 0.5.0'
70
+ s.add_dependency 'macaddr', '~> 1.4.0'
59
71
  s.add_dependency 'safely', '~> 0.3.0'
60
72
 
61
73
  if RUBY_PLATFORM.to_s == 'java'
62
- s.add_dependency 'euston-rabbitmq', '~> 1.0.0'
63
- s.add_dependency 'jessica', '~> 1.0.0'
64
- s.add_dependency 'jmongo', '~> 1.0.0'
74
+ s.add_dependency 'hot_bunnies', '~> 1.3.0.pre1'
75
+ s.add_dependency 'jmongo', '~> 1.1.0'
65
76
  end
66
77
 
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
-
78
+ s.add_development_dependency 'awesome_print', '~> 0.4.0'
79
+ s.add_development_dependency 'cranky', '~> 0.2.0'
80
+ s.add_development_dependency 'ffaker', '~> 1.8.0'
81
+ s.add_development_dependency 'fuubar', '~> 0.0.0'
82
+ s.add_development_dependency 'rabbitmqadmin-cli', '~> 1.0.2'
72
83
  s.add_development_dependency 'rspec', '~> 2.6.0'
73
84
  end
@@ -1,6 +1,6 @@
1
+ require 'erb-yaml'
1
2
  require 'hollywood'
2
3
  require 'logger'
3
- require 'require_all'
4
4
 
5
5
  if RUBY_PLATFORM.to_s == 'java'
6
6
  module Uuid
@@ -8,4 +8,17 @@ if RUBY_PLATFORM.to_s == 'java'
8
8
  Java::JavaUtil::UUID.randomUUID().toString()
9
9
  end
10
10
  end
11
+
12
+ require 'euston-daemons/euston/stopwatch'
13
+ require 'euston-daemons/euston/exceptions'
14
+ require 'euston-daemons/euston/daemon_environment'
15
+ require 'euston-daemons/euston/daemon_component'
16
+ require 'euston-daemons/euston/daemon_component_host'
17
+ require 'euston-daemons/euston/daemon'
18
+ else
19
+ require 'euston-daemons/pipeline/lib/command_processor/default_commands/retry_failed_message'
20
+ require 'euston-daemons/pipeline/lib/command_processor/failed_message'
21
+ require 'euston-daemons/pipeline/lib/message_buffer/buffer'
11
22
  end
23
+
24
+
@@ -0,0 +1,99 @@
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
+ post_shutdown_cleanup
20
+ report_shutdown_reasons
21
+ end
22
+
23
+ private
24
+
25
+ def pre_registration_setup
26
+ # virtual
27
+ end
28
+
29
+ def register_component name, klass
30
+ component = Euston::DaemonComponentHost.new @log, name, klass, self
31
+ component.when(:fatal_error_in_component => method(:shutdown))
32
+
33
+ @components << component
34
+ component
35
+ end
36
+
37
+ def post_shutdown_cleanup
38
+ # virtual
39
+ end
40
+
41
+ def register_components
42
+ # virtual
43
+ end
44
+
45
+ def report_shutdown_reasons
46
+ sleep 0.25
47
+ reports = []
48
+
49
+ until @errors.empty? do
50
+ e = @errors.shift
51
+ next if e.nil?
52
+
53
+ case e
54
+ when NativeException
55
+ Safely.report! e.cause
56
+ else
57
+ Safely.report! e
58
+ end
59
+ end
60
+ end
61
+
62
+ def report_component_statuses
63
+ @components.each do |component|
64
+ @log.debug "Thread state of #{component.name}: #{component.thread_state}"
65
+ end
66
+ end
67
+
68
+ def start_components
69
+ @components.each do |component|
70
+ @log.debug "Starting component: #{component.name}"
71
+ component.start
72
+ sleep 0.350
73
+ end
74
+ end
75
+
76
+ def stop_components
77
+ @components.each do |component|
78
+ @log.debug "Stopping component: #{component.name}"
79
+ component.stop
80
+ end
81
+ end
82
+
83
+ def shutdown error
84
+ @errors.push error unless error.nil?
85
+ @queue.push "SHUTDOWN"
86
+ end
87
+
88
+ def trap_exit_signals
89
+ signals = %W(INT TERM) & Signal.list.keys
90
+ signals.each { |sig| sig.freeze }.freeze
91
+ signals.each { |sig| Signal.trap(sig) { @queue.push(sig) } }
92
+ end
93
+
94
+ def wait_for_shutdown_event
95
+ @log.debug "Awaiting shutdown event"
96
+ @queue.pop #<-------- stops here until interrupted
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,25 @@
1
+ module Euston
2
+ class DaemonComponent
3
+ include Hollywood
4
+ include Daemons::Exceptions
5
+
6
+ def run
7
+ next_iteration unless stopped
8
+ end
9
+
10
+ def stop
11
+ @stopped = true
12
+ @channel.close unless @channel.nil? || !@channel.respond_to?(:close)
13
+ end
14
+
15
+ private
16
+
17
+ def next_iteration
18
+ # abstract
19
+ end
20
+
21
+ def stopped
22
+ @stopped ||= false
23
+ end
24
+ end
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
@@ -0,0 +1,59 @@
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
+ class << self.class
15
+ attr_accessor :amqp_connection
16
+ end
17
+
18
+ self.class.amqp_connection = HotBunnies.connect config
19
+ end
20
+
21
+ def setup_euston event_store_database_name
22
+ Euston::EventStore::Persistence::Mongodb::Config.instance.logger = @logger
23
+ Euston::EventStore::Persistence::Mongodb::Config.instance.database = event_store_database_name
24
+
25
+ class << self.class
26
+ attr_accessor :event_store
27
+ end
28
+
29
+ self.class.event_store = Euston::EventStore::Persistence::Mongodb::MongoPersistenceFactory.build
30
+ self.class.event_store.init
31
+
32
+ Euston::Repository.event_store = Euston::EventStore::OptimisticEventStore.new self.class.event_store
33
+ end
34
+
35
+ def setup_mongo config
36
+ # logger arg will not work until jmongo forwards it correctly
37
+ connection = Mongo::Connection.from_uri config[:uri], :logger => @logger
38
+
39
+ class << self.class
40
+ attr_accessor :event_store_mongodb, :projections_mongodb
41
+ end
42
+
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
45
+ end
46
+
47
+ def setup_safely hoptoad_key
48
+ safely_strategies = [ Safely::Strategy::Log ]
49
+
50
+ unless hoptoad_key.nil?
51
+ Safely::Strategy::Hoptoad.hoptoad_key = data[:environment]
52
+ safely_strategies << Safely::Strategy::Hoptoad
53
+ end
54
+
55
+ Safely::Strategy::Log.logger = @logger
56
+ Safely.configure { |config| config.strategies = safely_strategies }
57
+ end
58
+ end
59
+ end
@@ -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