diff options
author | Sami Hiltunen <shiltunen@gitlab.com> | 2023-07-28 18:09:44 +0300 |
---|---|---|
committer | Sami Hiltunen <shiltunen@gitlab.com> | 2023-09-26 20:10:28 +0300 |
commit | 3317e6d5f6c53032cf0e85efa456b3b1f43044e3 (patch) | |
tree | 9ceb2ecbc0314960dbc8fd5737b1a560f5d921d7 | |
parent | 35611d3840341ad2d8534776719604be6413f69c (diff) |
Implement a transaction registry
While generally the transaction would be accessible directly within a
request's context, transactions need to be referenceable across the process
boundary as well. Hooks for example involve stepping out from the main
Gitaly process and back in. When executing the hooks, we need to be able
to retrieve the transaction this hooks call is connected to. This commit
implements a simple registry where the transactions can be stored when
they are began and retrieved from later on. The hook payload can carry
the transaction ID and use it to retrieve the transaction object from
the registry when executing the hook.
`TransactionID` type is in the storage package to avoid cyclic
dependencies between the packages that will need it.
-rw-r--r-- | internal/gitaly/storage/storagemgr/transaction_registry.go | 51 | ||||
-rw-r--r-- | internal/gitaly/storage/storagemgr/transaction_registry_test.go | 33 | ||||
-rw-r--r-- | internal/gitaly/storage/transaction.go | 4 |
3 files changed, 88 insertions, 0 deletions
diff --git a/internal/gitaly/storage/storagemgr/transaction_registry.go b/internal/gitaly/storage/storagemgr/transaction_registry.go new file mode 100644 index 000000000..b11508acc --- /dev/null +++ b/internal/gitaly/storage/storagemgr/transaction_registry.go @@ -0,0 +1,51 @@ +package storagemgr + +import ( + "errors" + "sync" + + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" +) + +var errTransactionNotFound = errors.New("transaction not found") + +// TransactionRegistry stores references to transactions by their ID. +type TransactionRegistry struct { + m sync.RWMutex + idSequence storage.TransactionID + transactions map[storage.TransactionID]*Transaction +} + +// NewTransactionRegistry returns a new TransactionRegistry. +func NewTransactionRegistry() *TransactionRegistry { + return &TransactionRegistry{ + transactions: make(map[storage.TransactionID]*Transaction), + } +} + +func (r *TransactionRegistry) register(tx *Transaction) storage.TransactionID { + r.m.Lock() + defer r.m.Unlock() + + r.idSequence++ + r.transactions[r.idSequence] = tx + return r.idSequence +} + +func (r *TransactionRegistry) unregister(id storage.TransactionID) { + r.m.Lock() + defer r.m.Unlock() + delete(r.transactions, id) +} + +// Get retrieves a transaction by its ID. An error when a transaction is not found. +func (r *TransactionRegistry) Get(id storage.TransactionID) (*Transaction, error) { + r.m.RLock() + defer r.m.RUnlock() + tx, ok := r.transactions[id] + if !ok { + return nil, errTransactionNotFound + } + + return tx, nil +} diff --git a/internal/gitaly/storage/storagemgr/transaction_registry_test.go b/internal/gitaly/storage/storagemgr/transaction_registry_test.go new file mode 100644 index 000000000..f1f0dddaa --- /dev/null +++ b/internal/gitaly/storage/storagemgr/transaction_registry_test.go @@ -0,0 +1,33 @@ +package storagemgr + +import ( + "testing" + + "github.com/stretchr/testify/require" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" +) + +func TestTransactionRegistry(t *testing.T) { + registry := NewTransactionRegistry() + + expectedTX1 := &Transaction{} + txID1 := registry.register(expectedTX1) + require.Equal(t, txID1, storage.TransactionID(1)) + + expectedTX2 := &Transaction{} + txID2 := registry.register(expectedTX2) + require.Equal(t, txID2, storage.TransactionID(2)) + + actualTX, err := registry.Get(txID1) + require.NoError(t, err) + require.Same(t, expectedTX1, actualTX) + + registry.unregister(txID1) + actualTX, err = registry.Get(txID1) + require.Equal(t, errTransactionNotFound, err) + require.Nil(t, actualTX) + + actualTX, err = registry.Get(txID2) + require.NoError(t, err) + require.Same(t, expectedTX2, actualTX) +} diff --git a/internal/gitaly/storage/transaction.go b/internal/gitaly/storage/transaction.go new file mode 100644 index 000000000..c113ddbb8 --- /dev/null +++ b/internal/gitaly/storage/transaction.go @@ -0,0 +1,4 @@ +package storage + +// TransactionID is an ID that uniquely identifies a Transaction. +type TransactionID uint64 |