diff options
author | Sami Hiltunen <shiltunen@gitlab.com> | 2021-10-21 17:28:33 +0300 |
---|---|---|
committer | Sami Hiltunen <shiltunen@gitlab.com> | 2022-05-16 16:34:50 +0300 |
commit | aec4a9343a82c80b919bb081a86fa60d6115a6c7 (patch) | |
tree | c1f1ee958b0094650e47ce5b1dedacc53c129e3c /internal/praefect/router_per_repository.go | |
parent | 3e92c2cf29a757444e11b39f61e58a8820751e2a (diff) |
Generate unique replica paths for repositories
Renaming, creating and deleting repositories is racy in Praefect.
They can also partially fail in awkward ways due to Praefect first
applying the operations on the disks of the Gitalys and later updating
its metadata store. In order to make these operations atomic, there's
been ongoing work in the background to make it possible to perform these
in the database in a manner that races are not possible and partial
failures do not end up conflicting with future operations.
Renames can be fixed by doing the rename atomically in the database
without moving any repositories on the disks.
Deletes can be modeled as simply deleting the repository's database record.
Creates are atomic by creating the repository's database record as the
last step in the process.
The last piece of the puzzle is to ensure repositories always land in different
directories on the disk. This ensures that a partial failure doesn't block
a future operation from succeeding. This commit implements that piece by deriving
a unique path for each repository to store their replicas. Existing repositories
stay where they are but newly created repositories will land in unique directories.
Create might succeed on a disk but fail to be persisted in the database. Prior to
this change, attempting to recreate a repository might fail due to the stale state
on the disk. With this in place, the next attempt at creating the repository would
still succeed as the new attempt would land the repository in a different directory
on the disk.
Deletes have the same problem prior to this commit. The repository's metadata may
be successfully deleted but if we fail to delete the repository from the disk, future
creations and renames may fail if they conflict with the stale state. As creates now
always land in a different directory, the stale state no longer causes problems.
Renames will work purely in the database, so any stale state on the disk will not affect
them.
Changelog: fixed
Diffstat (limited to 'internal/praefect/router_per_repository.go')
-rw-r--r-- | internal/praefect/router_per_repository.go | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/internal/praefect/router_per_repository.go b/internal/praefect/router_per_repository.go index 6f1b4e7bd..7067cb36e 100644 --- a/internal/praefect/router_per_repository.go +++ b/internal/praefect/router_per_repository.go @@ -5,8 +5,11 @@ import ( "errors" "fmt" + "gitlab.com/gitlab-org/gitaly/v14/internal/git/housekeeping" + "gitlab.com/gitlab-org/gitaly/v14/internal/metadata/featureflag" "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/praefectutil" "google.golang.org/grpc" ) @@ -307,11 +310,19 @@ func (r *PerRepositoryRouter) RouteRepositoryCreation(ctx context.Context, virtu return RepositoryMutatorRoute{}, fmt.Errorf("reserve repository id: %w", err) } + replicaPath := relativePath + if featureflag.PraefectGeneratedReplicaPaths.IsEnabled(ctx) { + replicaPath = praefectutil.DeriveReplicaPath(id) + if housekeeping.IsRailsPoolPath(relativePath) { + replicaPath = praefectutil.DerivePoolPath(id) + } + } + replicationFactor := r.defaultReplicationFactors[virtualStorage] if replicationFactor == 1 { return RepositoryMutatorRoute{ RepositoryID: id, - ReplicaPath: relativePath, + ReplicaPath: replicaPath, Primary: primary, }, nil } @@ -360,7 +371,7 @@ func (r *PerRepositoryRouter) RouteRepositoryCreation(ctx context.Context, virtu return RepositoryMutatorRoute{ RepositoryID: id, - ReplicaPath: relativePath, + ReplicaPath: replicaPath, AdditionalReplicaPath: additionalReplicaPath, Primary: primary, Secondaries: secondaries, |