2026-04-04 01:28:57 +08:00

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")
}
}
}
}