diff --git a/apis/job_get_log.go b/apis/job_get_log.go index d397125..6a30d5e 100644 --- a/apis/job_get_log.go +++ b/apis/job_get_log.go @@ -17,8 +17,8 @@ func (api *API) JobGetLog(ctx context.Context, req *entity.JobGetLogRequest) (*e return &entity.JobGetLogReply{Logs: []byte{}}, nil } - if req.Offset > 0 { - if _, err := reader.Seek(req.Offset, 0); err != nil { + if req.Offset != nil { + if _, err := reader.Seek(*req.Offset, 0); err != nil { return nil, fmt.Errorf("seek log file fail, offset= %d, %w", req.Offset, err) } } diff --git a/cmd/tape-httpd/main.go b/cmd/tape-httpd/main.go index a52148c..a743d06 100644 --- a/cmd/tape-httpd/main.go +++ b/cmd/tape-httpd/main.go @@ -9,6 +9,7 @@ import ( "log" "net/http" "os" + "time" "github.com/abc950309/tapewriter/apis" "github.com/abc950309/tapewriter/entity" @@ -17,6 +18,7 @@ import ( "github.com/abc950309/tapewriter/resource" "github.com/abc950309/tapewriter/tools" "github.com/improbable-eng/grpc-web/go/grpcweb" + "github.com/sirupsen/logrus" "google.golang.org/grpc" "gopkg.in/yaml.v2" ) @@ -110,6 +112,15 @@ func main() { Addr: conf.Listen, } + go func() { + <-tools.ShutdownContext.Done() + logrus.Infof("Graceful shutdown, wait for working process") + start := time.Now() + tools.Wait() + logrus.Infof("Graceful shutdown, wait done, duration= %s", time.Since(start)) + srv.Shutdown(context.Background()) + }() + log.Printf("http server listening at %v", srv.Addr) if err := srv.ListenAndServe(); err != nil { log.Fatalf("failed to serve: %v", err) diff --git a/entity/job_archive.pb.go b/entity/job_archive.pb.go index a884e31..3923c42 100644 --- a/entity/job_archive.pb.go +++ b/entity/job_archive.pb.go @@ -412,11 +412,12 @@ type JobDisplayArchive struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - CopyedBytes int64 `protobuf:"varint,1,opt,name=copyedBytes,proto3" json:"copyedBytes,omitempty"` - CopyedFiles int64 `protobuf:"varint,2,opt,name=copyedFiles,proto3" json:"copyedFiles,omitempty"` - TotalBytes int64 `protobuf:"varint,3,opt,name=totalBytes,proto3" json:"totalBytes,omitempty"` - TotalFiles int64 `protobuf:"varint,4,opt,name=totalFiles,proto3" json:"totalFiles,omitempty"` - Speed int64 `protobuf:"varint,5,opt,name=speed,proto3" json:"speed,omitempty"` + CopyedBytes int64 `protobuf:"varint,1,opt,name=copyedBytes,proto3" json:"copyedBytes,omitempty"` + CopyedFiles int64 `protobuf:"varint,2,opt,name=copyedFiles,proto3" json:"copyedFiles,omitempty"` + TotalBytes int64 `protobuf:"varint,3,opt,name=totalBytes,proto3" json:"totalBytes,omitempty"` + TotalFiles int64 `protobuf:"varint,4,opt,name=totalFiles,proto3" json:"totalFiles,omitempty"` + Speed *int64 `protobuf:"varint,5,opt,name=speed,proto3,oneof" json:"speed,omitempty"` + StartTime int64 `protobuf:"varint,6,opt,name=startTime,proto3" json:"startTime,omitempty"` } func (x *JobDisplayArchive) Reset() { @@ -480,8 +481,15 @@ func (x *JobDisplayArchive) GetTotalFiles() int64 { } func (x *JobDisplayArchive) GetSpeed() int64 { + if x != nil && x.Speed != nil { + return *x.Speed + } + return 0 +} + +func (x *JobDisplayArchive) GetStartTime() int64 { if x != nil { - return x.Speed + return x.StartTime } return 0 } @@ -527,7 +535,7 @@ var file_job_archive_proto_rawDesc = []byte{ 0x76, 0x65, 0x53, 0x74, 0x65, 0x70, 0x52, 0x04, 0x73, 0x74, 0x65, 0x70, 0x12, 0x2d, 0x0a, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x52, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0xad, 0x01, 0x0a, 0x11, + 0x74, 0x65, 0x52, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0xda, 0x01, 0x0a, 0x11, 0x4a, 0x6f, 0x62, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x70, 0x79, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x6f, 0x70, 0x79, 0x65, 0x64, 0x42, 0x79, @@ -537,16 +545,19 @@ var file_job_archive_proto_rawDesc = []byte{ 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, - 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x70, 0x65, 0x65, 0x64, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, 0x70, 0x65, 0x65, 0x64, 0x2a, 0x4a, 0x0a, 0x0e, 0x4a, - 0x6f, 0x62, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x53, 0x74, 0x65, 0x70, 0x12, 0x0b, 0x0a, - 0x07, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x57, 0x61, - 0x69, 0x74, 0x46, 0x6f, 0x72, 0x54, 0x61, 0x70, 0x65, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x43, - 0x6f, 0x70, 0x79, 0x69, 0x6e, 0x67, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x08, 0x46, 0x69, 0x6e, 0x69, - 0x73, 0x68, 0x65, 0x64, 0x10, 0xff, 0x01, 0x42, 0x28, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x62, 0x63, 0x39, 0x35, 0x30, 0x33, 0x30, 0x39, 0x2f, - 0x74, 0x61, 0x70, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x72, 0x2f, 0x65, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x19, 0x0a, 0x05, 0x73, 0x70, 0x65, 0x65, 0x64, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x05, 0x73, 0x70, 0x65, 0x65, 0x64, 0x88, 0x01, 0x01, + 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x42, 0x08, + 0x0a, 0x06, 0x5f, 0x73, 0x70, 0x65, 0x65, 0x64, 0x2a, 0x4a, 0x0a, 0x0e, 0x4a, 0x6f, 0x62, 0x41, + 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x53, 0x74, 0x65, 0x70, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x65, + 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x57, 0x61, 0x69, 0x74, 0x46, + 0x6f, 0x72, 0x54, 0x61, 0x70, 0x65, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x6f, 0x70, 0x79, + 0x69, 0x6e, 0x67, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x08, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, + 0x64, 0x10, 0xff, 0x01, 0x42, 0x28, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x61, 0x62, 0x63, 0x39, 0x35, 0x30, 0x33, 0x30, 0x39, 0x2f, 0x74, 0x61, 0x70, + 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x72, 0x2f, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -686,6 +697,7 @@ func file_job_archive_proto_init() { (*JobArchiveNextParam_Copying)(nil), (*JobArchiveNextParam_Finished)(nil), } + file_job_archive_proto_msgTypes[6].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/entity/job_archive.proto b/entity/job_archive.proto index 8622082..a10faa1 100644 --- a/entity/job_archive.proto +++ b/entity/job_archive.proto @@ -46,4 +46,5 @@ message JobDisplayArchive { int64 totalFiles = 4; optional int64 speed = 5; + int64 startTime = 6; } diff --git a/entity/service.pb.go b/entity/service.pb.go index 8ff6e5d..789dcba 100644 --- a/entity/service.pb.go +++ b/entity/service.pb.go @@ -1029,7 +1029,7 @@ type JobDisplayReply struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Display *JobDisplay `protobuf:"bytes,1,opt,name=display,proto3,oneof" json:"display,omitempty"` + Display *JobDisplay `protobuf:"bytes,1,opt,name=display,proto3" json:"display,omitempty"` } func (x *JobDisplayReply) Reset() { @@ -1076,8 +1076,8 @@ type JobGetLogRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - JobId int64 `protobuf:"varint,1,opt,name=job_id,json=jobId,proto3" json:"job_id,omitempty"` - Offset int64 `protobuf:"varint,2,opt,name=offset,proto3" json:"offset,omitempty"` + JobId int64 `protobuf:"varint,1,opt,name=job_id,json=jobId,proto3" json:"job_id,omitempty"` + Offset *int64 `protobuf:"varint,2,opt,name=offset,proto3,oneof" json:"offset,omitempty"` } func (x *JobGetLogRequest) Reset() { @@ -1120,8 +1120,8 @@ func (x *JobGetLogRequest) GetJobId() int64 { } func (x *JobGetLogRequest) GetOffset() int64 { - if x != nil { - return x.Offset + if x != nil && x.Offset != nil { + return *x.Offset } return 0 } @@ -1447,93 +1447,93 @@ var file_service_proto_rawDesc = []byte{ 0x32, 0x08, 0x2e, 0x6a, 0x6f, 0x62, 0x2e, 0x4a, 0x6f, 0x62, 0x52, 0x03, 0x6a, 0x6f, 0x62, 0x22, 0x23, 0x0a, 0x11, 0x4a, 0x6f, 0x62, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x02, 0x69, 0x64, 0x22, 0x4d, 0x0a, 0x0f, 0x4a, 0x6f, 0x62, 0x44, 0x69, 0x73, 0x70, 0x6c, - 0x61, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x2e, 0x0a, 0x07, 0x64, 0x69, 0x73, 0x70, 0x6c, + 0x52, 0x02, 0x69, 0x64, 0x22, 0x3c, 0x0a, 0x0f, 0x4a, 0x6f, 0x62, 0x44, 0x69, 0x73, 0x70, 0x6c, + 0x61, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x29, 0x0a, 0x07, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x6a, 0x6f, 0x62, 0x2e, 0x4a, - 0x6f, 0x62, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x48, 0x00, 0x52, 0x07, 0x64, 0x69, 0x73, - 0x70, 0x6c, 0x61, 0x79, 0x88, 0x01, 0x01, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x64, 0x69, 0x73, 0x70, - 0x6c, 0x61, 0x79, 0x22, 0x41, 0x0a, 0x10, 0x4a, 0x6f, 0x62, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x16, - 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, - 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x24, 0x0a, 0x0e, 0x4a, 0x6f, 0x62, 0x47, 0x65, 0x74, - 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x22, 0x27, 0x0a, 0x11, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x93, 0x01, 0x0a, 0x0f, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x26, 0x0a, 0x04, 0x66, 0x69, 0x6c, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x04, 0x66, 0x69, 0x6c, - 0x65, 0x12, 0x28, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x46, 0x69, 0x6c, 0x65, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x2e, 0x0a, 0x08, 0x63, - 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x18, 0x11, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, - 0x65, 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x22, 0x13, 0x0a, 0x11, 0x44, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x22, 0x2b, 0x0a, 0x0f, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, - 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x32, 0xf6, 0x06, - 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x3b, 0x0a, 0x07, 0x46, 0x69, 0x6c, - 0x65, 0x47, 0x65, 0x74, 0x12, 0x17, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x46, - 0x69, 0x6c, 0x65, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x47, 0x65, 0x74, 0x52, - 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x3e, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x45, 0x64, - 0x69, 0x74, 0x12, 0x18, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x46, 0x69, 0x6c, - 0x65, 0x45, 0x64, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x45, 0x64, 0x69, 0x74, 0x52, - 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x09, 0x46, 0x69, 0x6c, 0x65, 0x4d, 0x6b, - 0x64, 0x69, 0x72, 0x12, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x46, 0x69, - 0x6c, 0x65, 0x4d, 0x6b, 0x64, 0x69, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, - 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4d, 0x6b, 0x64, - 0x69, 0x72, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x44, 0x0a, 0x0a, 0x46, 0x69, 0x6c, - 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1a, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x46, 0x69, - 0x6c, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, - 0x53, 0x0a, 0x0f, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x72, 0x65, 0x6e, - 0x74, 0x73, 0x12, 0x1f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x46, 0x69, 0x6c, - 0x65, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x46, 0x69, - 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x70, - 0x6c, 0x79, 0x22, 0x00, 0x12, 0x3e, 0x0a, 0x08, 0x54, 0x61, 0x70, 0x65, 0x4d, 0x47, 0x65, 0x74, - 0x12, 0x18, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x54, 0x61, 0x70, 0x65, 0x4d, - 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x54, 0x61, 0x70, 0x65, 0x4d, 0x47, 0x65, 0x74, 0x52, 0x65, 0x70, - 0x6c, 0x79, 0x22, 0x00, 0x12, 0x3b, 0x0a, 0x07, 0x4a, 0x6f, 0x62, 0x4c, 0x69, 0x73, 0x74, 0x12, - 0x17, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, - 0x00, 0x12, 0x41, 0x0a, 0x09, 0x4a, 0x6f, 0x62, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x19, - 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, - 0x6c, 0x79, 0x22, 0x00, 0x12, 0x3b, 0x0a, 0x07, 0x4a, 0x6f, 0x62, 0x4e, 0x65, 0x78, 0x74, 0x12, - 0x17, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x4e, 0x65, 0x78, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, - 0x00, 0x12, 0x44, 0x0a, 0x0a, 0x4a, 0x6f, 0x62, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x12, - 0x1a, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x44, 0x69, 0x73, - 0x70, 0x6c, 0x61, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, - 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x09, 0x4a, 0x6f, 0x62, 0x47, 0x65, - 0x74, 0x4c, 0x6f, 0x67, 0x12, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4a, - 0x6f, 0x62, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x17, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x47, 0x65, 0x74, - 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x44, 0x0a, 0x0a, 0x53, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1a, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, - 0x12, 0x44, 0x0a, 0x0a, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1a, - 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4c, - 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, 0x28, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x62, 0x63, 0x39, 0x35, 0x30, 0x33, 0x30, 0x39, 0x2f, 0x74, - 0x61, 0x70, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x72, 0x2f, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x62, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x52, 0x07, 0x64, 0x69, 0x73, 0x70, 0x6c, + 0x61, 0x79, 0x22, 0x51, 0x0a, 0x10, 0x4a, 0x6f, 0x62, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x1b, 0x0a, + 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, + 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x6f, + 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x24, 0x0a, 0x0e, 0x4a, 0x6f, 0x62, 0x47, 0x65, 0x74, 0x4c, + 0x6f, 0x67, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x22, 0x27, 0x0a, 0x11, 0x53, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x70, 0x61, 0x74, 0x68, 0x22, 0x93, 0x01, 0x0a, 0x0f, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x26, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, + 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, + 0x12, 0x28, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x12, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, + 0x69, 0x6c, 0x65, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x2e, 0x0a, 0x08, 0x63, 0x68, + 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x18, 0x11, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x65, + 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x22, 0x13, 0x0a, 0x11, 0x44, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, + 0x2b, 0x0a, 0x0f, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x70, + 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x32, 0xf6, 0x06, 0x0a, + 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x3b, 0x0a, 0x07, 0x46, 0x69, 0x6c, 0x65, + 0x47, 0x65, 0x74, 0x12, 0x17, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x46, 0x69, + 0x6c, 0x65, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x47, 0x65, 0x74, 0x52, 0x65, + 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x3e, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x45, 0x64, 0x69, + 0x74, 0x12, 0x18, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, + 0x45, 0x64, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x45, 0x64, 0x69, 0x74, 0x52, 0x65, + 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x09, 0x46, 0x69, 0x6c, 0x65, 0x4d, 0x6b, 0x64, + 0x69, 0x72, 0x12, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x46, 0x69, 0x6c, + 0x65, 0x4d, 0x6b, 0x64, 0x69, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4d, 0x6b, 0x64, 0x69, + 0x72, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x44, 0x0a, 0x0a, 0x46, 0x69, 0x6c, 0x65, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1a, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x46, 0x69, 0x6c, + 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x53, + 0x0a, 0x0f, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x73, 0x12, 0x1f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, + 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x46, 0x69, 0x6c, + 0x65, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x70, 0x6c, + 0x79, 0x22, 0x00, 0x12, 0x3e, 0x0a, 0x08, 0x54, 0x61, 0x70, 0x65, 0x4d, 0x47, 0x65, 0x74, 0x12, + 0x18, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x54, 0x61, 0x70, 0x65, 0x4d, 0x47, + 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x54, 0x61, 0x70, 0x65, 0x4d, 0x47, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6c, + 0x79, 0x22, 0x00, 0x12, 0x3b, 0x0a, 0x07, 0x4a, 0x6f, 0x62, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x17, + 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, + 0x12, 0x41, 0x0a, 0x09, 0x4a, 0x6f, 0x62, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x19, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6c, + 0x79, 0x22, 0x00, 0x12, 0x3b, 0x0a, 0x07, 0x4a, 0x6f, 0x62, 0x4e, 0x65, 0x78, 0x74, 0x12, 0x17, + 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x4e, 0x65, 0x78, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, + 0x12, 0x44, 0x0a, 0x0a, 0x4a, 0x6f, 0x62, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x12, 0x1a, + 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x44, 0x69, 0x73, 0x70, + 0x6c, 0x61, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x52, + 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x09, 0x4a, 0x6f, 0x62, 0x47, 0x65, 0x74, + 0x4c, 0x6f, 0x67, 0x12, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4a, 0x6f, + 0x62, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, + 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x47, 0x65, 0x74, 0x4c, + 0x6f, 0x67, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x44, 0x0a, 0x0a, 0x53, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1a, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, + 0x44, 0x0a, 0x0a, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1a, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, 0x28, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x62, 0x63, 0x39, 0x35, 0x30, 0x33, 0x30, 0x39, 0x2f, 0x74, 0x61, + 0x70, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x72, 0x2f, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1982,7 +1982,7 @@ func file_service_proto_init() { (*JobListRequest_Mget)(nil), (*JobListRequest_List)(nil), } - file_service_proto_msgTypes[20].OneofWrappers = []interface{}{} + file_service_proto_msgTypes[21].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/executor/executor.go b/executor/executor.go index 2ac7859..ba98c14 100644 --- a/executor/executor.go +++ b/executor/executor.go @@ -106,7 +106,7 @@ func (e *Executor) Submit(ctx context.Context, job *Job, param *entity.JobNextPa return err } - exe.submit(param.GetArchive()) + exe.submit(ctx, param.GetArchive()) return nil } diff --git a/executor/job.go b/executor/job.go index 53792ae..9cccb66 100644 --- a/executor/job.go +++ b/executor/job.go @@ -109,19 +109,19 @@ func (e *Executor) GetJob(ctx context.Context, id int64) (*Job, error) { func (e *Executor) ListJob(ctx context.Context, filter *entity.JobFilter) ([]*Job, error) { db := e.db.WithContext(ctx) if filter.Status != nil { - db.Where("status = ?", *filter.Status) + db = db.Where("status = ?", *filter.Status) } if filter.Limit != nil { - db.Limit(int(*filter.Limit)) + db = db.Limit(int(*filter.Limit)) } else { - db.Limit(20) + db = db.Limit(20) } if filter.Offset != nil { - db.Offset(int(*filter.Offset)) + db = db.Offset(int(*filter.Offset)) } - db.Order("create_time DESC") + db = db.Order("create_time DESC") jobs := make([]*Job, 0, 20) if r := db.Find(&jobs); r.Error != nil { diff --git a/executor/job_archive_display.go b/executor/job_archive_display.go index a5c9a1c..046f870 100644 --- a/executor/job_archive_display.go +++ b/executor/job_archive_display.go @@ -15,7 +15,10 @@ func (e *Executor) getArchiveDisplay(ctx context.Context, job *Job) (*entity.Job display.CopyedFiles = atomic.LoadInt64(&exe.progress.files) display.TotalBytes = atomic.LoadInt64(&exe.progress.totalBytes) display.TotalFiles = atomic.LoadInt64(&exe.progress.totalFiles) - display.Speed = atomic.LoadInt64(&exe.progress.speed) + display.StartTime = exe.progress.startTime.Unix() + + speed := atomic.LoadInt64(&exe.progress.speed) + display.Speed = &speed } return display, nil diff --git a/executor/job_archive_exe.go b/executor/job_archive_exe.go index 4a6997a..029f200 100644 --- a/executor/job_archive_exe.go +++ b/executor/job_archive_exe.go @@ -46,15 +46,13 @@ func (e *Executor) newArchiveExecutor(ctx context.Context, job *Job) (*jobArchiv logger.SetOutput(io.MultiWriter(os.Stderr, logFile)) exe := &jobArchiveExecutor{ - ctx: context.Background(), exe: e, job: job, state: job.State.GetArchive(), - progress: new(progress), - logFile: logFile, - logger: logger, + logFile: logFile, + logger: logger, } runningArchives.Store(job.ID, exe) @@ -62,7 +60,6 @@ func (e *Executor) newArchiveExecutor(ctx context.Context, job *Job) (*jobArchiv } type jobArchiveExecutor struct { - ctx context.Context exe *Executor job *Job @@ -74,22 +71,23 @@ type jobArchiveExecutor struct { logger *logrus.Logger } -func (a *jobArchiveExecutor) submit(param *entity.JobArchiveNextParam) { - if err := a.handle(param); err != nil { - a.logger.WithContext(a.ctx).Infof("handler param fail, err= %w", err) +func (a *jobArchiveExecutor) submit(ctx context.Context, param *entity.JobArchiveNextParam) { + if err := a.handle(ctx, param); err != nil { + a.logger.WithContext(ctx).Infof("handler param fail, err= %w", err) } } -func (a *jobArchiveExecutor) handle(param *entity.JobArchiveNextParam) error { +func (a *jobArchiveExecutor) handle(ctx context.Context, param *entity.JobArchiveNextParam) error { if p := param.GetCopying(); p != nil { - if err := a.switchStep(entity.JobArchiveStep_Copying, entity.JobStatus_Processing, mapset.NewThreadUnsafeSet(entity.JobArchiveStep_WaitForTape)); err != nil { + if err := a.switchStep(ctx, entity.JobArchiveStep_Copying, entity.JobStatus_Processing, mapset.NewThreadUnsafeSet(entity.JobArchiveStep_WaitForTape)); err != nil { return err } - go tools.Wrap(a.ctx, func() { - _, err := a.makeTape(p.Device, p.Barcode, p.Name) - if err != nil { - a.logger.WithContext(a.ctx).WithError(err).Errorf("make type has error, barcode= '%s' name= '%s'", p.Barcode, p.Name) + tools.Working() + go tools.Wrap(ctx, func() { + defer tools.Done() + if err := a.makeTape(tools.ShutdownContext, p.Device, p.Barcode, p.Name); err != nil { + a.logger.WithContext(ctx).WithError(err).Errorf("make type has error, barcode= '%s' name= '%s'", p.Barcode, p.Name) } }) @@ -97,11 +95,11 @@ func (a *jobArchiveExecutor) handle(param *entity.JobArchiveNextParam) error { } if p := param.GetWaitForTape(); p != nil { - return a.switchStep(entity.JobArchiveStep_WaitForTape, entity.JobStatus_Processing, mapset.NewThreadUnsafeSet(entity.JobArchiveStep_Pending, entity.JobArchiveStep_Copying)) + return a.switchStep(ctx, entity.JobArchiveStep_WaitForTape, entity.JobStatus_Processing, mapset.NewThreadUnsafeSet(entity.JobArchiveStep_Pending, entity.JobArchiveStep_Copying)) } if p := param.GetFinished(); p != nil { - if err := a.switchStep(entity.JobArchiveStep_Finished, entity.JobStatus_Completed, mapset.NewThreadUnsafeSet(entity.JobArchiveStep_Copying)); err != nil { + if err := a.switchStep(ctx, entity.JobArchiveStep_Finished, entity.JobStatus_Completed, mapset.NewThreadUnsafeSet(entity.JobArchiveStep_Copying)); err != nil { return err } @@ -113,51 +111,48 @@ func (a *jobArchiveExecutor) handle(param *entity.JobArchiveNextParam) error { return nil } -func (a *jobArchiveExecutor) makeTape(device, barcode, name string) (*library.Tape, error) { +func (a *jobArchiveExecutor) makeTape(ctx context.Context, device, barcode, name string) (rerr error) { if !a.exe.occupyDevice(device) { - return nil, fmt.Errorf("device is using, device= %s", device) + return fmt.Errorf("device is using, device= %s", device) } defer a.exe.releaseDevice(device) - defer a.makeTapeFinished() + defer a.makeTapeFinished(tools.WithoutTimeout(ctx)) encryption, keyPath, keyRecycle, err := a.exe.newKey() if err != nil { - return nil, err + return err } - defer func() { - time.Sleep(time.Second) - keyRecycle() - }() + defer keyRecycle() - if err := runCmd(a.logger, a.exe.makeEncryptCmd(a.ctx, device, keyPath, barcode, name)); err != nil { - return nil, fmt.Errorf("run encrypt script fail, %w", err) + if err := runCmd(a.logger, a.exe.makeEncryptCmd(ctx, device, keyPath, barcode, name)); err != nil { + return fmt.Errorf("run encrypt script fail, %w", err) } - mkfsCmd := exec.CommandContext(a.ctx, a.exe.mkfsScript) + mkfsCmd := exec.CommandContext(ctx, a.exe.mkfsScript) mkfsCmd.Env = append(mkfsCmd.Env, fmt.Sprintf("DEVICE=%s", device), fmt.Sprintf("TAPE_BARCODE=%s", barcode), fmt.Sprintf("TAPE_NAME=%s", name)) if err := runCmd(a.logger, mkfsCmd); err != nil { - return nil, fmt.Errorf("run mkfs script fail, %w", err) + return fmt.Errorf("run mkfs script fail, %w", err) } mountPoint, err := os.MkdirTemp("", "*.ltfs") if err != nil { - return nil, fmt.Errorf("create temp mountpoint, %w", err) + return fmt.Errorf("create temp mountpoint, %w", err) } - mountCmd := exec.CommandContext(a.ctx, a.exe.mountScript) + mountCmd := exec.CommandContext(ctx, a.exe.mountScript) mountCmd.Env = append(mountCmd.Env, fmt.Sprintf("DEVICE=%s", device), fmt.Sprintf("MOUNT_POINT=%s", mountPoint)) if err := runCmd(a.logger, mountCmd); err != nil { - return nil, fmt.Errorf("run mount script fail, %w", err) + return fmt.Errorf("run mount script fail, %w", err) } defer func() { - umountCmd := exec.CommandContext(a.ctx, a.exe.umountScript) + umountCmd := exec.CommandContext(tools.WithoutTimeout(ctx), a.exe.umountScript) umountCmd.Env = append(umountCmd.Env, fmt.Sprintf("MOUNT_POINT=%s", mountPoint)) if err := runCmd(a.logger, umountCmd); err != nil { - a.logger.WithContext(a.ctx).WithError(err).Errorf("run umount script fail, %s", mountPoint) + a.logger.WithContext(ctx).WithError(err).Errorf("run umount script fail, %s", mountPoint) return } if err := os.Remove(mountPoint); err != nil { - a.logger.WithContext(a.ctx).WithError(err).Errorf("remove mount point fail, %s", mountPoint) + a.logger.WithContext(ctx).WithError(err).Errorf("remove mount point fail, %s", mountPoint) return } }() @@ -177,6 +172,10 @@ func (a *jobArchiveExecutor) makeTape(device, barcode, name string) (*library.Ta reportHander, reportGetter := acp.NewReportGetter() opts = append(opts, acp.WithEventHandler(reportHander)) + + a.progress = newProgress() + defer func() { a.progress = nil }() + opts = append(opts, acp.WithEventHandler(func(ev acp.Event) { switch e := ev.(type) { case *acp.EventUpdateCount: @@ -184,9 +183,12 @@ func (a *jobArchiveExecutor) makeTape(device, barcode, name string) (*library.Ta atomic.StoreInt64(&a.progress.totalFiles, e.Files) return case *acp.EventUpdateProgress: - atomic.StoreInt64(&a.progress.bytes, e.Bytes) + a.progress.setBytes(e.Bytes) atomic.StoreInt64(&a.progress.files, e.Files) return + case *acp.EventReportError: + a.logger.WithContext(ctx).Errorf("acp report error, src= '%s' dst= '%s' err= '%s'", e.Error.Src, e.Error.Dst, e.Error.Err) + return case *acp.EventUpdateJob: job := e.Job src := entity.NewSourceFromACPJob(job) @@ -196,11 +198,17 @@ func (a *jobArchiveExecutor) makeTape(device, barcode, name string) (*library.Ta case "pending": targetStatus = entity.CopyStatus_Pending case "preparing": - a.logger.Infof("file '%s' starts to prepare for copy, size= %d", src.RealPath(), job.Size) targetStatus = entity.CopyStatus_Running case "finished": - a.logger.Infof("file '%s' copy finished, size= %d", src.RealPath(), job.Size) + a.logger.WithContext(ctx).Infof("file '%s' copy finished, size= %d", src.RealPath(), job.Size) targetStatus = entity.CopyStatus_Staged + + for dst, err := range job.FailTargets { + if err == nil { + continue + } + a.logger.WithContext(ctx).WithError(err).Errorf("file '%s' copy fail, dst= '%s'", src.RealPath(), dst) + } default: return } @@ -218,72 +226,89 @@ func (a *jobArchiveExecutor) makeTape(device, barcode, name string) (*library.Ta } target.Status = targetStatus - if _, err := a.exe.SaveJob(a.ctx, a.job); err != nil { - logrus.WithContext(a.ctx).Infof("save job for update file fail, name= %s", job.Base+path.Join(job.Path...)) + if _, err := a.exe.SaveJob(ctx, a.job); err != nil { + logrus.WithContext(ctx).Infof("save job for update file fail, name= %s", job.Base+path.Join(job.Path...)) } return } })) - copyer, err := acp.New(a.ctx, opts...) - if err != nil { - return nil, fmt.Errorf("start copy fail, %w", err) - } - copyer.Wait() + defer func() { + ctx := tools.WithoutTimeout(ctx) - report := reportGetter() - sort.Slice(report.Jobs, func(i, j int) bool { - return entity.NewSourceFromACPJob(report.Jobs[i]).Compare(entity.NewSourceFromACPJob(report.Jobs[j])) < 0 - }) - - filteredJobs := make([]*acp.Job, 0, len(report.Jobs)) - files := make([]*library.TapeFile, 0, len(report.Jobs)) - for _, job := range report.Jobs { - if len(job.SuccessTargets) == 0 { - continue - } - if !job.Mode.IsRegular() { - continue - } - - hash, err := hex.DecodeString(job.SHA256) - if err != nil { - return nil, fmt.Errorf("decode sha256 fail, err= %w", err) - } - - files = append(files, &library.TapeFile{ - Path: path.Join(job.Path...), - Size: job.Size, - Mode: job.Mode, - ModTime: job.ModTime, - WriteTime: job.WriteTime, - Hash: hash, + report := reportGetter() + sort.Slice(report.Jobs, func(i, j int) bool { + return entity.NewSourceFromACPJob(report.Jobs[i]).Compare(entity.NewSourceFromACPJob(report.Jobs[j])) < 0 }) - filteredJobs = append(filteredJobs, job) - } - tape, err := a.exe.lib.CreateTape(a.ctx, &library.Tape{ - Barcode: barcode, - Name: name, - Encryption: encryption, - CreateTime: time.Now(), - }, files) + reportFile, err := a.exe.newReportWriter(barcode) + if err != nil { + a.logger.WithContext(ctx).WithError(err).Warnf("open report file fail, barcode= '%s'", barcode) + } else { + defer reportFile.Close() + reportFile.Write([]byte(report.ToJSONString(false))) + } + + filteredJobs := make([]*acp.Job, 0, len(report.Jobs)) + files := make([]*library.TapeFile, 0, len(report.Jobs)) + for _, job := range report.Jobs { + if len(job.SuccessTargets) == 0 { + continue + } + if !job.Mode.IsRegular() { + continue + } + + hash, err := hex.DecodeString(job.SHA256) + if err != nil { + a.logger.WithContext(ctx).WithError(err).Warnf("decode sha256 fail, path= '%s'", entity.NewSourceFromACPJob(job).RealPath()) + continue + } + + files = append(files, &library.TapeFile{ + Path: path.Join(job.Path...), + Size: job.Size, + Mode: job.Mode, + ModTime: job.ModTime, + WriteTime: job.WriteTime, + Hash: hash, + }) + filteredJobs = append(filteredJobs, job) + } + + tape, err := a.exe.lib.CreateTape(ctx, &library.Tape{ + Barcode: barcode, + Name: name, + Encryption: encryption, + CreateTime: time.Now(), + }, files) + if err != nil { + rerr = tools.AppendError(rerr, fmt.Errorf("create tape fail, barcode= '%s' name= '%s', %w", barcode, name, err)) + return + } + a.logger.Infof("create tape success, tape_id= %d", tape.ID) + + if err := a.exe.lib.TrimFiles(ctx); err != nil { + a.logger.WithError(err).Warnf("trim library files fail") + } + + if err := a.markSourcesAsSubmited(ctx, filteredJobs); err != nil { + rerr = tools.AppendError(rerr, fmt.Errorf("mark source as submited fail, %w", err)) + return + } + }() + + copyer, err := acp.New(ctx, opts...) if err != nil { - return nil, fmt.Errorf("create tape fail, barcode= '%s' name= '%s', %w", barcode, name, err) - } - if err := a.exe.lib.TrimFiles(a.ctx); err != nil { - a.logger.WithError(err).Warnf("trim library files fail") + rerr = fmt.Errorf("start copy fail, %w", err) + return } - if err := a.markSourcesAsSubmited(filteredJobs); err != nil { - a.submit(&entity.JobArchiveNextParam{Param: &entity.JobArchiveNextParam_WaitForTape{WaitForTape: &entity.JobArchiveWaitForTapeParam{}}}) - return nil, err - } - - return tape, nil + copyer.Wait() + return } -func (a *jobArchiveExecutor) switchStep(target entity.JobArchiveStep, status entity.JobStatus, expect mapset.Set[entity.JobArchiveStep]) error { +func (a *jobArchiveExecutor) switchStep(ctx context.Context, target entity.JobArchiveStep, status entity.JobStatus, expect mapset.Set[entity.JobArchiveStep]) error { a.stateLock.Lock() defer a.stateLock.Unlock() @@ -293,14 +318,14 @@ func (a *jobArchiveExecutor) switchStep(target entity.JobArchiveStep, status ent a.state.Step = target a.job.Status = status - if _, err := a.exe.SaveJob(a.ctx, a.job); err != nil { + if _, err := a.exe.SaveJob(ctx, a.job); err != nil { return fmt.Errorf("switch to step copying, save job fail, %w", err) } return nil } -func (a *jobArchiveExecutor) markSourcesAsSubmited(jobs []*acp.Job) error { +func (a *jobArchiveExecutor) markSourcesAsSubmited(ctx context.Context, jobs []*acp.Job) error { a.stateLock.Lock() defer a.stateLock.Unlock() @@ -322,14 +347,9 @@ func (a *jobArchiveExecutor) markSourcesAsSubmited(jobs []*acp.Job) error { target.Status = entity.CopyStatus_Submited } - if _, err := a.exe.SaveJob(a.ctx, a.job); err != nil { + if _, err := a.exe.SaveJob(ctx, a.job); err != nil { return fmt.Errorf("mark sources as submited, save job, %w", err) } - - atomic.StoreInt64(&a.progress.bytes, 0) - atomic.StoreInt64(&a.progress.files, 0) - atomic.StoreInt64(&a.progress.totalBytes, 0) - atomic.StoreInt64(&a.progress.totalFiles, 0) return nil } @@ -348,10 +368,10 @@ func (a *jobArchiveExecutor) getTodoSources() int { return todo } -func (a *jobArchiveExecutor) makeTapeFinished() { +func (a *jobArchiveExecutor) makeTapeFinished(ctx context.Context) { if a.getTodoSources() > 0 { - a.submit(&entity.JobArchiveNextParam{Param: &entity.JobArchiveNextParam_WaitForTape{WaitForTape: &entity.JobArchiveWaitForTapeParam{}}}) + a.submit(ctx, &entity.JobArchiveNextParam{Param: &entity.JobArchiveNextParam_WaitForTape{WaitForTape: &entity.JobArchiveWaitForTapeParam{}}}) } else { - a.submit(&entity.JobArchiveNextParam{Param: &entity.JobArchiveNextParam_Finished{Finished: &entity.JobArchiveFinishedParam{}}}) + a.submit(ctx, &entity.JobArchiveNextParam{Param: &entity.JobArchiveNextParam_Finished{Finished: &entity.JobArchiveFinishedParam{}}}) } } diff --git a/executor/log.go b/executor/log.go index be98fba..296d4c6 100644 --- a/executor/log.go +++ b/executor/log.go @@ -48,3 +48,21 @@ func runCmd(logger *logrus.Logger, cmd *exec.Cmd) error { return cmd.Run() } + +func (e *Executor) reportPath(barcode string) (string, string) { + return path.Join(e.workDirectory, "write-reports"), fmt.Sprintf("%s.log", barcode) +} + +func (e *Executor) newReportWriter(barcode string) (*os.File, error) { + dir, filename := e.reportPath(barcode) + if err := os.MkdirAll(dir, 0755); err != nil { + return nil, fmt.Errorf("make job log dir fail, path= '%s', err= %w", dir, err) + } + + file, err := os.OpenFile(path.Join(dir, filename), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + if err != nil { + return nil, fmt.Errorf("create file fail, path= '%s', err= %w", path.Join(dir, filename), err) + } + + return file, nil +} diff --git a/executor/progress.go b/executor/progress.go index f09f7b3..0c5ebd5 100644 --- a/executor/progress.go +++ b/executor/progress.go @@ -1,8 +1,55 @@ package executor +import ( + "sync/atomic" + "time" +) + +const SpeedLen = 30 + +type speedEvent struct { + bytes int64 + time time.Time +} + type progress struct { - speed int64 + speedEvents []speedEvent + speedLen int + speedIdx int + + startTime time.Time + speed int64 totalBytes, totalFiles int64 bytes, files int64 } + +func newProgress() *progress { + return &progress{speedEvents: make([]speedEvent, SpeedLen), speedLen: SpeedLen, startTime: time.Now()} +} + +func (p *progress) setBytes(bytes int64) { + atomic.StoreInt64(&p.bytes, bytes) + now := time.Now() + + p.speedEvents[p.speedIdx] = speedEvent{bytes: bytes, time: now} + for earliest := p.speedIdx; ; { + earliest++ + if earliest >= p.speedLen { + earliest = 0 + } + if earliest == p.speedIdx { + break + } + + if !p.speedEvents[earliest].time.IsZero() { + p.speed = (bytes - p.speedEvents[earliest].bytes) * 1e9 / now.Sub(p.speedEvents[earliest].time).Nanoseconds() + break + } + } + + p.speedIdx++ + if p.speedIdx >= p.speedLen { + p.speedIdx = 0 + } +} diff --git a/frontend/.gitignore b/frontend/.gitignore index a547bf3..7ceb59f 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -22,3 +22,4 @@ dist-ssr *.njsproj *.sln *.sw? +.env diff --git a/frontend/package.json b/frontend/package.json index 05d887a..cb1ca11 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -25,6 +25,7 @@ "chonky-icon-fontawesome": "^2.3.2", "fast-text-encoding": "^1.0.6", "filesize": "^10.0.5", + "format-duration": "^2.0.0", "moment": "^2.29.4", "react": "^18.2.0", "react-dnd": "^11.1.3", @@ -34,6 +35,7 @@ }, "devDependencies": { "@protobuf-ts/plugin": "^2.8.2", + "@types/node": "^18.11.14", "@types/react": "^18.0.17", "@types/react-dom": "^18.0.6", "@vitejs/plugin-react": "^2.1.0", diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 886dbd1..cd5d74c 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -13,6 +13,7 @@ specifiers: '@protobuf-ts/plugin': ^2.8.2 '@protobuf-ts/runtime': ^2.8.2 '@protobuf-ts/runtime-rpc': ^2.8.2 + '@types/node': ^18.11.14 '@types/react': ^18.0.17 '@types/react-dom': ^18.0.6 '@vitejs/plugin-react': ^2.1.0 @@ -20,6 +21,7 @@ specifiers: chonky-icon-fontawesome: ^2.3.2 fast-text-encoding: ^1.0.6 filesize: ^10.0.5 + format-duration: ^2.0.0 less: ^4.1.3 moment: ^2.29.4 prettier: 2.7.1 @@ -48,6 +50,7 @@ dependencies: chonky-icon-fontawesome: 2.3.2_qge232svojtclvlhf4p5efbcfu fast-text-encoding: 1.0.6 filesize: 10.0.5 + format-duration: 2.0.0 moment: 2.29.4 react: 18.2.0 react-dnd: 11.1.3_biqbaboplfbrettd7655fr4n2y @@ -57,6 +60,7 @@ dependencies: devDependencies: '@protobuf-ts/plugin': 2.8.2 + '@types/node': 18.11.14 '@types/react': 18.0.21 '@types/react-dom': 18.0.6 '@vitejs/plugin-react': 2.1.0_vite@3.1.8 @@ -1043,6 +1047,10 @@ packages: resolution: {integrity: sha512-qDpXKGgwKywnQt/64fH1O0LiPA++QGIYeykEUiZ51HymKVRLnUSGcRuF60IfpPeeXiuRwiR/W4y7S5VzbrgLCA==} dev: false + /@types/node/18.11.14: + resolution: {integrity: sha512-0KXV57tENYmmJMl+FekeW9V3O/rlcqGQQJ/hNh9r8pKIj304pskWuEd8fCyNT86g/TpO0gcOTiLzsHLEURFMIQ==} + dev: true + /@types/parse-json/4.0.0: resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} dev: false @@ -1657,6 +1665,10 @@ packages: resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} dev: false + /format-duration/2.0.0: + resolution: {integrity: sha512-ARqJ9qXm71pw3SGAY7bibf8lRLvltOXLjWjzzR3UrUjHu1zdeYpA/Z+u+ltdhrfRa440OjEsHNzdmuZViqqQWQ==} + dev: false + /fsevents/2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} diff --git a/frontend/src/api.ts b/frontend/src/api.ts index c51b5fd..dd2177b 100644 --- a/frontend/src/api.ts +++ b/frontend/src/api.ts @@ -7,7 +7,7 @@ import moment from "moment"; const apiBase: string = (() => { const base = (window as any).apiBase as string; if (!base || base === "%%API_BASE%%") { - return "http://127.0.0.1:8080/services"; + return "http://localhost:5173/services"; } return base; })(); diff --git a/frontend/src/app.less b/frontend/src/app.less index 25b2a74..f574642 100644 --- a/frontend/src/app.less +++ b/frontend/src/app.less @@ -19,6 +19,7 @@ padding: 0.5em; height: 100%; box-sizing: border-box; + overflow-y: hidden; .browser-container { margin: 0; @@ -26,6 +27,7 @@ height: 100%; .browser { + height: 100%; box-sizing: border-box; padding-right: 0.5em; @@ -45,6 +47,19 @@ } } } + + .job-list { + min-height: min-content; + height: 100%; + box-sizing: border-box; + overflow-y: scroll; + // -ms-overflow-style: none; /* IE and Edge */ + // scrollbar-width: none; /* Firefox */ + + // &::-webkit-scrollbar { + // display: none; + // } + } } } diff --git a/frontend/src/entity/job_archive.ts b/frontend/src/entity/job_archive.ts index 9c0f9d7..68248fd 100644 --- a/frontend/src/entity/job_archive.ts +++ b/frontend/src/entity/job_archive.ts @@ -115,6 +115,10 @@ export interface JobDisplayArchive { * @generated from protobuf field: optional int64 speed = 5; */ speed?: bigint; + /** + * @generated from protobuf field: int64 startTime = 6; + */ + startTime: bigint; } /** * @generated from protobuf enum job_archive.JobArchiveStep @@ -429,11 +433,12 @@ class JobDisplayArchive$Type extends MessageType { { no: 2, name: "copyedFiles", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 3, name: "totalBytes", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 4, name: "totalFiles", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, - { no: 5, name: "speed", kind: "scalar", opt: true, T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ } + { no: 5, name: "speed", kind: "scalar", opt: true, T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, + { no: 6, name: "startTime", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ } ]); } create(value?: PartialMessage): JobDisplayArchive { - const message = { copyedBytes: 0n, copyedFiles: 0n, totalBytes: 0n, totalFiles: 0n }; + const message = { copyedBytes: 0n, copyedFiles: 0n, totalBytes: 0n, totalFiles: 0n, startTime: 0n }; globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); if (value !== undefined) reflectionMergePartial(this, message, value); @@ -459,6 +464,9 @@ class JobDisplayArchive$Type extends MessageType { case /* optional int64 speed */ 5: message.speed = reader.int64().toBigInt(); break; + case /* int64 startTime */ 6: + message.startTime = reader.int64().toBigInt(); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -486,6 +494,9 @@ class JobDisplayArchive$Type extends MessageType { /* optional int64 speed = 5; */ if (message.speed !== undefined) writer.tag(5, WireType.Varint).int64(message.speed); + /* int64 startTime = 6; */ + if (message.startTime !== 0n) + writer.tag(6, WireType.Varint).int64(message.startTime); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); diff --git a/frontend/src/jobs.tsx b/frontend/src/jobs.tsx index 3b5da0e..37b12fe 100644 --- a/frontend/src/jobs.tsx +++ b/frontend/src/jobs.tsx @@ -1,6 +1,7 @@ import { Fragment, ChangeEvent } from "react"; import { useState, useRef, useEffect, useMemo, useCallback, FC } from "react"; import { assert } from "@protobuf-ts/runtime"; +import format from "format-duration"; import Grid from "@mui/material/Grid"; import Box from "@mui/material/Box"; @@ -75,9 +76,11 @@ export const JobsBrowser = () => { - {jobs.map((job) => ( - - ))} +
+ {jobs.map((job) => ( + + ))} +
@@ -113,38 +116,6 @@ const ArchiveCard = ({ display: JobDisplayArchive | null; refresh: () => Promise; }): JSX.Element => { - const [lastDisplay, setLastDisplay] = useState(null); - const [speed, setSpeed] = useState(NaN); - const diffDisplay = useCallback( - (current: ArchiveLastDisplay | null) => { - if (!lastDisplay) { - setLastDisplay(current); - return; - } - if (!current) { - setLastDisplay(current); - setSpeed(NaN); - return; - } - - const duration = current.lastUpdate - lastDisplay.lastUpdate; - if (duration) { - const speed = ((Number(current.copyedBytes) - Number(lastDisplay.copyedBytes)) / duration) * 1000; - setSpeed(speed); - } - - setLastDisplay(current); - }, - [lastDisplay, setLastDisplay, setSpeed] - ); - useEffect(() => { - if (!display) { - diffDisplay(null); - return; - } - diffDisplay({ copyedBytes: display.copyedBytes, lastUpdate: Date.now() }); - }, [display]); - const [fields, progress] = useMemo(() => { const totalFiles = state.sources.length; let submitedFiles = 0, @@ -161,11 +132,25 @@ const ArchiveCard = ({ const copyedFiles = submitedFiles + Number(display?.copyedFiles || 0n); const copyedBytes = submitedBytes + Number(display?.copyedBytes || 0n); + const avgSpeed = (() => { + if (!display || !display.copyedBytes || !display.startTime) { + return NaN; + } + + const duration = Date.now() / 1000 - Number(display.startTime); + if (duration <= 0) { + return NaN; + } + + return Number(display.copyedBytes) / duration; + })(); const progress = (totalBytes > 0 ? copyedBytes / totalBytes : 1) * 100; const fields = [ { name: "Current Step", value: JobArchiveStep[state.step] }, - { name: "Current Speed", value: !Number.isNaN(speed) ? `${formatFilesize(speed)}/s` : "--" }, + { name: "Current Speed", value: display?.speed ? `${formatFilesize(display?.speed)}/s` : "--" }, + { name: "Average Speed", value: !isNaN(avgSpeed) ? `${formatFilesize(avgSpeed)}/s` : "--" }, + { name: "Estimated Time", value: !isNaN(avgSpeed) ? format(((totalBytes - copyedBytes) * 1000) / avgSpeed) : "--" }, { name: "Total Files", value: totalFiles }, { name: "Total Bytes", value: formatFilesize(totalBytes) }, { name: "Submited Files", value: submitedFiles }, @@ -175,7 +160,7 @@ const ArchiveCard = ({ ]; return [fields, progress]; - }, [state, display, speed]); + }, [state, display]); return ( { return () => { closed = true; }; - }, []); + }, [refreshLog]); return
{log || "loading..."}
; }; diff --git a/frontend/tsconfig.node.json b/frontend/tsconfig.node.json index 9d31e2a..5167ddc 100644 --- a/frontend/tsconfig.node.json +++ b/frontend/tsconfig.node.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "target": "es2020", "composite": true, "module": "ESNext", "moduleResolution": "Node", diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index d289dd6..b53ad6d 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -1,15 +1,26 @@ -import { defineConfig } from "vite"; +import { defineConfig, loadEnv } from "vite"; import react from "@vitejs/plugin-react"; // https://vitejs.dev/config/ -export default defineConfig({ - plugins: [react()], - build: { - target: "es2020", - }, - optimizeDeps: { - esbuildOptions: { +export default defineConfig(({ command, mode }) => { + const env = loadEnv(mode, process.cwd(), ""); + console.log(env); + + return { + plugins: [react()], + build: { target: "es2020", }, - }, + optimizeDeps: { + esbuildOptions: { + target: "es2020", + }, + }, + server: { + proxy: { + // target http://localhost:5173 + "/services": env.DEV_SERVICE_BASE, + }, + }, + }; }); diff --git a/go.mod b/go.mod index 734c017..cbfb7df 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/abc950309/tapewriter go 1.18 require ( - github.com/abc950309/acp v0.0.0-20221212144614-c5de5e555428 + github.com/abc950309/acp v0.0.0-20221213054500-913956ff10a1 github.com/aws/aws-sdk-go v1.44.118 github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set/v2 v2.1.0 diff --git a/go.sum b/go.sum index 843c962..b68f635 100644 --- a/go.sum +++ b/go.sum @@ -21,6 +21,12 @@ github.com/abc950309/acp v0.0.0-20221211170531-ae151264e710 h1:WedtGWyNGXdHZDft0 github.com/abc950309/acp v0.0.0-20221211170531-ae151264e710/go.mod h1:5RsleINAlZ326MJ8fmoCW9IJdnlpa6ZVdHqufsfcQMI= github.com/abc950309/acp v0.0.0-20221212144614-c5de5e555428 h1:NQDEsoxNJDxdMuZCJq0R9hqeaR64X8oyEhx0PKUCSwo= github.com/abc950309/acp v0.0.0-20221212144614-c5de5e555428/go.mod h1:5RsleINAlZ326MJ8fmoCW9IJdnlpa6ZVdHqufsfcQMI= +github.com/abc950309/acp v0.0.0-20221213013859-b7a44e4c0071 h1:sKxesiKeO5dX+TY96m0iegmqvthqH+lN7q5LRG2e8ck= +github.com/abc950309/acp v0.0.0-20221213013859-b7a44e4c0071/go.mod h1:5RsleINAlZ326MJ8fmoCW9IJdnlpa6ZVdHqufsfcQMI= +github.com/abc950309/acp v0.0.0-20221213025816-edd8196e43e6 h1:lgO5pSBYSHqkCYP3/iiFefcsi7udjX1NaujO2cPx5JE= +github.com/abc950309/acp v0.0.0-20221213025816-edd8196e43e6/go.mod h1:7gK/wICIhVBZ6B2AZm+0uN06wDhKLSsq4TME/fwJUJI= +github.com/abc950309/acp v0.0.0-20221213054500-913956ff10a1 h1:UgiD4G3c3WROUHp+elpLVvKuW0+9xErtgkilnDb+XdU= +github.com/abc950309/acp v0.0.0-20221213054500-913956ff10a1/go.mod h1:7gK/wICIhVBZ6B2AZm+0uN06wDhKLSsq4TME/fwJUJI= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= diff --git a/scripts/umount b/scripts/umount index 278c42a..7054ebc 100755 --- a/scripts/umount +++ b/scripts/umount @@ -1,6 +1,5 @@ #!/usr/bin/env bash set -ex; -sleep 15 +sleep 2 umount ${MOUNT_POINT} -sleep 60 diff --git a/tools/context.go b/tools/context.go new file mode 100644 index 0000000..30eb874 --- /dev/null +++ b/tools/context.go @@ -0,0 +1,42 @@ +package tools + +import ( + "context" + "log" + "os" + "os/signal" + "syscall" + "time" +) + +type noTimeout struct { + ctx context.Context +} + +func (c noTimeout) Deadline() (time.Time, bool) { return time.Time{}, false } +func (c noTimeout) Done() <-chan struct{} { return nil } +func (c noTimeout) Err() error { return nil } +func (c noTimeout) Value(key interface{}) interface{} { return c.ctx.Value(key) } + +// WithoutCancel returns a context that is never canceled. +func WithoutTimeout(ctx context.Context) context.Context { + return noTimeout{ctx: ctx} +} + +var ( + ShutdownContext context.Context +) + +func init() { + c := make(chan os.Signal, 1) + signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) + + bgctx, cancel := context.WithCancel(context.Background()) + go func() { + oscall := <-c + log.Printf("system call: %+v", oscall) + cancel() + }() + + ShutdownContext = bgctx +} diff --git a/tools/error.go b/tools/error.go new file mode 100644 index 0000000..6483f21 --- /dev/null +++ b/tools/error.go @@ -0,0 +1,12 @@ +package tools + +import ( + "github.com/hashicorp/go-multierror" +) + +func AppendError(err, e error) error { + if err != nil { + return multierror.Append(err, e) + } + return e +} diff --git a/tools/working.go b/tools/working.go new file mode 100644 index 0000000..3182519 --- /dev/null +++ b/tools/working.go @@ -0,0 +1,19 @@ +package tools + +import "sync" + +var ( + wg sync.WaitGroup +) + +func Working() { + wg.Add(1) +} + +func Done() { + wg.Done() +} + +func Wait() { + wg.Wait() +}