From 2543b3bce866762faede7536ab0085c366755d2f Mon Sep 17 00:00:00 2001 From: j-rafique Date: Thu, 5 Jun 2025 01:32:37 +0500 Subject: [PATCH] add health check endpoint on supernode gRPC server --- gen/supernode/action/cascade/service.pb.go | 332 ++++++++++++++++-- .../action/cascade/service_grpc.pb.go | 43 ++- go.mod | 8 + go.sum | 22 ++ proto/supernode/action/cascade/service.proto | 23 ++ .../server/cascade/cascade_action_server.go | 49 ++- .../node/action/server/cascade/helper.go | 39 ++ supernode/services/cascade/healthcheck.go | 71 ++++ .../services/cascade/healthcheck_test.go | 84 +++++ supernode/services/cascade/interfaces.go | 1 + .../cascade/mocks/cascade_interfaces_mock.go | 24 +- 11 files changed, 620 insertions(+), 76 deletions(-) create mode 100644 supernode/node/action/server/cascade/helper.go create mode 100644 supernode/services/cascade/healthcheck.go create mode 100644 supernode/services/cascade/healthcheck_test.go diff --git a/gen/supernode/action/cascade/service.pb.go b/gen/supernode/action/cascade/service.pb.go index c0a20173..534e5272 100644 --- a/gen/supernode/action/cascade/service.pb.go +++ b/gen/supernode/action/cascade/service.pb.go @@ -334,6 +334,226 @@ func (x *RegisterResponse) GetTxHash() string { return "" } +type HealthCheckRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *HealthCheckRequest) Reset() { + *x = HealthCheckRequest{} + mi := &file_supernode_action_cascade_service_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *HealthCheckRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HealthCheckRequest) ProtoMessage() {} + +func (x *HealthCheckRequest) ProtoReflect() protoreflect.Message { + mi := &file_supernode_action_cascade_service_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HealthCheckRequest.ProtoReflect.Descriptor instead. +func (*HealthCheckRequest) Descriptor() ([]byte, []int) { + return file_supernode_action_cascade_service_proto_rawDescGZIP(), []int{4} +} + +// The HealthCheckResponse represents system health status. +type HealthCheckResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Cpu *HealthCheckResponse_CPU `protobuf:"bytes,1,opt,name=cpu,proto3" json:"cpu,omitempty"` + Memory *HealthCheckResponse_Memory `protobuf:"bytes,2,opt,name=memory,proto3" json:"memory,omitempty"` + TasksInProgress []string `protobuf:"bytes,3,rep,name=tasks_in_progress,json=tasksInProgress,proto3" json:"tasks_in_progress,omitempty"` +} + +func (x *HealthCheckResponse) Reset() { + *x = HealthCheckResponse{} + mi := &file_supernode_action_cascade_service_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *HealthCheckResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HealthCheckResponse) ProtoMessage() {} + +func (x *HealthCheckResponse) ProtoReflect() protoreflect.Message { + mi := &file_supernode_action_cascade_service_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HealthCheckResponse.ProtoReflect.Descriptor instead. +func (*HealthCheckResponse) Descriptor() ([]byte, []int) { + return file_supernode_action_cascade_service_proto_rawDescGZIP(), []int{5} +} + +func (x *HealthCheckResponse) GetCpu() *HealthCheckResponse_CPU { + if x != nil { + return x.Cpu + } + return nil +} + +func (x *HealthCheckResponse) GetMemory() *HealthCheckResponse_Memory { + if x != nil { + return x.Memory + } + return nil +} + +func (x *HealthCheckResponse) GetTasksInProgress() []string { + if x != nil { + return x.TasksInProgress + } + return nil +} + +type HealthCheckResponse_CPU struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Usage string `protobuf:"bytes,1,opt,name=usage,proto3" json:"usage,omitempty"` + Remaining string `protobuf:"bytes,2,opt,name=remaining,proto3" json:"remaining,omitempty"` +} + +func (x *HealthCheckResponse_CPU) Reset() { + *x = HealthCheckResponse_CPU{} + mi := &file_supernode_action_cascade_service_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *HealthCheckResponse_CPU) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HealthCheckResponse_CPU) ProtoMessage() {} + +func (x *HealthCheckResponse_CPU) ProtoReflect() protoreflect.Message { + mi := &file_supernode_action_cascade_service_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HealthCheckResponse_CPU.ProtoReflect.Descriptor instead. +func (*HealthCheckResponse_CPU) Descriptor() ([]byte, []int) { + return file_supernode_action_cascade_service_proto_rawDescGZIP(), []int{5, 0} +} + +func (x *HealthCheckResponse_CPU) GetUsage() string { + if x != nil { + return x.Usage + } + return "" +} + +func (x *HealthCheckResponse_CPU) GetRemaining() string { + if x != nil { + return x.Remaining + } + return "" +} + +type HealthCheckResponse_Memory struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Total uint64 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"` + Used uint64 `protobuf:"varint,2,opt,name=used,proto3" json:"used,omitempty"` + Available uint64 `protobuf:"varint,3,opt,name=available,proto3" json:"available,omitempty"` + UsedPerc float64 `protobuf:"fixed64,4,opt,name=used_perc,json=usedPerc,proto3" json:"used_perc,omitempty"` +} + +func (x *HealthCheckResponse_Memory) Reset() { + *x = HealthCheckResponse_Memory{} + mi := &file_supernode_action_cascade_service_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *HealthCheckResponse_Memory) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HealthCheckResponse_Memory) ProtoMessage() {} + +func (x *HealthCheckResponse_Memory) ProtoReflect() protoreflect.Message { + mi := &file_supernode_action_cascade_service_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HealthCheckResponse_Memory.ProtoReflect.Descriptor instead. +func (*HealthCheckResponse_Memory) Descriptor() ([]byte, []int) { + return file_supernode_action_cascade_service_proto_rawDescGZIP(), []int{5, 1} +} + +func (x *HealthCheckResponse_Memory) GetTotal() uint64 { + if x != nil { + return x.Total + } + return 0 +} + +func (x *HealthCheckResponse_Memory) GetUsed() uint64 { + if x != nil { + return x.Used + } + return 0 +} + +func (x *HealthCheckResponse_Memory) GetAvailable() uint64 { + if x != nil { + return x.Available + } + return 0 +} + +func (x *HealthCheckResponse_Memory) GetUsedPerc() float64 { + if x != nil { + return x.UsedPerc + } + return 0 +} + var File_supernode_action_cascade_service_proto protoreflect.FileDescriptor var file_supernode_action_cascade_service_proto_rawDesc = []byte{ @@ -362,30 +582,58 @@ var file_supernode_action_cascade_service_proto_rawDesc = []byte{ 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x2a, 0x9c, 0x02, 0x0a, 0x12, 0x53, 0x75, 0x70, - 0x65, 0x72, 0x6e, 0x6f, 0x64, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, - 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x54, 0x52, 0x49, 0x45, 0x56, 0x45, 0x44, - 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x46, 0x45, 0x45, - 0x5f, 0x56, 0x45, 0x52, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x02, 0x12, 0x1e, 0x0a, 0x1a, 0x54, - 0x4f, 0x50, 0x5f, 0x53, 0x55, 0x50, 0x45, 0x52, 0x4e, 0x4f, 0x44, 0x45, 0x5f, 0x43, 0x48, 0x45, - 0x43, 0x4b, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x45, 0x44, 0x10, 0x03, 0x12, 0x14, 0x0a, 0x10, 0x4d, - 0x45, 0x54, 0x41, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x44, 0x45, 0x43, 0x4f, 0x44, 0x45, 0x44, 0x10, - 0x04, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x5f, 0x56, - 0x45, 0x52, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x05, 0x12, 0x11, 0x0a, 0x0d, 0x49, 0x4e, 0x50, - 0x55, 0x54, 0x5f, 0x45, 0x4e, 0x43, 0x4f, 0x44, 0x45, 0x44, 0x10, 0x06, 0x12, 0x16, 0x0a, 0x12, - 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x56, 0x45, 0x52, 0x49, 0x46, 0x49, - 0x45, 0x44, 0x10, 0x07, 0x12, 0x12, 0x0a, 0x0e, 0x52, 0x51, 0x49, 0x44, 0x5f, 0x47, 0x45, 0x4e, - 0x45, 0x52, 0x41, 0x54, 0x45, 0x44, 0x10, 0x08, 0x12, 0x11, 0x0a, 0x0d, 0x52, 0x51, 0x49, 0x44, - 0x5f, 0x56, 0x45, 0x52, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x09, 0x12, 0x14, 0x0a, 0x10, 0x41, - 0x52, 0x54, 0x45, 0x46, 0x41, 0x43, 0x54, 0x53, 0x5f, 0x53, 0x54, 0x4f, 0x52, 0x45, 0x44, 0x10, - 0x0a, 0x12, 0x14, 0x0a, 0x10, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x46, 0x49, 0x4e, 0x41, - 0x4c, 0x49, 0x5a, 0x45, 0x44, 0x10, 0x0b, 0x32, 0x55, 0x0a, 0x0e, 0x43, 0x61, 0x73, 0x63, 0x61, - 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x43, 0x0a, 0x08, 0x52, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x18, 0x2e, 0x63, 0x61, 0x73, 0x63, 0x61, 0x64, 0x65, 0x2e, - 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x19, 0x2e, 0x63, 0x61, 0x73, 0x63, 0x61, 0x64, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, - 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x42, 0x42, + 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x22, 0x14, 0x0a, 0x12, 0x48, 0x65, 0x61, 0x6c, + 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xdc, + 0x02, 0x0a, 0x13, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x03, 0x63, 0x70, 0x75, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x61, 0x73, 0x63, 0x61, 0x64, 0x65, 0x2e, 0x48, 0x65, + 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x2e, 0x43, 0x50, 0x55, 0x52, 0x03, 0x63, 0x70, 0x75, 0x12, 0x3b, 0x0a, 0x06, 0x6d, 0x65, + 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x61, 0x73, + 0x63, 0x61, 0x64, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x52, + 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x74, 0x61, 0x73, 0x6b, 0x73, + 0x5f, 0x69, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0f, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x49, 0x6e, 0x50, 0x72, 0x6f, 0x67, 0x72, + 0x65, 0x73, 0x73, 0x1a, 0x39, 0x0a, 0x03, 0x43, 0x50, 0x55, 0x12, 0x14, 0x0a, 0x05, 0x75, 0x73, + 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, + 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x1a, 0x6d, + 0x0a, 0x06, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, + 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x12, + 0x0a, 0x04, 0x75, 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x75, 0x73, + 0x65, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, + 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x01, 0x52, 0x08, 0x75, 0x73, 0x65, 0x64, 0x50, 0x65, 0x72, 0x63, 0x2a, 0x9c, 0x02, + 0x0a, 0x12, 0x53, 0x75, 0x70, 0x65, 0x72, 0x6e, 0x6f, 0x64, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, + 0x00, 0x12, 0x14, 0x0a, 0x10, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x54, 0x52, + 0x49, 0x45, 0x56, 0x45, 0x44, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x41, 0x43, 0x54, 0x49, 0x4f, + 0x4e, 0x5f, 0x46, 0x45, 0x45, 0x5f, 0x56, 0x45, 0x52, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x02, + 0x12, 0x1e, 0x0a, 0x1a, 0x54, 0x4f, 0x50, 0x5f, 0x53, 0x55, 0x50, 0x45, 0x52, 0x4e, 0x4f, 0x44, + 0x45, 0x5f, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x45, 0x44, 0x10, 0x03, + 0x12, 0x14, 0x0a, 0x10, 0x4d, 0x45, 0x54, 0x41, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x44, 0x45, 0x43, + 0x4f, 0x44, 0x45, 0x44, 0x10, 0x04, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x48, + 0x41, 0x53, 0x48, 0x5f, 0x56, 0x45, 0x52, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x05, 0x12, 0x11, + 0x0a, 0x0d, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f, 0x45, 0x4e, 0x43, 0x4f, 0x44, 0x45, 0x44, 0x10, + 0x06, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x56, + 0x45, 0x52, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x07, 0x12, 0x12, 0x0a, 0x0e, 0x52, 0x51, 0x49, + 0x44, 0x5f, 0x47, 0x45, 0x4e, 0x45, 0x52, 0x41, 0x54, 0x45, 0x44, 0x10, 0x08, 0x12, 0x11, 0x0a, + 0x0d, 0x52, 0x51, 0x49, 0x44, 0x5f, 0x56, 0x45, 0x52, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x09, + 0x12, 0x14, 0x0a, 0x10, 0x41, 0x52, 0x54, 0x45, 0x46, 0x41, 0x43, 0x54, 0x53, 0x5f, 0x53, 0x54, + 0x4f, 0x52, 0x45, 0x44, 0x10, 0x0a, 0x12, 0x14, 0x0a, 0x10, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, + 0x5f, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x49, 0x5a, 0x45, 0x44, 0x10, 0x0b, 0x32, 0x9f, 0x01, 0x0a, + 0x0e, 0x43, 0x61, 0x73, 0x63, 0x61, 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, + 0x43, 0x0a, 0x08, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x18, 0x2e, 0x63, 0x61, + 0x73, 0x63, 0x61, 0x64, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x63, 0x61, 0x73, 0x63, 0x61, 0x64, 0x65, 0x2e, + 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x28, 0x01, 0x30, 0x01, 0x12, 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x12, 0x1b, 0x2e, 0x63, 0x61, 0x73, 0x63, 0x61, 0x64, 0x65, 0x2e, 0x48, 0x65, + 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1c, 0x2e, 0x63, 0x61, 0x73, 0x63, 0x61, 0x64, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, + 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x42, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x4c, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x73, 0x75, 0x70, 0x65, 0x72, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x73, 0x75, 0x70, 0x65, 0x72, 0x6e, @@ -406,25 +654,33 @@ func file_supernode_action_cascade_service_proto_rawDescGZIP() []byte { } var file_supernode_action_cascade_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_supernode_action_cascade_service_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_supernode_action_cascade_service_proto_msgTypes = make([]protoimpl.MessageInfo, 8) var file_supernode_action_cascade_service_proto_goTypes = []any{ - (SupernodeEventType)(0), // 0: cascade.SupernodeEventType - (*RegisterRequest)(nil), // 1: cascade.RegisterRequest - (*DataChunk)(nil), // 2: cascade.DataChunk - (*Metadata)(nil), // 3: cascade.Metadata - (*RegisterResponse)(nil), // 4: cascade.RegisterResponse + (SupernodeEventType)(0), // 0: cascade.SupernodeEventType + (*RegisterRequest)(nil), // 1: cascade.RegisterRequest + (*DataChunk)(nil), // 2: cascade.DataChunk + (*Metadata)(nil), // 3: cascade.Metadata + (*RegisterResponse)(nil), // 4: cascade.RegisterResponse + (*HealthCheckRequest)(nil), // 5: cascade.HealthCheckRequest + (*HealthCheckResponse)(nil), // 6: cascade.HealthCheckResponse + (*HealthCheckResponse_CPU)(nil), // 7: cascade.HealthCheckResponse.CPU + (*HealthCheckResponse_Memory)(nil), // 8: cascade.HealthCheckResponse.Memory } var file_supernode_action_cascade_service_proto_depIdxs = []int32{ 2, // 0: cascade.RegisterRequest.chunk:type_name -> cascade.DataChunk 3, // 1: cascade.RegisterRequest.metadata:type_name -> cascade.Metadata 0, // 2: cascade.RegisterResponse.event_type:type_name -> cascade.SupernodeEventType - 1, // 3: cascade.CascadeService.Register:input_type -> cascade.RegisterRequest - 4, // 4: cascade.CascadeService.Register:output_type -> cascade.RegisterResponse - 4, // [4:5] is the sub-list for method output_type - 3, // [3:4] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name + 7, // 3: cascade.HealthCheckResponse.cpu:type_name -> cascade.HealthCheckResponse.CPU + 8, // 4: cascade.HealthCheckResponse.memory:type_name -> cascade.HealthCheckResponse.Memory + 1, // 5: cascade.CascadeService.Register:input_type -> cascade.RegisterRequest + 5, // 6: cascade.CascadeService.HealthCheck:input_type -> cascade.HealthCheckRequest + 4, // 7: cascade.CascadeService.Register:output_type -> cascade.RegisterResponse + 6, // 8: cascade.CascadeService.HealthCheck:output_type -> cascade.HealthCheckResponse + 7, // [7:9] is the sub-list for method output_type + 5, // [5:7] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name } func init() { file_supernode_action_cascade_service_proto_init() } @@ -442,7 +698,7 @@ func file_supernode_action_cascade_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_supernode_action_cascade_service_proto_rawDesc, NumEnums: 1, - NumMessages: 4, + NumMessages: 8, NumExtensions: 0, NumServices: 1, }, diff --git a/gen/supernode/action/cascade/service_grpc.pb.go b/gen/supernode/action/cascade/service_grpc.pb.go index 2dc82af2..c381031f 100644 --- a/gen/supernode/action/cascade/service_grpc.pb.go +++ b/gen/supernode/action/cascade/service_grpc.pb.go @@ -19,7 +19,8 @@ import ( const _ = grpc.SupportPackageIsVersion9 const ( - CascadeService_Register_FullMethodName = "/cascade.CascadeService/Register" + CascadeService_Register_FullMethodName = "/cascade.CascadeService/Register" + CascadeService_HealthCheck_FullMethodName = "/cascade.CascadeService/HealthCheck" ) // CascadeServiceClient is the client API for CascadeService service. @@ -27,6 +28,7 @@ const ( // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type CascadeServiceClient interface { Register(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[RegisterRequest, RegisterResponse], error) + HealthCheck(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error) } type cascadeServiceClient struct { @@ -50,11 +52,22 @@ func (c *cascadeServiceClient) Register(ctx context.Context, opts ...grpc.CallOp // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. type CascadeService_RegisterClient = grpc.BidiStreamingClient[RegisterRequest, RegisterResponse] +func (c *cascadeServiceClient) HealthCheck(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(HealthCheckResponse) + err := c.cc.Invoke(ctx, CascadeService_HealthCheck_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + // CascadeServiceServer is the server API for CascadeService service. // All implementations must embed UnimplementedCascadeServiceServer // for forward compatibility. type CascadeServiceServer interface { Register(grpc.BidiStreamingServer[RegisterRequest, RegisterResponse]) error + HealthCheck(context.Context, *HealthCheckRequest) (*HealthCheckResponse, error) mustEmbedUnimplementedCascadeServiceServer() } @@ -68,6 +81,9 @@ type UnimplementedCascadeServiceServer struct{} func (UnimplementedCascadeServiceServer) Register(grpc.BidiStreamingServer[RegisterRequest, RegisterResponse]) error { return status.Errorf(codes.Unimplemented, "method Register not implemented") } +func (UnimplementedCascadeServiceServer) HealthCheck(context.Context, *HealthCheckRequest) (*HealthCheckResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method HealthCheck not implemented") +} func (UnimplementedCascadeServiceServer) mustEmbedUnimplementedCascadeServiceServer() {} func (UnimplementedCascadeServiceServer) testEmbeddedByValue() {} @@ -96,13 +112,36 @@ func _CascadeService_Register_Handler(srv interface{}, stream grpc.ServerStream) // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. type CascadeService_RegisterServer = grpc.BidiStreamingServer[RegisterRequest, RegisterResponse] +func _CascadeService_HealthCheck_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(HealthCheckRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CascadeServiceServer).HealthCheck(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: CascadeService_HealthCheck_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CascadeServiceServer).HealthCheck(ctx, req.(*HealthCheckRequest)) + } + return interceptor(ctx, in, info, handler) +} + // CascadeService_ServiceDesc is the grpc.ServiceDesc for CascadeService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) var CascadeService_ServiceDesc = grpc.ServiceDesc{ ServiceName: "cascade.CascadeService", HandlerType: (*CascadeServiceServer)(nil), - Methods: []grpc.MethodDesc{}, + Methods: []grpc.MethodDesc{ + { + MethodName: "HealthCheck", + Handler: _CascadeService_HealthCheck_Handler, + }, + }, Streams: []grpc.StreamDesc{ { StreamName: "Register", diff --git a/go.mod b/go.mod index c0c82a4a..e00885ec 100644 --- a/go.mod +++ b/go.mod @@ -27,6 +27,7 @@ require ( github.com/mattn/go-sqlite3 v1.14.24 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pkg/errors v0.9.1 + github.com/shirou/gopsutil/v3 v3.24.5 github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.8.1 github.com/spf13/viper v1.19.0 @@ -96,6 +97,7 @@ require ( github.com/go-kit/kit v0.13.0 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect @@ -128,6 +130,7 @@ require ( github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/linxGnu/grocksdb v1.9.8 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect @@ -143,6 +146,7 @@ require ( github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/prometheus/client_golang v1.20.5 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.60.1 // indirect @@ -154,6 +158,7 @@ require ( github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sasha-s/go-deadlock v0.3.5 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.7.1 // indirect @@ -163,7 +168,10 @@ require ( github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tendermint/go-amino v0.16.0 // indirect github.com/tidwall/btree v1.7.0 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect github.com/zondax/hid v0.9.2 // indirect github.com/zondax/ledger-go v0.14.3 // indirect go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5 // indirect diff --git a/go.sum b/go.sum index 7254e1e0..0a885ae1 100644 --- a/go.sum +++ b/go.sum @@ -297,6 +297,8 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= @@ -531,6 +533,8 @@ github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-b github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/linxGnu/grocksdb v1.9.8 h1:vOIKv9/+HKiqJAElJIEYv3ZLcihRxyP7Suu/Mu8Dxjs= github.com/linxGnu/grocksdb v1.9.8/go.mod h1:C3CNe9UYc9hlEM2pC82AqiGS3LRW537u9LFV4wIZuHk= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= @@ -656,6 +660,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= @@ -716,6 +722,12 @@ github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6v github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shamaton/msgpack/v2 v2.2.0 h1:IP1m01pHwCrMa6ZccP9B3bqxEMKMSmMVAVKk54g3L/Y= github.com/shamaton/msgpack/v2 v2.2.0/go.mod h1:6khjYnkx73f7VQU7wjcFS9DFjs+59naVWJv1TB7qdOI= +github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI= +github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -772,6 +784,10 @@ github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2l github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= @@ -788,6 +804,8 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= @@ -935,6 +953,7 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -951,6 +970,7 @@ golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -971,6 +991,8 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= diff --git a/proto/supernode/action/cascade/service.proto b/proto/supernode/action/cascade/service.proto index c52f8b49..0615e131 100644 --- a/proto/supernode/action/cascade/service.proto +++ b/proto/supernode/action/cascade/service.proto @@ -4,6 +4,8 @@ option go_package = "github.com/LumeraProtocol/supernode/gen/supernode/action/ca service CascadeService { rpc Register (stream RegisterRequest) returns (stream RegisterResponse); + rpc HealthCheck(HealthCheckRequest) returns (HealthCheckResponse); + } message RegisterRequest { @@ -41,4 +43,25 @@ enum SupernodeEventType { RQID_VERIFIED = 9; ARTEFACTS_STORED = 10; ACTION_FINALIZED = 11; +} + +message HealthCheckRequest {} + +// The HealthCheckResponse represents system health status. +message HealthCheckResponse { + message CPU { + string usage = 1; + string remaining = 2; + } + + message Memory { + uint64 total = 1; + uint64 used = 2; + uint64 available = 3; + double used_perc = 4; + } + + CPU cpu = 1; + Memory memory = 2; + repeated string tasks_in_progress = 3; } \ No newline at end of file diff --git a/supernode/node/action/server/cascade/cascade_action_server.go b/supernode/node/action/server/cascade/cascade_action_server.go index ad77b421..7e045c91 100644 --- a/supernode/node/action/server/cascade/cascade_action_server.go +++ b/supernode/node/action/server/cascade/cascade_action_server.go @@ -1,18 +1,18 @@ package cascade import ( + "context" "encoding/hex" "fmt" - "github.com/LumeraProtocol/supernode/pkg/errors" - "google.golang.org/grpc" "io" - "lukechampine.com/blake3" "os" - "path/filepath" pb "github.com/LumeraProtocol/supernode/gen/supernode/action/cascade" + "github.com/LumeraProtocol/supernode/pkg/errors" "github.com/LumeraProtocol/supernode/pkg/logtrace" cascadeService "github.com/LumeraProtocol/supernode/supernode/services/cascade" + + "google.golang.org/grpc" ) type ActionServer struct { @@ -162,31 +162,24 @@ func (server *ActionServer) Register(stream pb.CascadeService_RegisterServer) er return nil } -func initializeHasherAndTempFile() (*blake3.Hasher, *os.File, string, error) { - hasher := blake3.New(32, nil) - - tempFilePath := filepath.Join(os.TempDir(), fmt.Sprintf("cascade-upload-%d.tmp", os.Getpid())) - tempFile, err := os.Create(tempFilePath) +func (server *ActionServer) HealthCheck(ctx context.Context, _ *pb.HealthCheckRequest) (*pb.HealthCheckResponse, error) { + resp, err := server.factory.NewCascadeRegistrationTask().HealthCheck(ctx) if err != nil { - return nil, nil, "", fmt.Errorf("could not create temp file: %w", err) - } - - return hasher, tempFile, tempFilePath, nil -} - -func replaceTempDirWithTaskDir(taskID, tempFilePath string, tempFile *os.File) (targetPath string, err error) { - if err := tempFile.Close(); err != nil && !errors.Is(err, os.ErrClosed) { - return "", fmt.Errorf("failed to close temp file: %w", err) - } - - targetDir := filepath.Join(os.TempDir(), taskID) - if err := os.MkdirAll(targetDir, 0755); err != nil { - return "", fmt.Errorf("could not create task directory: %w", err) - } - targetPath = filepath.Join(targetDir, fmt.Sprintf("uploaded-%s.dat", taskID)) - if err := os.Rename(tempFilePath, targetPath); err != nil { - return "", fmt.Errorf("could not move file to final location: %w", err) + logtrace.Error(ctx, "error retrieving health-check metrics for supernode", logtrace.Fields{}) + return nil, err } - return targetPath, nil + return &pb.HealthCheckResponse{ + Cpu: &pb.HealthCheckResponse_CPU{ + Usage: resp.CPU.Usage, + Remaining: resp.CPU.Remaining, + }, + Memory: &pb.HealthCheckResponse_Memory{ + Total: resp.Memory.Total, + Used: resp.Memory.Used, + Available: resp.Memory.Available, + UsedPerc: resp.Memory.UsedPerc, + }, + TasksInProgress: resp.TasksInProgress, + }, nil } diff --git a/supernode/node/action/server/cascade/helper.go b/supernode/node/action/server/cascade/helper.go new file mode 100644 index 00000000..96dbddb2 --- /dev/null +++ b/supernode/node/action/server/cascade/helper.go @@ -0,0 +1,39 @@ +package cascade + +import ( + "fmt" + "lukechampine.com/blake3" + "os" + "path/filepath" + + "github.com/LumeraProtocol/supernode/pkg/errors" +) + +func initializeHasherAndTempFile() (*blake3.Hasher, *os.File, string, error) { + hasher := blake3.New(32, nil) + + tempFilePath := filepath.Join(os.TempDir(), fmt.Sprintf("cascade-upload-%d.tmp", os.Getpid())) + tempFile, err := os.Create(tempFilePath) + if err != nil { + return nil, nil, "", fmt.Errorf("could not create temp file: %w", err) + } + + return hasher, tempFile, tempFilePath, nil +} + +func replaceTempDirWithTaskDir(taskID, tempFilePath string, tempFile *os.File) (targetPath string, err error) { + if err := tempFile.Close(); err != nil && !errors.Is(err, os.ErrClosed) { + return "", fmt.Errorf("failed to close temp file: %w", err) + } + + targetDir := filepath.Join(os.TempDir(), taskID) + if err := os.MkdirAll(targetDir, 0755); err != nil { + return "", fmt.Errorf("could not create task directory: %w", err) + } + targetPath = filepath.Join(targetDir, fmt.Sprintf("uploaded-%s.dat", taskID)) + if err := os.Rename(tempFilePath, targetPath); err != nil { + return "", fmt.Errorf("could not move file to final location: %w", err) + } + + return targetPath, nil +} diff --git a/supernode/services/cascade/healthcheck.go b/supernode/services/cascade/healthcheck.go new file mode 100644 index 00000000..d9e33122 --- /dev/null +++ b/supernode/services/cascade/healthcheck.go @@ -0,0 +1,71 @@ +package cascade + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/LumeraProtocol/supernode/pkg/logtrace" + "github.com/shirou/gopsutil/v3/cpu" + "github.com/shirou/gopsutil/v3/mem" +) + +type HealthCheckResponse struct { + CPU struct { + Usage string + Remaining string + } + Memory struct { + Total uint64 + Used uint64 + Available uint64 + UsedPerc float64 + } + TasksInProgress []string +} + +func (task *CascadeRegistrationTask) HealthCheck(ctx context.Context) (HealthCheckResponse, error) { + fields := logtrace.Fields{ + logtrace.FieldMethod: "HealthCheck", + logtrace.FieldModule: "CascadeActionServer", + } + logtrace.Info(ctx, "healthcheck request received", fields) + + var resp HealthCheckResponse + + percentages, err := cpu.Percent(time.Second, false) + if err != nil { + log.Fatal(err) + } + fmt.Println(percentages) + usage := percentages[0] + remaining := 100 - usage + + // Memory stats + vmem, err := mem.VirtualMemory() + if err != nil { + logtrace.Error(ctx, "failed to get memory info", logtrace.Fields{logtrace.FieldError: err.Error()}) + return resp, err + } + resp.Memory.Total = vmem.Total + resp.Memory.Used = vmem.Used + resp.Memory.Available = vmem.Available + resp.Memory.UsedPerc = vmem.UsedPercent + + // Tasks + for _, t := range task.Worker.Tasks() { + resp.TasksInProgress = append(resp.TasksInProgress, t.ID()) + } + + logtrace.Info(ctx, "top-style healthcheck data", logtrace.Fields{ + "cpu_usage": fmt.Sprintf("%.2f", usage), + "cpu_remaining": fmt.Sprintf("%.2f", remaining), + "mem_total": resp.Memory.Total, + "mem_used": resp.Memory.Used, + "mem_used%": resp.Memory.UsedPerc, + "task_count": len(resp.TasksInProgress), + }) + + return resp, nil +} diff --git a/supernode/services/cascade/healthcheck_test.go b/supernode/services/cascade/healthcheck_test.go new file mode 100644 index 00000000..4c2b3b9b --- /dev/null +++ b/supernode/services/cascade/healthcheck_test.go @@ -0,0 +1,84 @@ +package cascade + +import ( + "context" + "testing" + + "github.com/LumeraProtocol/supernode/supernode/services/common" + "github.com/stretchr/testify/assert" +) + +func TestHealthCheck(t *testing.T) { + ctx := context.Background() + + tests := []struct { + name string + taskCount int + expectErr bool + expectTasks int + }{ + { + name: "no tasks", + taskCount: 0, + expectErr: false, + expectTasks: 0, + }, + { + name: "one task", + taskCount: 1, + expectErr: false, + expectTasks: 1, + }, + { + name: "multiple tasks", + taskCount: 3, + expectErr: false, + expectTasks: 3, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Setup service and worker + service := &CascadeService{ + SuperNodeService: common.NewSuperNodeService(nil), + } + + var primaryTask *CascadeRegistrationTask + + go func() { + service.RunHelper(ctx, "node-id", "prefix") + }() + + // Register tasks + for i := 0; i < tt.taskCount; i++ { + task := NewCascadeRegistrationTask(service) + service.Worker.AddTask(task) + if i == 0 { + primaryTask = task + } + } + + // Always call HealthCheck from first task (if any), otherwise create a temp one + if primaryTask == nil { + primaryTask = NewCascadeRegistrationTask(service) + } + + resp, err := primaryTask.HealthCheck(ctx) + if tt.expectErr { + assert.Error(t, err) + return + } + + assert.NoError(t, err) + + // Memory checks + assert.True(t, resp.Memory.Total > 0) + assert.True(t, resp.Memory.Used <= resp.Memory.Total) + assert.True(t, resp.Memory.UsedPerc >= 0 && resp.Memory.UsedPerc <= 100) + + // Task count check + assert.Equal(t, tt.expectTasks, len(resp.TasksInProgress)) + }) + } +} diff --git a/supernode/services/cascade/interfaces.go b/supernode/services/cascade/interfaces.go index 930695f4..d592c8b3 100644 --- a/supernode/services/cascade/interfaces.go +++ b/supernode/services/cascade/interfaces.go @@ -14,4 +14,5 @@ type TaskFactory interface { // RegistrationTaskService interface allows to register a new cascade type RegistrationTaskService interface { Register(ctx context.Context, req *RegisterRequest, send func(resp *RegisterResponse) error) error + HealthCheck(ctx context.Context) (HealthCheckResponse, error) } diff --git a/supernode/services/cascade/mocks/cascade_interfaces_mock.go b/supernode/services/cascade/mocks/cascade_interfaces_mock.go index ac7a60e5..b3559fb4 100644 --- a/supernode/services/cascade/mocks/cascade_interfaces_mock.go +++ b/supernode/services/cascade/mocks/cascade_interfaces_mock.go @@ -1,10 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. // Source: interfaces.go -// -// Generated by this command: -// -// mockgen -destination=mocks/cascade_interfaces_mock.go -package=cascademocks -source=interfaces.go -// // Package cascademocks is a generated GoMock package. package cascademocks @@ -21,7 +16,6 @@ import ( type MockTaskFactory struct { ctrl *gomock.Controller recorder *MockTaskFactoryMockRecorder - isgomock struct{} } // MockTaskFactoryMockRecorder is the mock recorder for MockTaskFactory. @@ -59,7 +53,6 @@ func (mr *MockTaskFactoryMockRecorder) NewCascadeRegistrationTask() *gomock.Call type MockRegistrationTaskService struct { ctrl *gomock.Controller recorder *MockRegistrationTaskServiceMockRecorder - isgomock struct{} } // MockRegistrationTaskServiceMockRecorder is the mock recorder for MockRegistrationTaskService. @@ -79,6 +72,21 @@ func (m *MockRegistrationTaskService) EXPECT() *MockRegistrationTaskServiceMockR return m.recorder } +// HealthCheck mocks base method. +func (m *MockRegistrationTaskService) HealthCheck(ctx context.Context) (cascade.HealthCheckResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HealthCheck", ctx) + ret0, _ := ret[0].(cascade.HealthCheckResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// HealthCheck indicates an expected call of HealthCheck. +func (mr *MockRegistrationTaskServiceMockRecorder) HealthCheck(ctx interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HealthCheck", reflect.TypeOf((*MockRegistrationTaskService)(nil).HealthCheck), ctx) +} + // Register mocks base method. func (m *MockRegistrationTaskService) Register(ctx context.Context, req *cascade.RegisterRequest, send func(*cascade.RegisterResponse) error) error { m.ctrl.T.Helper() @@ -88,7 +96,7 @@ func (m *MockRegistrationTaskService) Register(ctx context.Context, req *cascade } // Register indicates an expected call of Register. -func (mr *MockRegistrationTaskServiceMockRecorder) Register(ctx, req, send any) *gomock.Call { +func (mr *MockRegistrationTaskServiceMockRecorder) Register(ctx, req, send interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Register", reflect.TypeOf((*MockRegistrationTaskService)(nil).Register), ctx, req, send) }