blob: 7f82b8f6669265da87f93c5e0d36a38e4b745a63 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
module ActiveRecord
module ConnectionAdapters
module Transaction # :nodoc:
class State
attr_reader :connection
def initialize(connection)
@connection = connection
end
end
class Closed < State
def number
0
end
def begin
Open.new(connection, self)
end
def closed?
true
end
def open?
false
end
# This is a noop when there are no open transactions
def add_record(record)
end
end
class Open < State
attr_reader :parent, :records
def initialize(connection, parent)
super connection
@parent = parent
@records = []
@finishing = false
if parent.open?
connection.create_savepoint
else
connection.begin_db_transaction
end
end
def number
if finishing?
parent.number
else
parent.number + 1
end
end
# Database adapters expect that #open_transactions will be decremented
# before we've actually executed a COMMIT or ROLLBACK. This is kinda
# annoying, but for now we use this @finishing flag to toggle what value
# #number should return.
def finishing?
@finishing
end
def begin
Open.new(connection, self)
end
def rollback
@finishing = true
if parent.open?
connection.rollback_to_savepoint
else
connection.rollback_db_transaction
end
rollback_records
parent
end
def commit
@finishing = true
if parent.open?
connection.release_savepoint
records.each { |r| parent.add_record(r) }
else
connection.commit_db_transaction
commit_records
end
parent
end
def add_record(record)
records << record
end
def rollback_records
records.uniq.each do |record|
begin
record.rolledback!(parent.closed?)
rescue => e
record.logger.error(e) if record.respond_to?(:logger) && record.logger
end
end
end
def commit_records
records.uniq.each do |record|
begin
record.committed!
rescue => e
record.logger.error(e) if record.respond_to?(:logger) && record.logger
end
end
end
def closed?
false
end
def open?
true
end
end
end
end
end
|