@@ -167,16 +167,18 @@ func httpClient(ctx context.Context, addr string, namespace string, outs []inter
167167 defer httpResp .Body .Close ()
168168
169169 var resp clientResponse
170- if err := json .NewDecoder (httpResp .Body ).Decode (& resp ); err != nil {
171- return clientResponse {}, xerrors .Errorf ("http status %s unmarshaling response: %w" , httpResp .Status , err )
172- }
170+ if cr .req .ID != nil { // non-notification
171+ if err := json .NewDecoder (httpResp .Body ).Decode (& resp ); err != nil {
172+ return clientResponse {}, xerrors .Errorf ("http status %s unmarshaling response: %w" , httpResp .Status , err )
173+ }
173174
174- if resp .ID , err = normalizeID (resp .ID ); err != nil {
175- return clientResponse {}, xerrors .Errorf ("failed to response ID: %w" , err )
176- }
175+ if resp .ID , err = normalizeID (resp .ID ); err != nil {
176+ return clientResponse {}, xerrors .Errorf ("failed to response ID: %w" , err )
177+ }
177178
178- if resp .ID != cr .req .ID {
179- return clientResponse {}, xerrors .New ("request and response id didn't match" )
179+ if resp .ID != cr .req .ID {
180+ return clientResponse {}, xerrors .New ("request and response id didn't match" )
181+ }
180182 }
181183
182184 return resp , nil
@@ -220,7 +222,7 @@ func websocketClient(ctx context.Context, addr string, namespace string, outs []
220222 errors : config .errors ,
221223 }
222224
223- requests := c .setup ()
225+ requests := c .setupRequestChan ()
224226
225227 stop := make (chan struct {})
226228 exiting := make (chan struct {})
@@ -258,7 +260,7 @@ func websocketClient(ctx context.Context, addr string, namespace string, outs []
258260 }, nil
259261}
260262
261- func (c * client ) setup () chan clientRequest {
263+ func (c * client ) setupRequestChan () chan clientRequest {
262264 requests := make (chan clientRequest )
263265
264266 c .doRequest = func (ctx context.Context , cr clientRequest ) (clientResponse , error ) {
@@ -290,6 +292,7 @@ func (c *client) setup() chan clientRequest {
290292 Method : wsCancel ,
291293 Params : []param {{v : reflect .ValueOf (cr .req .ID )}},
292294 },
295+ ready : make (chan clientResponse , 1 ),
293296 }
294297 select {
295298 case requests <- cancelReq :
@@ -452,7 +455,8 @@ type rpcFunc struct {
452455 hasCtx int
453456 returnValueIsChannel bool
454457
455- retry bool
458+ retry bool
459+ notify bool
456460}
457461
458462func (fn * rpcFunc ) processResponse (resp clientResponse , rval reflect.Value ) []reflect.Value {
@@ -487,7 +491,22 @@ func (fn *rpcFunc) processError(err error) []reflect.Value {
487491}
488492
489493func (fn * rpcFunc ) handleRpcCall (args []reflect.Value ) (results []reflect.Value ) {
490- var id interface {} = atomic .AddInt64 (& fn .client .idCtr , 1 )
494+ var id interface {}
495+ if ! fn .notify {
496+ id = atomic .AddInt64 (& fn .client .idCtr , 1 )
497+
498+ // Prepare the ID to send on the wire.
499+ // We track int64 ids as float64 in the inflight map (because that's what
500+ // they'll be decoded to). encoding/json outputs numbers with their minimal
501+ // encoding, avoding the decimal point when possible, i.e. 3 will never get
502+ // converted to 3.0.
503+ var err error
504+ id , err = normalizeID (id )
505+ if err != nil {
506+ return fn .processError (fmt .Errorf ("failed to normalize id" )) // should probably panic
507+ }
508+ }
509+
491510 params := make ([]param , len (args )- fn .hasCtx )
492511 for i , arg := range args [fn .hasCtx :] {
493512 enc , found := fn .client .paramEncoders [arg .Type ()]
@@ -522,16 +541,6 @@ func (fn *rpcFunc) handleRpcCall(args []reflect.Value) (results []reflect.Value)
522541 retVal , chCtor = fn .client .makeOutChan (ctx , fn .ftyp , fn .valOut )
523542 }
524543
525- // Prepare the ID to send on the wire.
526- // We track int64 ids as float64 in the inflight map (because that's what
527- // they'll be decoded to). encoding/json outputs numbers with their minimal
528- // encoding, avoding the decimal point when possible, i.e. 3 will never get
529- // converted to 3.0.
530- id , err := normalizeID (id )
531- if err != nil {
532- return fn .processError (fmt .Errorf ("failed to normalize id" )) // should probably panic
533- }
534-
535544 req := request {
536545 Jsonrpc : "2.0" ,
537546 ID : id ,
@@ -554,6 +563,7 @@ func (fn *rpcFunc) handleRpcCall(args []reflect.Value) (results []reflect.Value)
554563 minDelay : methodMinRetryDelay ,
555564 }
556565
566+ var err error
557567 var resp clientResponse
558568 // keep retrying if got a forced closed websocket conn and calling method
559569 // has retry annotation
@@ -563,7 +573,7 @@ func (fn *rpcFunc) handleRpcCall(args []reflect.Value) (results []reflect.Value)
563573 return fn .processError (fmt .Errorf ("sendRequest failed: %w" , err ))
564574 }
565575
566- if resp .ID != req .ID {
576+ if ! fn . notify && resp .ID != req .ID {
567577 return fn .processError (xerrors .New ("request and response id didn't match" ))
568578 }
569579
@@ -593,6 +603,7 @@ func (fn *rpcFunc) handleRpcCall(args []reflect.Value) (results []reflect.Value)
593603
594604const (
595605 ProxyTagRetry = "retry"
606+ ProxyTagNotify = "notify"
596607 ProxyTagRPCMethod = "rpc_method"
597608)
598609
@@ -612,9 +623,14 @@ func (c *client) makeRpcFunc(f reflect.StructField) (reflect.Value, error) {
612623 ftyp : ftyp ,
613624 name : name ,
614625 retry : f .Tag .Get (ProxyTagRetry ) == "true" ,
626+ notify : f .Tag .Get (ProxyTagNotify ) == "true" ,
615627 }
616628 fun .valOut , fun .errOut , fun .nout = processFuncOut (ftyp )
617629
630+ if fun .valOut != - 1 && fun .notify {
631+ return reflect.Value {}, xerrors .New ("notify methods cannot return values" )
632+ }
633+
618634 if ftyp .NumIn () > 0 && ftyp .In (0 ) == contextType {
619635 fun .hasCtx = 1
620636 }
0 commit comments