通过使用泛型可以减少grpc-client公共代码的重复编写。
// ------------------------------公共的------------------------------------------------------
type clientSvc[T any] struct {
*grpcpool.Pool
InitClientCall func(grpc.ClientConnInterface) T
}
func (c *clientSvc[T]) getCli(ctx context.Context) (T, func() error, error) {
defer timecost.LogFuncTimeCost(ctx)()
var defaultValue T
if c.Pool == nil {
return defaultValue, nil, fmt.Errorf("clientSvcConnPool not initialized yet")
}
conn, err := c.Pool.Get(ctx)
if err != nil {
return defaultValue, nil, fmt.Errorf("get client svc client err, available=%d capacity=%d err=%w", c.Pool.Available(), c.Pool.Capacity(), err)
}
return c.InitClientCall(conn), conn.Close, nil
}
func (c *clientSvc[T]) baseCall(ctx context.Context, reqCall func(T) error) error {
cli, closeFunc, err := c.getCli(ctx)
if err != nil {
return err
}
defer func() {
_ = closeFunc()
}()
if reqCall != nil {
err = reqCall(cli)
if err != nil {
return err
}
}
return nil
}
func newBaseClient[T any](addr string, poolCfg *grpcutils.PoolConfig, opts []grpcutils.Option, InitClientCall func(grpc.ClientConnInterface) T) (*clientSvc[T], error) {
connPool, err := grpcutils.NewGRPCPool(addr, poolCfg, opts...)
if err != nil {
return nil, fmt.Errorf("get client svc client err, available=%d capacity=%d err=%w", connPool.Available(), connPool.Capacity(), err)
}
return &clientSvc[T]{
Pool: connPool,
InitClientCall: InitClientCall,
}, nil
}
func (c *clientSvc[T]) Close() {
if c.Pool != nil && !c.Pool.IsClosed() {
c.Pool.Close()
}
}
//------------------------------Client服务的Client------------------------------------------------------
type IClient interface {
Close()
GetClientID(ctx context.Context, id uint64) (int64, error)
}
type clientSvcClient struct {
clientSvc[clientservicepb.InternalServiceClient]
}
func NewClientSvc(addr string, poolCfg *grpcutils.PoolConfig, opts []grpcutils.Option) (IClient, error) {
c, err := newBaseClient[clientservicepb.InternalServiceClient](addr, poolCfg, opts, func(conn grpc.ClientConnInterface) clientservicepb.InternalServiceClient {
return clientservicepb.NewInternalServiceClient(conn)
})
if err != nil {
return nil, err
}
return &clientSvcClient{
clientSvc: *c,
}, nil
}
func (c *clientSvcClient) GetClientID(ctx context.Context, id uint64) (int64, error){
var resultId int64
err := c.baseCall(ctx, func(cli clientservicepb.InternalServiceClient) error {
req := &clientcommonpb.IDRequest{
Id: clientMemberId,
}
resp, err := cli.GetClientIDByClientMemberID(ctx, req)
if err != nil {
return err
}
resultId = resp.GetData().GetId()
return nil
})
if err != nil {
return 0, err
}
return resultId, nil
}
网友评论