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