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:
authorPatrick Steinhardt <psteinhardt@gitlab.com>2022-03-03 16:53:21 +0300
committerPatrick Steinhardt <psteinhardt@gitlab.com>2022-03-03 16:53:21 +0300
commit83081534f551a4a37ac3f841b35397d751026a2f (patch)
tree69b3cc76dde047729d0496c026890e988c716e91
parent5800949732ddaf48f31cf56353a0117e50d90571 (diff)
parent8d3767c71c82d56e96eaf4427ab8f230cc467ffe (diff)
Merge branch 'smh-repository-replicas-rewriting' into 'master'
Rewrite relative path in RepositoryReplicas See merge request gitlab-org/gitaly!4384
-rw-r--r--internal/praefect/info_service_test.go93
-rw-r--r--internal/praefect/service/info/repositories.go37
2 files changed, 75 insertions, 55 deletions
diff --git a/internal/praefect/info_service_test.go b/internal/praefect/info_service_test.go
index 0ed0e926b..f7a24610e 100644
--- a/internal/praefect/info_service_test.go
+++ b/internal/praefect/info_service_test.go
@@ -2,10 +2,10 @@ package praefect
import (
"math/rand"
- "path/filepath"
"testing"
"github.com/stretchr/testify/require"
+ "gitlab.com/gitlab-org/gitaly/v14/internal/backchannel"
"gitlab.com/gitlab-org/gitaly/v14/internal/git/gittest"
gconfig "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/config"
"gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/service"
@@ -14,6 +14,9 @@ import (
"gitlab.com/gitlab-org/gitaly/v14/internal/praefect/datastore"
"gitlab.com/gitlab-org/gitaly/v14/internal/praefect/nodes"
"gitlab.com/gitlab-org/gitaly/v14/internal/praefect/protoregistry"
+ "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/service/transaction"
+ "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/transactions"
+ "gitlab.com/gitlab-org/gitaly/v14/internal/sidechannel"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper/testcfg"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper/testdb"
@@ -24,15 +27,13 @@ import (
func TestInfoService_RepositoryReplicas(t *testing.T) {
t.Parallel()
+
var cfgs []gconfig.Cfg
var cfgNodes []*config.Node
- var testRepo *gitalypb.Repository
storages := []string{"g-1", "g-2", "g-3"}
+
for i, storage := range storages {
- cfg, repo, _ := testcfg.BuildWithRepo(t, testcfg.WithStorages(storage))
- if testRepo == nil {
- testRepo = repo
- }
+ cfg := testcfg.Build(t, testcfg.WithStorages(storage))
cfgs = append(cfgs, cfg)
cfgs[i].SocketPath = testserver.RunGitalyServer(t, cfgs[i], nil, func(srv *grpc.Server, deps *service.Dependencies) {
gitalypb.RegisterRepositoryServiceServer(srv, repository.NewServer(
@@ -60,27 +61,42 @@ func TestInfoService_RepositoryReplicas(t *testing.T) {
Failover: config.Failover{Enabled: true},
}
- // create a commit in the second replica so we can check that its checksum is different than the primary
- gittest.WriteCommit(t, cfgs[1], filepath.Join(cfgs[1].Storages[0].Path, testRepo.GetRelativePath()), gittest.WithBranch("master"))
ctx := testhelper.Context(t)
- tx := testdb.New(t).Begin(t)
- defer tx.Rollback(t)
+ db := testdb.New(t)
+ logger := testhelper.NewDiscardingLogEntry(t)
+ // the only thing used from the config is the grpc_latency_buckets which is not relevant for the test
+ txManager := transactions.NewManager(config.Config{})
+ sidechannelRegistry := sidechannel.NewRegistry()
+ nodeSet, err := DialNodes(
+ ctx,
+ conf.VirtualStorages,
+ protoregistry.GitalyProtoPreregistered,
+ nil,
+ backchannel.NewClientHandshaker(
+ logger,
+ NewBackchannelServerFactory(
+ logger,
+ transaction.NewServer(txManager),
+ sidechannelRegistry,
+ ),
+ ),
+ sidechannelRegistry,
+ )
+ require.NoError(t, err)
+ t.Cleanup(nodeSet.Close)
+ // Use a transaction in the elector itself to avoid flakiness due to the health timeout. We mark
+ // only the first repo has healthy so the elector picks it always as the primary.
+ tx := db.Begin(t)
+ t.Cleanup(func() { tx.Rollback(t) })
testdb.SetHealthyNodes(t, ctx, tx, map[string]map[string][]string{
- "praefect-0": {virtualStorage: storages},
+ "praefect-0": {virtualStorage: storages[0:1]},
})
-
- nodeSet, err := DialNodes(ctx, conf.VirtualStorages, protoregistry.GitalyProtoPreregistered, nil, nil, nil)
- require.NoError(t, err)
- defer nodeSet.Close()
-
elector := nodes.NewPerRepositoryElector(tx)
+
conns := nodeSet.Connections()
- rs := datastore.NewPostgresRepositoryStore(tx, conf.StorageNames())
- require.NoError(t,
- rs.CreateRepository(ctx, 1, virtualStorage, testRepo.GetRelativePath(), testRepo.GetRelativePath(), "g-1", []string{"g-2", "g-3"}, nil, true, false),
- )
+ rs := datastore.NewPostgresRepositoryStore(db, conf.StorageNames())
cc, _, cleanup := runPraefectServer(t, ctx, conf, buildOptions{
withConnections: conns,
@@ -91,33 +107,38 @@ func TestInfoService_RepositoryReplicas(t *testing.T) {
StaticHealthChecker{virtualStorage: storages},
NewLockedRandom(rand.New(rand.NewSource(0))),
rs,
- datastore.NewAssignmentStore(tx, conf.StorageNames()),
+ datastore.NewAssignmentStore(db, conf.StorageNames()),
rs,
conf.DefaultReplicationFactors(),
),
withPrimaryGetter: elector,
+ withTxMgr: txManager,
})
- defer cleanup()
+ // use cleanup to close the connections as gittest.CreateRepository will still use the connection
+ // for clean up after the test.
+ t.Cleanup(cleanup)
client := gitalypb.NewPraefectInfoServiceClient(cc)
+ testRepository, testRepoPath := gittest.CreateRepository(ctx, t,
+ // The helper was implemented with the test server in mind. Here we need use the virtual storage's name
+ // as the storage and the path of the storage we want to modify the replica in.
+ gconfig.Cfg{Storages: []gconfig.Storage{{Name: virtualStorage, Path: cfgs[1].Storages[0].Path}}},
+ gittest.CreateRepositoryConfig{Seed: gittest.SeedGitLabTest, ClientConn: cc},
+ )
+
+ // create a commit in the second replica so we can check that its checksum is different than the primary
+ gittest.WriteCommit(t, cfgs[1], testRepoPath, gittest.WithBranch("master"))
+
+ // Increment the generation of the unmodified repositories so the below CalculateChecksum calls goes to one of them
+ // as the test expects the primary to have that checksum.
+ require.NoError(t, rs.IncrementGeneration(ctx, 1, cfgs[0].Storages[0].Name, []string{cfgs[2].Storages[0].Name}))
+
// CalculateChecksum through praefect will get the checksum of the primary
- repoClient := gitalypb.NewRepositoryServiceClient(cc)
- checksum, err := repoClient.CalculateChecksum(ctx, &gitalypb.CalculateChecksumRequest{
- Repository: &gitalypb.Repository{
- StorageName: conf.VirtualStorages[0].Name,
- RelativePath: testRepo.GetRelativePath(),
- },
- })
+ checksum, err := gitalypb.NewRepositoryServiceClient(cc).CalculateChecksum(ctx, &gitalypb.CalculateChecksumRequest{Repository: testRepository})
require.NoError(t, err)
- resp, err := client.RepositoryReplicas(ctx, &gitalypb.RepositoryReplicasRequest{
- Repository: &gitalypb.Repository{
- StorageName: conf.VirtualStorages[0].Name,
- RelativePath: testRepo.GetRelativePath(),
- },
- })
-
+ resp, err := client.RepositoryReplicas(ctx, &gitalypb.RepositoryReplicasRequest{Repository: testRepository})
require.NoError(t, err)
require.Equal(t, checksum.Checksum, resp.Primary.Checksum)
diff --git a/internal/praefect/service/info/repositories.go b/internal/praefect/service/info/repositories.go
index ba6f1f90a..ec6bb1a4b 100644
--- a/internal/praefect/service/info/repositories.go
+++ b/internal/praefect/service/info/repositories.go
@@ -7,7 +7,6 @@ import (
"gitlab.com/gitlab-org/gitaly/v14/internal/helper"
"gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
"golang.org/x/sync/errgroup"
- "google.golang.org/grpc"
)
// RepositoryReplicas returns a list of repositories that includes the checksum of the primary as well as the replicas
@@ -30,6 +29,11 @@ func (s *Server) RepositoryReplicas(ctx context.Context, in *gitalypb.Repository
return nil, fmt.Errorf("get host assignments: %w", err)
}
+ replicaPath, err := s.rs.GetReplicaPath(ctx, repositoryID)
+ if err != nil {
+ return nil, fmt.Errorf("get replica path: %w", err)
+ }
+
secondaries := make([]string, 0, len(assignments)-1)
primaryIsAssigned := false
for _, assignment := range assignments {
@@ -47,7 +51,7 @@ func (s *Server) RepositoryReplicas(ctx context.Context, in *gitalypb.Repository
var resp gitalypb.RepositoryReplicasResponse
- if resp.Primary, err = s.getRepositoryDetails(ctx, virtualStorage, primary, relativePath); err != nil {
+ if resp.Primary, err = s.getRepositoryDetails(ctx, virtualStorage, primary, relativePath, replicaPath); err != nil {
return nil, helper.ErrInternal(err)
}
@@ -60,7 +64,7 @@ func (s *Server) RepositoryReplicas(ctx context.Context, in *gitalypb.Repository
storage := storage // rescoping
g.Go(func() error {
var err error
- resp.Replicas[i], err = s.getRepositoryDetails(ctx, virtualStorage, storage, relativePath)
+ resp.Replicas[i], err = s.getRepositoryDetails(ctx, virtualStorage, storage, relativePath, replicaPath)
return err
})
}
@@ -72,33 +76,28 @@ func (s *Server) RepositoryReplicas(ctx context.Context, in *gitalypb.Repository
return &resp, nil
}
-func (s *Server) getRepositoryDetails(ctx context.Context, virtualStorage, storage, relativePath string) (*gitalypb.RepositoryReplicasResponse_RepositoryDetails, error) {
+func (s *Server) getRepositoryDetails(ctx context.Context, virtualStorage, storage, relativePath, replicaPath string) (*gitalypb.RepositoryReplicasResponse_RepositoryDetails, error) {
conn, ok := s.conns[virtualStorage][storage]
if !ok {
return nil, fmt.Errorf("no connection to %q/%q", virtualStorage, storage)
}
- return getChecksum(
- ctx,
- &gitalypb.Repository{
- StorageName: storage,
- RelativePath: relativePath,
- }, conn)
-}
-
-func getChecksum(ctx context.Context, repo *gitalypb.Repository, cc *grpc.ClientConn) (*gitalypb.RepositoryReplicasResponse_RepositoryDetails, error) {
- client := gitalypb.NewRepositoryServiceClient(cc)
-
- resp, err := client.CalculateChecksum(ctx,
+ resp, err := gitalypb.NewRepositoryServiceClient(conn).CalculateChecksum(ctx,
&gitalypb.CalculateChecksumRequest{
- Repository: repo,
+ Repository: &gitalypb.Repository{
+ StorageName: storage,
+ RelativePath: replicaPath,
+ },
})
if err != nil {
return nil, err
}
return &gitalypb.RepositoryReplicasResponse_RepositoryDetails{
- Repository: repo,
- Checksum: resp.GetChecksum(),
+ Repository: &gitalypb.Repository{
+ StorageName: storage,
+ RelativePath: relativePath,
+ },
+ Checksum: resp.GetChecksum(),
}, nil
}