diff --git a/internal/backup/partition_backup.go b/internal/backup/partition_backup.go index f2db683d6e93e81d24d7325417250256f5862889..ba2d7cb2072142f1b77ce096ac27072c7d535a1c 100644 --- a/internal/backup/partition_backup.go +++ b/internal/backup/partition_backup.go @@ -3,6 +3,7 @@ package backup import ( "context" "fmt" + "sync" "sync/atomic" "time" @@ -11,8 +12,7 @@ import ( "gitlab.com/gitlab-org/gitaly/v16/internal/log" "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" "golang.org/x/sync/errgroup" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/timestamppb" ) const ( @@ -108,19 +108,31 @@ func (pbm *PartitionBackupManager) Create(ctx context.Context, serverInfo storag return fmt.Errorf("create partition client: %w", err) } - g, ctx := errgroup.WithContext(ctx) + g, gCtx := errgroup.WithContext(ctx) partitionChan := make(chan *gitalypb.Partition) var successCount, errCount atomic.Uint64 + // Create a slice to store successful backups + var successfulBackups []*gitalypb.PartitionBackupInfo + var mu sync.Mutex + for i := 0; i < pbm.concurrencyLimit; i++ { g.Go(func() error { for partition := range partitionChan { - err := pbm.backupPartition(ctx, client, storageName, partition.GetId()) + backupResponse, err := pbm.backupPartition(gCtx, client, storageName, partition.GetId()) if err != nil { logger.Error(fmt.Sprintf("backup partition %s failed: %v", partition.GetId(), err)) errCount.Add(1) } else { successCount.Add(1) + // Store successful backup info + mu.Lock() + successfulBackups = append(successfulBackups, &gitalypb.PartitionBackupInfo{ + PartitionId: partition.GetId(), + BackupRelativePath: backupResponse.GetBackupRelativePath(), + Timestamp: timestamppb.Now(), + }) + mu.Unlock() } } return nil @@ -129,11 +141,26 @@ func (pbm *PartitionBackupManager) Create(ctx context.Context, serverInfo storag g.Go(func() error { defer close(partitionChan) - return pbm.listAndQueuePartitions(ctx, client, storageName, partitionChan, logger) + return pbm.listAndQueuePartitions(gCtx, client, storageName, partitionChan, logger) }) err = g.Wait() + // Update manifest with successful backups + if len(successfulBackups) > 0 { + _, updateErr := client.CreatePartitionBackupManifest(ctx, &gitalypb.CreatePartitionBackupManifestRequest{ + StorageName: storageName, + Timestamp: timestamppb.Now(), + Partitions: successfulBackups, + }) + if updateErr != nil { + logger.Error(fmt.Sprintf("failed to update manifest: %v", updateErr)) + // Decide whether to return this error or just log it + } else { + logger.Info("successfully updated backup manifest") + } + } + success := successCount.Load() failure := errCount.Load() logger.Info(fmt.Sprintf("Partition backup completed: %d succeeded, %d failed", success, failure)) @@ -145,21 +172,16 @@ func (pbm *PartitionBackupManager) Create(ctx context.Context, serverInfo storag return err } -func (pbm *PartitionBackupManager) backupPartition(ctx context.Context, client gitalypb.PartitionServiceClient, storageName string, partitionID string) error { +func (pbm *PartitionBackupManager) backupPartition(ctx context.Context, client gitalypb.PartitionServiceClient, storageName string, partitionID string) (*gitalypb.BackupPartitionResponse, error) { backupCtx, backupCancel := context.WithTimeout(ctx, pbm.backupTimeout) defer backupCancel() - _, err := client.BackupPartition(backupCtx, &gitalypb.BackupPartitionRequest{ + response, err := client.BackupPartition(backupCtx, &gitalypb.BackupPartitionRequest{ StorageName: storageName, PartitionId: partitionID, }) - if status.Code(err) == codes.AlreadyExists { - // If there is an up to date backup for the partition, we consider this as successful operation. - return nil - } - - return err + return response, err } func (pbm *PartitionBackupManager) listAndQueuePartitions(ctx context.Context, client gitalypb.PartitionServiceClient, storageName string, workQueue chan<- *gitalypb.Partition, logger log.Logger) error { diff --git a/internal/backup/partition_backup_test.go b/internal/backup/partition_backup_test.go index 44a3cba1b5d6f5246bdc78413c5250f585bedd3d..0e1f1846785e6ce21763955927c206a387ea00b8 100644 --- a/internal/backup/partition_backup_test.go +++ b/internal/backup/partition_backup_test.go @@ -111,7 +111,7 @@ func TestPartitionBackup_CreateSuccess(t *testing.T) { require.NoError(t, err) for _, expectedArchive := range tc.expectedArchives { - tarPath := filepath.Join(backupRoot, cfg.Storages[0].Name, expectedArchive, storage.LSN(1).String()) + ".tar" + tarPath := filepath.Join(backupRoot, "partition-backups", cfg.Storages[0].Name, expectedArchive, storage.LSN(1).String()) + ".tar" tar, err := os.Open(tarPath) require.NoError(t, err) testhelper.MustClose(t, tar) @@ -283,3 +283,7 @@ func (m *mockPartitionServiceClient) BackupPartition(ctx context.Context, req *g return &gitalypb.BackupPartitionResponse{}, nil } + +func (m *mockPartitionServiceClient) CreatePartitionBackupManifest(ctx context.Context, req *gitalypb.CreatePartitionBackupManifestRequest, opts ...grpc.CallOption) (*gitalypb.CreatePartitionBackupManifestResponse, error) { + return &gitalypb.CreatePartitionBackupManifestResponse{}, nil +} diff --git a/internal/cli/gitalybackup/partition_test.go b/internal/cli/gitalybackup/partition_test.go index 29e0bc7f24e5f2ad24b580610452a0560e8cd5a6..7de474e8e28166389312a4f0e6290694a642b633 100644 --- a/internal/cli/gitalybackup/partition_test.go +++ b/internal/cli/gitalybackup/partition_test.go @@ -110,7 +110,7 @@ func TestPartitionSubcommand_Create(t *testing.T) { require.NoError(t, err) lsn := storage.LSN(1) - tarPath := filepath.Join(path, cfg.Storages[0].Name, "2", lsn.String()) + ".tar" + tarPath := filepath.Join(path, "partition-backups", cfg.Storages[0].Name, "2", lsn.String()) + ".tar" tar, err := os.Open(tarPath) require.NoError(t, err) defer testhelper.MustClose(t, tar) diff --git a/internal/gitaly/service/partition/backup_partition.go b/internal/gitaly/service/partition/backup_partition.go index c6dff46e72cdf397d7549f974a1d036657473621..e94ba84e19533e2daa2eb4d2d4ade8857019d628 100644 --- a/internal/gitaly/service/partition/backup_partition.go +++ b/internal/gitaly/service/partition/backup_partition.go @@ -27,14 +27,16 @@ func (s *server) BackupPartition(ctx context.Context, in *gitalypb.BackupPartiti return nil, structerr.NewInternal("backup partition: transaction not initialized") } - backupRelativePath := filepath.Join(in.GetStorageName(), in.GetPartitionId(), lsn+".tar") + backupRelativePath := filepath.Join("partition-backups", in.GetStorageName(), in.GetPartitionId(), lsn+".tar") exists, err := s.backupSink.Exists(ctx, backupRelativePath) if err != nil { return nil, fmt.Errorf("backup exists: %w", err) } if exists { - return nil, structerr.NewAlreadyExists("there is an up-to-date backup for the given partition") + return &gitalypb.BackupPartitionResponse{ + BackupRelativePath: backupRelativePath, + }, nil } // Create a new context to abort the write on failure. @@ -60,5 +62,7 @@ func (s *server) BackupPartition(ctx context.Context, in *gitalypb.BackupPartiti return nil, fmt.Errorf("write tarball: %w", err) } - return &gitalypb.BackupPartitionResponse{}, nil + return &gitalypb.BackupPartitionResponse{ + BackupRelativePath: backupRelativePath, + }, nil } diff --git a/internal/gitaly/service/partition/backup_partition_test.go b/internal/gitaly/service/partition/backup_partition_test.go index 0d6dbc08e928e0ee0d597fd0287f93b96e1586eb..3d79d44cc21ca1eba4e820d3228d1ab2325f14f8 100644 --- a/internal/gitaly/service/partition/backup_partition_test.go +++ b/internal/gitaly/service/partition/backup_partition_test.go @@ -134,10 +134,12 @@ func TestBackupPartition(t *testing.T) { } require.NoError(t, err) - testhelper.ProtoEqual(t, &gitalypb.BackupPartitionResponse{}, resp) + testhelper.ProtoEqual(t, &gitalypb.BackupPartitionResponse{ + BackupRelativePath: filepath.Join("partition-backups", "default", "2", "0000000000002.tar"), + }, resp) lsn := storage.LSN(2) - tarPath := filepath.Join(backupRoot, data.storageName, data.partitionID, lsn.String()) + ".tar" + tarPath := filepath.Join(backupRoot, "partition-backups", data.storageName, data.partitionID, lsn.String()) + ".tar" tar, err := os.Open(tarPath) require.NoError(t, err) defer testhelper.MustClose(t, tar) @@ -166,7 +168,7 @@ func TestBackupPartition_BackupExists(t *testing.T) { testserver.WithBackupSink(backupSink), ) - _, err = ptnClient.BackupPartition(ctx, &gitalypb.BackupPartitionRequest{ + resp, err := ptnClient.BackupPartition(ctx, &gitalypb.BackupPartitionRequest{ StorageName: "default", PartitionId: "1", }) @@ -180,11 +182,14 @@ func TestBackupPartition_BackupExists(t *testing.T) { return } - // Calling the same backup again should fail as it already exists - _, err = ptnClient.BackupPartition(ctx, &gitalypb.BackupPartitionRequest{ + backupRelativePath := filepath.Join("partition-backups", "default", "1", "0000000000000.tar") + require.Equal(t, backupRelativePath, resp.GetBackupRelativePath()) + + // Calling the same backup again should not fail + resp, err = ptnClient.BackupPartition(ctx, &gitalypb.BackupPartitionRequest{ StorageName: "default", PartitionId: "1", }) - - testhelper.RequireGrpcError(t, structerr.NewAlreadyExists("there is an up-to-date backup for the given partition"), err) + require.NoError(t, err) + require.Equal(t, backupRelativePath, resp.GetBackupRelativePath()) } diff --git a/internal/gitaly/service/partition/create_partition_backup_manifest.go b/internal/gitaly/service/partition/create_partition_backup_manifest.go new file mode 100644 index 0000000000000000000000000000000000000000..e07b6351799fa411892f79552d8f4e008d94b564 --- /dev/null +++ b/internal/gitaly/service/partition/create_partition_backup_manifest.go @@ -0,0 +1,79 @@ +package partition + +import ( + "context" + "encoding/json" + "fmt" + "path/filepath" + "time" + + "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" + "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" +) + +// CreatePartitionBackupManifest creates the manifest for locating backups. +func (s *server) CreatePartitionBackupManifest(ctx context.Context, in *gitalypb.CreatePartitionBackupManifestRequest) (_ *gitalypb.CreatePartitionBackupManifestResponse, returnErr error) { + if s.backupSink == nil { + return nil, structerr.NewFailedPrecondition("create partition backup manifest: server-side backups are not configured") + } + + manifestRelativePath := filepath.Join("partition-manifests", in.GetStorageName(), in.GetTimestamp().AsTime().String()+".json") + + exists, err := s.backupSink.Exists(ctx, manifestRelativePath) + if err != nil || exists { + return nil, fmt.Errorf("manifest exists: %w", err) + } + + // Create a new context to abort the write on failure. + writeCtx, cancelWrite := context.WithCancel(ctx) + defer cancelWrite() + + w, err := s.backupSink.GetWriter(writeCtx, manifestRelativePath) + if err != nil { + return nil, fmt.Errorf("get backup writer: %w", err) + } + defer func() { + if returnErr != nil { + // End the context before calling Close to ensure we don't persist the failed + // write to object storage. + cancelWrite() + } + if err := w.Close(); err != nil && returnErr == nil { + returnErr = fmt.Errorf("close manifest writer: %w", err) + } + }() + + encoder := json.NewEncoder(w) + + // Write the global timestamp entry + if err := encoder.Encode(struct { + Timestamp time.Time `json:"timestamp"` + }{ + Timestamp: in.GetTimestamp().AsTime(), + }); err != nil { + return nil, fmt.Errorf("encode manifest timestamp: %w", err) + } + + // Process each partition backup + for _, partition := range in.GetPartitions() { + entry := ManifestEntry{ + PartitionID: partition.GetPartitionId(), + BackupRelativePath: partition.GetBackupRelativePath(), + Timestamp: partition.GetTimestamp().AsTime(), + } + + // Encode and write the entry + if err := encoder.Encode(entry); err != nil { + return nil, fmt.Errorf("encode manifest entry: %w", err) + } + } + + return &gitalypb.CreatePartitionBackupManifestResponse{}, nil +} + +// ManifestEntry is the representation of the backup manifest entry. +type ManifestEntry struct { + PartitionID string `json:"partition_id"` + BackupRelativePath string `json:"backup_relative_path"` + Timestamp time.Time `json:"timestamp"` +} diff --git a/proto/go/gitalypb/partition.pb.go b/proto/go/gitalypb/partition.pb.go index 29ee8b493a6b42e885c516abfdebd220cc9db4c4..d6d54c7d15171c4c5dbe0a9b402730ca41cb01d9 100644 --- a/proto/go/gitalypb/partition.pb.go +++ b/proto/go/gitalypb/partition.pb.go @@ -9,6 +9,7 @@ package gitalypb import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" reflect "reflect" sync "sync" ) @@ -82,6 +83,9 @@ type BackupPartitionResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + // backup_relative_path contains the relative path to the backup. + BackupRelativePath string `protobuf:"bytes,1,opt,name=backup_relative_path,json=backupRelativePath,proto3" json:"backup_relative_path,omitempty"` } func (x *BackupPartitionResponse) Reset() { @@ -114,6 +118,13 @@ func (*BackupPartitionResponse) Descriptor() ([]byte, []int) { return file_partition_proto_rawDescGZIP(), []int{1} } +func (x *BackupPartitionResponse) GetBackupRelativePath() string { + if x != nil { + return x.BackupRelativePath + } + return "" +} + // ListPartitionsRequest is a request for the ListPartitions RPC. type ListPartitionsRequest struct { state protoimpl.MessageState @@ -228,56 +239,262 @@ func (x *ListPartitionsResponse) GetPaginationCursor() *PaginationCursor { return nil } +// CreatePartitionBackupManifestRequest is a request for the CreatePartitionBackupManifest RPC. +type CreatePartitionBackupManifestRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // storage_name is the name of the storage containing the archived partitions. + StorageName string `protobuf:"bytes,1,opt,name=storage_name,json=storageName,proto3" json:"storage_name,omitempty"` + // timestamp is the global time of the backup. + Timestamp *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + // partitions contains the list of partitions that are archived. + Partitions []*PartitionBackupInfo `protobuf:"bytes,3,rep,name=partitions,proto3" json:"partitions,omitempty"` +} + +func (x *CreatePartitionBackupManifestRequest) Reset() { + *x = CreatePartitionBackupManifestRequest{} + mi := &file_partition_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreatePartitionBackupManifestRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreatePartitionBackupManifestRequest) ProtoMessage() {} + +func (x *CreatePartitionBackupManifestRequest) ProtoReflect() protoreflect.Message { + mi := &file_partition_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreatePartitionBackupManifestRequest.ProtoReflect.Descriptor instead. +func (*CreatePartitionBackupManifestRequest) Descriptor() ([]byte, []int) { + return file_partition_proto_rawDescGZIP(), []int{4} +} + +func (x *CreatePartitionBackupManifestRequest) GetStorageName() string { + if x != nil { + return x.StorageName + } + return "" +} + +func (x *CreatePartitionBackupManifestRequest) GetTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.Timestamp + } + return nil +} + +func (x *CreatePartitionBackupManifestRequest) GetPartitions() []*PartitionBackupInfo { + if x != nil { + return x.Partitions + } + return nil +} + +// PartitionBackupInfo metadata for the partition that is archived +type PartitionBackupInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // timestamp is the time of the partition backup. + Timestamp *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + // partition_id is the identifier of the partition. + PartitionId string `protobuf:"bytes,2,opt,name=partition_id,json=partitionId,proto3" json:"partition_id,omitempty"` + // backup_relative_path contains the relative path to the backup. + BackupRelativePath string `protobuf:"bytes,3,opt,name=backup_relative_path,json=backupRelativePath,proto3" json:"backup_relative_path,omitempty"` +} + +func (x *PartitionBackupInfo) Reset() { + *x = PartitionBackupInfo{} + mi := &file_partition_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PartitionBackupInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PartitionBackupInfo) ProtoMessage() {} + +func (x *PartitionBackupInfo) ProtoReflect() protoreflect.Message { + mi := &file_partition_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PartitionBackupInfo.ProtoReflect.Descriptor instead. +func (*PartitionBackupInfo) Descriptor() ([]byte, []int) { + return file_partition_proto_rawDescGZIP(), []int{5} +} + +func (x *PartitionBackupInfo) GetTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.Timestamp + } + return nil +} + +func (x *PartitionBackupInfo) GetPartitionId() string { + if x != nil { + return x.PartitionId + } + return "" +} + +func (x *PartitionBackupInfo) GetBackupRelativePath() string { + if x != nil { + return x.BackupRelativePath + } + return "" +} + +// CreatePartitionBackupManifestResponse is a response for the CreatePartitionBackupManifest RPC. +type CreatePartitionBackupManifestResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *CreatePartitionBackupManifestResponse) Reset() { + *x = CreatePartitionBackupManifestResponse{} + mi := &file_partition_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreatePartitionBackupManifestResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreatePartitionBackupManifestResponse) ProtoMessage() {} + +func (x *CreatePartitionBackupManifestResponse) ProtoReflect() protoreflect.Message { + mi := &file_partition_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreatePartitionBackupManifestResponse.ProtoReflect.Descriptor instead. +func (*CreatePartitionBackupManifestResponse) Descriptor() ([]byte, []int) { + return file_partition_proto_rawDescGZIP(), []int{6} +} + var File_partition_proto protoreflect.FileDescriptor var file_partition_proto_rawDesc = []byte{ 0x0a, 0x0f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x06, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x1a, 0x0a, 0x6c, 0x69, 0x6e, 0x74, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0c, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0x6a, 0x0a, 0x16, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x50, 0x61, 0x72, - 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, - 0x0c, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x04, 0x88, 0xc6, 0x2c, 0x01, 0x52, 0x0b, 0x73, 0x74, 0x6f, 0x72, 0x61, - 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0c, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x04, 0xa8, 0xc6, - 0x2c, 0x01, 0x52, 0x0b, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, - 0x19, 0x0a, 0x17, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x8a, 0x01, 0x0a, 0x15, 0x4c, - 0x69, 0x73, 0x74, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0c, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x04, 0x88, 0xc6, 0x2c, 0x01, - 0x52, 0x0b, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x48, 0x0a, - 0x11, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x72, 0x61, - 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, - 0x79, 0x2e, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, 0x10, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x92, 0x01, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, - 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x31, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, - 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x74, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x45, 0x0a, 0x11, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x18, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x52, 0x10, 0x70, 0x61, 0x67, 0x69, - 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x32, 0xcb, 0x01, 0x0a, - 0x10, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x12, 0x5c, 0x0a, 0x0f, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x50, 0x61, 0x72, 0x74, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x42, 0x61, - 0x63, 0x6b, 0x75, 0x70, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x42, 0x61, - 0x63, 0x6b, 0x75, 0x70, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, 0xfa, 0x97, 0x28, 0x04, 0x08, 0x02, 0x10, 0x03, 0x12, - 0x59, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x12, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, - 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, - 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x08, 0xfa, 0x97, 0x28, 0x04, 0x08, 0x02, 0x10, 0x02, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x69, - 0x74, 0x6c, 0x61, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2d, - 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2f, 0x76, 0x31, 0x36, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x70, 0x62, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x12, 0x06, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0a, 0x6c, 0x69, 0x6e, 0x74, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0c, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6a, 0x0a, 0x16, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x50, 0x61, + 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, + 0x0a, 0x0c, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x04, 0x88, 0xc6, 0x2c, 0x01, 0x52, 0x0b, 0x73, 0x74, 0x6f, 0x72, + 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0c, 0x70, 0x61, 0x72, 0x74, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x04, 0xa8, + 0xc6, 0x2c, 0x01, 0x52, 0x0b, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, + 0x22, 0x4b, 0x0a, 0x17, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x62, + 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x70, + 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x62, 0x61, 0x63, 0x6b, 0x75, + 0x70, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x50, 0x61, 0x74, 0x68, 0x22, 0x8a, 0x01, + 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0c, 0x73, 0x74, 0x6f, 0x72, 0x61, + 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x04, 0x88, + 0xc6, 0x2c, 0x01, 0x52, 0x0b, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x48, 0x0a, 0x11, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, + 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x69, + 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, + 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, 0x10, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x92, 0x01, 0x0a, 0x16, 0x4c, + 0x69, 0x73, 0x74, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, 0x69, 0x74, 0x61, + 0x6c, 0x79, 0x2e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x70, 0x61, + 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x45, 0x0a, 0x11, 0x70, 0x61, 0x67, 0x69, + 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x50, 0x61, 0x67, + 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x52, 0x10, 0x70, + 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x22, + 0xc6, 0x01, 0x0a, 0x24, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0c, 0x73, 0x74, 0x6f, 0x72, + 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x04, + 0x88, 0xc6, 0x2c, 0x01, 0x52, 0x0b, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x3b, 0x0a, 0x0a, 0x70, + 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1b, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x70, 0x61, + 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xa4, 0x01, 0x0a, 0x13, 0x50, 0x61, 0x72, + 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x49, 0x6e, 0x66, 0x6f, + 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, + 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, + 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x30, 0x0a, + 0x14, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, + 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x62, 0x61, 0x63, + 0x6b, 0x75, 0x70, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x50, 0x61, 0x74, 0x68, 0x22, + 0x27, 0x0a, 0x25, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xd4, 0x02, 0x0a, 0x10, 0x50, 0x61, 0x72, + 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5c, 0x0a, + 0x0f, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, + 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, + 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x08, 0xfa, 0x97, 0x28, 0x04, 0x08, 0x02, 0x10, 0x03, 0x12, 0x59, 0x0a, 0x0e, 0x4c, + 0x69, 0x73, 0x74, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1d, 0x2e, + 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x72, 0x74, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, + 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, 0xfa, 0x97, + 0x28, 0x04, 0x08, 0x02, 0x10, 0x02, 0x12, 0x86, 0x01, 0x0a, 0x1d, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, + 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, + 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, + 0x61, 0x63, 0x6b, 0x75, 0x70, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, 0xfa, 0x97, 0x28, 0x04, 0x08, 0x02, 0x10, 0x02, 0x42, + 0x34, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x69, + 0x74, 0x6c, 0x61, 0x62, 0x2d, 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2f, + 0x76, 0x31, 0x36, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x69, 0x74, + 0x61, 0x6c, 0x79, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -292,29 +509,38 @@ func file_partition_proto_rawDescGZIP() []byte { return file_partition_proto_rawDescData } -var file_partition_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_partition_proto_msgTypes = make([]protoimpl.MessageInfo, 7) var file_partition_proto_goTypes = []any{ - (*BackupPartitionRequest)(nil), // 0: gitaly.BackupPartitionRequest - (*BackupPartitionResponse)(nil), // 1: gitaly.BackupPartitionResponse - (*ListPartitionsRequest)(nil), // 2: gitaly.ListPartitionsRequest - (*ListPartitionsResponse)(nil), // 3: gitaly.ListPartitionsResponse - (*PaginationParameter)(nil), // 4: gitaly.PaginationParameter - (*Partition)(nil), // 5: gitaly.Partition - (*PaginationCursor)(nil), // 6: gitaly.PaginationCursor + (*BackupPartitionRequest)(nil), // 0: gitaly.BackupPartitionRequest + (*BackupPartitionResponse)(nil), // 1: gitaly.BackupPartitionResponse + (*ListPartitionsRequest)(nil), // 2: gitaly.ListPartitionsRequest + (*ListPartitionsResponse)(nil), // 3: gitaly.ListPartitionsResponse + (*CreatePartitionBackupManifestRequest)(nil), // 4: gitaly.CreatePartitionBackupManifestRequest + (*PartitionBackupInfo)(nil), // 5: gitaly.PartitionBackupInfo + (*CreatePartitionBackupManifestResponse)(nil), // 6: gitaly.CreatePartitionBackupManifestResponse + (*PaginationParameter)(nil), // 7: gitaly.PaginationParameter + (*Partition)(nil), // 8: gitaly.Partition + (*PaginationCursor)(nil), // 9: gitaly.PaginationCursor + (*timestamppb.Timestamp)(nil), // 10: google.protobuf.Timestamp } var file_partition_proto_depIdxs = []int32{ - 4, // 0: gitaly.ListPartitionsRequest.pagination_params:type_name -> gitaly.PaginationParameter - 5, // 1: gitaly.ListPartitionsResponse.partitions:type_name -> gitaly.Partition - 6, // 2: gitaly.ListPartitionsResponse.pagination_cursor:type_name -> gitaly.PaginationCursor - 0, // 3: gitaly.PartitionService.BackupPartition:input_type -> gitaly.BackupPartitionRequest - 2, // 4: gitaly.PartitionService.ListPartitions:input_type -> gitaly.ListPartitionsRequest - 1, // 5: gitaly.PartitionService.BackupPartition:output_type -> gitaly.BackupPartitionResponse - 3, // 6: gitaly.PartitionService.ListPartitions:output_type -> gitaly.ListPartitionsResponse - 5, // [5:7] is the sub-list for method output_type - 3, // [3:5] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name + 7, // 0: gitaly.ListPartitionsRequest.pagination_params:type_name -> gitaly.PaginationParameter + 8, // 1: gitaly.ListPartitionsResponse.partitions:type_name -> gitaly.Partition + 9, // 2: gitaly.ListPartitionsResponse.pagination_cursor:type_name -> gitaly.PaginationCursor + 10, // 3: gitaly.CreatePartitionBackupManifestRequest.timestamp:type_name -> google.protobuf.Timestamp + 5, // 4: gitaly.CreatePartitionBackupManifestRequest.partitions:type_name -> gitaly.PartitionBackupInfo + 10, // 5: gitaly.PartitionBackupInfo.timestamp:type_name -> google.protobuf.Timestamp + 0, // 6: gitaly.PartitionService.BackupPartition:input_type -> gitaly.BackupPartitionRequest + 2, // 7: gitaly.PartitionService.ListPartitions:input_type -> gitaly.ListPartitionsRequest + 4, // 8: gitaly.PartitionService.CreatePartitionBackupManifest:input_type -> gitaly.CreatePartitionBackupManifestRequest + 1, // 9: gitaly.PartitionService.BackupPartition:output_type -> gitaly.BackupPartitionResponse + 3, // 10: gitaly.PartitionService.ListPartitions:output_type -> gitaly.ListPartitionsResponse + 6, // 11: gitaly.PartitionService.CreatePartitionBackupManifest:output_type -> gitaly.CreatePartitionBackupManifestResponse + 9, // [9:12] is the sub-list for method output_type + 6, // [6:9] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name } func init() { file_partition_proto_init() } @@ -330,7 +556,7 @@ func file_partition_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_partition_proto_rawDesc, NumEnums: 0, - NumMessages: 4, + NumMessages: 7, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/go/gitalypb/partition_grpc.pb.go b/proto/go/gitalypb/partition_grpc.pb.go index a5d67cc18797a1a1eae059cb844210c04a3860f2..bb0fb45866247572b862c35dc252edc15a21cb24 100644 --- a/proto/go/gitalypb/partition_grpc.pb.go +++ b/proto/go/gitalypb/partition_grpc.pb.go @@ -19,8 +19,9 @@ import ( const _ = grpc.SupportPackageIsVersion9 const ( - PartitionService_BackupPartition_FullMethodName = "/gitaly.PartitionService/BackupPartition" - PartitionService_ListPartitions_FullMethodName = "/gitaly.PartitionService/ListPartitions" + PartitionService_BackupPartition_FullMethodName = "/gitaly.PartitionService/BackupPartition" + PartitionService_ListPartitions_FullMethodName = "/gitaly.PartitionService/ListPartitions" + PartitionService_CreatePartitionBackupManifest_FullMethodName = "/gitaly.PartitionService/CreatePartitionBackupManifest" ) // PartitionServiceClient is the client API for PartitionService service. @@ -34,6 +35,8 @@ type PartitionServiceClient interface { BackupPartition(ctx context.Context, in *BackupPartitionRequest, opts ...grpc.CallOption) (*BackupPartitionResponse, error) // ListPartitions lists partitions present in the storage. ListPartitions(ctx context.Context, in *ListPartitionsRequest, opts ...grpc.CallOption) (*ListPartitionsResponse, error) + // CreatePartitionBackupManifest creates the manifest for locating backups. + CreatePartitionBackupManifest(ctx context.Context, in *CreatePartitionBackupManifestRequest, opts ...grpc.CallOption) (*CreatePartitionBackupManifestResponse, error) } type partitionServiceClient struct { @@ -64,6 +67,16 @@ func (c *partitionServiceClient) ListPartitions(ctx context.Context, in *ListPar return out, nil } +func (c *partitionServiceClient) CreatePartitionBackupManifest(ctx context.Context, in *CreatePartitionBackupManifestRequest, opts ...grpc.CallOption) (*CreatePartitionBackupManifestResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CreatePartitionBackupManifestResponse) + err := c.cc.Invoke(ctx, PartitionService_CreatePartitionBackupManifest_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + // PartitionServiceServer is the server API for PartitionService service. // All implementations must embed UnimplementedPartitionServiceServer // for forward compatibility. @@ -75,6 +88,8 @@ type PartitionServiceServer interface { BackupPartition(context.Context, *BackupPartitionRequest) (*BackupPartitionResponse, error) // ListPartitions lists partitions present in the storage. ListPartitions(context.Context, *ListPartitionsRequest) (*ListPartitionsResponse, error) + // CreatePartitionBackupManifest creates the manifest for locating backups. + CreatePartitionBackupManifest(context.Context, *CreatePartitionBackupManifestRequest) (*CreatePartitionBackupManifestResponse, error) mustEmbedUnimplementedPartitionServiceServer() } @@ -91,6 +106,9 @@ func (UnimplementedPartitionServiceServer) BackupPartition(context.Context, *Bac func (UnimplementedPartitionServiceServer) ListPartitions(context.Context, *ListPartitionsRequest) (*ListPartitionsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListPartitions not implemented") } +func (UnimplementedPartitionServiceServer) CreatePartitionBackupManifest(context.Context, *CreatePartitionBackupManifestRequest) (*CreatePartitionBackupManifestResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreatePartitionBackupManifest not implemented") +} func (UnimplementedPartitionServiceServer) mustEmbedUnimplementedPartitionServiceServer() {} func (UnimplementedPartitionServiceServer) testEmbeddedByValue() {} @@ -148,6 +166,24 @@ func _PartitionService_ListPartitions_Handler(srv interface{}, ctx context.Conte return interceptor(ctx, in, info, handler) } +func _PartitionService_CreatePartitionBackupManifest_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreatePartitionBackupManifestRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PartitionServiceServer).CreatePartitionBackupManifest(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: PartitionService_CreatePartitionBackupManifest_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PartitionServiceServer).CreatePartitionBackupManifest(ctx, req.(*CreatePartitionBackupManifestRequest)) + } + return interceptor(ctx, in, info, handler) +} + // PartitionService_ServiceDesc is the grpc.ServiceDesc for PartitionService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -163,6 +199,10 @@ var PartitionService_ServiceDesc = grpc.ServiceDesc{ MethodName: "ListPartitions", Handler: _PartitionService_ListPartitions_Handler, }, + { + MethodName: "CreatePartitionBackupManifest", + Handler: _PartitionService_CreatePartitionBackupManifest_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "partition.proto", diff --git a/proto/partition.proto b/proto/partition.proto index 151814353e5a6f16f7c6d34cf7df302f2ee60dec..561d7dd7dceb1b0922c8f9381ecd53fa62659b37 100644 --- a/proto/partition.proto +++ b/proto/partition.proto @@ -2,6 +2,7 @@ syntax = "proto3"; package gitaly; +import "google/protobuf/timestamp.proto"; import "lint.proto"; import "shared.proto"; @@ -27,6 +28,14 @@ service PartitionService { }; } + // CreatePartitionBackupManifest creates the manifest for locating backups. + rpc CreatePartitionBackupManifest(CreatePartitionBackupManifestRequest) returns (CreatePartitionBackupManifestResponse) { + option (op_type) = { + op: ACCESSOR + scope_level: STORAGE + }; + } + } // BackupPartitionRequest is a request for the BackupPartition RPC. @@ -40,6 +49,8 @@ message BackupPartitionRequest { // BackupPartitionResponse is a response for the BackupPartition RPC. message BackupPartitionResponse { + // backup_relative_path contains the relative path to the backup. + string backup_relative_path = 1; } // ListPartitionsRequest is a request for the ListPartitions RPC. @@ -60,3 +71,27 @@ message ListPartitionsResponse { // documentation for further info. PaginationCursor pagination_cursor = 2; } + +// CreatePartitionBackupManifestRequest is a request for the CreatePartitionBackupManifest RPC. +message CreatePartitionBackupManifestRequest { + // storage_name is the name of the storage containing the archived partitions. + string storage_name = 1 [(gitaly.storage)=true]; + // timestamp is the global time of the backup. + google.protobuf.Timestamp timestamp = 2; + // partitions contains the list of partitions that are archived. + repeated PartitionBackupInfo partitions = 3; +} + +// PartitionBackupInfo metadata for the partition that is archived +message PartitionBackupInfo { + // timestamp is the time of the partition backup. + google.protobuf.Timestamp timestamp = 1; + // partition_id is the identifier of the partition. + string partition_id = 2; + // backup_relative_path contains the relative path to the backup. + string backup_relative_path = 3; +} + +// CreatePartitionBackupManifestResponse is a response for the CreatePartitionBackupManifest RPC. +message CreatePartitionBackupManifestResponse { +}