euston-daemons 1.0.5 → 1.2.1

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 (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