Unified Storage: Adds health check service for entity server (#86471)

This commit is contained in:
owensmallwood
2024-05-01 11:36:44 -06:00
committed by GitHub
parent a9ac648cf6
commit 40558899e4
12 changed files with 679 additions and 122 deletions
@@ -16,6 +16,10 @@ func ProvideFakeEntityServer() entity.EntityStoreServer {
type fakeEntityStore struct{}
func (i fakeEntityStore) IsHealthy(ctx context.Context, r *entity.HealthCheckRequest) (*entity.HealthCheckResponse, error) {
return nil, fmt.Errorf("unimplemented")
}
func (i fakeEntityStore) Create(ctx context.Context, r *entity.CreateEntityRequest) (*entity.CreateEntityResponse, error) {
return nil, fmt.Errorf("unimplemented")
}
+305 -111
View File
@@ -272,6 +272,58 @@ func (EntityWatchRequest_WatchAction) EnumDescriptor() ([]byte, []int) {
return file_entity_proto_rawDescGZIP(), []int{15, 0}
}
type HealthCheckResponse_ServingStatus int32
const (
HealthCheckResponse_UNKNOWN HealthCheckResponse_ServingStatus = 0
HealthCheckResponse_SERVING HealthCheckResponse_ServingStatus = 1
HealthCheckResponse_NOT_SERVING HealthCheckResponse_ServingStatus = 2
HealthCheckResponse_SERVICE_UNKNOWN HealthCheckResponse_ServingStatus = 3 // Used only by the Watch method.
)
// Enum value maps for HealthCheckResponse_ServingStatus.
var (
HealthCheckResponse_ServingStatus_name = map[int32]string{
0: "UNKNOWN",
1: "SERVING",
2: "NOT_SERVING",
3: "SERVICE_UNKNOWN",
}
HealthCheckResponse_ServingStatus_value = map[string]int32{
"UNKNOWN": 0,
"SERVING": 1,
"NOT_SERVING": 2,
"SERVICE_UNKNOWN": 3,
}
)
func (x HealthCheckResponse_ServingStatus) Enum() *HealthCheckResponse_ServingStatus {
p := new(HealthCheckResponse_ServingStatus)
*p = x
return p
}
func (x HealthCheckResponse_ServingStatus) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (HealthCheckResponse_ServingStatus) Descriptor() protoreflect.EnumDescriptor {
return file_entity_proto_enumTypes[5].Descriptor()
}
func (HealthCheckResponse_ServingStatus) Type() protoreflect.EnumType {
return &file_entity_proto_enumTypes[5]
}
func (x HealthCheckResponse_ServingStatus) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use HealthCheckResponse_ServingStatus.Descriptor instead.
func (HealthCheckResponse_ServingStatus) EnumDescriptor() ([]byte, []int) {
return file_entity_proto_rawDescGZIP(), []int{20, 0}
}
// The canonical entity/document data -- this represents the raw bytes and storage level metadata
type Entity struct {
state protoimpl.MessageState
@@ -2031,6 +2083,100 @@ func (x *EntityExternalReference) GetIdentifier() string {
return ""
}
type HealthCheckRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Service string `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"`
}
func (x *HealthCheckRequest) Reset() {
*x = HealthCheckRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_entity_proto_msgTypes[19]
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_entity_proto_msgTypes[19]
if protoimpl.UnsafeEnabled && 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_entity_proto_rawDescGZIP(), []int{19}
}
func (x *HealthCheckRequest) GetService() string {
if x != nil {
return x.Service
}
return ""
}
type HealthCheckResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Status HealthCheckResponse_ServingStatus `protobuf:"varint,1,opt,name=status,proto3,enum=entity.HealthCheckResponse_ServingStatus" json:"status,omitempty"`
}
func (x *HealthCheckResponse) Reset() {
*x = HealthCheckResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_entity_proto_msgTypes[20]
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_entity_proto_msgTypes[20]
if protoimpl.UnsafeEnabled && 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_entity_proto_rawDescGZIP(), []int{20}
}
func (x *HealthCheckResponse) GetStatus() HealthCheckResponse_ServingStatus {
if x != nil {
return x.Status
}
return HealthCheckResponse_UNKNOWN
}
var File_entity_proto protoreflect.FileDescriptor
var file_entity_proto_rawDesc = []byte{
@@ -2334,41 +2480,59 @@ var file_entity_proto_rawDesc = []byte{
0x6d, 0x69, 0x6c, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e,
0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x64,
0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x32, 0xdc, 0x03, 0x0a, 0x0b, 0x45, 0x6e, 0x74,
0x69, 0x74, 0x79, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x31, 0x0a, 0x04, 0x52, 0x65, 0x61, 0x64,
0x12, 0x19, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x45, 0x6e,
0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x65, 0x6e,
0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x43, 0x0a, 0x06, 0x43,
0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x43,
0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61,
0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x12, 0x43, 0x0a, 0x06, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x2e, 0x65, 0x6e, 0x74,
0x69, 0x74, 0x79, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79,
0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12,
0x1b, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x45,
0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x65,
0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69,
0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x07, 0x48, 0x69,
0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1c, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45,
0x6e, 0x74, 0x69, 0x74, 0x79, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74,
0x69, 0x74, 0x79, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x19, 0x2e, 0x65, 0x6e, 0x74,
0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45,
0x6e, 0x74, 0x69, 0x74, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x44, 0x0a, 0x05, 0x57, 0x61, 0x74, 0x63, 0x68, 0x12, 0x1a, 0x2e, 0x65, 0x6e, 0x74,
0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e,
0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75,
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x67, 0x72,
0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x73, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2f, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x22, 0x2e, 0x0a, 0x12, 0x48, 0x65, 0x61, 0x6c,
0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18,
0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0xa9, 0x01, 0x0a, 0x13, 0x48, 0x65, 0x61,
0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x12, 0x41, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e,
0x32, 0x29, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68,
0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x65,
0x72, 0x76, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61,
0x74, 0x75, 0x73, 0x22, 0x4f, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x53, 0x74,
0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10,
0x00, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x45, 0x52, 0x56, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0f,
0x0a, 0x0b, 0x4e, 0x4f, 0x54, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12,
0x13, 0x0a, 0x0f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f,
0x57, 0x4e, 0x10, 0x03, 0x32, 0xa2, 0x04, 0x0a, 0x0b, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x53,
0x74, 0x6f, 0x72, 0x65, 0x12, 0x31, 0x0a, 0x04, 0x52, 0x65, 0x61, 0x64, 0x12, 0x19, 0x2e, 0x65,
0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79,
0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x43, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74,
0x65, 0x12, 0x1b, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74,
0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c,
0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e,
0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x06,
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e,
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x55, 0x70, 0x64,
0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x43, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1b, 0x2e, 0x65, 0x6e,
0x74, 0x69, 0x74, 0x79, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74,
0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74,
0x79, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x07, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72,
0x79, 0x12, 0x1c, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74,
0x79, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x1d, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x48,
0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d,
0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x19, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e,
0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x1a, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74,
0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a,
0x05, 0x57, 0x61, 0x74, 0x63, 0x68, 0x12, 0x1a, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e,
0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69,
0x74, 0x79, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28,
0x01, 0x30, 0x01, 0x12, 0x44, 0x0a, 0x09, 0x49, 0x73, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79,
0x12, 0x1a, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68,
0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x65,
0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63,
0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74,
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f,
0x67, 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x73, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2f, 0x65, 0x6e, 0x74, 0x69, 0x74,
0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -2383,88 +2547,94 @@ func file_entity_proto_rawDescGZIP() []byte {
return file_entity_proto_rawDescData
}
var file_entity_proto_enumTypes = make([]protoimpl.EnumInfo, 5)
var file_entity_proto_msgTypes = make([]protoimpl.MessageInfo, 25)
var file_entity_proto_enumTypes = make([]protoimpl.EnumInfo, 6)
var file_entity_proto_msgTypes = make([]protoimpl.MessageInfo, 27)
var file_entity_proto_goTypes = []interface{}{
(Entity_Action)(0), // 0: entity.Entity.Action
(CreateEntityResponse_Status)(0), // 1: entity.CreateEntityResponse.Status
(UpdateEntityResponse_Status)(0), // 2: entity.UpdateEntityResponse.Status
(DeleteEntityResponse_Status)(0), // 3: entity.DeleteEntityResponse.Status
(EntityWatchRequest_WatchAction)(0), // 4: entity.EntityWatchRequest.WatchAction
(*Entity)(nil), // 5: entity.Entity
(*EntityOriginInfo)(nil), // 6: entity.EntityOriginInfo
(*EntityErrorInfo)(nil), // 7: entity.EntityErrorInfo
(*ReadEntityRequest)(nil), // 8: entity.ReadEntityRequest
(*CreateEntityRequest)(nil), // 9: entity.CreateEntityRequest
(*CreateEntityResponse)(nil), // 10: entity.CreateEntityResponse
(*UpdateEntityRequest)(nil), // 11: entity.UpdateEntityRequest
(*UpdateEntityResponse)(nil), // 12: entity.UpdateEntityResponse
(*DeleteEntityRequest)(nil), // 13: entity.DeleteEntityRequest
(*DeleteEntityResponse)(nil), // 14: entity.DeleteEntityResponse
(*EntityHistoryRequest)(nil), // 15: entity.EntityHistoryRequest
(*EntityHistoryResponse)(nil), // 16: entity.EntityHistoryResponse
(*EntityListRequest)(nil), // 17: entity.EntityListRequest
(*ReferenceRequest)(nil), // 18: entity.ReferenceRequest
(*EntityListResponse)(nil), // 19: entity.EntityListResponse
(*EntityWatchRequest)(nil), // 20: entity.EntityWatchRequest
(*EntityWatchResponse)(nil), // 21: entity.EntityWatchResponse
(*EntitySummary)(nil), // 22: entity.EntitySummary
(*EntityExternalReference)(nil), // 23: entity.EntityExternalReference
nil, // 24: entity.Entity.LabelsEntry
nil, // 25: entity.Entity.FieldsEntry
nil, // 26: entity.EntityListRequest.LabelsEntry
nil, // 27: entity.EntityWatchRequest.LabelsEntry
nil, // 28: entity.EntitySummary.LabelsEntry
nil, // 29: entity.EntitySummary.FieldsEntry
(Entity_Action)(0), // 0: entity.Entity.Action
(CreateEntityResponse_Status)(0), // 1: entity.CreateEntityResponse.Status
(UpdateEntityResponse_Status)(0), // 2: entity.UpdateEntityResponse.Status
(DeleteEntityResponse_Status)(0), // 3: entity.DeleteEntityResponse.Status
(EntityWatchRequest_WatchAction)(0), // 4: entity.EntityWatchRequest.WatchAction
(HealthCheckResponse_ServingStatus)(0), // 5: entity.HealthCheckResponse.ServingStatus
(*Entity)(nil), // 6: entity.Entity
(*EntityOriginInfo)(nil), // 7: entity.EntityOriginInfo
(*EntityErrorInfo)(nil), // 8: entity.EntityErrorInfo
(*ReadEntityRequest)(nil), // 9: entity.ReadEntityRequest
(*CreateEntityRequest)(nil), // 10: entity.CreateEntityRequest
(*CreateEntityResponse)(nil), // 11: entity.CreateEntityResponse
(*UpdateEntityRequest)(nil), // 12: entity.UpdateEntityRequest
(*UpdateEntityResponse)(nil), // 13: entity.UpdateEntityResponse
(*DeleteEntityRequest)(nil), // 14: entity.DeleteEntityRequest
(*DeleteEntityResponse)(nil), // 15: entity.DeleteEntityResponse
(*EntityHistoryRequest)(nil), // 16: entity.EntityHistoryRequest
(*EntityHistoryResponse)(nil), // 17: entity.EntityHistoryResponse
(*EntityListRequest)(nil), // 18: entity.EntityListRequest
(*ReferenceRequest)(nil), // 19: entity.ReferenceRequest
(*EntityListResponse)(nil), // 20: entity.EntityListResponse
(*EntityWatchRequest)(nil), // 21: entity.EntityWatchRequest
(*EntityWatchResponse)(nil), // 22: entity.EntityWatchResponse
(*EntitySummary)(nil), // 23: entity.EntitySummary
(*EntityExternalReference)(nil), // 24: entity.EntityExternalReference
(*HealthCheckRequest)(nil), // 25: entity.HealthCheckRequest
(*HealthCheckResponse)(nil), // 26: entity.HealthCheckResponse
nil, // 27: entity.Entity.LabelsEntry
nil, // 28: entity.Entity.FieldsEntry
nil, // 29: entity.EntityListRequest.LabelsEntry
nil, // 30: entity.EntityWatchRequest.LabelsEntry
nil, // 31: entity.EntitySummary.LabelsEntry
nil, // 32: entity.EntitySummary.FieldsEntry
}
var file_entity_proto_depIdxs = []int32{
6, // 0: entity.Entity.origin:type_name -> entity.EntityOriginInfo
24, // 1: entity.Entity.labels:type_name -> entity.Entity.LabelsEntry
25, // 2: entity.Entity.fields:type_name -> entity.Entity.FieldsEntry
7, // 3: entity.Entity.errors:type_name -> entity.EntityErrorInfo
7, // 0: entity.Entity.origin:type_name -> entity.EntityOriginInfo
27, // 1: entity.Entity.labels:type_name -> entity.Entity.LabelsEntry
28, // 2: entity.Entity.fields:type_name -> entity.Entity.FieldsEntry
8, // 3: entity.Entity.errors:type_name -> entity.EntityErrorInfo
0, // 4: entity.Entity.action:type_name -> entity.Entity.Action
5, // 5: entity.CreateEntityRequest.entity:type_name -> entity.Entity
7, // 6: entity.CreateEntityResponse.error:type_name -> entity.EntityErrorInfo
5, // 7: entity.CreateEntityResponse.entity:type_name -> entity.Entity
6, // 5: entity.CreateEntityRequest.entity:type_name -> entity.Entity
8, // 6: entity.CreateEntityResponse.error:type_name -> entity.EntityErrorInfo
6, // 7: entity.CreateEntityResponse.entity:type_name -> entity.Entity
1, // 8: entity.CreateEntityResponse.status:type_name -> entity.CreateEntityResponse.Status
5, // 9: entity.UpdateEntityRequest.entity:type_name -> entity.Entity
7, // 10: entity.UpdateEntityResponse.error:type_name -> entity.EntityErrorInfo
5, // 11: entity.UpdateEntityResponse.entity:type_name -> entity.Entity
6, // 9: entity.UpdateEntityRequest.entity:type_name -> entity.Entity
8, // 10: entity.UpdateEntityResponse.error:type_name -> entity.EntityErrorInfo
6, // 11: entity.UpdateEntityResponse.entity:type_name -> entity.Entity
2, // 12: entity.UpdateEntityResponse.status:type_name -> entity.UpdateEntityResponse.Status
7, // 13: entity.DeleteEntityResponse.error:type_name -> entity.EntityErrorInfo
5, // 14: entity.DeleteEntityResponse.entity:type_name -> entity.Entity
8, // 13: entity.DeleteEntityResponse.error:type_name -> entity.EntityErrorInfo
6, // 14: entity.DeleteEntityResponse.entity:type_name -> entity.Entity
3, // 15: entity.DeleteEntityResponse.status:type_name -> entity.DeleteEntityResponse.Status
5, // 16: entity.EntityHistoryResponse.versions:type_name -> entity.Entity
26, // 17: entity.EntityListRequest.labels:type_name -> entity.EntityListRequest.LabelsEntry
5, // 18: entity.EntityListResponse.results:type_name -> entity.Entity
6, // 16: entity.EntityHistoryResponse.versions:type_name -> entity.Entity
29, // 17: entity.EntityListRequest.labels:type_name -> entity.EntityListRequest.LabelsEntry
6, // 18: entity.EntityListResponse.results:type_name -> entity.Entity
4, // 19: entity.EntityWatchRequest.action:type_name -> entity.EntityWatchRequest.WatchAction
27, // 20: entity.EntityWatchRequest.labels:type_name -> entity.EntityWatchRequest.LabelsEntry
5, // 21: entity.EntityWatchResponse.entity:type_name -> entity.Entity
5, // 22: entity.EntityWatchResponse.previous:type_name -> entity.Entity
28, // 23: entity.EntitySummary.labels:type_name -> entity.EntitySummary.LabelsEntry
7, // 24: entity.EntitySummary.error:type_name -> entity.EntityErrorInfo
29, // 25: entity.EntitySummary.fields:type_name -> entity.EntitySummary.FieldsEntry
22, // 26: entity.EntitySummary.nested:type_name -> entity.EntitySummary
23, // 27: entity.EntitySummary.references:type_name -> entity.EntityExternalReference
8, // 28: entity.EntityStore.Read:input_type -> entity.ReadEntityRequest
9, // 29: entity.EntityStore.Create:input_type -> entity.CreateEntityRequest
11, // 30: entity.EntityStore.Update:input_type -> entity.UpdateEntityRequest
13, // 31: entity.EntityStore.Delete:input_type -> entity.DeleteEntityRequest
15, // 32: entity.EntityStore.History:input_type -> entity.EntityHistoryRequest
17, // 33: entity.EntityStore.List:input_type -> entity.EntityListRequest
20, // 34: entity.EntityStore.Watch:input_type -> entity.EntityWatchRequest
5, // 35: entity.EntityStore.Read:output_type -> entity.Entity
10, // 36: entity.EntityStore.Create:output_type -> entity.CreateEntityResponse
12, // 37: entity.EntityStore.Update:output_type -> entity.UpdateEntityResponse
14, // 38: entity.EntityStore.Delete:output_type -> entity.DeleteEntityResponse
16, // 39: entity.EntityStore.History:output_type -> entity.EntityHistoryResponse
19, // 40: entity.EntityStore.List:output_type -> entity.EntityListResponse
21, // 41: entity.EntityStore.Watch:output_type -> entity.EntityWatchResponse
35, // [35:42] is the sub-list for method output_type
28, // [28:35] is the sub-list for method input_type
28, // [28:28] is the sub-list for extension type_name
28, // [28:28] is the sub-list for extension extendee
0, // [0:28] is the sub-list for field type_name
30, // 20: entity.EntityWatchRequest.labels:type_name -> entity.EntityWatchRequest.LabelsEntry
6, // 21: entity.EntityWatchResponse.entity:type_name -> entity.Entity
6, // 22: entity.EntityWatchResponse.previous:type_name -> entity.Entity
31, // 23: entity.EntitySummary.labels:type_name -> entity.EntitySummary.LabelsEntry
8, // 24: entity.EntitySummary.error:type_name -> entity.EntityErrorInfo
32, // 25: entity.EntitySummary.fields:type_name -> entity.EntitySummary.FieldsEntry
23, // 26: entity.EntitySummary.nested:type_name -> entity.EntitySummary
24, // 27: entity.EntitySummary.references:type_name -> entity.EntityExternalReference
5, // 28: entity.HealthCheckResponse.status:type_name -> entity.HealthCheckResponse.ServingStatus
9, // 29: entity.EntityStore.Read:input_type -> entity.ReadEntityRequest
10, // 30: entity.EntityStore.Create:input_type -> entity.CreateEntityRequest
12, // 31: entity.EntityStore.Update:input_type -> entity.UpdateEntityRequest
14, // 32: entity.EntityStore.Delete:input_type -> entity.DeleteEntityRequest
16, // 33: entity.EntityStore.History:input_type -> entity.EntityHistoryRequest
18, // 34: entity.EntityStore.List:input_type -> entity.EntityListRequest
21, // 35: entity.EntityStore.Watch:input_type -> entity.EntityWatchRequest
25, // 36: entity.EntityStore.IsHealthy:input_type -> entity.HealthCheckRequest
6, // 37: entity.EntityStore.Read:output_type -> entity.Entity
11, // 38: entity.EntityStore.Create:output_type -> entity.CreateEntityResponse
13, // 39: entity.EntityStore.Update:output_type -> entity.UpdateEntityResponse
15, // 40: entity.EntityStore.Delete:output_type -> entity.DeleteEntityResponse
17, // 41: entity.EntityStore.History:output_type -> entity.EntityHistoryResponse
20, // 42: entity.EntityStore.List:output_type -> entity.EntityListResponse
22, // 43: entity.EntityStore.Watch:output_type -> entity.EntityWatchResponse
26, // 44: entity.EntityStore.IsHealthy:output_type -> entity.HealthCheckResponse
37, // [37:45] is the sub-list for method output_type
29, // [29:37] is the sub-list for method input_type
29, // [29:29] is the sub-list for extension type_name
29, // [29:29] is the sub-list for extension extendee
0, // [0:29] is the sub-list for field type_name
}
func init() { file_entity_proto_init() }
@@ -2701,14 +2871,38 @@ func file_entity_proto_init() {
return nil
}
}
file_entity_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*HealthCheckRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_entity_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*HealthCheckResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_entity_proto_rawDesc,
NumEnums: 5,
NumMessages: 25,
NumEnums: 6,
NumMessages: 27,
NumExtensions: 0,
NumServices: 1,
},
+19 -1
View File
@@ -439,12 +439,29 @@ message EntityExternalReference {
string identifier = 3;
}
//-----------------------------------------------
// Health
//-----------------------------------------------
message HealthCheckRequest {
string service = 1;
}
message HealthCheckResponse {
enum ServingStatus {
UNKNOWN = 0;
SERVING = 1;
NOT_SERVING = 2;
SERVICE_UNKNOWN = 3; // Used only by the Watch method.
}
ServingStatus status = 1;
}
//-----------------------------------------------
// Storage interface
//-----------------------------------------------
// The entity store provides a basic CRUD (+watch eventually) interface for generic entitys
// The entity store provides a basic CRUD (+watch eventually) interface for generic entities
service EntityStore {
rpc Read(ReadEntityRequest) returns (Entity);
rpc Create(CreateEntityRequest) returns (CreateEntityResponse);
@@ -453,4 +470,5 @@ service EntityStore {
rpc History(EntityHistoryRequest) returns (EntityHistoryResponse);
rpc List(EntityListRequest) returns (EntityListResponse);
rpc Watch(stream EntityWatchRequest) returns (stream EntityWatchResponse);
rpc IsHealthy(HealthCheckRequest) returns (HealthCheckResponse);
}
+44 -7
View File
@@ -19,13 +19,14 @@ import (
const _ = grpc.SupportPackageIsVersion7
const (
EntityStore_Read_FullMethodName = "/entity.EntityStore/Read"
EntityStore_Create_FullMethodName = "/entity.EntityStore/Create"
EntityStore_Update_FullMethodName = "/entity.EntityStore/Update"
EntityStore_Delete_FullMethodName = "/entity.EntityStore/Delete"
EntityStore_History_FullMethodName = "/entity.EntityStore/History"
EntityStore_List_FullMethodName = "/entity.EntityStore/List"
EntityStore_Watch_FullMethodName = "/entity.EntityStore/Watch"
EntityStore_Read_FullMethodName = "/entity.EntityStore/Read"
EntityStore_Create_FullMethodName = "/entity.EntityStore/Create"
EntityStore_Update_FullMethodName = "/entity.EntityStore/Update"
EntityStore_Delete_FullMethodName = "/entity.EntityStore/Delete"
EntityStore_History_FullMethodName = "/entity.EntityStore/History"
EntityStore_List_FullMethodName = "/entity.EntityStore/List"
EntityStore_Watch_FullMethodName = "/entity.EntityStore/Watch"
EntityStore_IsHealthy_FullMethodName = "/entity.EntityStore/IsHealthy"
)
// EntityStoreClient is the client API for EntityStore service.
@@ -39,6 +40,7 @@ type EntityStoreClient interface {
History(ctx context.Context, in *EntityHistoryRequest, opts ...grpc.CallOption) (*EntityHistoryResponse, error)
List(ctx context.Context, in *EntityListRequest, opts ...grpc.CallOption) (*EntityListResponse, error)
Watch(ctx context.Context, opts ...grpc.CallOption) (EntityStore_WatchClient, error)
IsHealthy(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error)
}
type entityStoreClient struct {
@@ -134,6 +136,15 @@ func (x *entityStoreWatchClient) Recv() (*EntityWatchResponse, error) {
return m, nil
}
func (c *entityStoreClient) IsHealthy(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error) {
out := new(HealthCheckResponse)
err := c.cc.Invoke(ctx, EntityStore_IsHealthy_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// EntityStoreServer is the server API for EntityStore service.
// All implementations should embed UnimplementedEntityStoreServer
// for forward compatibility
@@ -145,6 +156,7 @@ type EntityStoreServer interface {
History(context.Context, *EntityHistoryRequest) (*EntityHistoryResponse, error)
List(context.Context, *EntityListRequest) (*EntityListResponse, error)
Watch(EntityStore_WatchServer) error
IsHealthy(context.Context, *HealthCheckRequest) (*HealthCheckResponse, error)
}
// UnimplementedEntityStoreServer should be embedded to have forward compatible implementations.
@@ -172,6 +184,9 @@ func (UnimplementedEntityStoreServer) List(context.Context, *EntityListRequest)
func (UnimplementedEntityStoreServer) Watch(EntityStore_WatchServer) error {
return status.Errorf(codes.Unimplemented, "method Watch not implemented")
}
func (UnimplementedEntityStoreServer) IsHealthy(context.Context, *HealthCheckRequest) (*HealthCheckResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method IsHealthy not implemented")
}
// UnsafeEntityStoreServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to EntityStoreServer will
@@ -318,6 +333,24 @@ func (x *entityStoreWatchServer) Recv() (*EntityWatchRequest, error) {
return m, nil
}
func _EntityStore_IsHealthy_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.(EntityStoreServer).IsHealthy(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: EntityStore_IsHealthy_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(EntityStoreServer).IsHealthy(ctx, req.(*HealthCheckRequest))
}
return interceptor(ctx, in, info, handler)
}
// EntityStore_ServiceDesc is the grpc.ServiceDesc for EntityStore service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@@ -349,6 +382,10 @@ var EntityStore_ServiceDesc = grpc.ServiceDesc{
MethodName: "List",
Handler: _EntityStore_List_Handler,
},
{
MethodName: "IsHealthy",
Handler: _EntityStore_IsHealthy_Handler,
},
},
Streams: []grpc.StreamDesc{
{
+88
View File
@@ -0,0 +1,88 @@
package entity
import (
"context"
"errors"
"time"
grpcAuth "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/auth"
"google.golang.org/grpc/health/grpc_health_v1"
)
// Compile-time assertion
var _ HealthService = &healthServer{}
type HealthService interface {
grpc_health_v1.HealthServer
grpcAuth.ServiceAuthFuncOverride
}
func ProvideHealthService(server EntityStoreServer) (grpc_health_v1.HealthServer, error) {
h := &healthServer{entityServer: server}
return h, nil
}
type healthServer struct {
entityServer EntityStoreServer
}
// AuthFuncOverride for no auth for health service.
func (s *healthServer) AuthFuncOverride(ctx context.Context, _ string) (context.Context, error) {
return ctx, nil
}
func (s *healthServer) Check(ctx context.Context, req *grpc_health_v1.HealthCheckRequest) (*grpc_health_v1.HealthCheckResponse, error) {
r, err := s.entityServer.IsHealthy(ctx, &HealthCheckRequest{})
if err != nil {
return nil, err
}
return &grpc_health_v1.HealthCheckResponse{
Status: grpc_health_v1.HealthCheckResponse_ServingStatus(r.Status.Number()),
}, nil
}
func (s *healthServer) Watch(req *grpc_health_v1.HealthCheckRequest, stream grpc_health_v1.Health_WatchServer) error {
h, err := s.entityServer.IsHealthy(stream.Context(), &HealthCheckRequest{})
if err != nil {
return err
}
// send initial health status
err = stream.Send(&grpc_health_v1.HealthCheckResponse{
Status: grpc_health_v1.HealthCheckResponse_ServingStatus(h.Status.Number()),
})
if err != nil {
return err
}
currHealth := h.Status.Number()
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
// get current health status
h, err := s.entityServer.IsHealthy(stream.Context(), &HealthCheckRequest{})
if err != nil {
return err
}
// if health status has not changed, continue
if h.Status.Number() == currHealth {
continue
}
// send the new health status
currHealth = h.Status.Number()
err = stream.Send(&grpc_health_v1.HealthCheckResponse{
Status: grpc_health_v1.HealthCheckResponse_ServingStatus(h.Status.Number()),
})
if err != nil {
return err
}
case <-stream.Context().Done():
return errors.New("stream closed, context cancelled")
}
}
}
+150
View File
@@ -0,0 +1,150 @@
package entity
import (
"context"
"errors"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/grpc"
"google.golang.org/grpc/health/grpc_health_v1"
)
func TestHealthCheck(t *testing.T) {
t.Run("will return serving response when healthy", func(t *testing.T) {
stub := &entityStoreStub{healthResponse: HealthCheckResponse_SERVING}
svc, err := ProvideHealthService(stub)
require.NoError(t, err)
req := &grpc_health_v1.HealthCheckRequest{}
res, err := svc.Check(context.Background(), req)
require.NoError(t, err)
assert.Equal(t, grpc_health_v1.HealthCheckResponse_SERVING, res.Status)
})
t.Run("will return not serving response when not healthy", func(t *testing.T) {
stub := &entityStoreStub{healthResponse: HealthCheckResponse_NOT_SERVING}
svc, err := ProvideHealthService(stub)
require.NoError(t, err)
req := &grpc_health_v1.HealthCheckRequest{}
res, err := svc.Check(context.Background(), req)
require.NoError(t, err)
assert.Equal(t, grpc_health_v1.HealthCheckResponse_NOT_SERVING, res.Status)
})
}
func TestHealthWatch(t *testing.T) {
t.Run("watch will return message when called", func(t *testing.T) {
stub := &entityStoreStub{healthResponse: HealthCheckResponse_SERVING}
svc, err := ProvideHealthService(stub)
require.NoError(t, err)
req := &grpc_health_v1.HealthCheckRequest{}
stream := &fakeHealthWatchServer{}
go func() {
err := svc.Watch(req, stream)
require.NoError(t, err)
}()
time.Sleep(100 * time.Millisecond)
err = stream.RecvMsg(nil)
require.NoError(t, err)
})
t.Run("watch will return error when context cancelled", func(t *testing.T) {
stub := &entityStoreStub{healthResponse: HealthCheckResponse_NOT_SERVING}
svc, err := ProvideHealthService(stub)
require.NoError(t, err)
req := &grpc_health_v1.HealthCheckRequest{}
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel()
stream := &fakeHealthWatchServer{context: ctx}
err = svc.Watch(req, stream)
require.Error(t, err)
})
}
var _ EntityStoreServer = &entityStoreStub{}
type entityStoreStub struct {
healthResponse HealthCheckResponse_ServingStatus
error error
}
func (s *entityStoreStub) IsHealthy(ctx context.Context, req *HealthCheckRequest) (*HealthCheckResponse, error) {
if s.error != nil {
return nil, s.error
}
return &HealthCheckResponse{Status: s.healthResponse}, nil
}
// Implement the EntityStoreServer methods
func (s *entityStoreStub) Create(ctx context.Context, r *CreateEntityRequest) (*CreateEntityResponse, error) {
return nil, nil
}
func (s *entityStoreStub) Update(ctx context.Context, r *UpdateEntityRequest) (*UpdateEntityResponse, error) {
return nil, nil
}
func (s *entityStoreStub) Read(ctx context.Context, r *ReadEntityRequest) (*Entity, error) {
return nil, nil
}
func (s *entityStoreStub) Delete(ctx context.Context, r *DeleteEntityRequest) (*DeleteEntityResponse, error) {
return nil, nil
}
func (s *entityStoreStub) History(ctx context.Context, r *EntityHistoryRequest) (*EntityHistoryResponse, error) {
return nil, nil
}
func (s *entityStoreStub) List(ctx context.Context, r *EntityListRequest) (*EntityListResponse, error) {
return nil, nil
}
func (s *entityStoreStub) Watch(EntityStore_WatchServer) error {
return nil
}
func (s *entityStoreStub) FindReferences(ctx context.Context, r *ReferenceRequest) (*EntityListResponse, error) {
return nil, nil
}
type fakeHealthWatchServer struct {
grpc.ServerStream
healthChecks []*grpc_health_v1.HealthCheckResponse
context context.Context
}
func (f *fakeHealthWatchServer) Send(resp *grpc_health_v1.HealthCheckResponse) error {
f.healthChecks = append(f.healthChecks, resp)
return nil
}
func (f *fakeHealthWatchServer) RecvMsg(m interface{}) error {
if len(f.healthChecks) == 0 {
return errors.New("no health checks received")
}
f.healthChecks = f.healthChecks[1:]
return nil
}
func (f *fakeHealthWatchServer) SendMsg(m interface{}) error {
return errors.New("not implemented")
}
func (f *fakeHealthWatchServer) Context() context.Context {
if f.context == nil {
f.context = context.Background()
}
return f.context
}
@@ -17,6 +17,7 @@ import (
"github.com/grafana/grafana/pkg/services/store/entity/sqlstash"
"github.com/grafana/grafana/pkg/setting"
"github.com/prometheus/client_golang/prometheus"
"google.golang.org/grpc/health/grpc_health_v1"
)
var (
@@ -125,7 +126,18 @@ func (s *service) start(ctx context.Context) error {
return err
}
healthService, err := entity.ProvideHealthService(store)
if err != nil {
return err
}
entity.RegisterEntityStoreServer(s.handler.GetServer(), store)
grpc_health_v1.RegisterHealthServer(s.handler.GetServer(), healthService)
// register reflection service
_, err = grpcserver.ProvideReflectionService(s.cfg, s.handler)
if err != nil {
return err
}
err = s.handler.Run(ctx)
if err != nil {
@@ -130,6 +130,19 @@ func (s *sqlEntityServer) Init() error {
return nil
}
func (s *sqlEntityServer) IsHealthy(ctx context.Context, r *entity.HealthCheckRequest) (*entity.HealthCheckResponse, error) {
sess, err := s.db.GetSession()
if err != nil {
return nil, err
}
_, err = sess.Query(ctx, "SELECT 1")
if err != nil {
return nil, err
}
return &entity.HealthCheckResponse{Status: entity.HealthCheckResponse_SERVING}, nil
}
func (s *sqlEntityServer) Stop() {
s.cancel()
}
@@ -18,6 +18,13 @@ func TestMain(m *testing.M) {
testsuite.Run(m)
}
func TestIsHealthy(t *testing.T) {
s := setUpTestServer(t)
_, err := s.IsHealthy(context.Background(), &entity.HealthCheckRequest{})
require.NoError(t, err)
}
func TestCreate(t *testing.T) {
s := setUpTestServer(t)