diff --git a/ctx.go b/ctx.go index 579488c2..bdfa0d01 100644 --- a/ctx.go +++ b/ctx.go @@ -17,13 +17,14 @@ type Context struct { utils.SpinLock ctx context.Context //nolint:containedctx - nb *northBridge - kv map[string]interface{} - hdr map[string]string - conn Conn - in *Envelope - wf WriteFunc - err error + nb *northBridge + kv map[string]interface{} + hdr map[string]string + conn Conn + in *Envelope + wf WriteFunc + modifiers []Modifier + err error handlers HandlerFuncChain index int @@ -54,6 +55,12 @@ func (ctx *Context) StopExecution() { ctx.index = abortIndex } +// AddModifier adds one or more modifiers to the context which will be executed on each outgoing +// Envelope before writing it to the wire. +func (ctx *Context) AddModifier(modifiers ...Modifier) { + ctx.modifiers = append(ctx.modifiers, modifiers...) +} + // SetUserContext replaces the default context with the provided context. func (ctx *Context) SetUserContext(userCtx context.Context) { ctx.ctx = userCtx @@ -131,5 +138,6 @@ func (ctx *Context) reset() { ctx.in.release() ctx.index = 0 ctx.handlers = ctx.handlers[:0] + ctx.modifiers = ctx.modifiers[:0] ctx.ctx = nil } diff --git a/desc/desc.go b/desc/desc.go index e84540e7..c90dde1e 100644 --- a/desc/desc.go +++ b/desc/desc.go @@ -4,15 +4,22 @@ import ( "github.com/clubpay/ronykit" ) +type Error struct { + Code int + Item string + Message ronykit.Message +} + // Contract is the description of the ronykit.Contract you are going to create. type Contract struct { - Name string - Handlers []ronykit.HandlerFunc - Wrappers []ronykit.ContractWrapper - Input ronykit.Message - Output ronykit.Message - Selectors []ronykit.RouteSelector - Modifiers []ronykit.Modifier + Name string + Handlers []ronykit.HandlerFunc + Wrappers []ronykit.ContractWrapper + Input ronykit.Message + Output ronykit.Message + PossibleErrors []Error + Selectors []ronykit.RouteSelector + Modifiers []ronykit.Modifier } func NewContract() *Contract { @@ -37,14 +44,26 @@ func (c *Contract) SetInput(m ronykit.Message) *Contract { return c } -// SetOutput sets the outgoing message for this Contract. This is an optional parameter, which -// mostly could be used by external tools such as Swagger generator etc. +// SetOutput sets the outgoing message for this Contract. This is an OPTIONAL parameter, which +// mostly could be used by external tools such as Swagger or any other doc generator tools. func (c *Contract) SetOutput(m ronykit.Message) *Contract { c.Output = m return c } +// AddPossibleError sets the possible errors for this Contract. This is OPTIONAL parameter, which +// mostly could be used by external tools such as Swagger or any other doc generator tools. +func (c *Contract) AddPossibleError(code int, item string, m ronykit.Message) *Contract { + c.PossibleErrors = append(c.PossibleErrors, Error{ + Code: code, + Item: item, + Message: m, + }) + + return c +} + // AddSelector adds a ronykit.RouteSelector for this contract. Selectors are bundle specific. func (c *Contract) AddSelector(s ronykit.RouteSelector) *Contract { c.Selectors = append(c.Selectors, s) diff --git a/envelope.go b/envelope.go index ac842e0c..66701fb6 100644 --- a/envelope.go +++ b/envelope.go @@ -134,6 +134,12 @@ func (e *Envelope) Send() { panic("BUG!! do not call Send on incoming envelope") } + // run the modifiers in LIFO order + modifiersCount := len(e.ctx.modifiers) - 1 + for idx := range e.ctx.modifiers { + e.ctx.modifiers[modifiersCount-idx](e) + } + // Use WriteFunc to write the Envelope into the connection e.ctx.Error(e.ctx.wf(e.conn, e)) diff --git a/std/bundle/fasthttp/bundle.go b/std/bundle/fasthttp/bundle.go index 07d8886e..6cd96ae0 100644 --- a/std/bundle/fasthttp/bundle.go +++ b/std/bundle/fasthttp/bundle.go @@ -194,10 +194,6 @@ func (b *bundle) dispatchWS(in []byte) (ronykit.DispatchFunc, error) { } writeFunc := func(conn ronykit.Conn, e *ronykit.Envelope) error { - for idx := range routeData.Modifiers { - routeData.Modifiers[idx](e) - } - outputMsgContainer := acquireOutgoingMessage() outputMsgContainer.Payload = e.GetMsg() e.WalkHdr(func(key string, val string) bool { @@ -228,6 +224,8 @@ func (b *bundle) dispatchWS(in []byte) (ronykit.DispatchFunc, error) { Set(ronykit.CtxServiceName, routeData.ServiceName). Set(ronykit.CtxRoute, routeData.Predicate) + ctx.AddModifier(routeData.Modifiers...) + // run the execFunc with generated params execFunc(writeFunc, routeData.Handlers...) @@ -265,10 +263,6 @@ func (b *bundle) dispatchHTTP(conn *httpConn, in []byte) (ronykit.DispatchFunc, panic("BUG!! incorrect connection") } - for idx := range routeData.Modifiers { - routeData.Modifiers[idx](e) - } - data, err := e.GetMsg().Marshal() if err != nil { return err @@ -296,6 +290,8 @@ func (b *bundle) dispatchHTTP(conn *httpConn, in []byte) (ronykit.DispatchFunc, SetHdrWalker(conn). SetMsg(routeData.Decoder(params, in)) + ctx.AddModifier(routeData.Modifiers...) + // execute handler functions execFunc(writeFunc, routeData.Handlers...) diff --git a/std/bundle/fastws/bundle.go b/std/bundle/fastws/bundle.go index ee7f7d16..175f03f8 100644 --- a/std/bundle/fastws/bundle.go +++ b/std/bundle/fastws/bundle.go @@ -96,10 +96,6 @@ func (b *bundle) Dispatch(c ronykit.Conn, in []byte) (ronykit.DispatchFunc, erro } writeFunc := func(conn ronykit.Conn, e *ronykit.Envelope) error { - for idx := range routeData.Modifiers { - routeData.Modifiers[idx](e) - } - outputMsgContainer := acquireOutgoingMessage() outputMsgContainer.Payload = e.GetMsg() e.WalkHdr(func(key string, val string) bool { @@ -130,6 +126,8 @@ func (b *bundle) Dispatch(c ronykit.Conn, in []byte) (ronykit.DispatchFunc, erro Set(ronykit.CtxServiceName, routeData.ServiceName). Set(ronykit.CtxRoute, routeData.Predicate) + ctx.AddModifier(routeData.Modifiers...) + // run the execFunc with generated params execFunc(writeFunc, routeData.Handlers...)