feat(core/handlers): improve handlers registration DevX (#22007)

This commit is contained in:
testinginprod
2024-10-01 19:16:20 +00:00
committed by GitHub
parent a0f96930ab
commit a3729c1ad6
4 changed files with 45 additions and 18 deletions
+34 -16
View File
@@ -10,8 +10,8 @@ import (
type (
// PreMsgHandler is a handler that is executed before Handler. If it errors the execution reverts.
PreMsgHandler = func(ctx context.Context, msg transaction.Msg) error
// Handler handles the state transition of the provided message.
Handler = func(ctx context.Context, msg transaction.Msg) (msgResp transaction.Msg, err error)
// HandlerFunc handles the state transition of the provided message.
HandlerFunc = func(ctx context.Context, msg transaction.Msg) (msgResp transaction.Msg, err error)
// PostMsgHandler runs after Handler, only if Handler does not error. If PostMsgHandler errors
// then the execution is reverted.
PostMsgHandler = func(ctx context.Context, msg, msgResp transaction.Msg) error
@@ -19,10 +19,10 @@ type (
// PreMsgRouter is a router that allows you to register PreMsgHandlers for specific message types.
type PreMsgRouter interface {
// RegisterPreHandler will register a specific message handler hooking into the message with
// RegisterPreMsgHandler will register a specific message handler hooking into the message with
// the provided name.
RegisterPreMsgHandler(msgName string, handler PreMsgHandler)
// RegisterGlobalPreHandler will register a global message handler hooking into any message
// RegisterGlobalPreMsgHandler will register a global message handler hooking into any message
// being executed.
RegisterGlobalPreMsgHandler(handler PreMsgHandler)
}
@@ -64,10 +64,10 @@ func RegisterMsgPreHandler[Req transaction.Msg](
// PostMsgRouter is a router that allows you to register PostMsgHandlers for specific message types.
type PostMsgRouter interface {
// RegisterPostHandler will register a specific message handler hooking after the execution of message with
// RegisterPostMsgHandler will register a specific message handler hooking after the execution of message with
// the provided name.
RegisterPostMsgHandler(msgName string, handler PostMsgHandler)
// RegisterGlobalPostHandler will register a global message handler hooking after the execution of any message.
// RegisterGlobalPostMsgHandler will register a global message handler hooking after the execution of any message.
RegisterGlobalPostMsgHandler(handler PostMsgHandler)
}
@@ -76,7 +76,7 @@ type HasPostMsgHandlers interface {
RegisterPostMsgHandlers(router PostMsgRouter)
}
// RegisterPostHandler is a helper function that modules can use to not lose type safety when registering handlers to the
// RegisterPostMsgHandler is a helper function that modules can use to not lose type safety when registering handlers to the
// PostMsgRouter. Example usage:
// ```go
//
@@ -110,9 +110,20 @@ func RegisterPostMsgHandler[Req, Resp transaction.Msg](
router.RegisterPostMsgHandler(msgName, untypedHandler)
}
// Handler defines a handler descriptor.
type Handler struct {
// Func defines the actual handler, the function that runs a request and returns a response.
// Can be query handler or msg handler.
Func HandlerFunc
// MakeMsg instantiates the type of the request, can be used in decoding contexts.
MakeMsg func() transaction.Msg
// MakeMsgResp instantiates a new response, can be used in decoding contexts.
MakeMsgResp func() transaction.Msg
}
// MsgRouter is a router that allows you to register Handlers for specific message types.
type MsgRouter = interface {
RegisterHandler(msgName string, handler Handler) error
RegisterHandler(handler Handler)
}
// HasMsgHandlers is an interface that modules must implement if they want to register Handlers.
@@ -142,27 +153,34 @@ type HasQueryHandlers interface {
//
// func (m Module) RegisterMsgHandlers(router appmodule.MsgRouter) {
// handlers := keeper.NewHandlers(m.keeper)
// err := appmodule.RegisterHandler(router, gogoproto.MessageName(types.MsgMint{}), handlers.MsgMint)
// err := appmodule.RegisterHandler(router, handlers.MsgMint)
// }
//
// func (m Module) RegisterQueryHandlers(router appmodule.QueryRouter) {
// handlers := keeper.NewHandlers(m.keeper)
// err := appmodule.RegisterHandler(router, gogoproto.MessageName(types.QueryBalanceRequest{}), handlers.QueryBalance)
// err := appmodule.RegisterHandler(router, handlers.QueryBalance)
// }
//
// ```
func RegisterHandler[Req, Resp transaction.Msg](
func RegisterMsgHandler[Req, Resp any, PReq transaction.GenericMsg[Req], PResp transaction.GenericMsg[Resp]](
router MsgRouter,
msgName string,
handler func(ctx context.Context, msg Req) (msgResp Resp, err error),
) error {
handler func(ctx context.Context, msg PReq) (msgResp PResp, err error),
) {
untypedHandler := func(ctx context.Context, m transaction.Msg) (transaction.Msg, error) {
typed, ok := m.(Req)
typed, ok := m.(PReq)
if !ok {
return nil, fmt.Errorf("unexpected type %T, wanted: %T", m, *new(Req))
}
return handler(ctx, typed)
}
return router.RegisterHandler(msgName, untypedHandler)
router.RegisterHandler(Handler{
Func: untypedHandler,
MakeMsg: func() transaction.Msg {
return PReq(new(Req))
},
MakeMsgResp: func() transaction.Msg {
return PResp(new(Resp))
},
})
}