aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support
diff options
context:
space:
mode:
authorMatthew Draper <matthew@trebex.net>2016-04-07 03:30:03 +0930
committerMatthew Draper <matthew@trebex.net>2016-04-07 03:30:03 +0930
commit1c3afbab779f052a3fc6d5e2747874b3347d58cf (patch)
treeba078fa6f8d0ecf3b5c520ae4b269e53fe5a5545 /activesupport/lib/active_support
parentc908a902b3c3d4bdf3d18dcf83570277c706bd35 (diff)
parent291a098c111ff419506094e14c0186389b0020ca (diff)
downloadrails-1c3afbab779f052a3fc6d5e2747874b3347d58cf.tar.gz
rails-1c3afbab779f052a3fc6d5e2747874b3347d58cf.tar.bz2
rails-1c3afbab779f052a3fc6d5e2747874b3347d58cf.zip
Merge pull request #24422 from matthewd/extinguish-executor-exceptions
Clean up after a failure in a run callback
Diffstat (limited to 'activesupport/lib/active_support')
-rw-r--r--activesupport/lib/active_support/execution_wrapper.rb45
-rw-r--r--activesupport/lib/active_support/reloader.rb8
2 files changed, 49 insertions, 4 deletions
diff --git a/activesupport/lib/active_support/execution_wrapper.rb b/activesupport/lib/active_support/execution_wrapper.rb
index 2bd1c01d35..00c5745a25 100644
--- a/activesupport/lib/active_support/execution_wrapper.rb
+++ b/activesupport/lib/active_support/execution_wrapper.rb
@@ -19,6 +19,32 @@ module ActiveSupport
set_callback(:complete, *args, &block)
end
+ # Register an object to be invoked during both the +run+ and
+ # +complete+ steps.
+ #
+ # +hook.complete+ will be passed the value returned from +hook.run+,
+ # and will only be invoked if +run+ has previously been called.
+ # (Mostly, this means it won't be invoked if an exception occurs in
+ # a preceding +to_run+ block; all ordinary +to_complete+ blocks are
+ # invoked in that situation.)
+ def self.register_hook(hook, outer: false)
+ if outer
+ run_args = [prepend: true]
+ complete_args = [:after]
+ else
+ run_args = complete_args = []
+ end
+
+ to_run(*run_args) do
+ hook_state[hook] = hook.run
+ end
+ to_complete(*complete_args) do
+ if hook_state.key?(hook)
+ hook.complete hook_state[hook]
+ end
+ end
+ end
+
# Run this execution.
#
# Returns an instance, whose +complete!+ method *must* be invoked
@@ -29,7 +55,15 @@ module ActiveSupport
if active?
Null
else
- new.tap(&:run!)
+ new.tap do |instance|
+ success = nil
+ begin
+ instance.run!
+ success = true
+ ensure
+ instance.complete! unless success
+ end
+ end
end
end
@@ -37,11 +71,11 @@ module ActiveSupport
def self.wrap
return yield if active?
- state = run!
+ instance = run!
begin
yield
ensure
- state.complete!
+ instance.complete!
end
end
@@ -74,5 +108,10 @@ module ActiveSupport
ensure
self.class.active.delete Thread.current
end
+
+ private
+ def hook_state
+ @_hook_state ||= {}
+ end
end
end
diff --git a/activesupport/lib/active_support/reloader.rb b/activesupport/lib/active_support/reloader.rb
index 5d1f0e1e66..5623bdd349 100644
--- a/activesupport/lib/active_support/reloader.rb
+++ b/activesupport/lib/active_support/reloader.rb
@@ -43,7 +43,13 @@ module ActiveSupport
# Initiate a manual reload
def self.reload!
executor.wrap do
- new.tap(&:run!).complete!
+ new.tap do |instance|
+ begin
+ instance.run!
+ ensure
+ instance.complete!
+ end
+ end
end
prepare!
end