fix: store large log outputs in tar bundles of logs

This commit is contained in:
garethgeorge
2024-02-03 02:37:31 -08:00
parent 8a11822aec
commit ca9cf5093e
27 changed files with 572 additions and 413 deletions
+9 -1
View File
@@ -21,6 +21,7 @@ import (
"github.com/garethgeorge/backrest/internal/oplog"
"github.com/garethgeorge/backrest/internal/orchestrator"
"github.com/garethgeorge/backrest/internal/resticinstaller"
"github.com/garethgeorge/backrest/internal/rotatinglog"
"github.com/mattn/go-colorable"
"go.etcd.io/bbolt"
"go.uber.org/zap"
@@ -63,8 +64,14 @@ func main() {
}
defer oplog.Close()
// Create rotating log storage
logStore := rotatinglog.NewRotatingLog(path.Join(config.DataDir(), "rotatinglogs"), 30)
if err != nil {
zap.S().Fatalf("Error creating rotating log storage: %v", err)
}
// Create orchestrator and start task loop.
orchestrator, err := orchestrator.NewOrchestrator(resticPath, cfg, oplog)
orchestrator, err := orchestrator.NewOrchestrator(resticPath, cfg, oplog, logStore)
if err != nil {
zap.S().Fatalf("Error creating orchestrator: %v", err)
}
@@ -80,6 +87,7 @@ func main() {
configStore,
orchestrator,
oplog,
logStore,
)
apiAuthenticationHandler := api.NewAuthenticationHandler(authenticator)
+30 -30
View File
@@ -792,8 +792,8 @@ type OperationRunHook struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // description of the hook that was run. typically repo/hook_idx or plan/hook_idx.
OutputRef string `protobuf:"bytes,2,opt,name=output_ref,json=outputRef,proto3" json:"output_ref,omitempty"` // reference to the output of the hook.
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // description of the hook that was run. typically repo/hook_idx or plan/hook_idx.
OutputLogref string `protobuf:"bytes,2,opt,name=output_logref,json=outputLogref,proto3" json:"output_logref,omitempty"` // logref of the hook's output.
}
func (x *OperationRunHook) Reset() {
@@ -835,9 +835,9 @@ func (x *OperationRunHook) GetName() string {
return ""
}
func (x *OperationRunHook) GetOutputRef() string {
func (x *OperationRunHook) GetOutputLogref() string {
if x != nil {
return x.OutputRef
return x.OutputLogref
}
return ""
}
@@ -941,33 +941,33 @@ var file_v1_operations_proto_rawDesc = []byte{
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x23, 0x0a, 0x05, 0x73, 0x74,
0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x76, 0x31, 0x2e, 0x52,
0x65, 0x70, 0x6f, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x22,
0x45, 0x0a, 0x10, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x75, 0x6e, 0x48,
0x4b, 0x0a, 0x10, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x75, 0x6e, 0x48,
0x6f, 0x6f, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x70, 0x75,
0x74, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x75, 0x74,
0x70, 0x75, 0x74, 0x52, 0x65, 0x66, 0x2a, 0x60, 0x0a, 0x12, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x11, 0x0a, 0x0d,
0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12,
0x11, 0x0a, 0x0d, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44,
0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x55, 0x50, 0x44, 0x41,
0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x44,
0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x03, 0x2a, 0xc2, 0x01, 0x0a, 0x0f, 0x4f, 0x70, 0x65,
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x0e,
0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00,
0x12, 0x12, 0x0a, 0x0e, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49,
0x4e, 0x47, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49,
0x4e, 0x50, 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x53,
0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x03, 0x12,
0x12, 0x0a, 0x0e, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e,
0x47, 0x10, 0x07, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x45, 0x52,
0x52, 0x4f, 0x52, 0x10, 0x04, 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f,
0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x5f, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x4c, 0x45, 0x44,
0x10, 0x05, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x53, 0x45,
0x52, 0x5f, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x4c, 0x45, 0x44, 0x10, 0x06, 0x42, 0x2c, 0x5a,
0x2a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x61, 0x72, 0x65,
0x74, 0x68, 0x67, 0x65, 0x6f, 0x72, 0x67, 0x65, 0x2f, 0x62, 0x61, 0x63, 0x6b, 0x72, 0x65, 0x73,
0x74, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x33,
0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6f, 0x75, 0x74, 0x70, 0x75,
0x74, 0x5f, 0x6c, 0x6f, 0x67, 0x72, 0x65, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c,
0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x4c, 0x6f, 0x67, 0x72, 0x65, 0x66, 0x2a, 0x60, 0x0a, 0x12,
0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79,
0x70, 0x65, 0x12, 0x11, 0x0a, 0x0d, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x4b, 0x4e,
0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x43,
0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x45, 0x56, 0x45, 0x4e,
0x54, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x45,
0x56, 0x45, 0x4e, 0x54, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x03, 0x2a, 0xc2,
0x01, 0x0a, 0x0f, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74,
0x75, 0x73, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x4b,
0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53,
0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x54,
0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, 0x4e, 0x50, 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10,
0x02, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x53, 0x55, 0x43, 0x43,
0x45, 0x53, 0x53, 0x10, 0x03, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f,
0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x07, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x41,
0x54, 0x55, 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, 0x12, 0x1b, 0x0a, 0x17, 0x53,
0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x5f, 0x43, 0x41, 0x4e,
0x43, 0x45, 0x4c, 0x4c, 0x45, 0x44, 0x10, 0x05, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x54, 0x41, 0x54,
0x55, 0x53, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x4c, 0x45,
0x44, 0x10, 0x06, 0x42, 0x2c, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
0x6d, 0x2f, 0x67, 0x61, 0x72, 0x65, 0x74, 0x68, 0x67, 0x65, 0x6f, 0x72, 0x67, 0x65, 0x2f, 0x62,
0x61, 0x63, 0x6b, 0x72, 0x65, 0x73, 0x74, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x76,
0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
+100 -110
View File
@@ -409,17 +409,16 @@ func (x *ListSnapshotFilesResponse) GetEntries() []*LsEntry {
return nil
}
type OperationDataRequest struct {
type LogDataRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` // operation id
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` // data key
Ref string `protobuf:"bytes,1,opt,name=ref,proto3" json:"ref,omitempty"`
}
func (x *OperationDataRequest) Reset() {
*x = OperationDataRequest{}
func (x *LogDataRequest) Reset() {
*x = LogDataRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_v1_service_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -427,13 +426,13 @@ func (x *OperationDataRequest) Reset() {
}
}
func (x *OperationDataRequest) String() string {
func (x *LogDataRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*OperationDataRequest) ProtoMessage() {}
func (*LogDataRequest) ProtoMessage() {}
func (x *OperationDataRequest) ProtoReflect() protoreflect.Message {
func (x *LogDataRequest) ProtoReflect() protoreflect.Message {
mi := &file_v1_service_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -445,21 +444,14 @@ func (x *OperationDataRequest) ProtoReflect() protoreflect.Message {
return mi.MessageOf(x)
}
// Deprecated: Use OperationDataRequest.ProtoReflect.Descriptor instead.
func (*OperationDataRequest) Descriptor() ([]byte, []int) {
// Deprecated: Use LogDataRequest.ProtoReflect.Descriptor instead.
func (*LogDataRequest) Descriptor() ([]byte, []int) {
return file_v1_service_proto_rawDescGZIP(), []int{6}
}
func (x *OperationDataRequest) GetId() int64 {
func (x *LogDataRequest) GetRef() string {
if x != nil {
return x.Id
}
return 0
}
func (x *OperationDataRequest) GetKey() string {
if x != nil {
return x.Key
return x.Ref
}
return ""
}
@@ -636,95 +628,93 @@ var file_v1_service_proto_rawDesc = []byte{
0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12,
0x25, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x0b, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x65,
0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x22, 0x38, 0x0a, 0x14, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e,
0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x10,
0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79,
0x22, 0xd3, 0x01, 0x0a, 0x07, 0x4c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01,
0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18,
0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x69,
0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x67, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04,
0x73, 0x69, 0x7a, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65,
0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04,
0x6d, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x74, 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, 0xba, 0x08, 0x0a, 0x08, 0x42, 0x61, 0x63, 0x6b, 0x72,
0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x22, 0x22, 0x0a, 0x0e, 0x4c, 0x6f, 0x67, 0x44, 0x61, 0x74,
0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x65, 0x66, 0x22, 0xd3, 0x01, 0x0a, 0x07, 0x4c,
0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79,
0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12,
0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61,
0x74, 0x68, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52,
0x03, 0x75, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28,
0x03, 0x52, 0x03, 0x67, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x06,
0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f,
0x64, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x14,
0x0a, 0x05, 0x6d, 0x74, 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, 0xa8, 0x08, 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, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x00,
0x12, 0x25, 0x0a, 0x09, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x0a, 0x2e,
0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x0a, 0x2e, 0x76, 0x31, 0x2e, 0x43,
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x00, 0x12, 0x21, 0x0a, 0x07, 0x41, 0x64, 0x64, 0x52, 0x65,
0x70, 0x6f, 0x12, 0x08, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x1a, 0x0a, 0x2e, 0x76,
0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x00, 0x12, 0x44, 0x0a, 0x12, 0x47, 0x65,
0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73,
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, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x22, 0x00, 0x12, 0x25, 0x0a, 0x09, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x12, 0x0a, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a,
0x0a, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x00, 0x12, 0x21, 0x0a,
0x07, 0x41, 0x64, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x12, 0x08, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65,
0x70, 0x6f, 0x1a, 0x0a, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x00,
0x12, 0x44, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 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, 0x12,
0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65,
0x6e, 0x74, 0x22, 0x00, 0x30, 0x01, 0x12, 0x3e, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x65,
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x18, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74,
0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x11, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x4c, 0x69, 0x73, 0x74, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6e,
0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x12, 0x18, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73,
0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x16, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x69, 0x63, 0x53, 0x6e, 0x61,
0x70, 0x73, 0x68, 0x6f, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x00, 0x12, 0x52, 0x0a, 0x11, 0x4c,
0x69, 0x73, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73,
0x12, 0x1c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 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,
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,
0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x12, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70,
0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x00, 0x30, 0x01,
0x12, 0x3e, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x73, 0x12, 0x18, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x76, 0x31,
0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x00,
0x12, 0x43, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74,
0x73, 0x12, 0x18, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73,
0x68, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x76, 0x31,
0x2e, 0x52, 0x65, 0x73, 0x74, 0x69, 0x63, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x4c,
0x69, 0x73, 0x74, 0x22, 0x00, 0x12, 0x52, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6e, 0x61,
0x70, 0x73, 0x68, 0x6f, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x1c, 0x2e, 0x76, 0x31, 0x2e,
0x4c, 0x69, 0x73, 0x74, 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, 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, 0x05, 0x50, 0x72, 0x75, 0x6e, 0x65, 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, 0x46, 0x6f, 0x72, 0x67,
0x65, 0x74, 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, 0x3f, 0x0a, 0x07, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x1a, 0x2e, 0x76, 0x31,
0x2e, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x55, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 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, 0x05, 0x53, 0x74, 0x61,
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, 0x35, 0x0a, 0x06, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x12, 0x11, 0x2e, 0x74, 0x79, 0x70,
0x65, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x36, 0x34, 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, 0x05, 0x50, 0x72, 0x75, 0x6e, 0x65,
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, 0x46, 0x6f, 0x72, 0x67, 0x65, 0x74, 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, 0x3f, 0x0a, 0x07, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72,
0x65, 0x12, 0x1a, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x6e,
0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x55, 0x6e, 0x6c, 0x6f, 0x63,
0x6b, 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, 0x05, 0x53, 0x74, 0x61, 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, 0x35, 0x0a, 0x06, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c,
0x12, 0x11, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x36, 0x34, 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, 0x44, 0x0a,
0x13, 0x47, 0x65, 0x74, 0x42, 0x69, 0x67, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x44, 0x61, 0x74, 0x61, 0x12, 0x18, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11,
0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x56, 0x61, 0x6c, 0x75,
0x65, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x0c, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x48, 0x69, 0x73, 0x74,
0x6f, 0x72, 0x79, 0x12, 0x17, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x48, 0x69,
0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x3b, 0x0a, 0x10, 0x50, 0x61, 0x74, 0x68, 0x41, 0x75,
0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x12, 0x2e, 0x74, 0x79, 0x70,
0x65, 0x73, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x11,
0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73,
0x74, 0x22, 0x00, 0x42, 0x2c, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
0x6d, 0x2f, 0x67, 0x61, 0x72, 0x65, 0x74, 0x68, 0x67, 0x65, 0x6f, 0x72, 0x67, 0x65, 0x2f, 0x62,
0x61, 0x63, 0x6b, 0x72, 0x65, 0x73, 0x74, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x76,
0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x32, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x4c, 0x6f,
0x67, 0x73, 0x12, 0x12, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x44, 0x61, 0x74, 0x61, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x42,
0x79, 0x74, 0x65, 0x73, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x0c, 0x43,
0x6c, 0x65, 0x61, 0x72, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x17, 0x2e, 0x76, 0x31,
0x2e, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 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, 0x3b,
0x0a, 0x10, 0x50, 0x61, 0x74, 0x68, 0x41, 0x75, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65,
0x74, 0x65, 0x12, 0x12, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e,
0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x11, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53,
0x74, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x00, 0x42, 0x2c, 0x5a, 0x2a, 0x67,
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x61, 0x72, 0x65, 0x74, 0x68,
0x67, 0x65, 0x6f, 0x72, 0x67, 0x65, 0x2f, 0x62, 0x61, 0x63, 0x6b, 0x72, 0x65, 0x73, 0x74, 0x2f,
0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x33,
}
var (
@@ -747,7 +737,7 @@ var file_v1_service_proto_goTypes = []interface{}{
(*RestoreSnapshotRequest)(nil), // 3: v1.RestoreSnapshotRequest
(*ListSnapshotFilesRequest)(nil), // 4: v1.ListSnapshotFilesRequest
(*ListSnapshotFilesResponse)(nil), // 5: v1.ListSnapshotFilesResponse
(*OperationDataRequest)(nil), // 6: v1.OperationDataRequest
(*LogDataRequest)(nil), // 6: v1.LogDataRequest
(*LsEntry)(nil), // 7: v1.LsEntry
(*emptypb.Empty)(nil), // 8: google.protobuf.Empty
(*Config)(nil), // 9: v1.Config
@@ -777,7 +767,7 @@ var file_v1_service_proto_depIdxs = []int32{
11, // 13: v1.Backrest.Unlock:input_type -> types.StringValue
11, // 14: v1.Backrest.Stats:input_type -> types.StringValue
12, // 15: v1.Backrest.Cancel:input_type -> types.Int64Value
6, // 16: v1.Backrest.GetBigOperationData:input_type -> v1.OperationDataRequest
6, // 16: v1.Backrest.GetLogs:input_type -> v1.LogDataRequest
0, // 17: v1.Backrest.ClearHistory:input_type -> v1.ClearHistoryRequest
11, // 18: v1.Backrest.PathAutocomplete:input_type -> types.StringValue
9, // 19: v1.Backrest.GetConfig:output_type -> v1.Config
@@ -795,7 +785,7 @@ var file_v1_service_proto_depIdxs = []int32{
8, // 31: v1.Backrest.Unlock:output_type -> google.protobuf.Empty
8, // 32: v1.Backrest.Stats:output_type -> google.protobuf.Empty
8, // 33: v1.Backrest.Cancel:output_type -> google.protobuf.Empty
16, // 34: v1.Backrest.GetBigOperationData:output_type -> types.BytesValue
16, // 34: v1.Backrest.GetLogs:output_type -> types.BytesValue
8, // 35: v1.Backrest.ClearHistory:output_type -> google.protobuf.Empty
17, // 36: v1.Backrest.PathAutocomplete:output_type -> types.StringList
19, // [19:37] is the sub-list for method output_type
@@ -887,7 +877,7 @@ func file_v1_service_proto_init() {
}
}
file_v1_service_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*OperationDataRequest); i {
switch v := v.(*LogDataRequest); i {
case 0:
return &v.state
case 1:
+31 -31
View File
@@ -21,24 +21,24 @@ import (
const _ = grpc.SupportPackageIsVersion7
const (
Backrest_GetConfig_FullMethodName = "/v1.Backrest/GetConfig"
Backrest_SetConfig_FullMethodName = "/v1.Backrest/SetConfig"
Backrest_AddRepo_FullMethodName = "/v1.Backrest/AddRepo"
Backrest_GetOperationEvents_FullMethodName = "/v1.Backrest/GetOperationEvents"
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"
Backrest_Restore_FullMethodName = "/v1.Backrest/Restore"
Backrest_Unlock_FullMethodName = "/v1.Backrest/Unlock"
Backrest_Stats_FullMethodName = "/v1.Backrest/Stats"
Backrest_Cancel_FullMethodName = "/v1.Backrest/Cancel"
Backrest_GetBigOperationData_FullMethodName = "/v1.Backrest/GetBigOperationData"
Backrest_ClearHistory_FullMethodName = "/v1.Backrest/ClearHistory"
Backrest_PathAutocomplete_FullMethodName = "/v1.Backrest/PathAutocomplete"
Backrest_GetConfig_FullMethodName = "/v1.Backrest/GetConfig"
Backrest_SetConfig_FullMethodName = "/v1.Backrest/SetConfig"
Backrest_AddRepo_FullMethodName = "/v1.Backrest/AddRepo"
Backrest_GetOperationEvents_FullMethodName = "/v1.Backrest/GetOperationEvents"
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"
Backrest_Restore_FullMethodName = "/v1.Backrest/Restore"
Backrest_Unlock_FullMethodName = "/v1.Backrest/Unlock"
Backrest_Stats_FullMethodName = "/v1.Backrest/Stats"
Backrest_Cancel_FullMethodName = "/v1.Backrest/Cancel"
Backrest_GetLogs_FullMethodName = "/v1.Backrest/GetLogs"
Backrest_ClearHistory_FullMethodName = "/v1.Backrest/ClearHistory"
Backrest_PathAutocomplete_FullMethodName = "/v1.Backrest/PathAutocomplete"
)
// BackrestClient is the client API for Backrest service.
@@ -69,7 +69,7 @@ type BackrestClient interface {
// Cancel attempts to cancel a task with the given operation ID. Not guaranteed to succeed.
Cancel(ctx context.Context, in *types.Int64Value, opts ...grpc.CallOption) (*emptypb.Empty, error)
// GetBigOperationData returns the keyed large data for the given operation.
GetBigOperationData(ctx context.Context, in *OperationDataRequest, opts ...grpc.CallOption) (*types.BytesValue, error)
GetLogs(ctx context.Context, in *LogDataRequest, opts ...grpc.CallOption) (*types.BytesValue, error)
// Clears the history of operations
ClearHistory(ctx context.Context, in *ClearHistoryRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
// PathAutocomplete provides path autocompletion options for a given filesystem path.
@@ -242,9 +242,9 @@ func (c *backrestClient) Cancel(ctx context.Context, in *types.Int64Value, opts
return out, nil
}
func (c *backrestClient) GetBigOperationData(ctx context.Context, in *OperationDataRequest, opts ...grpc.CallOption) (*types.BytesValue, error) {
func (c *backrestClient) GetLogs(ctx context.Context, in *LogDataRequest, opts ...grpc.CallOption) (*types.BytesValue, error) {
out := new(types.BytesValue)
err := c.cc.Invoke(ctx, Backrest_GetBigOperationData_FullMethodName, in, out, opts...)
err := c.cc.Invoke(ctx, Backrest_GetLogs_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
@@ -297,7 +297,7 @@ type BackrestServer interface {
// Cancel attempts to cancel a task with the given operation ID. Not guaranteed to succeed.
Cancel(context.Context, *types.Int64Value) (*emptypb.Empty, error)
// GetBigOperationData returns the keyed large data for the given operation.
GetBigOperationData(context.Context, *OperationDataRequest) (*types.BytesValue, error)
GetLogs(context.Context, *LogDataRequest) (*types.BytesValue, error)
// Clears the history of operations
ClearHistory(context.Context, *ClearHistoryRequest) (*emptypb.Empty, error)
// PathAutocomplete provides path autocompletion options for a given filesystem path.
@@ -354,8 +354,8 @@ func (UnimplementedBackrestServer) Stats(context.Context, *types.StringValue) (*
func (UnimplementedBackrestServer) Cancel(context.Context, *types.Int64Value) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method Cancel not implemented")
}
func (UnimplementedBackrestServer) GetBigOperationData(context.Context, *OperationDataRequest) (*types.BytesValue, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetBigOperationData not implemented")
func (UnimplementedBackrestServer) GetLogs(context.Context, *LogDataRequest) (*types.BytesValue, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetLogs not implemented")
}
func (UnimplementedBackrestServer) ClearHistory(context.Context, *ClearHistoryRequest) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method ClearHistory not implemented")
@@ -649,20 +649,20 @@ func _Backrest_Cancel_Handler(srv interface{}, ctx context.Context, dec func(int
return interceptor(ctx, in, info, handler)
}
func _Backrest_GetBigOperationData_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(OperationDataRequest)
func _Backrest_GetLogs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(LogDataRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(BackrestServer).GetBigOperationData(ctx, in)
return srv.(BackrestServer).GetLogs(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Backrest_GetBigOperationData_FullMethodName,
FullMethod: Backrest_GetLogs_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(BackrestServer).GetBigOperationData(ctx, req.(*OperationDataRequest))
return srv.(BackrestServer).GetLogs(ctx, req.(*LogDataRequest))
}
return interceptor(ctx, in, info, handler)
}
@@ -767,8 +767,8 @@ var Backrest_ServiceDesc = grpc.ServiceDesc{
Handler: _Backrest_Cancel_Handler,
},
{
MethodName: "GetBigOperationData",
Handler: _Backrest_GetBigOperationData_Handler,
MethodName: "GetLogs",
Handler: _Backrest_GetLogs_Handler,
},
{
MethodName: "ClearHistory",
+55 -56
View File
@@ -67,9 +67,8 @@ const (
BackrestStatsProcedure = "/v1.Backrest/Stats"
// BackrestCancelProcedure is the fully-qualified name of the Backrest's Cancel RPC.
BackrestCancelProcedure = "/v1.Backrest/Cancel"
// BackrestGetBigOperationDataProcedure is the fully-qualified name of the Backrest's
// GetBigOperationData RPC.
BackrestGetBigOperationDataProcedure = "/v1.Backrest/GetBigOperationData"
// BackrestGetLogsProcedure is the fully-qualified name of the Backrest's GetLogs RPC.
BackrestGetLogsProcedure = "/v1.Backrest/GetLogs"
// BackrestClearHistoryProcedure is the fully-qualified name of the Backrest's ClearHistory RPC.
BackrestClearHistoryProcedure = "/v1.Backrest/ClearHistory"
// BackrestPathAutocompleteProcedure is the fully-qualified name of the Backrest's PathAutocomplete
@@ -79,25 +78,25 @@ const (
// These variables are the protoreflect.Descriptor objects for the RPCs defined in this package.
var (
backrestServiceDescriptor = v1.File_v1_service_proto.Services().ByName("Backrest")
backrestGetConfigMethodDescriptor = backrestServiceDescriptor.Methods().ByName("GetConfig")
backrestSetConfigMethodDescriptor = backrestServiceDescriptor.Methods().ByName("SetConfig")
backrestAddRepoMethodDescriptor = backrestServiceDescriptor.Methods().ByName("AddRepo")
backrestGetOperationEventsMethodDescriptor = backrestServiceDescriptor.Methods().ByName("GetOperationEvents")
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")
backrestRestoreMethodDescriptor = backrestServiceDescriptor.Methods().ByName("Restore")
backrestUnlockMethodDescriptor = backrestServiceDescriptor.Methods().ByName("Unlock")
backrestStatsMethodDescriptor = backrestServiceDescriptor.Methods().ByName("Stats")
backrestCancelMethodDescriptor = backrestServiceDescriptor.Methods().ByName("Cancel")
backrestGetBigOperationDataMethodDescriptor = backrestServiceDescriptor.Methods().ByName("GetBigOperationData")
backrestClearHistoryMethodDescriptor = backrestServiceDescriptor.Methods().ByName("ClearHistory")
backrestPathAutocompleteMethodDescriptor = backrestServiceDescriptor.Methods().ByName("PathAutocomplete")
backrestServiceDescriptor = v1.File_v1_service_proto.Services().ByName("Backrest")
backrestGetConfigMethodDescriptor = backrestServiceDescriptor.Methods().ByName("GetConfig")
backrestSetConfigMethodDescriptor = backrestServiceDescriptor.Methods().ByName("SetConfig")
backrestAddRepoMethodDescriptor = backrestServiceDescriptor.Methods().ByName("AddRepo")
backrestGetOperationEventsMethodDescriptor = backrestServiceDescriptor.Methods().ByName("GetOperationEvents")
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")
backrestRestoreMethodDescriptor = backrestServiceDescriptor.Methods().ByName("Restore")
backrestUnlockMethodDescriptor = backrestServiceDescriptor.Methods().ByName("Unlock")
backrestStatsMethodDescriptor = backrestServiceDescriptor.Methods().ByName("Stats")
backrestCancelMethodDescriptor = backrestServiceDescriptor.Methods().ByName("Cancel")
backrestGetLogsMethodDescriptor = backrestServiceDescriptor.Methods().ByName("GetLogs")
backrestClearHistoryMethodDescriptor = backrestServiceDescriptor.Methods().ByName("ClearHistory")
backrestPathAutocompleteMethodDescriptor = backrestServiceDescriptor.Methods().ByName("PathAutocomplete")
)
// BackrestClient is a client for the v1.Backrest service.
@@ -126,7 +125,7 @@ type BackrestClient interface {
// Cancel attempts to cancel a task with the given operation ID. Not guaranteed to succeed.
Cancel(context.Context, *connect.Request[types.Int64Value]) (*connect.Response[emptypb.Empty], error)
// GetBigOperationData returns the keyed large data for the given operation.
GetBigOperationData(context.Context, *connect.Request[v1.OperationDataRequest]) (*connect.Response[types.BytesValue], error)
GetLogs(context.Context, *connect.Request[v1.LogDataRequest]) (*connect.Response[types.BytesValue], error)
// Clears the history of operations
ClearHistory(context.Context, *connect.Request[v1.ClearHistoryRequest]) (*connect.Response[emptypb.Empty], error)
// PathAutocomplete provides path autocompletion options for a given filesystem path.
@@ -233,10 +232,10 @@ func NewBackrestClient(httpClient connect.HTTPClient, baseURL string, opts ...co
connect.WithSchema(backrestCancelMethodDescriptor),
connect.WithClientOptions(opts...),
),
getBigOperationData: connect.NewClient[v1.OperationDataRequest, types.BytesValue](
getLogs: connect.NewClient[v1.LogDataRequest, types.BytesValue](
httpClient,
baseURL+BackrestGetBigOperationDataProcedure,
connect.WithSchema(backrestGetBigOperationDataMethodDescriptor),
baseURL+BackrestGetLogsProcedure,
connect.WithSchema(backrestGetLogsMethodDescriptor),
connect.WithClientOptions(opts...),
),
clearHistory: connect.NewClient[v1.ClearHistoryRequest, emptypb.Empty](
@@ -256,24 +255,24 @@ func NewBackrestClient(httpClient connect.HTTPClient, baseURL string, opts ...co
// backrestClient implements BackrestClient.
type backrestClient struct {
getConfig *connect.Client[emptypb.Empty, v1.Config]
setConfig *connect.Client[v1.Config, v1.Config]
addRepo *connect.Client[v1.Repo, v1.Config]
getOperationEvents *connect.Client[emptypb.Empty, v1.OperationEvent]
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]
restore *connect.Client[v1.RestoreSnapshotRequest, emptypb.Empty]
unlock *connect.Client[types.StringValue, emptypb.Empty]
stats *connect.Client[types.StringValue, emptypb.Empty]
cancel *connect.Client[types.Int64Value, emptypb.Empty]
getBigOperationData *connect.Client[v1.OperationDataRequest, types.BytesValue]
clearHistory *connect.Client[v1.ClearHistoryRequest, emptypb.Empty]
pathAutocomplete *connect.Client[types.StringValue, types.StringList]
getConfig *connect.Client[emptypb.Empty, v1.Config]
setConfig *connect.Client[v1.Config, v1.Config]
addRepo *connect.Client[v1.Repo, v1.Config]
getOperationEvents *connect.Client[emptypb.Empty, v1.OperationEvent]
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]
restore *connect.Client[v1.RestoreSnapshotRequest, emptypb.Empty]
unlock *connect.Client[types.StringValue, emptypb.Empty]
stats *connect.Client[types.StringValue, emptypb.Empty]
cancel *connect.Client[types.Int64Value, emptypb.Empty]
getLogs *connect.Client[v1.LogDataRequest, types.BytesValue]
clearHistory *connect.Client[v1.ClearHistoryRequest, emptypb.Empty]
pathAutocomplete *connect.Client[types.StringValue, types.StringList]
}
// GetConfig calls v1.Backrest.GetConfig.
@@ -351,9 +350,9 @@ func (c *backrestClient) Cancel(ctx context.Context, req *connect.Request[types.
return c.cancel.CallUnary(ctx, req)
}
// GetBigOperationData calls v1.Backrest.GetBigOperationData.
func (c *backrestClient) GetBigOperationData(ctx context.Context, req *connect.Request[v1.OperationDataRequest]) (*connect.Response[types.BytesValue], error) {
return c.getBigOperationData.CallUnary(ctx, req)
// GetLogs calls v1.Backrest.GetLogs.
func (c *backrestClient) GetLogs(ctx context.Context, req *connect.Request[v1.LogDataRequest]) (*connect.Response[types.BytesValue], error) {
return c.getLogs.CallUnary(ctx, req)
}
// ClearHistory calls v1.Backrest.ClearHistory.
@@ -392,7 +391,7 @@ type BackrestHandler interface {
// Cancel attempts to cancel a task with the given operation ID. Not guaranteed to succeed.
Cancel(context.Context, *connect.Request[types.Int64Value]) (*connect.Response[emptypb.Empty], error)
// GetBigOperationData returns the keyed large data for the given operation.
GetBigOperationData(context.Context, *connect.Request[v1.OperationDataRequest]) (*connect.Response[types.BytesValue], error)
GetLogs(context.Context, *connect.Request[v1.LogDataRequest]) (*connect.Response[types.BytesValue], error)
// Clears the history of operations
ClearHistory(context.Context, *connect.Request[v1.ClearHistoryRequest]) (*connect.Response[emptypb.Empty], error)
// PathAutocomplete provides path autocompletion options for a given filesystem path.
@@ -495,10 +494,10 @@ func NewBackrestHandler(svc BackrestHandler, opts ...connect.HandlerOption) (str
connect.WithSchema(backrestCancelMethodDescriptor),
connect.WithHandlerOptions(opts...),
)
backrestGetBigOperationDataHandler := connect.NewUnaryHandler(
BackrestGetBigOperationDataProcedure,
svc.GetBigOperationData,
connect.WithSchema(backrestGetBigOperationDataMethodDescriptor),
backrestGetLogsHandler := connect.NewUnaryHandler(
BackrestGetLogsProcedure,
svc.GetLogs,
connect.WithSchema(backrestGetLogsMethodDescriptor),
connect.WithHandlerOptions(opts...),
)
backrestClearHistoryHandler := connect.NewUnaryHandler(
@@ -545,8 +544,8 @@ func NewBackrestHandler(svc BackrestHandler, opts ...connect.HandlerOption) (str
backrestStatsHandler.ServeHTTP(w, r)
case BackrestCancelProcedure:
backrestCancelHandler.ServeHTTP(w, r)
case BackrestGetBigOperationDataProcedure:
backrestGetBigOperationDataHandler.ServeHTTP(w, r)
case BackrestGetLogsProcedure:
backrestGetLogsHandler.ServeHTTP(w, r)
case BackrestClearHistoryProcedure:
backrestClearHistoryHandler.ServeHTTP(w, r)
case BackrestPathAutocompleteProcedure:
@@ -620,8 +619,8 @@ func (UnimplementedBackrestHandler) Cancel(context.Context, *connect.Request[typ
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("v1.Backrest.Cancel is not implemented"))
}
func (UnimplementedBackrestHandler) GetBigOperationData(context.Context, *connect.Request[v1.OperationDataRequest]) (*connect.Response[types.BytesValue], error) {
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("v1.Backrest.GetBigOperationData is not implemented"))
func (UnimplementedBackrestHandler) GetLogs(context.Context, *connect.Request[v1.LogDataRequest]) (*connect.Response[types.BytesValue], error) {
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("v1.Backrest.GetLogs is not implemented"))
}
func (UnimplementedBackrestHandler) ClearHistory(context.Context, *connect.Request[v1.ClearHistoryRequest]) (*connect.Response[emptypb.Empty], error) {
+7 -4
View File
@@ -19,6 +19,7 @@ import (
"github.com/garethgeorge/backrest/internal/orchestrator"
"github.com/garethgeorge/backrest/internal/protoutil"
"github.com/garethgeorge/backrest/internal/resticinstaller"
"github.com/garethgeorge/backrest/internal/rotatinglog"
"github.com/garethgeorge/backrest/pkg/restic"
"go.uber.org/zap"
"google.golang.org/protobuf/proto"
@@ -30,15 +31,17 @@ type BackrestHandler struct {
config config.ConfigStore
orchestrator *orchestrator.Orchestrator
oplog *oplog.OpLog
logStore *rotatinglog.RotatingLog
}
var _ v1connect.BackrestHandler = &BackrestHandler{}
func NewBackrestHandler(config config.ConfigStore, orchestrator *orchestrator.Orchestrator, oplog *oplog.OpLog) *BackrestHandler {
func NewBackrestHandler(config config.ConfigStore, orchestrator *orchestrator.Orchestrator, oplog *oplog.OpLog, logStore *rotatinglog.RotatingLog) *BackrestHandler {
s := &BackrestHandler{
config: config,
orchestrator: orchestrator,
oplog: oplog,
logStore: logStore,
}
return s
@@ -397,10 +400,10 @@ func (s *BackrestHandler) ClearHistory(ctx context.Context, req *connect.Request
return connect.NewResponse(&emptypb.Empty{}), err
}
func (s *BackrestHandler) GetBigOperationData(ctx context.Context, req *connect.Request[v1.OperationDataRequest]) (*connect.Response[types.BytesValue], error) {
data, err := s.oplog.GetBigData(req.Msg.Id, req.Msg.Key)
func (s *BackrestHandler) GetLogs(ctx context.Context, req *connect.Request[v1.LogDataRequest]) (*connect.Response[types.BytesValue], error) {
data, err := s.logStore.Read(req.Msg.GetRef())
if err != nil {
return nil, fmt.Errorf("get operation data: %w", err)
return nil, fmt.Errorf("get log data %v: %w", req.Msg.GetRef(), err)
}
return connect.NewResponse(&types.BytesValue{Value: data}), nil
}
+24 -9
View File
@@ -12,6 +12,7 @@ import (
v1 "github.com/garethgeorge/backrest/gen/go/v1"
"github.com/garethgeorge/backrest/internal/oplog"
"github.com/garethgeorge/backrest/internal/rotatinglog"
"go.uber.org/zap"
"google.golang.org/protobuf/proto"
)
@@ -20,9 +21,21 @@ var (
defaultTemplate = `{{ .Summary }}`
)
type HookExecutor struct {
oplog *oplog.OpLog
logStore *rotatinglog.RotatingLog
}
func NewHookExecutor(oplog *oplog.OpLog, bigOutputStore *rotatinglog.RotatingLog) *HookExecutor {
return &HookExecutor{
oplog: oplog,
logStore: bigOutputStore,
}
}
// ExecuteHooks schedules tasks for the hooks subscribed to the given event. The vars map is used to substitute variables
// Hooks are pulled both from the provided plan and from the repo config.
func ExecuteHooks(oplog *oplog.OpLog, repo *v1.Repo, plan *v1.Plan, snapshotId string, events []v1.Hook_Condition, vars HookVars) {
func (e *HookExecutor) ExecuteHooks(repo *v1.Repo, plan *v1.Plan, snapshotId string, events []v1.Hook_Condition, vars HookVars) {
operationBase := v1.Operation{
Status: v1.OperationStatus_STATUS_INPROGRESS,
PlanId: plan.Id,
@@ -51,7 +64,7 @@ func ExecuteHooks(oplog *oplog.OpLog, repo *v1.Repo, plan *v1.Plan, snapshotId s
},
}
zap.L().Info("Running hook", zap.String("plan", plan.Id), zap.Int64("opId", operation.Id), zap.String("hook", name))
executeHook(oplog, operation, h, event, vars)
e.executeHook(operation, h, event, vars)
}
for idx, hook := range plan.GetHooks() {
@@ -70,7 +83,7 @@ func ExecuteHooks(oplog *oplog.OpLog, repo *v1.Repo, plan *v1.Plan, snapshotId s
},
}
zap.L().Info("Running hook", zap.String("plan", plan.Id), zap.Int64("opId", operation.Id), zap.String("hook", name))
executeHook(oplog, operation, (*Hook)(hook), event, vars)
e.executeHook(operation, h, event, vars)
}
}
@@ -83,8 +96,8 @@ func firstMatchingCondition(hook *Hook, events []v1.Hook_Condition) v1.Hook_Cond
return v1.Hook_CONDITION_UNKNOWN
}
func executeHook(oplog *oplog.OpLog, op *v1.Operation, hook *Hook, event v1.Hook_Condition, vars HookVars) {
if err := oplog.Add(op); err != nil {
func (e *HookExecutor) executeHook(op *v1.Operation, hook *Hook, event v1.Hook_Condition, vars HookVars) {
if err := e.oplog.Add(op); err != nil {
zap.S().Errorf("execute hook: add operation: %v", err)
return
}
@@ -108,13 +121,15 @@ func executeHook(oplog *oplog.OpLog, op *v1.Operation, hook *Hook, event v1.Hook
op.Status = v1.OperationStatus_STATUS_SUCCESS
}
if err := oplog.SetBigData(op.Id, "hook.log", output.Bytes()); err != nil {
zap.S().Errorf("execute hook: set big data %q: %v", "hook.log", err)
outputRef, err := e.logStore.Write(output.Bytes())
if err != nil {
zap.S().Errorf("execute hook: write log: %v", err)
return
}
op.Op.(*v1.Operation_OperationRunHook).OperationRunHook.OutputRef = "hook.log"
op.Op.(*v1.Operation_OperationRunHook).OperationRunHook.OutputLogref = outputRef
op.UnixTimeEndMs = curTimeMs()
if err := oplog.Update(op); err != nil {
if err := e.oplog.Update(op); err != nil {
zap.S().Errorf("execute hook: update operation: %v", err)
return
}
-62
View File
@@ -1,62 +0,0 @@
package oplog
import (
"bytes"
"os"
"strconv"
"github.com/natefinch/atomic"
"go.uber.org/zap"
)
type BigOpDataStore struct {
path string
}
func NewBigOpDataStore(path string) *BigOpDataStore {
return &BigOpDataStore{
path: path,
}
}
func (s *BigOpDataStore) resolvePath(opId int64) string {
return s.path + "/" + strconv.FormatInt(opId&0xFF, 16) + "/" + strconv.FormatInt(opId, 16)
}
func (s *BigOpDataStore) DeleteOperationData(opId int64) error {
dir := s.resolvePath(opId)
files, err := os.ReadDir(dir)
if err != nil {
if os.IsNotExist(err) {
return nil
}
return err
}
for _, dirent := range files {
if dirent.Name() == "." || dirent.Name() == ".." {
continue
}
if err := os.Remove(dir + "/" + dirent.Name()); err != nil {
zap.S().Errorf("deleting big operation data for operation %v failed to delete %v: %v", opId, dirent.Name(), err)
continue
}
}
return os.Remove(dir)
}
func (s *BigOpDataStore) SetBigData(opId int64, key string, data []byte) error {
dir := s.resolvePath(opId)
if err := os.MkdirAll(dir, 0755); err != nil {
return err
}
return atomic.WriteFile(dir+"/"+key, bytes.NewReader(data))
}
func (s *BigOpDataStore) GetBigData(opId int64, key string) ([]byte, error) {
return os.ReadFile(s.resolvePath(opId) + "/" + key)
}
func (s *BigOpDataStore) DeleteBigData(opId int64, key string) error {
return os.Remove(s.resolvePath(opId) + "/" + key)
}
-35
View File
@@ -1,35 +0,0 @@
package oplog
import (
"testing"
)
func TestBigOpLogDataStore(t *testing.T) {
store := &BigOpDataStore{
path: t.TempDir(),
}
if err := store.SetBigData(1, "test", []byte("hello world")); err != nil {
t.Fatal(err)
}
if byte, err := store.GetBigData(1, "test"); err != nil || string(byte) != "hello world" {
t.Fatalf("expected %q, got %q", "hello world", string(byte))
}
if err := store.SetBigData(1, "test", []byte("hello world 2")); err != nil {
t.Fatal(err)
}
if byte, err := store.GetBigData(1, "test"); err != nil || string(byte) != "hello world 2" {
t.Fatalf("expected %q, got %q", "hello world 2", string(byte))
}
if err := store.DeleteOperationData(1); err != nil {
t.Fatal(err)
}
if _, err := store.GetBigData(1, "test"); err == nil {
t.Fatalf("expected error, got nil")
}
}
-10
View File
@@ -13,7 +13,6 @@ import (
"github.com/garethgeorge/backrest/internal/oplog/serializationutil"
"github.com/garethgeorge/backrest/internal/protoutil"
"github.com/garethgeorge/backrest/pkg/restic"
"github.com/hashicorp/go-multierror"
bolt "go.etcd.io/bbolt"
"go.uber.org/zap"
"google.golang.org/protobuf/proto"
@@ -42,7 +41,6 @@ var (
// Operations are indexed by repo and plan.
type OpLog struct {
db *bolt.DB
*BigOpDataStore
subscribersMu sync.RWMutex
subscribers []*func(*v1.Operation, *v1.Operation)
@@ -60,9 +58,6 @@ func NewOpLog(databasePath string) (*OpLog, error) {
o := &OpLog{
db: db,
BigOpDataStore: &BigOpDataStore{
path: path.Dir(databasePath) + "/opdatav1",
},
}
if err := db.Update(func(tx *bolt.Tx) error {
@@ -215,11 +210,6 @@ func (o *OpLog) Delete(ids ...int64) error {
for _, op := range removedOps {
o.notifyHelper(op, nil)
}
for _, id := range ids {
if e := o.DeleteOperationData(id); e != nil {
err = multierror.Append(err, fmt.Errorf("deleting big data for operation %v: %w", id, e))
}
}
}
return err
}
+10 -6
View File
@@ -11,7 +11,9 @@ import (
v1 "github.com/garethgeorge/backrest/gen/go/v1"
"github.com/garethgeorge/backrest/internal/config"
"github.com/garethgeorge/backrest/internal/hook"
"github.com/garethgeorge/backrest/internal/oplog"
"github.com/garethgeorge/backrest/internal/rotatinglog"
"github.com/garethgeorge/backrest/pkg/restic"
"go.uber.org/zap"
"google.golang.org/protobuf/proto"
@@ -33,11 +35,12 @@ const (
// Orchestrator is responsible for managing repos and backups.
type Orchestrator struct {
mu sync.Mutex
config *v1.Config
OpLog *oplog.OpLog
repoPool *resticRepoPool
taskQueue taskQueue
mu sync.Mutex
config *v1.Config
OpLog *oplog.OpLog
repoPool *resticRepoPool
taskQueue taskQueue
hookExecutor *hook.HookExecutor
// now for the purpose of testing; used by Run() to get the current time.
now func() time.Time
@@ -45,7 +48,7 @@ type Orchestrator struct {
runningTask atomic.Pointer[taskExecutionInfo]
}
func NewOrchestrator(resticBin string, cfg *v1.Config, oplog *oplog.OpLog) (*Orchestrator, error) {
func NewOrchestrator(resticBin string, cfg *v1.Config, oplog *oplog.OpLog, logStore *rotatinglog.RotatingLog) (*Orchestrator, error) {
cfg = proto.Clone(cfg).(*v1.Config)
// create the orchestrator.
@@ -58,6 +61,7 @@ func NewOrchestrator(resticBin string, cfg *v1.Config, oplog *oplog.OpLog) (*Orc
taskQueue: newTaskQueue(func() time.Time {
return o.curTime()
}),
hookExecutor: hook.NewHookExecutor(oplog, logStore),
}
// verify the operation log and mark any incomplete operations as failed.
+4 -4
View File
@@ -42,7 +42,7 @@ func TestTaskScheduling(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
orch, err := NewOrchestrator("", config.NewDefaultConfig(), nil)
orch, err := NewOrchestrator("", config.NewDefaultConfig(), nil, nil)
if err != nil {
t.Fatalf("failed to create orchestrator: %v", err)
}
@@ -81,7 +81,7 @@ func TestTaskRescheduling(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
orch, err := NewOrchestrator("", config.NewDefaultConfig(), nil)
orch, err := NewOrchestrator("", config.NewDefaultConfig(), nil, nil)
if err != nil {
t.Fatalf("failed to create orchestrator: %v", err)
}
@@ -130,7 +130,7 @@ func TestGracefulShutdown(t *testing.T) {
t.Parallel()
// Arrange
orch, err := NewOrchestrator("", config.NewDefaultConfig(), nil)
orch, err := NewOrchestrator("", config.NewDefaultConfig(), nil, nil)
if err != nil {
t.Fatalf("failed to create orchestrator: %v", err)
}
@@ -150,7 +150,7 @@ func TestSchedulerWait(t *testing.T) {
// Arrange
curTime := time.Now()
orch, err := NewOrchestrator("", config.NewDefaultConfig(), nil)
orch, err := NewOrchestrator("", config.NewDefaultConfig(), nil, nil)
if err != nil {
t.Fatalf("failed to create orchestrator: %v", err)
}
+3 -3
View File
@@ -104,7 +104,7 @@ func backupHelper(ctx context.Context, t Task, orchestrator *Orchestrator, plan
return fmt.Errorf("couldn't get repo %q: %w", plan.Repo, err)
}
hook.ExecuteHooks(orchestrator.OpLog, repo.Config(), plan, "", []v1.Hook_Condition{
orchestrator.hookExecutor.ExecuteHooks(repo.Config(), plan, "", []v1.Hook_Condition{
v1.Hook_CONDITION_SNAPSHOT_START,
}, hook.HookVars{
Task: t.Name(),
@@ -137,7 +137,7 @@ func backupHelper(ctx context.Context, t Task, orchestrator *Orchestrator, plan
}
if err != nil {
vars.Error = err.Error()
hook.ExecuteHooks(orchestrator.OpLog, repo.Config(), plan, "", []v1.Hook_Condition{
orchestrator.hookExecutor.ExecuteHooks(repo.Config(), plan, "", []v1.Hook_Condition{
v1.Hook_CONDITION_SNAPSHOT_ERROR, v1.Hook_CONDITION_ANY_ERROR,
}, vars)
@@ -148,7 +148,7 @@ func backupHelper(ctx context.Context, t Task, orchestrator *Orchestrator, plan
op.DisplayMessage = "Partial backup, some files may not have been read completely."
}
hook.ExecuteHooks(orchestrator.OpLog, repo.Config(), plan, summary.SnapshotId, []v1.Hook_Condition{
orchestrator.hookExecutor.ExecuteHooks(repo.Config(), plan, summary.SnapshotId, []v1.Hook_Condition{
v1.Hook_CONDITION_SNAPSHOT_END,
}, vars)
+1 -1
View File
@@ -109,7 +109,7 @@ func (t *ForgetTask) Run(ctx context.Context) error {
return err
}); err != nil {
repo, _ := t.orch.GetRepo(t.plan.Repo)
hook.ExecuteHooks(t.orch.OpLog, repo.Config(), t.plan, t.linkSnapshot, []v1.Hook_Condition{
t.orch.hookExecutor.ExecuteHooks(repo.Config(), t.plan, t.linkSnapshot, []v1.Hook_Condition{
v1.Hook_CONDITION_ANY_ERROR,
}, hook.HookVars{
Task: t.Name(),
+1 -1
View File
@@ -48,7 +48,7 @@ func (t *IndexSnapshotsTask) Next(now time.Time) *time.Time {
func (t *IndexSnapshotsTask) Run(ctx context.Context) error {
if err := indexSnapshotsHelper(ctx, t.orchestrator, t.repoId); err != nil {
repo, _ := t.orchestrator.GetRepo(t.repoId)
hook.ExecuteHooks(t.orchestrator.OpLog, repo.Config(), nil, "", []v1.Hook_Condition{
t.orchestrator.hookExecutor.ExecuteHooks(repo.Config(), nil, "", []v1.Hook_Condition{
v1.Hook_CONDITION_ANY_ERROR,
}, hook.HookVars{
Task: t.Name(),
+1 -1
View File
@@ -163,7 +163,7 @@ func (t *PruneTask) Run(ctx context.Context) error {
return nil
}); err != nil {
repo, _ := t.orch.GetRepo(t.plan.Repo)
hook.ExecuteHooks(t.orch.OpLog, repo.Config(), t.plan, "", []v1.Hook_Condition{
t.orch.hookExecutor.ExecuteHooks(repo.Config(), t.plan, "", []v1.Hook_Condition{
v1.Hook_CONDITION_ANY_ERROR,
}, hook.HookVars{
Task: t.Name(),
+1 -1
View File
@@ -96,7 +96,7 @@ func (t *RestoreTask) Run(ctx context.Context) error {
return nil
}); err != nil {
repo, _ := t.orch.GetRepo(t.restoreOpts.Plan.Repo)
hook.ExecuteHooks(t.orch.OpLog, repo.Config(), nil, t.restoreOpts.SnapshotId, []v1.Hook_Condition{
t.orch.hookExecutor.ExecuteHooks(repo.Config(), nil, t.restoreOpts.SnapshotId, []v1.Hook_Condition{
v1.Hook_CONDITION_ANY_ERROR,
}, hook.HookVars{
Task: t.Name(),
+4 -1
View File
@@ -47,6 +47,9 @@ func (t *StatsTask) shouldRun() (bool, error) {
return oplog.ErrStopIteration
} else if backup, ok := op.Op.(*v1.Operation_OperationBackup); ok && backup.OperationBackup.LastStatus != nil {
if summary, ok := backup.OperationBackup.LastStatus.Entry.(*v1.BackupProgressEntry_Summary); ok {
if bytesSinceLastStat == -1 {
bytesSinceLastStat = 0
}
bytesSinceLastStat += summary.Summary.DataAdded
}
}
@@ -115,7 +118,7 @@ func (t *StatsTask) Run(ctx context.Context) error {
return err
}); err != nil {
repo, _ := t.orch.GetRepo(t.plan.Repo)
hook.ExecuteHooks(t.orch.OpLog, repo.Config(), t.plan, "", []v1.Hook_Condition{
t.orch.hookExecutor.ExecuteHooks(repo.Config(), t.plan, "", []v1.Hook_Condition{
v1.Hook_CONDITION_ANY_ERROR,
}, hook.HookVars{
Task: t.Name(),
+195
View File
@@ -0,0 +1,195 @@
package rotatinglog
import (
"archive/tar"
"bytes"
"compress/gzip"
"errors"
"fmt"
"io"
"io/fs"
"os"
"path"
"slices"
"sort"
"strconv"
"strings"
"sync"
"time"
)
var ErrFileNotFound = errors.New("file not found")
var ErrNotFound = errors.New("entry not found")
var ErrBadName = errors.New("bad name")
type RotatingLog struct {
mu sync.Mutex
dir string
lastFile string
maxLogFiles int
}
func NewRotatingLog(dir string, maxLogFiles int) *RotatingLog {
return &RotatingLog{dir: dir, maxLogFiles: maxLogFiles}
}
func (r *RotatingLog) curfile() string {
return path.Join(r.dir, time.Now().Format("2006-01-02.tar.gz"))
}
func (r *RotatingLog) removeExpiredFiles() error {
if r.maxLogFiles < 0 {
return nil
}
files, err := os.ReadDir(r.dir)
if err != nil {
return err
}
files = slices.DeleteFunc(files, func(f fs.DirEntry) bool {
return f.IsDir()
})
sort.Slice(files, func(i, j int) bool {
return files[i].Name() < files[j].Name()
})
if len(files) >= r.maxLogFiles {
for i := 0; i < len(files)-r.maxLogFiles+1; i++ {
if err := os.Remove(path.Join(r.dir, files[i].Name())); err != nil {
return err
}
}
}
return nil
}
func (r *RotatingLog) Write(data []byte) (string, error) {
r.mu.Lock()
defer r.mu.Unlock()
data, err := compress(data)
if err != nil {
return "", err
}
file := r.curfile()
if file != r.lastFile {
if err := os.MkdirAll(r.dir, os.ModePerm); err != nil {
return "", err
}
r.lastFile = file
}
f, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE, os.ModePerm)
if err != nil {
return "", err
}
defer f.Close()
size, err := f.Seek(0, io.SeekEnd)
if err != nil {
return "", err
}
pos := int64(0)
if size != 0 {
pos, err = f.Seek(-1024, io.SeekEnd)
if err != nil {
return "", err
}
}
tw := tar.NewWriter(f)
defer tw.Close()
name := fmt.Sprintf("%s/%d", path.Base(file), pos)
tw.WriteHeader(&tar.Header{
Name: name,
Size: int64(len(data)),
Mode: 0600,
Typeflag: tar.TypeReg,
ModTime: time.Now(),
})
_, err = tw.Write(data)
if err != nil {
return "", err
}
return name, nil
}
func (r *RotatingLog) Read(name string) ([]byte, error) {
r.mu.Lock()
defer r.mu.Unlock()
// parse name e.g. of the form "2006-01-02-15-04-05.tar/1234"
splitAt := strings.Index(name, "/")
if splitAt == -1 {
return nil, ErrBadName
}
offset, err := strconv.Atoi(name[splitAt+1:])
if err != nil {
return nil, ErrBadName
}
// open file and seek to the offset where the tarball segment should start
f, err := os.Open(path.Join(r.dir, name[:splitAt]))
if err != nil {
if os.IsNotExist(err) {
return nil, ErrFileNotFound
}
return nil, fmt.Errorf("open failed: %w", err)
}
defer f.Close()
f.Seek(int64(offset), io.SeekStart)
// search for the tarball segment in the tarball and read + decompress it if found
tr := tar.NewReader(f)
for {
hdr, err := tr.Next()
if err == io.EOF {
break
}
if err != nil {
return nil, fmt.Errorf("next failed: %v", err)
}
if hdr.Name == name {
buf := make([]byte, hdr.Size)
_, err := io.ReadFull(tr, buf)
if err != nil {
return nil, fmt.Errorf("read failed: %v", err)
}
return decompress(buf)
}
}
return nil, ErrNotFound
}
func compress(data []byte) ([]byte, error) {
var buf bytes.Buffer
zw := gzip.NewWriter(&buf)
if _, err := zw.Write(data); err != nil {
return nil, err
}
if err := zw.Close(); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func decompress(compressedData []byte) ([]byte, error) {
var buf bytes.Buffer
zr, err := gzip.NewReader(bytes.NewReader(compressedData))
if err != nil {
return nil, err
}
if _, err := io.Copy(&buf, zr); err != nil {
return nil, err
}
if err := zr.Close(); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
+61
View File
@@ -0,0 +1,61 @@
package rotatinglog
import (
"fmt"
"strings"
"testing"
)
func TestRotatingLog(t *testing.T) {
log := NewRotatingLog(t.TempDir()+"/rotatinglog", 10)
name, err := log.Write([]byte("test"))
if err != nil {
t.Fatalf("Write failed: %v", err)
}
data, err := log.Read(name)
if err != nil {
t.Fatalf("Read failed: %v", err)
}
if string(data) != "test" {
t.Fatalf("Read failed: expected test, got %s", string(data))
}
}
func TestRotatingLogMultipleEntries(t *testing.T) {
log := NewRotatingLog(t.TempDir()+"/rotatinglog", 10)
for i := 0; i < 10; i++ {
name, err := log.Write([]byte(fmt.Sprintf("%d", i)))
if err != nil {
t.Fatalf("Write failed: %v", err)
}
data, err := log.Read(name)
if err != nil {
t.Fatalf("Read failed: %v", err)
}
if fmt.Sprintf("%d", i) != string(data) {
t.Fatalf("Read failed: expected %d, got %s", i, string(data))
}
}
}
func TestBigEntries(t *testing.T) {
log := NewRotatingLog(t.TempDir()+"/rotatinglog", 10)
for size := range []int{10, 100, 1234, 5938, 1023, 1025} {
data := genstr(size)
name, err := log.Write([]byte(data))
if err != nil {
t.Fatalf("Write failed: %v", err)
}
read, err := log.Read(name)
if err != nil {
t.Fatalf("Read failed: %v", err)
}
if string(read) != data {
t.Fatalf("Read failed: expected %s, got %s", data, string(read))
}
}
}
func genstr(size int) string {
return strings.Repeat("a", size)
}
+1 -1
View File
@@ -98,5 +98,5 @@ message OperationStats {
message OperationRunHook {
string name = 1; // description of the hook that was run. typically repo/hook_idx or plan/hook_idx.
string output_ref = 2; // reference to the output of the hook.
string output_logref = 2; // logref of the hook's output.
}
+3 -4
View File
@@ -51,7 +51,7 @@ service Backrest {
rpc Cancel(types.Int64Value) returns (google.protobuf.Empty) {}
// GetBigOperationData returns the keyed large data for the given operation.
rpc GetBigOperationData(OperationDataRequest) returns (types.BytesValue) {}
rpc GetLogs(LogDataRequest) returns (types.BytesValue) {}
// Clears the history of operations
rpc ClearHistory(ClearHistoryRequest) returns (google.protobuf.Empty) {}
@@ -97,9 +97,8 @@ message ListSnapshotFilesResponse {
repeated LsEntry entries = 2;
}
message OperationDataRequest {
int64 id = 1; // operation id
string key = 2; // data key
message LogDataRequest {
string ref = 1;
}
message LsEntry {
+4 -4
View File
@@ -627,11 +627,11 @@ export class OperationRunHook extends Message<OperationRunHook> {
name = "";
/**
* reference to the output of the hook.
* logref of the hook's output.
*
* @generated from field: string output_ref = 2;
* @generated from field: string output_logref = 2;
*/
outputRef = "";
outputLogref = "";
constructor(data?: PartialMessage<OperationRunHook>) {
super();
@@ -642,7 +642,7 @@ export class OperationRunHook extends Message<OperationRunHook> {
static readonly typeName = "v1.OperationRunHook";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 2, name: "output_ref", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 2, name: "output_logref", kind: "scalar", T: 9 /* ScalarType.STRING */ },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): OperationRunHook {
+5 -5
View File
@@ -6,7 +6,7 @@
import { Empty, MethodKind } from "@bufbuild/protobuf";
import { Config, Repo } from "./config_pb.js";
import { OperationEvent, OperationList } from "./operations_pb.js";
import { ClearHistoryRequest, GetOperationsRequest, ListSnapshotFilesRequest, ListSnapshotFilesResponse, ListSnapshotsRequest, OperationDataRequest, RestoreSnapshotRequest } from "./service_pb.js";
import { ClearHistoryRequest, GetOperationsRequest, ListSnapshotFilesRequest, ListSnapshotFilesResponse, ListSnapshotsRequest, LogDataRequest, RestoreSnapshotRequest } from "./service_pb.js";
import { ResticSnapshotList } from "./restic_pb.js";
import { BytesValue, Int64Value, StringList, StringValue } from "../types/value_pb.js";
@@ -170,11 +170,11 @@ export const Backrest = {
/**
* GetBigOperationData returns the keyed large data for the given operation.
*
* @generated from rpc v1.Backrest.GetBigOperationData
* @generated from rpc v1.Backrest.GetLogs
*/
getBigOperationData: {
name: "GetBigOperationData",
I: OperationDataRequest,
getLogs: {
name: "GetLogs",
I: LogDataRequest,
O: BytesValue,
kind: MethodKind.Unary,
},
+15 -25
View File
@@ -309,49 +309,39 @@ export class ListSnapshotFilesResponse extends Message<ListSnapshotFilesResponse
}
/**
* @generated from message v1.OperationDataRequest
* @generated from message v1.LogDataRequest
*/
export class OperationDataRequest extends Message<OperationDataRequest> {
export class LogDataRequest extends Message<LogDataRequest> {
/**
* operation id
*
* @generated from field: int64 id = 1;
* @generated from field: string ref = 1;
*/
id = protoInt64.zero;
ref = "";
/**
* data key
*
* @generated from field: string key = 2;
*/
key = "";
constructor(data?: PartialMessage<OperationDataRequest>) {
constructor(data?: PartialMessage<LogDataRequest>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "v1.OperationDataRequest";
static readonly typeName = "v1.LogDataRequest";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "id", kind: "scalar", T: 3 /* ScalarType.INT64 */ },
{ no: 2, name: "key", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 1, name: "ref", kind: "scalar", T: 9 /* ScalarType.STRING */ },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): OperationDataRequest {
return new OperationDataRequest().fromBinary(bytes, options);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): LogDataRequest {
return new LogDataRequest().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): OperationDataRequest {
return new OperationDataRequest().fromJson(jsonValue, options);
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): LogDataRequest {
return new LogDataRequest().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): OperationDataRequest {
return new OperationDataRequest().fromJsonString(jsonString, options);
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): LogDataRequest {
return new LogDataRequest().fromJsonString(jsonString, options);
}
static equals(a: OperationDataRequest | PlainMessage<OperationDataRequest> | undefined, b: OperationDataRequest | PlainMessage<OperationDataRequest> | undefined): boolean {
return proto3.util.equals(OperationDataRequest, a, b);
static equals(a: LogDataRequest | PlainMessage<LogDataRequest> | undefined, b: LogDataRequest | PlainMessage<LogDataRequest> | undefined): boolean {
return proto3.util.equals(LogDataRequest, a, b);
}
}
+7 -8
View File
@@ -44,7 +44,7 @@ import {
normalizeSnapshotId,
} from "../lib/formatting";
import _ from "lodash";
import { GetOperationsRequest, OperationDataRequest } from "../../gen/ts/v1/service_pb";
import { GetOperationsRequest, LogDataRequest } from "../../gen/ts/v1/service_pb";
import { useAlertApi } from "./Alerts";
import { MessageInstance } from "antd/es/message/interface";
import { backrestService } from "../api";
@@ -494,7 +494,7 @@ const RunHookOperationStatus = ({ op }: { op: Operation }) => {
key: 1,
label: "Logs for hook " + hook.name,
children: <>
<BigOperationDataVerbatim id={op.id!} outputRef={hook.outputRef} />
<BigOperationDataVerbatim logref={hook.outputLogref} />
</>
},
]} />
@@ -502,22 +502,21 @@ const RunHookOperationStatus = ({ op }: { op: Operation }) => {
}
// TODO: refactor this to use the provider pattern
const BigOperationDataVerbatim = ({ id, outputRef }: { id: bigint, outputRef: string }) => {
const BigOperationDataVerbatim = ({ logref }: { logref: string }) => {
const [output, setOutput] = useState<string | undefined>(undefined);
useEffect(() => {
if (!outputRef) {
if (!logref) {
return;
}
backrestService.getBigOperationData(new OperationDataRequest({
id: id,
key: outputRef,
backrestService.getLogs(new LogDataRequest({
ref: logref,
})).then((resp) => {
setOutput(new TextDecoder("utf-8").decode(resp.value));
}).catch((e) => {
console.error("Failed to fetch hook output: ", e);
});
}, [id, outputRef]);
}, [logref]);
return <pre>{output}</pre>;
}