From 845a02c72d898110b37ec7ff1e501ea9790faa2d Mon Sep 17 00:00:00 2001 From: John Cai Date: Mon, 28 Mar 2022 16:45:22 -0400 Subject: internalgitaly: WalkRepos to return last accessed timestamp In order to make a decision on which repositories to clean up, Praefect's repocleaner will match repository paths with what it sees in the database. If it doesn't see a record in the database, that means Praefect doesn't know about this repository. However, it could be the case that a repository has just been created and the record for it doesn't yet exist in the database. In order for repocleaner to know, it needs the information to be returned from Gitaly. Add a field in the RPC response, and return the last modified date on the refs/ dir so we can use it as a proxy for when the repository was created. --- .../gitaly/service/internalgitaly/walkrepos.go | 9 ++++++- .../service/internalgitaly/walkrepos_test.go | 29 +++++++++++++++------- 2 files changed, 28 insertions(+), 10 deletions(-) (limited to 'internal/gitaly/service') diff --git a/internal/gitaly/service/internalgitaly/walkrepos.go b/internal/gitaly/service/internalgitaly/walkrepos.go index 08979f92b..71a023fdd 100644 --- a/internal/gitaly/service/internalgitaly/walkrepos.go +++ b/internal/gitaly/service/internalgitaly/walkrepos.go @@ -9,6 +9,7 @@ import ( "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/timestamppb" ) func (s *server) WalkRepos(req *gitalypb.WalkReposRequest, stream gitalypb.InternalGitaly_WalkReposServer) error { @@ -55,8 +56,14 @@ func walkStorage(ctx context.Context, storagePath string, stream gitalypb.Intern return err } + gitDirInfo, err := os.Stat(path) + if err != nil { + return err + } + if err := stream.Send(&gitalypb.WalkReposResponse{ - RelativePath: relPath, + RelativePath: relPath, + ModificationTime: timestamppb.New(gitDirInfo.ModTime()), }); err != nil { return err } diff --git a/internal/gitaly/service/internalgitaly/walkrepos_test.go b/internal/gitaly/service/internalgitaly/walkrepos_test.go index c4aad9fcd..23a3aaec4 100644 --- a/internal/gitaly/service/internalgitaly/walkrepos_test.go +++ b/internal/gitaly/service/internalgitaly/walkrepos_test.go @@ -6,6 +6,7 @@ import ( "path/filepath" "sync" "testing" + "time" "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitaly/v14/internal/git/gittest" @@ -42,16 +43,26 @@ func TestWalkRepos(t *testing.T) { // file walk happens lexicographically, so we delete repository in the middle // of the seqeuence to ensure the walk proceeds normally - testRepo1, _ := gittest.CloneRepo(t, cfg, cfg.Storages[0], gittest.CloneRepoOpts{ + testRepo1, testRepo1Path := gittest.CloneRepo(t, cfg, cfg.Storages[0], gittest.CloneRepoOpts{ RelativePath: "a", }) deletedRepo, _ := gittest.CloneRepo(t, cfg, cfg.Storages[0], gittest.CloneRepoOpts{ RelativePath: "b", }) - testRepo2, _ := gittest.CloneRepo(t, cfg, cfg.Storages[0], gittest.CloneRepoOpts{ + testRepo2, testRepo2Path := gittest.CloneRepo(t, cfg, cfg.Storages[0], gittest.CloneRepoOpts{ RelativePath: "c", }) + modifiedDate := time.Now().Add(-1 * time.Hour) + require.NoError( + t, + os.Chtimes(testRepo1Path, time.Now(), modifiedDate), + ) + require.NoError( + t, + os.Chtimes(testRepo2Path, time.Now(), modifiedDate), + ) + // to test a directory being deleted during a walk, we must delete a directory after // the file walk has started. To achieve that, we wrap the server to pass down a wrapped // stream that allows us to hook in to stream responses. We then delete 'b' when @@ -93,14 +104,14 @@ func TestWalkRepos(t *testing.T) { require.NoError(t, err) actualRepos := consumeWalkReposStream(t, stream) - require.Equal(t, []string{ - testRepo1.GetRelativePath(), - testRepo2.GetRelativePath(), - }, actualRepos) + require.Equal(t, testRepo1.GetRelativePath(), actualRepos[0].GetRelativePath()) + require.Equal(t, modifiedDate.UTC(), actualRepos[0].GetModificationTime().AsTime()) + require.Equal(t, testRepo2.GetRelativePath(), actualRepos[1].GetRelativePath()) + require.Equal(t, modifiedDate.UTC(), actualRepos[1].GetModificationTime().AsTime()) } -func consumeWalkReposStream(t *testing.T, stream gitalypb.InternalGitaly_WalkReposClient) []string { - var repos []string +func consumeWalkReposStream(t *testing.T, stream gitalypb.InternalGitaly_WalkReposClient) []*gitalypb.WalkReposResponse { + var repos []*gitalypb.WalkReposResponse for { resp, err := stream.Recv() if err == io.EOF { @@ -108,7 +119,7 @@ func consumeWalkReposStream(t *testing.T, stream gitalypb.InternalGitaly_WalkRep } else { require.NoError(t, err) } - repos = append(repos, resp.RelativePath) + repos = append(repos, resp) } return repos } -- cgit v1.2.3