2023-02-24 15:41:50 +08:00

98 lines
2.4 KiB
Go

package api2rpc
import (
"context"
"google.golang.org/grpc"
)
// NewRpc A: apiReq B: apiResp C: rpcReq D: rpcResp Z: rpcClient (group.GroupClient)
func NewRpc[A, B any, C, D any, Z any](bind ApiBind[A, B], client func(conn *grpc.ClientConn) Z, rpc func(client Z, ctx context.Context, req *C, options ...grpc.CallOption) (*D, error)) *Rpc[A, B, C, D, Z] {
return &Rpc[A, B, C, D, Z]{
bind: bind,
client: client,
rpc: rpc,
}
}
type Rpc[A, B any, C, D any, Z any] struct {
bind ApiBind[A, B]
name string
client func(conn *grpc.ClientConn) Z
rpc func(client Z, ctx context.Context, req *C, options ...grpc.CallOption) (*D, error)
before func(apiReq *A, rpcReq *C, bind func() error) error
after func(rpcResp *D, apiResp *B, bind func() error) error
}
func (a *Rpc[A, B, C, D, Z]) Name(name string) *Rpc[A, B, C, D, Z] {
a.name = name
return a
}
func (a *Rpc[A, B, C, D, Z]) Before(fn func(apiReq *A, rpcReq *C, bind func() error) error) *Rpc[A, B, C, D, Z] {
a.before = fn
return a
}
func (a *Rpc[A, B, C, D, Z]) After(fn func(rpcResp *D, apiResp *B, bind func() error) error) *Rpc[A, B, C, D, Z] {
a.after = fn
return a
}
func (a *Rpc[A, B, C, D, Z]) defaultCopyReq(apiReq *A, rpcReq *C) error {
CopyAny(apiReq, rpcReq)
return nil
}
func (a *Rpc[A, B, C, D, Z]) defaultCopyResp(rpcResp *D, apiResp *B) error {
CopyAny(rpcResp, apiResp)
return nil
}
func (a *Rpc[A, B, C, D, Z]) GetGrpcConn() (*grpc.ClientConn, error) {
return nil, nil // todo
}
func (a *Rpc[A, B, C, D, Z]) execute() (*B, error) {
var apiReq A
if err := a.bind.Bind(&apiReq); err != nil {
return nil, err
}
opID := a.bind.OperationID()
userID, err := a.bind.OpUserID()
if err != nil {
return nil, err
}
_, _ = opID, userID
var rpcReq C
if a.before == nil {
err = a.defaultCopyReq(&apiReq, &rpcReq)
} else {
err = a.before(&apiReq, &rpcReq, func() error { return a.defaultCopyReq(&apiReq, &rpcReq) })
}
if err != nil {
return nil, err
}
conn, err := a.GetGrpcConn()
if err != nil {
return nil, err
}
rpcResp, err := a.rpc(a.client(conn), a.bind.Context(), &rpcReq)
if err != nil {
return nil, err
}
var apiResp B
if a.after == nil {
err = a.defaultCopyResp(rpcResp, &apiResp)
} else {
err = a.after(rpcResp, &apiResp, func() error { return a.defaultCopyResp(rpcResp, &apiResp) })
}
if err != nil {
return nil, err
}
return &apiResp, nil
}
func (a *Rpc[A, B, C, D, Z]) Call() {
a.bind.Resp(a.execute())
}