granite 0.8.0 → 0.8.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.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f9bc00868502247ad725644cccc110d93845426e
|
4
|
+
data.tar.gz: '09710e9fbf2c004ef8d369869e3479f92377b51f'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 29d0c0a27c84fb772a96af9b1fd110d0ea1453b0d47252c803ba29f32201c6cd50a9665da4137ba8349ec7c0cd01c9dddca7e408d8054daec694adfe8442d931
|
7
|
+
data.tar.gz: 6c7d51a1f438c7d1958d261f5f7e51be1aa38adf161877ef96500b3a5d19069907f7d615f0335ca63f898a5b06268afeb40f72f3bf040b610e41abebb683f6ef
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Granite
|
2
|
+
class Action
|
3
|
+
module ExceptionsHandling
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
class_attribute :_exception_handlers, instance_writer: false
|
8
|
+
self._exception_handlers = {}
|
9
|
+
|
10
|
+
protected :_exception_handlers
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
# Register default handler for exceptions thrown inside execute_perform! and after_commit methods.
|
15
|
+
# @param klass Exception class, could be parent class too [Class]
|
16
|
+
# @param block [Block<Exception>] with default behavior for handling specified
|
17
|
+
# type exceptions. First block argument is raised exception instance.
|
18
|
+
#
|
19
|
+
# @return [Hash<Class, Proc>] Registered handlers
|
20
|
+
def handle_exception(klass, &block)
|
21
|
+
self._exception_handlers = _exception_handlers.merge(klass => block)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def handled_exceptions
|
28
|
+
_exception_handlers.keys
|
29
|
+
end
|
30
|
+
|
31
|
+
def handle_exception(e)
|
32
|
+
klass = e.class.ancestors.detect do |ancestor|
|
33
|
+
ancestor <= Exception && _exception_handlers[ancestor]
|
34
|
+
end
|
35
|
+
instance_exec(e, &_exception_handlers[klass]) if klass
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'granite/action/exceptions_handling'
|
1
2
|
require 'granite/action/transaction'
|
2
3
|
require 'granite/action/error'
|
3
4
|
|
@@ -17,28 +18,14 @@ module Granite
|
|
17
18
|
module Performing
|
18
19
|
extend ActiveSupport::Concern
|
19
20
|
|
21
|
+
include ExceptionsHandling
|
20
22
|
include Transaction
|
21
23
|
|
22
24
|
included do
|
23
|
-
class_attribute :_exception_handlers, instance_writer: false
|
24
|
-
self._exception_handlers = {}
|
25
|
-
|
26
|
-
protected :_exception_handlers
|
27
|
-
|
28
25
|
define_callbacks :execute_perform
|
29
26
|
end
|
30
27
|
|
31
28
|
module ClassMethods
|
32
|
-
# Register default handler for exceptions thrown inside execute_perform! method.
|
33
|
-
# @param klass Exception class, could be parent class too [Class]
|
34
|
-
# @param block [Block<Exception>] with default behavior for handling specified
|
35
|
-
# type exceptions. First block argument is raised exception instance.
|
36
|
-
#
|
37
|
-
# @return [Hash<Class, Proc>] Registered handlers
|
38
|
-
def handle_exception(klass, &block)
|
39
|
-
self._exception_handlers = _exception_handlers.merge(klass => block)
|
40
|
-
end
|
41
|
-
|
42
29
|
def perform(*)
|
43
30
|
fail 'Perform block declaration was removed! Please declare `private def execute_perform!(*)` method'
|
44
31
|
end
|
@@ -54,7 +41,7 @@ module Granite
|
|
54
41
|
# using `:on`)
|
55
42
|
# @return [Object] result of execute_perform! method execution or false in case of errors
|
56
43
|
def perform(context: nil, **options)
|
57
|
-
|
44
|
+
transaction do
|
58
45
|
valid?(context) && perform_action(options)
|
59
46
|
end
|
60
47
|
end
|
@@ -72,7 +59,7 @@ module Granite
|
|
72
59
|
# @raise [Granite::Action::ValidationError] Action or associated objects are invalid
|
73
60
|
# @raise [NotImplementedError] execute_perform! method was not defined yet
|
74
61
|
def perform!(context: nil, **options)
|
75
|
-
|
62
|
+
transaction do
|
76
63
|
validate!(context)
|
77
64
|
perform_action!(**options)
|
78
65
|
end
|
@@ -88,7 +75,7 @@ module Granite
|
|
88
75
|
# @raise [NotImplementedError] execute_perform! method was not defined yet
|
89
76
|
def try_perform!(context: nil, **options)
|
90
77
|
return unless satisfy_preconditions?
|
91
|
-
|
78
|
+
transaction do
|
92
79
|
validate!(context)
|
93
80
|
perform_action!(**options)
|
94
81
|
end
|
@@ -108,7 +95,7 @@ module Granite
|
|
108
95
|
result = run_callbacks(:execute_perform) { execute_perform!(options) }
|
109
96
|
@_action_performed = true
|
110
97
|
result || true
|
111
|
-
rescue *
|
98
|
+
rescue *handled_exceptions => e
|
112
99
|
handle_exception(e)
|
113
100
|
raise_validation_error(e) if raise_errors
|
114
101
|
raise Rollback
|
@@ -121,13 +108,6 @@ module Granite
|
|
121
108
|
def execute_perform!(**_options)
|
122
109
|
fail NotImplementedError, "BA perform body MUST be defined for #{self}"
|
123
110
|
end
|
124
|
-
|
125
|
-
def handle_exception(e)
|
126
|
-
klass = e.class.ancestors.detect do |ancestor|
|
127
|
-
ancestor <= Exception && _exception_handlers[ancestor]
|
128
|
-
end
|
129
|
-
instance_exec(e, &_exception_handlers[klass]) if klass
|
130
|
-
end
|
131
111
|
end
|
132
112
|
end
|
133
113
|
end
|
@@ -1,40 +1,44 @@
|
|
1
|
+
require 'granite/action/transaction_manager'
|
2
|
+
|
1
3
|
module Granite
|
2
4
|
class Action
|
3
|
-
class Rollback < defined?(ActiveRecord) ? ActiveRecord::Rollback : StandardError
|
4
|
-
end
|
5
|
-
|
6
5
|
module Transaction
|
7
6
|
extend ActiveSupport::Concern
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
def transactional(&block)
|
12
|
-
if transactional?
|
13
|
-
yield
|
14
|
-
else
|
15
|
-
@_transactional = true
|
16
|
-
result = transaction(&block) || false
|
17
|
-
@_transactional = nil
|
18
|
-
result
|
19
|
-
end
|
8
|
+
included do
|
9
|
+
define_callbacks :commit
|
20
10
|
end
|
21
11
|
|
22
|
-
|
23
|
-
|
24
|
-
|
12
|
+
module ClassMethods
|
13
|
+
delegate :transaction, to: :'Granite::Action::TransactionManager'
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
# Defines a callback which will be triggered right after transaction committed
|
18
|
+
# Uses the same arguments as `ActiveSupport::Callbacks.set_callback` except for the first two
|
19
|
+
#
|
20
|
+
def after_commit(*args, &block)
|
21
|
+
set_callback :commit, :after, *args, &block
|
22
|
+
end
|
25
23
|
end
|
26
24
|
|
27
|
-
def
|
28
|
-
if
|
29
|
-
ActiveRecord::Base.transaction(&block)
|
30
|
-
else
|
25
|
+
def run_callbacks(event)
|
26
|
+
if event.to_s == 'commit'
|
31
27
|
begin
|
32
|
-
|
33
|
-
rescue
|
34
|
-
|
28
|
+
super event
|
29
|
+
rescue *handled_exceptions => e
|
30
|
+
handle_exception(e)
|
35
31
|
end
|
32
|
+
else
|
33
|
+
super event
|
36
34
|
end
|
37
35
|
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def transaction(&block)
|
40
|
+
self.class.transaction(trigger_callbacks_for: self, &block)
|
41
|
+
end
|
38
42
|
end
|
39
43
|
end
|
40
44
|
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Granite
|
2
|
+
class Action
|
3
|
+
class Rollback < defined?(ActiveRecord) ? ActiveRecord::Rollback : StandardError
|
4
|
+
end
|
5
|
+
|
6
|
+
module TransactionManager
|
7
|
+
class << self
|
8
|
+
# Runs a block in a transaction
|
9
|
+
# It will open a new transaction or append a block to the current one if it exists
|
10
|
+
#
|
11
|
+
# @param [Object] trigger_callbacks_for - object which will receive `run_callbacks(:commit)` after transaction commited
|
12
|
+
# @return [Object] result of a block
|
13
|
+
def transaction(trigger_callbacks_for: nil, &block)
|
14
|
+
(callback_listeners << trigger_callbacks_for) if trigger_callbacks_for
|
15
|
+
|
16
|
+
if in_a_transaction?
|
17
|
+
yield
|
18
|
+
else
|
19
|
+
wrap_in_transaction_with_callbacks(&block)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
IN_A_TRANSACTION_KEY = :granite_transaction_manager_in_a_transaction
|
26
|
+
CALLBACK_LISTENERS_KEY = :granite_transaction_manager_callback_listeners
|
27
|
+
|
28
|
+
def callback_listeners
|
29
|
+
Thread.current[CALLBACK_LISTENERS_KEY] ||= []
|
30
|
+
end
|
31
|
+
|
32
|
+
def in_a_transaction?
|
33
|
+
!!(Thread.current[IN_A_TRANSACTION_KEY])
|
34
|
+
end
|
35
|
+
|
36
|
+
def in_a_transaction=(value)
|
37
|
+
Thread.current[IN_A_TRANSACTION_KEY] = value
|
38
|
+
end
|
39
|
+
|
40
|
+
def wrap_in_transaction_with_callbacks(&block)
|
41
|
+
self.in_a_transaction = true
|
42
|
+
|
43
|
+
result = wrap_in_transaction(&block) || false
|
44
|
+
|
45
|
+
trigger_callbacks if result
|
46
|
+
|
47
|
+
result
|
48
|
+
ensure
|
49
|
+
callback_listeners.clear
|
50
|
+
self.in_a_transaction = nil
|
51
|
+
end
|
52
|
+
|
53
|
+
def wrap_in_transaction(&block)
|
54
|
+
if defined?(ActiveRecord::Base)
|
55
|
+
ActiveRecord::Base.transaction(&block)
|
56
|
+
else
|
57
|
+
begin
|
58
|
+
yield
|
59
|
+
rescue Granite::Action::Rollback
|
60
|
+
false
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def trigger_callbacks
|
66
|
+
collected_errors = []
|
67
|
+
|
68
|
+
callback_listeners.reverse.each do |listener|
|
69
|
+
begin
|
70
|
+
listener.run_callbacks :commit
|
71
|
+
rescue StandardError => e
|
72
|
+
collected_errors << e
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
if collected_errors.any?
|
77
|
+
collected_errors[1..-1].each do |error|
|
78
|
+
ActiveData.config.logger.error "Unhandled error in callback: #{error.inspect}\n#{error.backtrace.join("\n")}"
|
79
|
+
end
|
80
|
+
fail collected_errors.first
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/granite/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: granite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arkadiy Zabazhanov & friends
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-08-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -280,6 +280,7 @@ files:
|
|
280
280
|
- lib/granite.rb
|
281
281
|
- lib/granite/action.rb
|
282
282
|
- lib/granite/action/error.rb
|
283
|
+
- lib/granite/action/exceptions_handling.rb
|
283
284
|
- lib/granite/action/performer.rb
|
284
285
|
- lib/granite/action/performing.rb
|
285
286
|
- lib/granite/action/policies.rb
|
@@ -292,6 +293,7 @@ files:
|
|
292
293
|
- lib/granite/action/projectors.rb
|
293
294
|
- lib/granite/action/subject.rb
|
294
295
|
- lib/granite/action/transaction.rb
|
296
|
+
- lib/granite/action/transaction_manager.rb
|
295
297
|
- lib/granite/action/types.rb
|
296
298
|
- lib/granite/action/types/collection.rb
|
297
299
|
- lib/granite/base.rb
|