func (conn *Conn) runRequest(
	req boundRequest,
	arg reflect.Value,
	version int,
	recorder Recorder,
) {
	// If the request causes a panic, ensure we log that before closing the connection.
	defer func() {
		if panicResult := recover(); panicResult != nil {
			logger.Criticalf(
				"panic running request %+v with arg %+v: %v\n%v", req, arg, panicResult, string(debug.Stack()))
			_ = conn.writeErrorResponse(&req.hdr, errors.Errorf("%v", panicResult), recorder)
		}
	}()
	defer conn.srvPending.Done()

	// Create a request-specific context, cancelled when the
	// request returns.
	//
	// TODO(axw) provide a means for clients to cancel a request.
	ctx, cancel := context.WithCancel(conn.context)
	defer cancel()

	rv, err := req.Call(ctx, req.hdr.Request.Id, arg)
	if err != nil {
		err = conn.writeErrorResponse(&req.hdr, req.transformErrors(err), recorder)
	} else {
		hdr := &Header{
			RequestId: req.hdr.RequestId,
			Version:   version,
		}
		var rvi interface{}
		if rv.IsValid() {
			rvi = rv.Interface()
		} else {
			rvi = struct{}{}
		}
		if err := recorder.HandleReply(req.hdr.Request, hdr, rvi); err != nil {
			logger.Errorf("error recording reply %+v: %T %+v", hdr, err, err)
		}
		conn.sending.Lock()
		err = conn.codec.WriteMessage(hdr, rvi)
		conn.sending.Unlock()
	}
	if err != nil {
		// If the message failed due to the other end closing the socket, that
		// is expected when an agent restarts so no need to log an  error.
		// The error type here is errors.errorString so all we can do is a match
		// on the error string content.
		msg := err.Error()
		if !strings.Contains(msg, "websocket: close sent") &&
			!strings.Contains(msg, "write: broken pipe") {
			logger.Errorf("error writing response: %T %+v", err, err)
		}
	}
}
// runRequest runs the given request and sends the reply.
runRequest runs the given request and sends the reply.
// runRequest runs the given request and sends the reply .
func (conn *Conn) runRequest(
	req boundRequest,
	arg reflect.Value,
	version int,
	recorder Recorder,
) {
	defer func() {
		if panicResult := recover(); panicResult != nil {
			logger.Criticalf(
				"panic running request %+v with arg %+v: %v\n%v", req, arg, panicResult, string(debug.Stack()))
			_ = conn.writeErrorResponse(&req.hdr, errors.Errorf("%v", panicResult), recorder)
		}
	}()
	defer conn.srvPending.Done()
	 TODO(axw) provide a means for clients to cancel a request.
	ctx, cancel := context.WithCancel(conn.context)
	defer cancel()
	rv, err := req.Call(ctx, req.hdr.Request.Id, arg)
	if err != nil {
		err = conn.writeErrorResponse(&req.hdr, req.transformErrors(err), recorder)
	} else {
		hdr := &Header{
			RequestId: req.hdr.RequestId,
			Version:   version,
		}
		var rvi interface{}
		if rv.IsValid() {
			rvi = rv.Interface()
		} else {
			rvi = struct{}{}
		}
		if err := recorder.HandleReply(req.hdr.Request, hdr, rvi); err != nil {
			logger.Errorf("error recording reply %+v: %T %+v", hdr, err, err)
		}
		conn.sending.Lock()
		err = conn.codec.WriteMessage(hdr, rvi)
		conn.sending.Unlock()
	}
	if err != nil {
		 If the message failed due to the other end closing the socket, that
		 is expected when an agent restarts so no need to log an  error.
		 The error type here is errors.errorString so all we can do is a match
		 on the error string content.
		msg := err.Error()
		if !strings.Contains(msg, "websocket: close sent") &&
			!strings.Contains(msg, "write: broken pipe") {
			logger.Errorf("error writing response: %T %+v", err, err)
		}
	}
}
func ( conn * Conn ) runRequest ( req boundRequest , arg reflect . Value , version int , recorder Recorder , ) { defer func ( ) { if panicResult := recover ( ) ; panicResult != nil { logger . Criticalf ( " \n " , req , arg , panicResult , string ( debug . Stack ( ) ) ) _ = conn . writeErrorResponse ( & req . hdr , errors . Errorf ( " " , panicResult ) , recorder ) } } ( ) defer conn . srvPending . Done ( ) ctx , cancel := context . WithCancel ( conn . context ) defer cancel ( ) rv , err := req . Call ( ctx , req . hdr . Request . Id , arg ) if err != nil { err = conn . writeErrorResponse ( & req . hdr , req . transformErrors ( err ) , recorder ) } else { hdr := & Header { RequestId : req . hdr . RequestId , Version : version , } var rvi interface { } if rv . IsValid ( ) { rvi = rv . Interface ( ) } else { rvi = struct { } { } } if err := recorder . HandleReply ( req . hdr . Request , hdr , rvi ) ; err != nil { logger . Errorf ( " " , hdr , err , err ) } conn . sending . Lock ( ) err = conn . codec . WriteMessage ( hdr , rvi ) conn . sending . Unlock ( ) } if err != nil { msg := err . Error ( ) if ! strings . Contains ( msg , " " ) && ! strings . Contains ( msg , " " ) { logger . Errorf ( " " , err , err ) } } }
runRequest runs the given request and sends the reply.
runRequest runs the given request and sends the reply .
// If the request causes a panic, ensure we log that before closing the connection. // Create a request-specific context, cancelled when the // request returns. // // TODO(axw) provide a means for clients to cancel a request. // If the message failed due to the other end closing the socket, that // is expected when an agent restarts so no need to log an  error. // The error type here is errors.errorString so all we can do is a match // on the error string content.