// Get package common func (g GenRoot) PackageOut() (res []byte, err error) { res, err = tpl.Run("package", TPL_PACKAGE, g) if err != nil { return } return }
// Generate processor type. func (p *GenProcessor) Processor() (res []byte, err error) { src := `package {{ .Options.Package }} import ( "{{ .Options.Core }}" . "{{ .Options.Core }}/builtin" "golang.org/x/net/context" "bytes" "fmt" "time" ) const ( processor_VERSION = TL_VERSION ) type ProcessorFactory struct { handler Handler encoderFactory tl.EncoderFactory decoderFactory tl.DecoderFactory waitress tl.Waitress idBrokerFactory tl.IDBrokerFactory } func NewProcessorFactory(handler Handler, encoderFactory tl.EncoderFactory, decoderFactory tl.DecoderFactory, waitress tl.Waitress, idBrokerFactory tl.IDBrokerFactory) tl.ProcessorFactory { return &ProcessorFactory{handler, encoderFactory, decoderFactory, waitress, idBrokerFactory} } func (f *ProcessorFactory) GetProcessor(ctx context.Context, id int64) tl.Processor { return NewProcessor(ctx, f.handler, f.encoderFactory, f.decoderFactory, f.waitress, f.idBrokerFactory.GetIDBroker(id)) } type Processor struct { ctx context.Context handler Handler tl.EncoderFactory tl.DecoderFactory tl.Waitress tl.IDBroker } func NewProcessor( ctx context.Context, handler Handler, encoderFactory tl.EncoderFactory, decoderFactory tl.DecoderFactory, waitress tl.Waitress, idBroker tl.IDBroker, ) *Processor { return &Processor{ ctx, handler, encoderFactory, decoderFactory, waitress, idBroker, } } func (p *Processor) Process(reqCtx tl.RequestContext, data []byte, result tl.ProcessorResult) (err error) { decoder := p.DecoderFactory.GetDecoder(bytes.NewBuffer(data)) box := &ObjectBox{} if err = box.Read(decoder, p.Waitress, reqCtx.Session); err != nil { return err } bare, err := box.Bare() if err != nil { return err } // Add ack if needed if (reqCtx.SeqNo & 1) == 1 { if err = p.sendAck(result, reqCtx); err != nil { return err } } switch bare.(type) { case *MsgsAck: for _, msgId := range bare.(*MsgsAck).MsgIds { p.Waitress.DoneAck(reqCtx.Session, msgId) } case *MsgContainer: // Requeue messages for _, msg := range bare.(*MsgContainer).Messages { box := msg.Body buff := new(bytes.Buffer) encoder := p.EncoderFactory.GetEncoder(buff) if err = box.Write(encoder); err != nil { return err } newReqCtx := tl.RequestContext{ reqCtx.Conn, reqCtx.Session, msg.MsgId, msg.Seqno, } if err = result.EnqueueRequest(newReqCtx, buff.Bytes()); err != nil { return err } } case *RpcResult: rpcResult := bare.(*RpcResult) var handlerErr error ctx := tl.HandlerContext{reqCtx, p, p.ctx} switch rpcResult.Result.(type) { {{range .RPCs}} {{if .WithResult}} {{range .GBox.Bares}} case *{{.Ident.ToName}}Res: handlerErr = p.handler.{{.Ident.ToName}}Result(ctx, rpcResult.ReqMsgId, rpcResult.Result.(*{{.Ident.ToName}}Res).Arg, rpcResult.RpcError) {{end}} {{end}} {{end}} default: // unknown constructor handlerErr = fmt.Errorf("unknown RpcResult for %0xd (ctx %v)", rpcResult.ReqMsgId, reqCtx) } err = p.Waitress.DoneResult(reqCtx.Session, rpcResult.ReqMsgId, handlerErr) {{ range .RPCs }} {{ if eq .WithResult false }} case *{{.GBox.Ident.ToName}}: // Unwrapped {{.GBox.Ident.ToName}} result ctx := tl.HandlerContext{reqCtx, p, p.ctx} handlerErr := p.handler.{{.GBox.Ident.ToName}}(ctx, bare.(*{{.GBox.Ident.ToName}}).Boxed()) err = p.Waitress.DoneResult(reqCtx.Session, reqCtx.MessageID, handlerErr) {{end}} {{end}} {{ range .RPCs }} {{$RPC:=.}} {{range .GBox.Bares}} {{$ARG_SRC := printf "bare.(*%s)" .Ident.ToName}} {{ if $RPC.WithResult }} case *{{.Ident.ToName}}: // {{.Ident.ToName}} request with wrapped result ctx := tl.HandlerContext{reqCtx, p, p.ctx} res, handlerErr := p.handler.{{.Ident.ToName}}({{$RPC.HandlerArgs . $ARG_SRC "ctx" ""}}) var resMsgID int64 resMsgID, err = p.IDBroker.NewMessageID(reqCtx.Session, time.Now(), 1) if err != nil { return } err = p.sendResponse( result, tl.ResponseContext{reqCtx, resMsgID, reqCtx.SeqNo + 2}, (&RpcResult{reqCtx.MessageID, &{{.Ident.ToName}}Res{res}, handlerErr}).Box()) {{end}} {{end}} {{end}} {{ range .RPCs }} {{$RPC:=.}} {{range .GBox.Bares}} {{$ARG_SRC := printf "bare.(*%s)" .Ident.ToName}} {{ if eq $RPC.WithResult false }} case *{{.Ident.ToName}}: // {{.Ident.ToName}} request with unwrapped {{.BoxIdent}} result ctx := tl.HandlerContext{reqCtx, p, p.ctx} var res {{.BoxIdent}} var resCtx tl.ResponseContext res, resCtx, err = p.handler.{{.Ident.ToName}}({{$RPC.HandlerArgs . $ARG_SRC "ctx" ""}}) if err != nil { return } err = p.sendResponse(result, resCtx, &res) {{end}} {{end}} {{end}} } return } // Send ack func (p *Processor) sendAck(result tl.ProcessorResult, reqCtx tl.RequestContext) (err error) { resMsgID, err := p.IDBroker.NewMessageID(reqCtx.Session, time.Now(), 1) if err != nil { return } err = p.sendResponse( result, tl.ResponseContext{reqCtx, resMsgID, reqCtx.SeqNo + 1}, (&MsgsAck{[]int64{reqCtx.MessageID}}).Box()) return } // Send response and register ack in waitress func (p *Processor) sendResponse(result tl.ProcessorResult, resCtx tl.ResponseContext, box tl.Box) (err error) { buff := new(bytes.Buffer) encoder := p.EncoderFactory.GetEncoder(buff) if err = box.Write(encoder); err != nil { return err } if (resCtx.SeqNo & 1) == 1 { if err = p.Waitress.WaitAck(resCtx.Request.Session, resCtx.MessageID); err != nil { return err } } err = result.SendResponse(resCtx, buff.Bytes()) return } ` res, err = tpl.Run("pipe", src, p) return }
// Get generated source func (b GenBox) Res() (res []byte, err error) { res, err = tpl.Run(b.Filename(), TPL_BOX, b) return }