@@ -19,6 +19,7 @@ import (
1919
2020 amino "github.com/tendermint/go-amino"
2121 cmn "github.com/tendermint/tendermint/libs/common"
22+ "github.com/tendermint/tendermint/libs/gopool"
2223 "github.com/tendermint/tendermint/libs/log"
2324 types "github.com/tendermint/tendermint/rpc/lib/types"
2425)
@@ -436,6 +437,8 @@ type wsConnection struct {
436437
437438 // object that is used to subscribe / unsubscribe from events
438439 eventSub types.EventSubscriber
440+
441+ workerPool * gopool.Pool
439442}
440443
441444// NewWSConnection wraps websocket.Conn.
@@ -477,6 +480,12 @@ func EventSubscriber(eventSub types.EventSubscriber) func(*wsConnection) {
477480 }
478481}
479482
483+ func SetWorkerPool (workerPool * gopool.Pool ) func (* wsConnection ) {
484+ return func (wsc * wsConnection ) {
485+ wsc .workerPool = workerPool
486+ }
487+ }
488+
480489// WriteWait sets the amount of time to wait before a websocket write times out.
481490// It should only be used in the constructor - not Goroutine-safe.
482491func WriteWait (writeWait time.Duration ) func (* wsConnection ) {
@@ -611,57 +620,68 @@ func (wsc *wsConnection) readRoutine() {
611620 wsc .Stop ()
612621 return
613622 }
614-
615- var request types.RPCRequest
616- err = json .Unmarshal (in , & request )
617- if err != nil {
618- wsc .WriteRPCResponse (types .RPCParseError (types .JSONRPCStringID ("" ), errors .Wrap (err , "Error unmarshaling request" )))
619- continue
620- }
621-
622- // A Notification is a Request object without an "id" member.
623- // The Server MUST NOT reply to a Notification, including those that are within a batch request.
624- if request .ID == types .JSONRPCStringID ("" ) {
625- wsc .Logger .Debug ("WSJSONRPC received a notification, skipping... (please send a non-empty ID if you want to call a method)" )
626- continue
623+ // Fetch the RPCFunc and execute it.
624+ if wsc .workerPool != nil {
625+ wsc .workerPool .Schedule (func () {
626+ wsc .processRequest (in )
627+ })
628+ } else {
629+ wsc .processRequest (in )
627630 }
628631
629- // Now, fetch the RPCFunc and execute it.
632+ }
633+ }
634+ }
630635
631- rpcFunc := wsc .funcMap [request .Method ]
632- if rpcFunc == nil {
633- wsc .WriteRPCResponse (types .RPCMethodNotFoundError (request .ID ))
634- continue
635- }
636- var args []reflect.Value
637- if rpcFunc .ws {
638- wsCtx := types.WSRPCContext {Request : request , WSRPCConnection : wsc }
639- if len (request .Params ) > 0 {
640- args , err = jsonParamsToArgsWS (rpcFunc , wsc .cdc , request .Params , wsCtx )
641- }
642- } else {
643- if len (request .Params ) > 0 {
644- args , err = jsonParamsToArgsRPC (rpcFunc , wsc .cdc , request .Params )
645- }
646- }
647- if err != nil {
648- wsc .WriteRPCResponse (types .RPCInternalError (request .ID , errors .Wrap (err , "Error converting json params to arguments" )))
649- continue
650- }
651- returns := rpcFunc .f .Call (args )
636+ func (wsc * wsConnection ) processRequest (message []byte ) {
637+ var request types.RPCRequest
638+ err := json .Unmarshal (message , & request )
639+ if err != nil {
640+ wsc .WriteRPCResponse (types .RPCParseError (types .JSONRPCStringID ("" ), errors .Wrap (err , "Error unmarshaling request" )))
641+ return
642+ }
652643
653- // TODO: Need to encode args/returns to string if we want to log them
654- wsc .Logger .Info ("WSJSONRPC" , "method" , request .Method )
644+ // A Notification is a Request object without an "id" member.
645+ // The Server MUST NOT reply to a Notification, including those that are within a batch request.
646+ if request .ID == types .JSONRPCStringID ("" ) {
647+ wsc .Logger .Debug ("WSJSONRPC received a notification, skipping... (please send a non-empty ID if you want to call a method)" )
648+ return
649+ }
655650
656- result , err := unreflectResult (returns )
657- if err != nil {
658- wsc .WriteRPCResponse (types .RPCInternalError (request .ID , err ))
659- continue
660- }
651+ // Now, fetch the RPCFunc and execute it.
661652
662- wsc .WriteRPCResponse (types .NewRPCSuccessResponse (wsc .cdc , request .ID , result ))
653+ rpcFunc := wsc .funcMap [request .Method ]
654+ if rpcFunc == nil {
655+ wsc .WriteRPCResponse (types .RPCMethodNotFoundError (request .ID ))
656+ return
657+ }
658+ var args []reflect.Value
659+ if rpcFunc .ws {
660+ wsCtx := types.WSRPCContext {Request : request , WSRPCConnection : wsc }
661+ if len (request .Params ) > 0 {
662+ args , err = jsonParamsToArgsWS (rpcFunc , wsc .cdc , request .Params , wsCtx )
663663 }
664+ } else {
665+ if len (request .Params ) > 0 {
666+ args , err = jsonParamsToArgsRPC (rpcFunc , wsc .cdc , request .Params )
667+ }
668+ }
669+ if err != nil {
670+ wsc .WriteRPCResponse (types .RPCInternalError (request .ID , errors .Wrap (err , "Error converting json params to arguments" )))
671+ return
672+ }
673+ returns := rpcFunc .f .Call (args )
674+
675+ // TODO: Need to encode args/returns to string if we want to log them
676+ wsc .Logger .Info ("WSJSONRPC" , "method" , request .Method )
677+
678+ result , err := unreflectResult (returns )
679+ if err != nil {
680+ wsc .WriteRPCResponse (types .RPCInternalError (request .ID , err ))
681+ return
664682 }
683+
684+ wsc .WriteRPCResponse (types .NewRPCSuccessResponse (wsc .cdc , request .ID , result ))
665685}
666686
667687// receives on a write channel and writes out on the socket
0 commit comments