-
Notifications
You must be signed in to change notification settings - Fork 368
/
Copy pathtransactional.go
58 lines (52 loc) · 2.45 KB
/
transactional.go
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
// Copyright © 2025 Ory Corp
// SPDX-License-Identifier: Apache-2.0
package storage
import "context"
// A storage provider that has support for transactions should implement this interface to ensure atomicity for certain flows
// that require transactional semantics. Fosite will call these methods (when atomicity is required) if and only if the storage
// provider has implemented `Transactional`. It is expected that the storage provider will examine context for an existing transaction
// each time a database operation is to be performed.
//
// An implementation of `BeginTX` should attempt to initiate a new transaction and store that under a unique key
// in the context that can be accessible by `Commit` and `Rollback`. The "transactional aware" context will then be
// returned for further propagation, eventually to be consumed by `Commit` or `Rollback` to finish the transaction.
//
// Implementations for `Commit` & `Rollback` should look for the transaction object inside the supplied context using the same
// key used by `BeginTX`. If these methods have been called, it is expected that a txn object should be available in the provided
// context.
type Transactional interface {
BeginTX(ctx context.Context) (context.Context, error)
Commit(ctx context.Context) error
Rollback(ctx context.Context) error
}
// MaybeBeginTx is a helper function that can be used to initiate a transaction if the supplied storage
// implements the `Transactional` interface.
func MaybeBeginTx(ctx context.Context, storage interface{}) (context.Context, error) {
// the type assertion checks whether the dynamic type of `storage` implements `Transactional`
txnStorage, transactional := storage.(Transactional)
if transactional {
return txnStorage.BeginTX(ctx)
} else {
return ctx, nil
}
}
// MaybeCommitTx is a helper function that can be used to commit a transaction if the supplied storage
// implements the `Transactional` interface.
func MaybeCommitTx(ctx context.Context, storage interface{}) error {
txnStorage, transactional := storage.(Transactional)
if transactional {
return txnStorage.Commit(ctx)
} else {
return nil
}
}
// MaybeRollbackTx is a helper function that can be used to rollback a transaction if the supplied storage
// implements the `Transactional` interface.
func MaybeRollbackTx(ctx context.Context, storage interface{}) error {
txnStorage, transactional := storage.(Transactional)
if transactional {
return txnStorage.Rollback(ctx)
} else {
return nil
}
}