Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSami Hiltunen <shiltunen@gitlab.com>2023-07-28 18:09:44 +0300
committerSami Hiltunen <shiltunen@gitlab.com>2023-09-26 20:10:28 +0300
commit3317e6d5f6c53032cf0e85efa456b3b1f43044e3 (patch)
tree9ceb2ecbc0314960dbc8fd5737b1a560f5d921d7
parent35611d3840341ad2d8534776719604be6413f69c (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.go51
-rw-r--r--internal/gitaly/storage/storagemgr/transaction_registry_test.go33
-rw-r--r--internal/gitaly/storage/transaction.go4
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