diff options
author | Patrick Steinhardt <psteinhardt@gitlab.com> | 2020-07-20 08:41:13 +0300 |
---|---|---|
committer | Patrick Steinhardt <psteinhardt@gitlab.com> | 2020-07-20 09:55:41 +0300 |
commit | a965a24b38c521b81378e15a25ec9cbde9cbb62f (patch) | |
tree | 44d2d7cc225b08b669f9681e1ca70d14af24d6a8 | |
parent | 783d33d4c873997e92fb79e2ff889913101c59ad (diff) |
transactions: Make transaction type public
Currently, users of transactions only interact with a transaction via
the proxy of its identifier. While it worked just fine in the beginning
where transactions didn't really do a lot, they start to become more
complex and thus carry more information that may be of interest to the
user.
So let's make the transaction type public as a preparatory step to
returning it directly when registering a transaction instead of
returning its identifier, only. In order to avoid abuse of transactions,
only accessors are made public.
-rw-r--r-- | internal/praefect/transactions/manager.go | 10 | ||||
-rw-r--r-- | internal/praefect/transactions/transaction.go | 27 |
2 files changed, 23 insertions, 14 deletions
diff --git a/internal/praefect/transactions/manager.go b/internal/praefect/transactions/manager.go index 719d4826c..e33ec1c06 100644 --- a/internal/praefect/transactions/manager.go +++ b/internal/praefect/transactions/manager.go @@ -24,7 +24,7 @@ var ErrNotFound = errors.New("transaction not found") type Manager struct { txIDGenerator TransactionIDGenerator lock sync.Mutex - transactions map[uint64]*transaction + transactions map[uint64]*Transaction counterMetric *prometheus.CounterVec delayMetric metrics.HistogramVec subtransactionsMetric metrics.Histogram @@ -92,7 +92,7 @@ func WithTransactionIDGenerator(generator TransactionIDGenerator) ManagerOpt { func NewManager(opts ...ManagerOpt) *Manager { mgr := &Manager{ txIDGenerator: newTransactionIDGenerator(), - transactions: make(map[uint64]*transaction), + transactions: make(map[uint64]*Transaction), counterMetric: prometheus.NewCounterVec(prometheus.CounterOpts{}, []string{"action"}), delayMetric: prometheus.NewHistogramVec(prometheus.HistogramOpts{}, []string{"action"}), subtransactionsMetric: prometheus.NewHistogram(prometheus.HistogramOpts{}), @@ -129,7 +129,7 @@ func (mgr *Manager) RegisterTransaction(ctx context.Context, voters []Voter, thr // nodes still have in-flight transactions. transactionID := mgr.txIDGenerator.ID() - transaction, err := newTransaction(voters, threshold) + transaction, err := newTransaction(transactionID, voters, threshold) if err != nil { return 0, nil, err } @@ -151,14 +151,14 @@ func (mgr *Manager) RegisterTransaction(ctx context.Context, voters []Voter, thr }, nil } -func (mgr *Manager) cancelTransaction(transactionID uint64, transaction *transaction) (map[string]bool, error) { +func (mgr *Manager) cancelTransaction(transactionID uint64, transaction *Transaction) (map[string]bool, error) { mgr.lock.Lock() defer mgr.lock.Unlock() delete(mgr.transactions, transactionID) transaction.cancel() - mgr.subtransactionsMetric.Observe(float64(transaction.countSubtransactions())) + mgr.subtransactionsMetric.Observe(float64(transaction.CountSubtransactions())) return transaction.State(), nil } diff --git a/internal/praefect/transactions/transaction.go b/internal/praefect/transactions/transaction.go index 90dc877cb..388625a83 100644 --- a/internal/praefect/transactions/transaction.go +++ b/internal/praefect/transactions/transaction.go @@ -34,11 +34,12 @@ type Voter struct { result voteResult } -// transaction is a session where a set of voters votes on one or more +// Transaction is a session where a set of voters votes on one or more // subtransactions. Subtransactions are a sequence of sessions, where each node // needs to go through the same sequence and agree on the same thing in the end // in order to have the complete transaction succeed. -type transaction struct { +type Transaction struct { + id uint64 threshold uint voters []Voter @@ -46,7 +47,7 @@ type transaction struct { subtransactions []*subtransaction } -func newTransaction(voters []Voter, threshold uint) (*transaction, error) { +func newTransaction(id uint64, voters []Voter, threshold uint) (*Transaction, error) { if len(voters) == 0 { return nil, ErrMissingNodes } @@ -74,13 +75,14 @@ func newTransaction(voters []Voter, threshold uint) (*transaction, error) { return nil, ErrInvalidThreshold } - return &transaction{ + return &Transaction{ + id: id, threshold: threshold, voters: voters, }, nil } -func (t *transaction) cancel() { +func (t *Transaction) cancel() { t.lock.Lock() defer t.lock.Unlock() @@ -89,10 +91,15 @@ func (t *transaction) cancel() { } } +// ID returns the identifier used to uniquely identify a transaction. +func (t *Transaction) ID() uint64 { + return t.id +} + // State returns the voting state mapped by voters. A voting state of `true` // means all subtransactions were successful, a voting state of `false` means // either no subtransactions were created or any of the subtransactions failed. -func (t *transaction) State() map[string]bool { +func (t *Transaction) State() map[string]bool { t.lock.Lock() defer t.lock.Unlock() @@ -115,7 +122,9 @@ func (t *transaction) State() map[string]bool { return results } -func (t *transaction) countSubtransactions() int { +// CountSubtransactions counts the number of subtransactions created as part of +// the transaction. +func (t *Transaction) CountSubtransactions() int { return len(t.subtransactions) } @@ -123,7 +132,7 @@ func (t *transaction) countSubtransactions() int { // node hasn't yet voted on or creates a new one if the node has succeeded on // all subtransactions. In case the node has failed on any of the // subtransactions, an error will be returned. -func (t *transaction) getOrCreateSubtransaction(node string) (*subtransaction, error) { +func (t *Transaction) getOrCreateSubtransaction(node string) (*subtransaction, error) { t.lock.Lock() defer t.lock.Unlock() @@ -161,7 +170,7 @@ func (t *transaction) getOrCreateSubtransaction(node string) (*subtransaction, e return subtransaction, nil } -func (t *transaction) vote(ctx context.Context, node string, hash []byte) error { +func (t *Transaction) vote(ctx context.Context, node string, hash []byte) error { subtransaction, err := t.getOrCreateSubtransaction(node) if err != nil { return err |