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.
- data/Gemfile +4 -1
- data/Rakefile +2 -3
- data/euston-daemons.gemspec +50 -39
- data/lib/euston-daemons.rb +14 -1
- data/lib/euston-daemons/euston/daemon.rb +99 -0
- data/lib/euston-daemons/euston/daemon_component.rb +25 -0
- data/lib/euston-daemons/euston/daemon_component_host.rb +66 -0
- data/lib/euston-daemons/euston/daemon_environment.rb +59 -0
- data/lib/euston-daemons/euston/exceptions.rb +9 -0
- data/lib/euston-daemons/euston/stopwatch.rb +15 -0
- data/lib/euston-daemons/pipeline/config/environment.rb +78 -0
- data/lib/euston-daemons/pipeline/lib/command_logger/component.rb +54 -0
- data/lib/euston-daemons/pipeline/lib/command_logger/log.rb +31 -0
- data/lib/euston-daemons/pipeline/lib/command_processor/component.rb +50 -0
- data/lib/euston-daemons/pipeline/lib/command_processor/default_commands/retry_failed_message.rb +13 -0
- data/lib/euston-daemons/pipeline/lib/command_processor/default_handlers/retry_failed_message.rb +34 -0
- data/lib/euston-daemons/pipeline/lib/command_processor/failed_message.rb +36 -0
- data/lib/euston-daemons/pipeline/lib/daemon.rb +85 -0
- data/lib/euston-daemons/pipeline/lib/event_processor/component.rb +67 -0
- data/lib/euston-daemons/pipeline/lib/event_processor/default_handlers/message_failure.rb +30 -0
- data/lib/euston-daemons/pipeline/lib/event_store_dispatcher/component.rb +68 -0
- data/lib/euston-daemons/pipeline/lib/message_buffer/buffer.rb +85 -0
- data/lib/euston-daemons/pipeline/lib/message_buffer/component.rb +59 -0
- data/lib/euston-daemons/pipeline/lib/snapshotter/component.rb +48 -0
- data/lib/euston-daemons/pipeline/rake_task.rb +49 -0
- data/lib/euston-daemons/rake_task.rb +63 -66
- data/lib/euston-daemons/rake_tasks.rb +3 -5
- data/lib/euston-daemons/version.rb +1 -1
- data/spec/daemons/command_processor_spec.rb +48 -0
- data/spec/daemons/event_processor_spec.rb +55 -0
- data/spec/daemons/message_buffer_spec.rb +106 -0
- data/spec/daemons/snapshotter_spec.rb +96 -0
- data/spec/spec_helper.rb +91 -0
- data/spec/support/factories/commands.rb +16 -0
- data/spec/support/factories/commit.rb +7 -0
- data/spec/support/factories/event_message.rb +12 -0
- data/spec/support/factories/events.rb +8 -0
- data/spec/support/filters.rb +13 -0
- data/spec/support/sample_model/commands.rb +14 -0
- data/spec/support/sample_model/counter.rb +36 -0
- data/spec/support/sample_model/counter2.rb +46 -0
- data/spec/support/stub_retrying_subscription.rb +9 -0
- metadata +131 -67
- data/lib/euston-daemons/command_processor_daemon/config/environment.rb +0 -25
- data/lib/euston-daemons/command_processor_daemon/lib/components/command_handler_component.rb +0 -56
- data/lib/euston-daemons/command_processor_daemon/lib/daemon.rb +0 -43
- data/lib/euston-daemons/command_processor_daemon/lib/settings.rb +0 -22
- data/lib/euston-daemons/command_processor_daemon/rake_task.rb +0 -34
- data/lib/euston-daemons/event_processor_daemon/config/environment.rb +0 -25
- data/lib/euston-daemons/event_processor_daemon/lib/components/event_handler_component.rb +0 -58
- data/lib/euston-daemons/event_processor_daemon/lib/daemon.rb +0 -71
- data/lib/euston-daemons/event_processor_daemon/lib/settings.rb +0 -26
- data/lib/euston-daemons/event_processor_daemon/rake_task.rb +0 -37
- data/lib/euston-daemons/framework/basic_component.rb +0 -33
- data/lib/euston-daemons/framework/channel_thread.rb +0 -22
- data/lib/euston-daemons/framework/component_shutdown.rb +0 -22
- data/lib/euston-daemons/framework/daemon.rb +0 -27
- data/lib/euston-daemons/framework/handler_bindings_component.rb +0 -56
- data/lib/euston-daemons/framework/queue.rb +0 -71
- data/lib/euston-daemons/message_buffer_daemon/config/environment.rb +0 -28
- data/lib/euston-daemons/message_buffer_daemon/lib/components/buffer_component.rb +0 -73
- data/lib/euston-daemons/message_buffer_daemon/lib/components/event_store_component.rb +0 -52
- data/lib/euston-daemons/message_buffer_daemon/lib/daemon.rb +0 -48
- data/lib/euston-daemons/message_buffer_daemon/lib/message_logger.rb +0 -54
- data/lib/euston-daemons/message_buffer_daemon/lib/publisher.rb +0 -56
- data/lib/euston-daemons/message_buffer_daemon/lib/read_model/message_log.rb +0 -36
- data/lib/euston-daemons/message_buffer_daemon/lib/settings.rb +0 -14
- data/lib/euston-daemons/message_buffer_daemon/lib/subscriber.rb +0 -60
- 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 '
|
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 =
|
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
|
#############################################################################
|
data/euston-daemons.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'euston-daemons'
|
3
|
-
s.version = '1.
|
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/
|
19
|
-
lib/euston-daemons/
|
20
|
-
lib/euston-daemons/
|
21
|
-
lib/euston-daemons/
|
22
|
-
lib/euston-daemons/
|
23
|
-
lib/euston-daemons/
|
24
|
-
lib/euston-daemons/
|
25
|
-
lib/euston-daemons/
|
26
|
-
lib/euston-daemons/
|
27
|
-
lib/euston-daemons/
|
28
|
-
lib/euston-daemons/
|
29
|
-
lib/euston-daemons/
|
30
|
-
lib/euston-daemons/
|
31
|
-
lib/euston-daemons/
|
32
|
-
lib/euston-daemons/
|
33
|
-
lib/euston-daemons/
|
34
|
-
lib/euston-daemons/
|
35
|
-
lib/euston-daemons/
|
36
|
-
lib/euston-daemons/
|
37
|
-
lib/euston-daemons/
|
38
|
-
lib/euston-daemons/
|
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', '
|
54
|
-
s.add_dependency 'activesupport', '
|
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', '
|
58
|
-
s.add_dependency '
|
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 '
|
63
|
-
s.add_dependency '
|
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.
|
68
|
-
s.
|
69
|
-
s.
|
70
|
-
|
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
|
data/lib/euston-daemons.rb
CHANGED
@@ -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,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
|