63 lines
1.4 KiB
Go
63 lines
1.4 KiB
Go
package app
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/connectivity"
|
|
)
|
|
|
|
// ReadinessChecker 定义统一的就绪检查能力。
|
|
type ReadinessChecker interface {
|
|
Ready(ctx context.Context) error
|
|
}
|
|
|
|
type readinessGroup struct {
|
|
checkers []namedChecker
|
|
}
|
|
|
|
type namedChecker struct {
|
|
name string
|
|
check func(context.Context) error
|
|
}
|
|
|
|
// newReadinessGroup 创建一个按顺序执行的就绪检查器组合。
|
|
func newReadinessGroup(checkers ...namedChecker) ReadinessChecker {
|
|
return readinessGroup{checkers: checkers}
|
|
}
|
|
|
|
// Ready 逐个执行检查,只要有一个失败就返回未就绪。
|
|
func (g readinessGroup) Ready(ctx context.Context) error {
|
|
for _, checker := range g.checkers {
|
|
if err := checker.check(ctx); err != nil {
|
|
return fmt.Errorf("%s not ready: %w", checker.name, err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func grpcConnectionReady(conn *grpc.ClientConn) func(context.Context) error {
|
|
return func(ctx context.Context) error {
|
|
// 主动触发一次连接过程,避免懒连接状态下 readiness 永远不去拨号。
|
|
conn.Connect()
|
|
|
|
for {
|
|
state := conn.GetState()
|
|
switch state {
|
|
case connectivity.Ready:
|
|
return nil
|
|
case connectivity.Shutdown:
|
|
return fmt.Errorf("connection shutdown")
|
|
}
|
|
|
|
if !conn.WaitForStateChange(ctx, state) {
|
|
if err := ctx.Err(); err != nil {
|
|
return err
|
|
}
|
|
return fmt.Errorf("state did not change")
|
|
}
|
|
}
|
|
}
|
|
}
|