Skip to content
Snippets Groups Projects
Commit 5a20e685 authored by Justin Tobler's avatar Justin Tobler
Browse files

objectpool: Cast transaction vote when repository already linked

If a repository is already linked to the object pool, cast a vote to
ensure that repository state is consistent among replicas.
parent 8182eb83
No related branches found
No related tags found
Loading
......@@ -2,6 +2,7 @@ package objectpool
import (
"context"
"errors"
"fmt"
"io"
"os"
......@@ -11,6 +12,7 @@ import (
"gitlab.com/gitlab-org/gitaly/v16/internal/git/localrepo"
"gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/transaction"
"gitlab.com/gitlab-org/gitaly/v16/internal/safe"
"gitlab.com/gitlab-org/gitaly/v16/internal/transaction/voting"
)
// Link will link the given repository to the object pool. This is done by writing the object pool's
......@@ -33,6 +35,12 @@ func (o *ObjectPool) Link(ctx context.Context, repo *localrepo.Repo) (returnedEr
}
if linked {
// When the repository is already linked to the repository, cast a vote to ensure the
// repository is consistent with the other replicas.
if err := transaction.VoteOnContext(ctx, o.txManager, voting.VoteFromData([]byte("repository linked")), voting.Committed); err != nil {
return fmt.Errorf("vote on linked repository: %w", err)
}
return nil
}
......@@ -148,7 +156,7 @@ func (o *ObjectPool) LinkedToRepository(repo *localrepo.Repo) (bool, error) {
relPath, err := getAlternateObjectDir(repo)
if err != nil {
if err == ErrAlternateObjectDirNotExist {
if errors.Is(err, ErrAlternateObjectDirNotExist) {
return false, nil
}
return false, err
......
......@@ -182,6 +182,32 @@ func TestLink(t *testing.T) {
}
},
},
{
desc: "transactional repository already linked",
setup: func(t *testing.T, ctx context.Context) setupData {
cfg, pool, repo := setupObjectPool(t, ctx)
// Inject transaction manager to record transactions.
txManager := transaction.NewTrackingManager()
pool.txManager = txManager
// When transactions are enabled, a vote is cast if the repository is already linked
// to the same object pool.
altPath, err := repo.InfoAlternatesPath()
require.NoError(t, err)
require.NoError(t, os.WriteFile(altPath, []byte(getRelAltPath(t, repo, pool.Repo)), perm.SharedFile))
return setupData{
cfg: cfg,
repo: repo,
pool: pool,
txManager: txManager,
expectedVotes: []transaction.PhasedVote{
{Vote: voting.VoteFromData([]byte("repository linked")), Phase: voting.Committed},
},
}
},
},
{
desc: "repository link transaction fails",
setup: func(t *testing.T, ctx context.Context) setupData {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment