update micro, add Health/Live/Ready checks

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
2024-12-02 15:47:30 +03:00
parent 2deb9d3df9
commit dace6eef67
8 changed files with 189 additions and 24 deletions

View File

@@ -13,15 +13,30 @@ type Handler struct {
opts Options
}
type CheckFunc func(context.Context) error
type (
CheckFunc func(context.Context) error
Option func(*Options)
)
type Option func(*Options)
type Stater interface {
Live() bool
Ready() bool
Health() bool
}
type Options struct {
Version string
Name string
LiveChecks []CheckFunc
ReadyChecks []CheckFunc
Version string
Name string
Staters []Stater
LiveChecks []CheckFunc
ReadyChecks []CheckFunc
HealthChecks []CheckFunc
}
func Service(s ...Stater) Option {
return func(o *Options) {
o.Staters = append(o.Staters, s...)
}
}
func LiveChecks(fns ...CheckFunc) Option {
@@ -36,6 +51,12 @@ func ReadyChecks(fns ...CheckFunc) Option {
}
}
func HealthChecks(fns ...CheckFunc) Option {
return func(o *Options) {
o.HealthChecks = append(o.HealthChecks, fns...)
}
}
func Name(name string) Option {
return func(o *Options) {
o.Name = name
@@ -56,18 +77,51 @@ func NewHandler(opts ...Option) *Handler {
return &Handler{opts: options}
}
func (h *Handler) Healthy(ctx context.Context, req *codecpb.Frame, rsp *codecpb.Frame) error {
var err error
for _, s := range h.opts.Staters {
if !s.Health() {
return errors.ServiceUnavailable(h.opts.Name, "%v", err)
}
}
for _, fn := range h.opts.HealthChecks {
if err = fn(ctx); err != nil {
return errors.ServiceUnavailable(h.opts.Name, "%v", err)
}
}
return nil
}
func (h *Handler) Live(ctx context.Context, req *codecpb.Frame, rsp *codecpb.Frame) error {
var err error
for _, s := range h.opts.Staters {
if !s.Live() {
return errors.ServiceUnavailable(h.opts.Name, "%v", err)
}
}
for _, fn := range h.opts.LiveChecks {
if err = fn(ctx); err != nil {
return errors.ServiceUnavailable(h.opts.Name, "%v", err)
}
}
return nil
}
func (h *Handler) Ready(ctx context.Context, req *codecpb.Frame, rsp *codecpb.Frame) error {
var err error
for _, s := range h.opts.Staters {
if !s.Ready() {
return errors.ServiceUnavailable(h.opts.Name, "%v", err)
}
}
for _, fn := range h.opts.ReadyChecks {
if err = fn(ctx); err != nil {
return errors.ServiceUnavailable(h.opts.Name, "%v", err)

View File

@@ -8,6 +8,22 @@ import "openapiv3/annotations.proto";
import "codec/frame.proto";
service HealthService {
rpc Healthy(micro.codec.Frame) returns (micro.codec.Frame) {
option (micro.openapiv3.openapiv3_operation) = {
operation_id: "Healthy";
responses: {
default: {
reference: {
_ref: "micro.codec.Frame";
};
};
};
};
option (micro.api.http) = {
get: "/health";
additional_bindings: { get: "/healthz"; }
};
};
rpc Live(micro.codec.Frame) returns (micro.codec.Frame) {
option (micro.openapiv3.openapiv3_operation) = {
operation_id: "Live";
@@ -19,7 +35,10 @@ service HealthService {
};
};
};
option (micro.api.http) = { get: "/live"; };
option (micro.api.http) = {
get: "/live";
additional_bindings: { get: "/livez"; }
};
};
rpc Ready(micro.codec.Frame) returns (micro.codec.Frame) {
option (micro.openapiv3.openapiv3_operation) = {
@@ -32,7 +51,9 @@ service HealthService {
};
};
};
option (micro.api.http) = { get: "/ready"; };
option (micro.api.http) = { get: "/ready";
additional_bindings: { get: "/readyz"; }
};
};
rpc Version(micro.codec.Frame) returns (micro.codec.Frame) {
option (micro.openapiv3.openapiv3_operation) = {

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-micro. DO NOT EDIT.
// versions:
// - protoc-gen-go-micro v3.10.4
// - protoc v5.26.1
// - protoc v5.28.3
// source: health/health.proto
package health_handler
@@ -17,12 +17,14 @@ var (
)
type HealthServiceClient interface {
Healthy(ctx context.Context, req *codec.Frame, opts ...client.CallOption) (*codec.Frame, error)
Live(ctx context.Context, req *codec.Frame, opts ...client.CallOption) (*codec.Frame, error)
Ready(ctx context.Context, req *codec.Frame, opts ...client.CallOption) (*codec.Frame, error)
Version(ctx context.Context, req *codec.Frame, opts ...client.CallOption) (*codec.Frame, error)
}
type HealthServiceServer interface {
Healthy(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error
Live(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error
Ready(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error
Version(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error

View File

@@ -16,6 +16,20 @@ import (
var (
HealthServiceServerEndpoints = []v3.EndpointMetadata{
{
Name: "HealthService.Healthy",
Path: "/health",
Method: "GET",
Body: "",
Stream: false,
},
{
Name: "HealthService.Healthy",
Path: "/healthz",
Method: "GET",
Body: "",
Stream: false,
},
{
Name: "HealthService.Live",
Path: "/live",
@@ -23,6 +37,13 @@ var (
Body: "",
Stream: false,
},
{
Name: "HealthService.Live",
Path: "/livez",
Method: "GET",
Body: "",
Stream: false,
},
{
Name: "HealthService.Ready",
Path: "/ready",
@@ -30,6 +51,13 @@ var (
Body: "",
Stream: false,
},
{
Name: "HealthService.Ready",
Path: "/readyz",
Method: "GET",
Body: "",
Stream: false,
},
{
Name: "HealthService.Version",
Path: "/version",
@@ -49,6 +77,24 @@ func NewHealthServiceClient(name string, c client.Client) HealthServiceClient {
return &healthServiceClient{c: c, name: name}
}
func (c *healthServiceClient) Healthy(ctx context.Context, req *codec.Frame, opts ...client.CallOption) (*codec.Frame, error) {
errmap := make(map[string]interface{}, 1)
errmap["default"] = &codec.Frame{}
opts = append(opts,
v31.ErrorMap(errmap),
)
opts = append(opts,
v31.Method(http.MethodGet),
v31.Path("/health"),
)
rsp := &codec.Frame{}
err := c.c.Call(ctx, c.c.NewRequest(c.name, "HealthService.Healthy", req), rsp, opts...)
if err != nil {
return nil, err
}
return rsp, nil
}
func (c *healthServiceClient) Live(ctx context.Context, req *codec.Frame, opts ...client.CallOption) (*codec.Frame, error) {
errmap := make(map[string]interface{}, 1)
errmap["default"] = &codec.Frame{}
@@ -107,6 +153,10 @@ type healthServiceServer struct {
HealthServiceServer
}
func (h *healthServiceServer) Healthy(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error {
return h.HealthServiceServer.Healthy(ctx, req, rsp)
}
func (h *healthServiceServer) Live(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error {
return h.HealthServiceServer.Live(ctx, req, rsp)
}
@@ -121,6 +171,7 @@ func (h *healthServiceServer) Version(ctx context.Context, req *codec.Frame, rsp
func RegisterHealthServiceServer(s server.Server, sh HealthServiceServer, opts ...server.HandlerOption) error {
type healthService interface {
Healthy(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error
Live(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error
Ready(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error
Version(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-micro. DO NOT EDIT.
// versions:
// - protoc-gen-go-micro v3.10.4
// - protoc v5.26.1
// - protoc v5.28.3
// source: meter/meter.proto
package meter_handler