diff --git a/internal/api/group/group.go b/internal/api/group/group.go index c33f9778b..e044b81b2 100644 --- a/internal/api/group/group.go +++ b/internal/api/group/group.go @@ -1,12 +1,5 @@ package group -import ( - "OpenIM/internal/api2rpc" - "OpenIM/pkg/apistruct" - "OpenIM/pkg/proto/group" - "github.com/gin-gonic/gin" -) - //import ( // common "OpenIM/internal/api_to_rpc" // api "OpenIM/pkg/apistruct" @@ -34,20 +27,6 @@ import ( // api2rpc.NewRpc(api2rpc.NewGin[apistruct.KickGroupMemberReq, apistruct.KickGroupMemberResp](c), group.NewGroupClient, group.GroupClient.KickGroupMember).Name("group").Call() //} -func KickGroupMember(c *gin.Context) { - // 默认 全部自动 - api := api2rpc.NewGin[apistruct.KickGroupMemberReq, apistruct.KickGroupMemberResp](c) - api2rpc.NewRpc(api, group.NewGroupClient, group.GroupClient.KickGroupMember).Name("group").Call() - - //// 可以自定义编辑请求和响应 - //a := NewRpc(NewGin[apistruct.KickGroupMemberReq, apistruct.KickGroupMemberResp](c), group.NewGroupClient, group.GroupClient.KickGroupMember) - //a.Before(func(apiReq *apistruct.KickGroupMemberReq, rpcReq *group.KickGroupMemberReq, bind func() error) error { - // return bind() - //}).After(func(rpcResp *group.KickGroupMemberResp, apiResp *apistruct.KickGroupMemberResp, bind func() error) error { - // return bind() - //}).Name("group").Call() -} - // //// @Summary 获取群成员信息 //// @Description 获取群成员信息 diff --git a/internal/api/group/group1.go b/internal/api/group/group1.go new file mode 100644 index 000000000..07ce95105 --- /dev/null +++ b/internal/api/group/group1.go @@ -0,0 +1,35 @@ +package group + +import ( + "OpenIM/internal/api2rpc" + "OpenIM/pkg/apistruct" + "OpenIM/pkg/common/config" + "OpenIM/pkg/proto/group" + "github.com/OpenIMSDK/openKeeper" + "github.com/gin-gonic/gin" +) + +type Group struct { + zk *openKeeper.ZkClient +} + +func (g *Group) getGroupClient() (group.GroupClient, error) { + conn, err := g.zk.GetConn(config.Config.RpcRegisterName.OpenImGroupName) + if err != nil { + return nil, err + } + return group.NewGroupClient(conn), nil +} + +func (g *Group) KickGroupMember(c *gin.Context) { + api2rpc.Rpc( + &apistruct.KickGroupMemberReq{}, + &apistruct.KickGroupMemberResp{}, + group.GroupClient.KickGroupMember, + ).Must(c, g.getGroupClient).Call() +} + +//func (g *Group) KickGroupMember1(c *gin.Context) { +// var fn func(client group.GroupClient, ctx context.Context, in *group.KickGroupMemberReq, opts ...grpc.CallOption) (*group.KickGroupMemberResp, error) = group.GroupClient.KickGroupMember +// api2rpc.Rpc(&apistruct.KickGroupMemberReq{}, &apistruct.KickGroupMemberResp{}, fn).Must(c, g.getGroupClient).Call() +//} diff --git a/internal/api/group/group1_test.go b/internal/api/group/group1_test.go new file mode 100644 index 000000000..38a10af8c --- /dev/null +++ b/internal/api/group/group1_test.go @@ -0,0 +1,10 @@ +package group + +import "testing" + +func TestName(t *testing.T) { + var g Group + + g.KickGroupMember(nil) + +} diff --git a/internal/api/group/group_test.go b/internal/api/group/group_test.go deleted file mode 100644 index 16146a01b..000000000 --- a/internal/api/group/group_test.go +++ /dev/null @@ -1,171 +0,0 @@ -package group - -import ( - common "OpenIM/internal/api2rpc" - "OpenIM/pkg/apistruct" - "OpenIM/pkg/proto/group" - "context" - "github.com/gin-gonic/gin" - "google.golang.org/grpc" -) - -type ApiBind[A, B any] interface { - OperationID() string - OpUserID() (string, error) - Bind(*A) error - Context() context.Context - Resp(resp *B, err error) -} - -func NewGin[A, B any](c *gin.Context) ApiBind[A, B] { - return &ginApiBind[A, B]{ - c: c, - } -} - -type ginApiBind[A, B any] struct { - c *gin.Context -} - -func (g *ginApiBind[A, B]) OperationID() string { - return g.c.GetHeader("operationID") -} - -func (g *ginApiBind[A, B]) OpUserID() (string, error) { - return "", nil -} - -func (g *ginApiBind[A, B]) Bind(a *A) error { - return g.c.BindJSON(a) -} - -func (g *ginApiBind[A, B]) Resp(resp *B, err error) { - if err == nil { - g.Write(resp) - } else { - g.Error(err) - } -} - -func (g *ginApiBind[A, B]) Error(err error) { - //TODO implement me -} - -func (g *ginApiBind[A, B]) Write(b *B) { - //TODO implement me -} - -func (g *ginApiBind[A, B]) Context() context.Context { - return g.c -} - -//func TestName(t *testing.T) { -// //var bind ApiBind[int, int] -// //NewRpc(bind, "", group.NewGroupClient, temp) -// -// var c *gin.Context -// NewRpc(NewGin[apistruct.KickGroupMemberReq, apistruct.KickGroupMemberResp](c), "", group.NewGroupClient, group.GroupClient.KickGroupMember) -//} - -func KickGroupMember(c *gin.Context) { - // 默认 全部自动 - NewRpc(NewGin[apistruct.KickGroupMemberReq, apistruct.KickGroupMemberResp](c), group.NewGroupClient, group.GroupClient.KickGroupMember).Call() - // 可以自定义编辑请求和响应 - a := NewRpc(NewGin[apistruct.KickGroupMemberReq, apistruct.KickGroupMemberResp](c), group.NewGroupClient, group.GroupClient.KickGroupMember) - a.Before(func(apiReq *apistruct.KickGroupMemberReq, rpcReq *group.KickGroupMemberReq, bind func() error) error { - return bind() - }).After(func(rpcResp *group.KickGroupMemberResp, apiResp *apistruct.KickGroupMemberResp, bind func() error) error { - return bind() - }).Call() -} - -// 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 { - common.CopyAny(apiReq, rpcReq) - return nil -} - -func (a *Rpc[A, B, C, D, Z]) defaultCopyResp(rpcResp *D, apiResp *B) error { - common.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()) -} diff --git a/internal/api2rpc/api.go b/internal/api2rpc/api.go index 624b9ebde..2e6ee02e5 100644 --- a/internal/api2rpc/api.go +++ b/internal/api2rpc/api.go @@ -23,7 +23,7 @@ import ( // return // } // tracelog.SetCtxInfo(ctx, logFuncName, nil, "apiReq", apiReq) -// etcdConn, err := rpc.GetConn(ctx, rpcName) +// etcdConn, err := rpcFn.GetConn(ctx, rpcName) // if err != nil { // WriteErrorResponse(ctx, "GetConn", err) // return diff --git a/internal/api2rpc/api2rpc.go b/internal/api2rpc/api2rpc.go index 328341339..a2589c5fe 100644 --- a/internal/api2rpc/api2rpc.go +++ b/internal/api2rpc/api2rpc.go @@ -13,3 +13,11 @@ type ApiBind[A, B any] interface { Context() context.Context Resp(resp *B, err error) } + +type Api interface { + OperationID() string + OpUserID() string + Context() context.Context + Bind(req any) error + Resp(resp any, err error) +} diff --git a/internal/api2rpc/gin.go b/internal/api2rpc/gin.go index ea829f5e9..3a66ce355 100644 --- a/internal/api2rpc/gin.go +++ b/internal/api2rpc/gin.go @@ -10,9 +10,9 @@ import ( // //var api ApiBind[apistruct.KickGroupMemberReq, apistruct.KickGroupMemberResp] = NewGin[apistruct.KickGroupMemberReq, apistruct.KickGroupMemberResp](c) // var api ApiBind[apistruct.KickGroupMemberReq, apistruct.KickGroupMemberResp] = nil // var client func(conn *grpc.ClientConn) group.GroupClient = nil -// var rpc func(ctx context.Context, in *group.KickGroupMemberReq, opts ...grpc.CallOption) (*group.KickGroupMemberResp, error) = nil -// //NewRpc(api, client, rpc).Name("group").Call() -// NewRpc(api, client, rpc).Name("group").Call() +// var rpcFn func(ctx context.Context, in *group.KickGroupMemberReq, opts ...grpc.CallOption) (*group.KickGroupMemberResp, error) = nil +// //NewRpc(api, client, rpcFn).Name("group").Call() +// NewRpc(api, client, rpcFn).Name("group").Call() // // // 可以自定义编辑请求和响应 // //a := NewRpc(NewGin[apistruct.KickGroupMemberReq, apistruct.KickGroupMemberResp](c), "", group.NewGroupClient, group.GroupClient.KickGroupMember) @@ -65,3 +65,34 @@ func (g *ginApiBind[A, B]) Write(b *B) { func (g *ginApiBind[A, B]) Context() context.Context { return g.c } + +func NewGin1(c *gin.Context) Api { + return &ginApi{ + c: c, + } +} + +type ginApi struct { + c *gin.Context +} + +func (g *ginApi) OperationID() string { + return g.c.GetHeader("operationID") +} + +func (g *ginApi) OpUserID() string { + return g.c.MustGet("opUserID").(string) +} + +func (g *ginApi) Context() context.Context { + return g.c +} + +func (g *ginApi) Bind(req any) error { + return g.c.BindJSON(req) +} + +func (g *ginApi) Resp(resp any, err error) { + //TODO implement me + panic("implement me") +} diff --git a/internal/api2rpc/rpc.go b/internal/api2rpc/rpc.go index 0e1a7b51b..58a95e3c4 100644 --- a/internal/api2rpc/rpc.go +++ b/internal/api2rpc/rpc.go @@ -3,18 +3,26 @@ package api2rpc import ( "context" "google.golang.org/grpc" + "reflect" ) +var nameMap = map[string]string{} + +func getName[T any]() string { + var t T + return reflect.TypeOf(&t).Elem().Name() +} + // 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]{ +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)) *RpcXXXX[A, B, C, D, Z] { + return &RpcXXXX[A, B, C, D, Z]{ bind: bind, client: client, rpc: rpc, } } -type Rpc[A, B any, C, D any, Z any] struct { +type RpcXXXX[A, B any, C, D any, Z any] struct { bind ApiBind[A, B] name string client func(conn *grpc.ClientConn) Z @@ -23,36 +31,45 @@ type Rpc[A, B any, C, D any, Z any] struct { 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] { +func (a *RpcXXXX[A, B, C, D, Z]) Name(name string) *RpcXXXX[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] { +func (a *RpcXXXX[A, B, C, D, Z]) Before(fn func(apiReq *A, rpcReq *C, bind func() error) error) *RpcXXXX[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] { +func (a *RpcXXXX[A, B, C, D, Z]) After(fn func(rpcResp *D, apiResp *B, bind func() error) error) *RpcXXXX[A, B, C, D, Z] { a.after = fn return a } -func (a *Rpc[A, B, C, D, Z]) defaultCopyReq(apiReq *A, rpcReq *C) error { +func (a *RpcXXXX[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 { +func (a *RpcXXXX[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) { +func (a *RpcXXXX[A, B, C, D, Z]) getZtype() string { + return "" +} + +func (a *RpcXXXX[A, B, C, D, Z]) GetGrpcConn() (*grpc.ClientConn, error) { + if a.name == "" { + a.name = nameMap[getName[Z]()] + } + // todo 获取连接 + return nil, nil // todo } -func (a *Rpc[A, B, C, D, Z]) execute() (*B, error) { +func (a *RpcXXXX[A, B, C, D, Z]) execute() (*B, error) { var apiReq A if err := a.bind.Bind(&apiReq); err != nil { return nil, err @@ -92,6 +109,6 @@ func (a *Rpc[A, B, C, D, Z]) execute() (*B, error) { return &apiResp, nil } -func (a *Rpc[A, B, C, D, Z]) Call() { +func (a *RpcXXXX[A, B, C, D, Z]) Call() { a.bind.Resp(a.execute()) } diff --git a/internal/api2rpc/rpc1.go b/internal/api2rpc/rpc1.go new file mode 100644 index 000000000..cccdb23f7 --- /dev/null +++ b/internal/api2rpc/rpc1.go @@ -0,0 +1,98 @@ +package api2rpc + +import ( + "context" + "github.com/gin-gonic/gin" + "google.golang.org/grpc" +) + +type rpcFunc[E, C, D any] func(client E, ctx context.Context, req *C, options ...grpc.CallOption) (*D, error) + +func Rpc[A, B, C, D any, E any](apiReq *A, apiResp *B, rpc func(client E, ctx context.Context, req *C, options ...grpc.CallOption) (*D, error)) RpcCall[A, B, C, D, E] { + return &rpcCall[A, B, C, D, E]{ + apiReq: apiReq, + apiResp: apiResp, + rpcFn: rpc, + } +} + +type rpcCall[A, B, C, D any, E any] struct { + apiReq *A + apiResp *B + client func() (E, error) + rpcFn func(client E, ctx context.Context, req *C, options ...grpc.CallOption) (*D, error) + api Api + before func(apiReq *A, rpcReq *C, bind func() error) error + after func(rpcResp *D, apiResp *B, bind func() error) error +} + +func (r *rpcCall[A, B, C, D, E]) Before(fn func(apiReq *A, rpcReq *C, bind func() error) error) RpcCall[A, B, C, D, E] { + r.before = fn + return r +} + +func (r *rpcCall[A, B, C, D, E]) After(fn func(rpcResp *D, apiResp *B, bind func() error) error) RpcCall[A, B, C, D, E] { + r.after = fn + return r +} + +func (r *rpcCall[A, B, C, D, E]) Must(c *gin.Context, client func() (E, error)) RpcCall[A, B, C, D, E] { + r.api = NewGin1(c) + r.client = client + return r +} + +func (r *rpcCall[A, B, C, D, E]) Call() { + r.api.Resp(r.apiResp, r.call()) +} + +func (r *rpcCall[A, B, C, D, E]) defaultCopyReq(rpcReq *C) error { + if r.apiReq != nil { + CopyAny(r.apiReq, rpcReq) + } + return nil +} + +func (r *rpcCall[A, B, C, D, E]) defaultCopyResp(rpcResp *D) error { + if r.apiResp != nil { + CopyAny(rpcResp, r.apiResp) + } + return nil +} + +func (r *rpcCall[A, B, C, D, E]) call() error { + if err := r.api.Bind(r.apiReq); err != nil { + return err + } + var err error + var rpcReq C + if r.before == nil { + err = r.defaultCopyReq(&rpcReq) + } else { + err = r.before(r.apiReq, &rpcReq, func() error { return r.defaultCopyReq(&rpcReq) }) + } + if err != nil { + return err + } + client, err := r.client() + if err != nil { + return err + } + rpcResp, err := r.rpcFn(client, r.api.Context(), &rpcReq) + if err != nil { + return err + } + var apiResp B + if r.after == nil { + return r.defaultCopyResp(rpcResp) + } else { + return r.after(rpcResp, &apiResp, func() error { return r.defaultCopyResp(rpcResp) }) + } +} + +type RpcCall[A, B, C, D, E any] interface { + Before(fn func(apiReq *A, rpcReq *C, bind func() error) error) RpcCall[A, B, C, D, E] + After(fn func(rpcResp *D, apiResp *B, bind func() error) error) RpcCall[A, B, C, D, E] + Must(c *gin.Context, client func() (E, error)) RpcCall[A, B, C, D, E] + Call() +} diff --git a/internal/common/a_test.go b/internal/common/a_test.go index 69b9014ee..3567cb9ab 100644 --- a/internal/common/a_test.go +++ b/internal/common/a_test.go @@ -3,8 +3,11 @@ package common import ( "OpenIM/internal/api2rpc" "OpenIM/pkg/proto/group" + "fmt" "github.com/gin-gonic/gin" + "reflect" "testing" + "time" ) type AReq struct { @@ -15,7 +18,7 @@ type AResp struct { func KickGroupMember(c *gin.Context) { // 默认 全部自动 - api2rpc.NewRpc(api2rpc.NewGin[AReq, AResp](c), group.NewGroupClient, group.GroupClient.KickGroupMember).Name("group").Call() + api2rpc.NewRpc(api2rpc.NewGin[AReq, AResp](c), group.NewGroupClient, group.GroupClient.KickGroupMember).Call() //// 可以自定义编辑请求和响应 //a := NewRpc(NewGin[apistruct.KickGroupMemberReq, apistruct.KickGroupMemberResp](c), group.NewGroupClient, group.GroupClient.KickGroupMember) @@ -26,6 +29,24 @@ func KickGroupMember(c *gin.Context) { //}).Name("group").Call() } +//func getInterfaceName(handler PackerHandler) string { +// funcInfo := runtime.FuncForPC(reflect.ValueOf(handler).Pointer()) +// name := funcInfo.Name() +// names := strings.Split(name, "/") +// if len(names) == 0 { +// return "" +// } +// +// return names[len(names)-1] +//} + func TestName(t *testing.T) { - KickGroupMember(nil) + n := 100000000 + start := time.Now().UnixNano() + for i := 0; i < n; i++ { + var val group.GroupClient + reflect.TypeOf(&val).Elem().String() + } + end := time.Now().UnixNano() + fmt.Println(time.Duration(end-start) / time.Duration(n)) } diff --git a/pkg/apistruct/manage.go b/pkg/apistruct/manage.go index 85fa57c0e..3f0cc5998 100644 --- a/pkg/apistruct/manage.go +++ b/pkg/apistruct/manage.go @@ -1,7 +1,6 @@ package apistruct import ( - pbRelay "OpenIM/pkg/proto/relay" sdkws "OpenIM/pkg/proto/sdkws" ) @@ -26,7 +25,7 @@ type GetUsersOnlineStatusReq struct { } type GetUsersOnlineStatusResp struct { CommResp - SuccessResult []*pbRelay.GetUsersOnlineStatusResp_SuccessResult `json:"data"` + //SuccessResult []*pbRelay.GetUsersOnlineStatusResp_SuccessResult `json:"data"` } type AccountCheckReq struct { OperationID string `json:"operationID" binding:"required"` diff --git a/pkg/common/config/config.go b/pkg/common/config/config.go index 8590f1d0d..de6156748 100644 --- a/pkg/common/config/config.go +++ b/pkg/common/config/config.go @@ -510,6 +510,7 @@ func unmarshalConfig(config interface{}, configPath string) error { if err = yaml.Unmarshal(bytes, config); err != nil { return err } + return nil } func initConfig(config interface{}, configName, configPath string) error {