@@ -10,13 +10,21 @@ import (
10
10
type DBTx struct {
11
11
database.Store
12
12
mu sync.Mutex
13
- err error
14
- errC chan error
13
+ done chan error
15
14
finalErr chan error
16
15
}
17
16
18
17
// StartTx starts a transaction and returns a DBTx object. This allows running
19
18
// 2 transactions concurrently in a test more easily.
19
+ // Example:
20
+ //
21
+ // a := StartTx(t, db, opts)
22
+ // b := StartTx(t, db, opts)
23
+ //
24
+ // a.GetUsers(...)
25
+ // b.GetUsers(...)
26
+ //
27
+ // require.NoError(t, a.Done()
20
28
func StartTx (t * testing.T , db database.Store , opts * database.TxOptions ) * DBTx {
21
29
errC := make (chan error )
22
30
finalErr := make (chan error )
@@ -34,31 +42,31 @@ func StartTx(t *testing.T, db database.Store, opts *database.TxOptions) *DBTx {
34
42
})
35
43
count ++
36
44
if count > 1 {
45
+ // If you recursively call InTx, then don't use this.
37
46
t .Logf ("InTx called more than once: %d" , count )
47
+ t .Fatal ("InTx called more than once, this is not allowed with the StartTx helper" )
38
48
}
39
- return <- errC
49
+
50
+ select {
51
+ case _ , _ = <- errC :
52
+ }
53
+ // Just return nil. The caller should be checking their own errors.
54
+ return nil
40
55
}, opts )
41
56
finalErr <- err
42
57
}()
43
58
44
59
txStore := <- txC
45
60
close (txC )
46
61
47
- return & DBTx {Store : txStore , errC : errC , finalErr : finalErr }
48
- }
49
-
50
- func (tx * DBTx ) SetError (err error ) {
51
- tx .mu .Lock ()
52
- defer tx .mu .Unlock ()
53
- tx .err = err
62
+ return & DBTx {Store : txStore , done : errC , finalErr : finalErr }
54
63
}
55
64
56
65
// Done can only be called once. If you call it twice, it will panic.
57
66
func (tx * DBTx ) Done () error {
58
67
tx .mu .Lock ()
59
68
defer tx .mu .Unlock ()
60
69
61
- tx .errC <- tx .err
62
- close (tx .errC )
70
+ close (tx .done )
63
71
return <- tx .finalErr
64
72
}
0 commit comments