feat: index snapshots created outside of backrest

This commit is contained in:
Gareth George
2023-12-28 08:41:51 +00:00
parent 9c7f227ad0
commit 7711297a84
10 changed files with 185 additions and 69 deletions
+35 -29
View File
@@ -594,7 +594,7 @@ var file_v1_service_proto_rawDesc = []byte{
0x69, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x74, 0x69, 0x6d, 0x65,
0x12, 0x14, 0x0a, 0x05, 0x61, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52,
0x05, 0x61, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x74, 0x69, 0x6d, 0x65, 0x18,
0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x74, 0x69, 0x6d, 0x65, 0x32, 0xb4, 0x07, 0x0a,
0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x74, 0x69, 0x6d, 0x65, 0x32, 0xf4, 0x07, 0x0a,
0x08, 0x42, 0x61, 0x63, 0x6b, 0x72, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x09, 0x47, 0x65, 0x74,
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0a,
@@ -621,7 +621,11 @@ var file_v1_service_proto_rawDesc = []byte{
0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6e,
0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x06, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12,
0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3e, 0x0a, 0x0e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x53, 0x6e,
0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x12, 0x12, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e,
0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d,
0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x06, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12,
0x12, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61,
0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x35, 0x0a,
@@ -700,33 +704,35 @@ var file_v1_service_proto_depIdxs = []int32{
2, // 5: v1.Backrest.GetOperations:input_type -> v1.GetOperationsRequest
1, // 6: v1.Backrest.ListSnapshots:input_type -> v1.ListSnapshotsRequest
4, // 7: v1.Backrest.ListSnapshotFiles:input_type -> v1.ListSnapshotFilesRequest
10, // 8: v1.Backrest.Backup:input_type -> types.StringValue
10, // 9: v1.Backrest.Prune:input_type -> types.StringValue
10, // 10: v1.Backrest.Forget:input_type -> types.StringValue
3, // 11: v1.Backrest.Restore:input_type -> v1.RestoreSnapshotRequest
10, // 12: v1.Backrest.Unlock:input_type -> types.StringValue
10, // 13: v1.Backrest.Stats:input_type -> types.StringValue
11, // 14: v1.Backrest.Cancel:input_type -> types.Int64Value
0, // 15: v1.Backrest.ClearHistory:input_type -> v1.ClearHistoryRequest
10, // 16: v1.Backrest.PathAutocomplete:input_type -> types.StringValue
8, // 17: v1.Backrest.GetConfig:output_type -> v1.Config
8, // 18: v1.Backrest.SetConfig:output_type -> v1.Config
8, // 19: v1.Backrest.AddRepo:output_type -> v1.Config
12, // 20: v1.Backrest.GetOperationEvents:output_type -> v1.OperationEvent
13, // 21: v1.Backrest.GetOperations:output_type -> v1.OperationList
14, // 22: v1.Backrest.ListSnapshots:output_type -> v1.ResticSnapshotList
5, // 23: v1.Backrest.ListSnapshotFiles:output_type -> v1.ListSnapshotFilesResponse
7, // 24: v1.Backrest.Backup:output_type -> google.protobuf.Empty
7, // 25: v1.Backrest.Prune:output_type -> google.protobuf.Empty
7, // 26: v1.Backrest.Forget:output_type -> google.protobuf.Empty
7, // 27: v1.Backrest.Restore:output_type -> google.protobuf.Empty
7, // 28: v1.Backrest.Unlock:output_type -> google.protobuf.Empty
7, // 29: v1.Backrest.Stats:output_type -> google.protobuf.Empty
7, // 30: v1.Backrest.Cancel:output_type -> google.protobuf.Empty
7, // 31: v1.Backrest.ClearHistory:output_type -> google.protobuf.Empty
15, // 32: v1.Backrest.PathAutocomplete:output_type -> types.StringList
17, // [17:33] is the sub-list for method output_type
1, // [1:17] is the sub-list for method input_type
10, // 8: v1.Backrest.IndexSnapshots:input_type -> types.StringValue
10, // 9: v1.Backrest.Backup:input_type -> types.StringValue
10, // 10: v1.Backrest.Prune:input_type -> types.StringValue
10, // 11: v1.Backrest.Forget:input_type -> types.StringValue
3, // 12: v1.Backrest.Restore:input_type -> v1.RestoreSnapshotRequest
10, // 13: v1.Backrest.Unlock:input_type -> types.StringValue
10, // 14: v1.Backrest.Stats:input_type -> types.StringValue
11, // 15: v1.Backrest.Cancel:input_type -> types.Int64Value
0, // 16: v1.Backrest.ClearHistory:input_type -> v1.ClearHistoryRequest
10, // 17: v1.Backrest.PathAutocomplete:input_type -> types.StringValue
8, // 18: v1.Backrest.GetConfig:output_type -> v1.Config
8, // 19: v1.Backrest.SetConfig:output_type -> v1.Config
8, // 20: v1.Backrest.AddRepo:output_type -> v1.Config
12, // 21: v1.Backrest.GetOperationEvents:output_type -> v1.OperationEvent
13, // 22: v1.Backrest.GetOperations:output_type -> v1.OperationList
14, // 23: v1.Backrest.ListSnapshots:output_type -> v1.ResticSnapshotList
5, // 24: v1.Backrest.ListSnapshotFiles:output_type -> v1.ListSnapshotFilesResponse
7, // 25: v1.Backrest.IndexSnapshots:output_type -> google.protobuf.Empty
7, // 26: v1.Backrest.Backup:output_type -> google.protobuf.Empty
7, // 27: v1.Backrest.Prune:output_type -> google.protobuf.Empty
7, // 28: v1.Backrest.Forget:output_type -> google.protobuf.Empty
7, // 29: v1.Backrest.Restore:output_type -> google.protobuf.Empty
7, // 30: v1.Backrest.Unlock:output_type -> google.protobuf.Empty
7, // 31: v1.Backrest.Stats:output_type -> google.protobuf.Empty
7, // 32: v1.Backrest.Cancel:output_type -> google.protobuf.Empty
7, // 33: v1.Backrest.ClearHistory:output_type -> google.protobuf.Empty
15, // 34: v1.Backrest.PathAutocomplete:output_type -> types.StringList
18, // [18:35] is the sub-list for method output_type
1, // [1:18] is the sub-list for method input_type
1, // [1:1] is the sub-list for extension type_name
1, // [1:1] is the sub-list for extension extendee
0, // [0:1] is the sub-list for field type_name
+43 -4
View File
@@ -28,6 +28,7 @@ const (
Backrest_GetOperations_FullMethodName = "/v1.Backrest/GetOperations"
Backrest_ListSnapshots_FullMethodName = "/v1.Backrest/ListSnapshots"
Backrest_ListSnapshotFiles_FullMethodName = "/v1.Backrest/ListSnapshotFiles"
Backrest_IndexSnapshots_FullMethodName = "/v1.Backrest/IndexSnapshots"
Backrest_Backup_FullMethodName = "/v1.Backrest/Backup"
Backrest_Prune_FullMethodName = "/v1.Backrest/Prune"
Backrest_Forget_FullMethodName = "/v1.Backrest/Forget"
@@ -50,11 +51,13 @@ type BackrestClient interface {
GetOperations(ctx context.Context, in *GetOperationsRequest, opts ...grpc.CallOption) (*OperationList, error)
ListSnapshots(ctx context.Context, in *ListSnapshotsRequest, opts ...grpc.CallOption) (*ResticSnapshotList, error)
ListSnapshotFiles(ctx context.Context, in *ListSnapshotFilesRequest, opts ...grpc.CallOption) (*ListSnapshotFilesResponse, error)
// IndexSnapshots triggers indexin. It accepts a repo id and returns empty if the task is enqueued.
IndexSnapshots(ctx context.Context, in *types.StringValue, opts ...grpc.CallOption) (*emptypb.Empty, error)
// Backup schedules a backup operation. It accepts a plan id and returns empty if the task is enqueued.
Backup(ctx context.Context, in *types.StringValue, opts ...grpc.CallOption) (*emptypb.Empty, error)
// Prune schedules a prune operation.
// Prune schedules a prune operation. It accepts a plan id and returns empty if the task is enqueued.
Prune(ctx context.Context, in *types.StringValue, opts ...grpc.CallOption) (*emptypb.Empty, error)
// Forget schedules a forget operation.
// Forget schedules a forget operation. It accepts a plan id and returns empty if the task is enqueued.
Forget(ctx context.Context, in *types.StringValue, opts ...grpc.CallOption) (*emptypb.Empty, error)
// Restore schedules a restore operation.
Restore(ctx context.Context, in *RestoreSnapshotRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
@@ -164,6 +167,15 @@ func (c *backrestClient) ListSnapshotFiles(ctx context.Context, in *ListSnapshot
return out, nil
}
func (c *backrestClient) IndexSnapshots(ctx context.Context, in *types.StringValue, opts ...grpc.CallOption) (*emptypb.Empty, error) {
out := new(emptypb.Empty)
err := c.cc.Invoke(ctx, Backrest_IndexSnapshots_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *backrestClient) Backup(ctx context.Context, in *types.StringValue, opts ...grpc.CallOption) (*emptypb.Empty, error) {
out := new(emptypb.Empty)
err := c.cc.Invoke(ctx, Backrest_Backup_FullMethodName, in, out, opts...)
@@ -256,11 +268,13 @@ type BackrestServer interface {
GetOperations(context.Context, *GetOperationsRequest) (*OperationList, error)
ListSnapshots(context.Context, *ListSnapshotsRequest) (*ResticSnapshotList, error)
ListSnapshotFiles(context.Context, *ListSnapshotFilesRequest) (*ListSnapshotFilesResponse, error)
// IndexSnapshots triggers indexin. It accepts a repo id and returns empty if the task is enqueued.
IndexSnapshots(context.Context, *types.StringValue) (*emptypb.Empty, error)
// Backup schedules a backup operation. It accepts a plan id and returns empty if the task is enqueued.
Backup(context.Context, *types.StringValue) (*emptypb.Empty, error)
// Prune schedules a prune operation.
// Prune schedules a prune operation. It accepts a plan id and returns empty if the task is enqueued.
Prune(context.Context, *types.StringValue) (*emptypb.Empty, error)
// Forget schedules a forget operation.
// Forget schedules a forget operation. It accepts a plan id and returns empty if the task is enqueued.
Forget(context.Context, *types.StringValue) (*emptypb.Empty, error)
// Restore schedules a restore operation.
Restore(context.Context, *RestoreSnapshotRequest) (*emptypb.Empty, error)
@@ -302,6 +316,9 @@ func (UnimplementedBackrestServer) ListSnapshots(context.Context, *ListSnapshots
func (UnimplementedBackrestServer) ListSnapshotFiles(context.Context, *ListSnapshotFilesRequest) (*ListSnapshotFilesResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListSnapshotFiles not implemented")
}
func (UnimplementedBackrestServer) IndexSnapshots(context.Context, *types.StringValue) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method IndexSnapshots not implemented")
}
func (UnimplementedBackrestServer) Backup(context.Context, *types.StringValue) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method Backup not implemented")
}
@@ -471,6 +488,24 @@ func _Backrest_ListSnapshotFiles_Handler(srv interface{}, ctx context.Context, d
return interceptor(ctx, in, info, handler)
}
func _Backrest_IndexSnapshots_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(types.StringValue)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(BackrestServer).IndexSnapshots(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Backrest_IndexSnapshots_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(BackrestServer).IndexSnapshots(ctx, req.(*types.StringValue))
}
return interceptor(ctx, in, info, handler)
}
func _Backrest_Backup_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(types.StringValue)
if err := dec(in); err != nil {
@@ -664,6 +699,10 @@ var Backrest_ServiceDesc = grpc.ServiceDesc{
MethodName: "ListSnapshotFiles",
Handler: _Backrest_ListSnapshotFiles_Handler,
},
{
MethodName: "IndexSnapshots",
Handler: _Backrest_IndexSnapshots_Handler,
},
{
MethodName: "Backup",
Handler: _Backrest_Backup_Handler,
+35 -4
View File
@@ -51,6 +51,8 @@ const (
// BackrestListSnapshotFilesProcedure is the fully-qualified name of the Backrest's
// ListSnapshotFiles RPC.
BackrestListSnapshotFilesProcedure = "/v1.Backrest/ListSnapshotFiles"
// BackrestIndexSnapshotsProcedure is the fully-qualified name of the Backrest's IndexSnapshots RPC.
BackrestIndexSnapshotsProcedure = "/v1.Backrest/IndexSnapshots"
// BackrestBackupProcedure is the fully-qualified name of the Backrest's Backup RPC.
BackrestBackupProcedure = "/v1.Backrest/Backup"
// BackrestPruneProcedure is the fully-qualified name of the Backrest's Prune RPC.
@@ -82,6 +84,7 @@ var (
backrestGetOperationsMethodDescriptor = backrestServiceDescriptor.Methods().ByName("GetOperations")
backrestListSnapshotsMethodDescriptor = backrestServiceDescriptor.Methods().ByName("ListSnapshots")
backrestListSnapshotFilesMethodDescriptor = backrestServiceDescriptor.Methods().ByName("ListSnapshotFiles")
backrestIndexSnapshotsMethodDescriptor = backrestServiceDescriptor.Methods().ByName("IndexSnapshots")
backrestBackupMethodDescriptor = backrestServiceDescriptor.Methods().ByName("Backup")
backrestPruneMethodDescriptor = backrestServiceDescriptor.Methods().ByName("Prune")
backrestForgetMethodDescriptor = backrestServiceDescriptor.Methods().ByName("Forget")
@@ -102,11 +105,13 @@ type BackrestClient interface {
GetOperations(context.Context, *connect.Request[v1.GetOperationsRequest]) (*connect.Response[v1.OperationList], error)
ListSnapshots(context.Context, *connect.Request[v1.ListSnapshotsRequest]) (*connect.Response[v1.ResticSnapshotList], error)
ListSnapshotFiles(context.Context, *connect.Request[v1.ListSnapshotFilesRequest]) (*connect.Response[v1.ListSnapshotFilesResponse], error)
// IndexSnapshots triggers indexin. It accepts a repo id and returns empty if the task is enqueued.
IndexSnapshots(context.Context, *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error)
// Backup schedules a backup operation. It accepts a plan id and returns empty if the task is enqueued.
Backup(context.Context, *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error)
// Prune schedules a prune operation.
// Prune schedules a prune operation. It accepts a plan id and returns empty if the task is enqueued.
Prune(context.Context, *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error)
// Forget schedules a forget operation.
// Forget schedules a forget operation. It accepts a plan id and returns empty if the task is enqueued.
Forget(context.Context, *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error)
// Restore schedules a restore operation.
Restore(context.Context, *connect.Request[v1.RestoreSnapshotRequest]) (*connect.Response[emptypb.Empty], error)
@@ -174,6 +179,12 @@ func NewBackrestClient(httpClient connect.HTTPClient, baseURL string, opts ...co
connect.WithSchema(backrestListSnapshotFilesMethodDescriptor),
connect.WithClientOptions(opts...),
),
indexSnapshots: connect.NewClient[types.StringValue, emptypb.Empty](
httpClient,
baseURL+BackrestIndexSnapshotsProcedure,
connect.WithSchema(backrestIndexSnapshotsMethodDescriptor),
connect.WithClientOptions(opts...),
),
backup: connect.NewClient[types.StringValue, emptypb.Empty](
httpClient,
baseURL+BackrestBackupProcedure,
@@ -240,6 +251,7 @@ type backrestClient struct {
getOperations *connect.Client[v1.GetOperationsRequest, v1.OperationList]
listSnapshots *connect.Client[v1.ListSnapshotsRequest, v1.ResticSnapshotList]
listSnapshotFiles *connect.Client[v1.ListSnapshotFilesRequest, v1.ListSnapshotFilesResponse]
indexSnapshots *connect.Client[types.StringValue, emptypb.Empty]
backup *connect.Client[types.StringValue, emptypb.Empty]
prune *connect.Client[types.StringValue, emptypb.Empty]
forget *connect.Client[types.StringValue, emptypb.Empty]
@@ -286,6 +298,11 @@ func (c *backrestClient) ListSnapshotFiles(ctx context.Context, req *connect.Req
return c.listSnapshotFiles.CallUnary(ctx, req)
}
// IndexSnapshots calls v1.Backrest.IndexSnapshots.
func (c *backrestClient) IndexSnapshots(ctx context.Context, req *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) {
return c.indexSnapshots.CallUnary(ctx, req)
}
// Backup calls v1.Backrest.Backup.
func (c *backrestClient) Backup(ctx context.Context, req *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) {
return c.backup.CallUnary(ctx, req)
@@ -340,11 +357,13 @@ type BackrestHandler interface {
GetOperations(context.Context, *connect.Request[v1.GetOperationsRequest]) (*connect.Response[v1.OperationList], error)
ListSnapshots(context.Context, *connect.Request[v1.ListSnapshotsRequest]) (*connect.Response[v1.ResticSnapshotList], error)
ListSnapshotFiles(context.Context, *connect.Request[v1.ListSnapshotFilesRequest]) (*connect.Response[v1.ListSnapshotFilesResponse], error)
// IndexSnapshots triggers indexin. It accepts a repo id and returns empty if the task is enqueued.
IndexSnapshots(context.Context, *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error)
// Backup schedules a backup operation. It accepts a plan id and returns empty if the task is enqueued.
Backup(context.Context, *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error)
// Prune schedules a prune operation.
// Prune schedules a prune operation. It accepts a plan id and returns empty if the task is enqueued.
Prune(context.Context, *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error)
// Forget schedules a forget operation.
// Forget schedules a forget operation. It accepts a plan id and returns empty if the task is enqueued.
Forget(context.Context, *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error)
// Restore schedules a restore operation.
Restore(context.Context, *connect.Request[v1.RestoreSnapshotRequest]) (*connect.Response[emptypb.Empty], error)
@@ -408,6 +427,12 @@ func NewBackrestHandler(svc BackrestHandler, opts ...connect.HandlerOption) (str
connect.WithSchema(backrestListSnapshotFilesMethodDescriptor),
connect.WithHandlerOptions(opts...),
)
backrestIndexSnapshotsHandler := connect.NewUnaryHandler(
BackrestIndexSnapshotsProcedure,
svc.IndexSnapshots,
connect.WithSchema(backrestIndexSnapshotsMethodDescriptor),
connect.WithHandlerOptions(opts...),
)
backrestBackupHandler := connect.NewUnaryHandler(
BackrestBackupProcedure,
svc.Backup,
@@ -478,6 +503,8 @@ func NewBackrestHandler(svc BackrestHandler, opts ...connect.HandlerOption) (str
backrestListSnapshotsHandler.ServeHTTP(w, r)
case BackrestListSnapshotFilesProcedure:
backrestListSnapshotFilesHandler.ServeHTTP(w, r)
case BackrestIndexSnapshotsProcedure:
backrestIndexSnapshotsHandler.ServeHTTP(w, r)
case BackrestBackupProcedure:
backrestBackupHandler.ServeHTTP(w, r)
case BackrestPruneProcedure:
@@ -533,6 +560,10 @@ func (UnimplementedBackrestHandler) ListSnapshotFiles(context.Context, *connect.
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("v1.Backrest.ListSnapshotFiles is not implemented"))
}
func (UnimplementedBackrestHandler) IndexSnapshots(context.Context, *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) {
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("v1.Backrest.IndexSnapshots is not implemented"))
}
func (UnimplementedBackrestHandler) Backup(context.Context, *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) {
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("v1.Backrest.Backup is not implemented"))
}
+15 -1
View File
@@ -111,6 +111,9 @@ func (s *Server) AddRepo(ctx context.Context, req *connect.Request[v1.Repo]) (*c
s.orchestrator.ApplyConfig(c)
// index snapshots for the newly added repository.
s.orchestrator.ScheduleTask(orchestrator.NewOneoffIndexSnapshotsTask(s.orchestrator, req.Msg.Id, time.Now()), orchestrator.TaskPriorityInteractive+orchestrator.TaskPriorityIndexSnapshots)
return connect.NewResponse(c), nil
}
@@ -249,6 +252,17 @@ func (s *Server) GetOperations(ctx context.Context, req *connect.Request[v1.GetO
}), nil
}
func (s *Server) IndexSnapshots(ctx context.Context, req *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) {
_, err := s.orchestrator.GetRepo(req.Msg.Value)
if err != nil {
return nil, fmt.Errorf("failed to get repo %q: %w", req.Msg.Value, err)
}
s.orchestrator.ScheduleTask(orchestrator.NewOneoffIndexSnapshotsTask(s.orchestrator, req.Msg.Value, time.Now()), orchestrator.TaskPriorityInteractive+orchestrator.TaskPriorityIndexSnapshots)
return connect.NewResponse(&emptypb.Empty{}), nil
}
func (s *Server) Backup(ctx context.Context, req *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) {
plan, err := s.orchestrator.GetPlan(req.Msg.Value)
if err != nil {
@@ -267,7 +281,7 @@ func (s *Server) Forget(ctx context.Context, req *connect.Request[types.StringVa
at := time.Now()
s.orchestrator.ScheduleTask(orchestrator.NewOneoffForgetTask(s.orchestrator, plan, "", at), orchestrator.TaskPriorityInteractive+orchestrator.TaskPriorityForget)
s.orchestrator.ScheduleTask(orchestrator.NewOneoffIndexSnapshotsTask(s.orchestrator, plan, at), orchestrator.TaskPriorityInteractive+orchestrator.TaskPriorityIndexSnapshots)
s.orchestrator.ScheduleTask(orchestrator.NewOneoffIndexSnapshotsTask(s.orchestrator, plan.Repo, at), orchestrator.TaskPriorityInteractive+orchestrator.TaskPriorityIndexSnapshots)
return connect.NewResponse(&emptypb.Empty{}), nil
}
+2 -1
View File
@@ -229,10 +229,11 @@ func (o *Orchestrator) Run(mainCtx context.Context) {
zap.L().Fatal("failed to start task, another task is already running. Was Run() called twice?")
}
start := time.Now()
if err := t.task.Run(taskCtx); err != nil {
zap.L().Error("task failed", zap.String("task", t.task.Name()), zap.Error(err))
} else {
zap.L().Info("task finished", zap.String("task", t.task.Name()))
zap.L().Info("task finished", zap.String("task", t.task.Name()), zap.Duration("duration", time.Since(start)))
}
o.runningTask.Store(nil)
+1 -1
View File
@@ -145,7 +145,7 @@ func backupHelper(ctx context.Context, orchestrator *Orchestrator, plan *v1.Plan
orchestrator.ScheduleTask(NewOneoffForgetTask(orchestrator, plan, op.SnapshotId, at), TaskPriorityForget)
}
orchestrator.ScheduleTask(NewOneoffIndexSnapshotsTask(orchestrator, plan, at), TaskPriorityIndexSnapshots)
orchestrator.ScheduleTask(NewOneoffIndexSnapshotsTask(orchestrator, plan.Repo, at), TaskPriorityIndexSnapshots)
orchestrator.ScheduleTask(NewOneoffStatsTask(orchestrator, plan, op.SnapshotId, at), TaskPriorityStats)
return nil
+36 -24
View File
@@ -3,6 +3,7 @@ package orchestrator
import (
"context"
"fmt"
"strings"
"time"
v1 "github.com/garethgeorge/backrest/gen/go/v1"
@@ -12,25 +13,27 @@ import (
"go.uber.org/zap"
)
const planForUntrackedSnapshots = "_unassociated_"
// IndexSnapshotsTask tracks a forget operation.
type IndexSnapshotsTask struct {
orchestrator *Orchestrator // owning orchestrator
plan *v1.Plan
repoId string
at *time.Time
}
var _ Task = &IndexSnapshotsTask{}
func NewOneoffIndexSnapshotsTask(orchestrator *Orchestrator, plan *v1.Plan, at time.Time) *IndexSnapshotsTask {
func NewOneoffIndexSnapshotsTask(orchestrator *Orchestrator, repoId string, at time.Time) *IndexSnapshotsTask {
return &IndexSnapshotsTask{
orchestrator: orchestrator,
plan: plan,
repoId: repoId,
at: &at,
}
}
func (t *IndexSnapshotsTask) Name() string {
return fmt.Sprintf("index snapshots for plan %q", t.plan.Id)
return fmt.Sprintf("index snapshots for plan %q", t.repoId)
}
func (t *IndexSnapshotsTask) Next(now time.Time) *time.Time {
@@ -42,7 +45,7 @@ func (t *IndexSnapshotsTask) Next(now time.Time) *time.Time {
}
func (t *IndexSnapshotsTask) Run(ctx context.Context) error {
return indexSnapshotsHelper(ctx, t.orchestrator, t.plan)
return indexSnapshotsHelper(ctx, t.orchestrator, t.repoId)
}
func (t *IndexSnapshotsTask) Cancel(withStatus v1.OperationStatus) error {
@@ -57,22 +60,22 @@ func (t *IndexSnapshotsTask) OperationId() int64 {
// - If the snapshot is already indexed, it is skipped.
// - If the snapshot is not indexed, an index snapshot operation with it's metadata is added.
// - If an index snapshot operation is found for a snapshot that is not returned by the repo, it is marked as forgotten.
func indexSnapshotsHelper(ctx context.Context, orchestrator *Orchestrator, plan *v1.Plan) error {
repo, err := orchestrator.GetRepo(plan.Repo)
func indexSnapshotsHelper(ctx context.Context, orchestrator *Orchestrator, repoId string) error {
repo, err := orchestrator.GetRepo(repoId)
if err != nil {
return fmt.Errorf("couldn't get repo %q: %w", plan.Repo, err)
return fmt.Errorf("couldn't get repo %q: %w", repoId, err)
}
// collect all tracked snapshots for the plan.
snapshots, err := repo.SnapshotsForPlan(ctx, plan)
snapshots, err := repo.Snapshots(ctx)
if err != nil {
return fmt.Errorf("get snapshots for plan %q: %w", plan.Id, err)
return fmt.Errorf("get snapshots for repo %q: %w", repoId, err)
}
// collect all current snapshot IDs.
currentIds, err := indexCurrentSnapshotIdsForPlan(orchestrator.OpLog, plan.Id)
currentIds, err := indexCurrentSnapshotIdsForRepo(orchestrator.OpLog, repoId)
if err != nil {
return fmt.Errorf("get known snapshot IDs for plan %q: %w", plan.Id, err)
return fmt.Errorf("get known snapshot IDs for repo %q: %w", repoId, err)
}
foundIds := make(map[string]bool)
@@ -87,9 +90,10 @@ func indexSnapshotsHelper(ctx context.Context, orchestrator *Orchestrator, plan
}
snapshotProto := protoutil.SnapshotToProto(snapshot)
planId := planForSnapshot(snapshotProto)
indexOps = append(indexOps, &v1.Operation{
RepoId: plan.Repo,
PlanId: plan.Id,
RepoId: repoId,
PlanId: planId,
UnixTimeStartMs: snapshotProto.UnixTimeMs,
UnixTimeEndMs: snapshotProto.UnixTimeMs,
Status: v1.OperationStatus_STATUS_SUCCESS,
@@ -107,14 +111,13 @@ func indexSnapshotsHelper(ctx context.Context, orchestrator *Orchestrator, plan
}
// Mark missing operations as newly forgotten.
var forgetIds []int64
for id, opId := range currentIds {
if _, ok := foundIds[id]; !ok {
forgetIds = append(forgetIds, opId)
if _, ok := foundIds[id]; ok {
// skip snapshots that were found.
continue
}
}
for _, opId := range forgetIds {
// mark snapshot forgotten.
op, err := orchestrator.OpLog.Get(opId)
if err != nil {
// should only be possible in the case of a data race (e.g. operation was somehow deleted).
@@ -134,7 +137,7 @@ func indexSnapshotsHelper(ctx context.Context, orchestrator *Orchestrator, plan
// Print stats at the end of indexing.
zap.L().Debug("Indexed snapshots",
zap.String("plan", plan.Id),
zap.String("repo", repoId),
zap.Duration("duration", time.Since(startTime)),
zap.Int("alreadyIndexed", len(foundIds)),
zap.Int("newlyAdded", len(indexOps)),
@@ -145,14 +148,14 @@ func indexSnapshotsHelper(ctx context.Context, orchestrator *Orchestrator, plan
}
// returns a map of current (e.g. not forgotten) snapshot IDs for the plan.
func indexCurrentSnapshotIdsForPlan(log *oplog.OpLog, planId string) (map[string]int64, error) {
func indexCurrentSnapshotIdsForRepo(log *oplog.OpLog, repoId string) (map[string]int64, error) {
knownIds := make(map[string]int64)
startTime := time.Now()
if err := log.ForEachByPlan(planId, indexutil.CollectAll(), func(op *v1.Operation) error {
if err := log.ForEachByRepo(repoId, indexutil.CollectAll(), func(op *v1.Operation) error {
if snapshotOp, ok := op.Op.(*v1.Operation_OperationIndexSnapshot); ok {
if snapshotOp.OperationIndexSnapshot == nil {
return fmt.Errorf("operation %q has nil OperationIndexSnapshot, this shouldn't be possible.", op.Id)
return fmt.Errorf("operation %q has nil OperationIndexSnapshot, this shouldn't be possible", op.Id)
}
if !snapshotOp.OperationIndexSnapshot.Forgot {
knownIds[snapshotOp.OperationIndexSnapshot.Snapshot.Id] = op.Id
@@ -162,6 +165,15 @@ func indexCurrentSnapshotIdsForPlan(log *oplog.OpLog, planId string) (map[string
}); err != nil {
return nil, err
}
zap.S().Debugf("Indexed known (and not forgotten) snapshot IDs for plan %v in %v", planId, time.Since(startTime))
zap.S().Debugf("Indexed known (and not forgotten) snapshot IDs for plan %v in %v", repoId, time.Since(startTime))
return knownIds, nil
}
func planForSnapshot(snapshot *v1.ResticSnapshot) string {
for _, tag := range snapshot.Tags {
if strings.HasPrefix(tag, "plan:") {
return tag[5:]
}
}
return planForUntrackedSnapshots
}
-1
View File
@@ -54,7 +54,6 @@ func (t *StatsTask) shouldRun() (bool, error) {
}
zap.L().Debug("bytes since last stat", zap.Int64("bytes", bytesSinceLastStat), zap.String("repo", t.plan.Repo))
if bytesSinceLastStat == -1 || bytesSinceLastStat > statBytesThreshold {
zap.S().Debugf("bytes since last stat (%v) exceeds threshold (%v)", bytesSinceLastStat, statBytesThreshold)
return true, nil
+5 -2
View File
@@ -26,13 +26,16 @@ service Backrest {
rpc ListSnapshotFiles(ListSnapshotFilesRequest) returns (ListSnapshotFilesResponse) {}
// IndexSnapshots triggers indexin. It accepts a repo id and returns empty if the task is enqueued.
rpc IndexSnapshots(types.StringValue) returns (google.protobuf.Empty) {}
// Backup schedules a backup operation. It accepts a plan id and returns empty if the task is enqueued.
rpc Backup(types.StringValue) returns (google.protobuf.Empty) {}
// Prune schedules a prune operation.
// Prune schedules a prune operation. It accepts a plan id and returns empty if the task is enqueued.
rpc Prune(types.StringValue) returns (google.protobuf.Empty) {}
// Forget schedules a forget operation.
// Forget schedules a forget operation. It accepts a plan id and returns empty if the task is enqueued.
rpc Forget(types.StringValue) returns (google.protobuf.Empty) {}
// Restore schedules a restore operation.
+13 -2
View File
@@ -79,6 +79,17 @@ export const Backrest = {
O: ListSnapshotFilesResponse,
kind: MethodKind.Unary,
},
/**
* IndexSnapshots triggers indexin. It accepts a repo id and returns empty if the task is enqueued.
*
* @generated from rpc v1.Backrest.IndexSnapshots
*/
indexSnapshots: {
name: "IndexSnapshots",
I: StringValue,
O: Empty,
kind: MethodKind.Unary,
},
/**
* Backup schedules a backup operation. It accepts a plan id and returns empty if the task is enqueued.
*
@@ -91,7 +102,7 @@ export const Backrest = {
kind: MethodKind.Unary,
},
/**
* Prune schedules a prune operation.
* Prune schedules a prune operation. It accepts a plan id and returns empty if the task is enqueued.
*
* @generated from rpc v1.Backrest.Prune
*/
@@ -102,7 +113,7 @@ export const Backrest = {
kind: MethodKind.Unary,
},
/**
* Forget schedules a forget operation.
* Forget schedules a forget operation. It accepts a plan id and returns empty if the task is enqueued.
*
* @generated from rpc v1.Backrest.Forget
*/