Function: jsonrpc-request

jsonrpc-request is a byte-compiled function defined in jsonrpc.el.gz.

Signature

(jsonrpc-request CONNECTION METHOD PARAMS &rest ARGS &key DEFERRED TIMEOUT CANCEL-ON-QUIT CANCEL-ON-INPUT CANCEL-ON-INPUT-RETVAL)

Documentation

Make a request to CONNECTION, synchronously wait for a reply.

CONNECTION, METHOD, PARAMS, DEFERRED and TIMEOUT are interpreted as in jsonrpc-async-request, which see.

This function has two exit modes: local and non-local. Except for CANCEL-ON-INPUT, explained below, the only normal local exit occurs when the remote endpoint succeeds, in which case a JSONRPC result object is returned. A remote endpoint error or a local timeout cause a non-local exit with a jsonrpc-error condition.

A user quit (C-g'/keyboard-quit) causes a non-local exit with a quit condition. A non-nil CANCEL-ON-QUIT must be a function of a single argument, ID, which identifies the request as specified in the JSONRPC 2.0 spec. Callers may use this function to issue a cancel notification to the endpoint, thus preventing it from continuing to work on the request.

If CANCEL-ON-INPUT is non-nil and any type of user input is detected while waiting for a response jsonrpc-request locally exits immediately, returning CANCEL-ON-INPUT-RETVAL. CANCEL-ON-INPUT can also be a function with the same semantics as CANCEL-ON-QUIT. Since the a C-g/keyboard-quit also counts as user input, CANCEL-ON-INPUT nullifies the effect of CANCEL-ON-QUIT.

On either cancellation scenario, any future remote endpoint replies to the original request (normal or error) are ignored.

View in manual

Source Code

;; Defined in /usr/src/emacs/lisp/jsonrpc.el.gz
(cl-defun jsonrpc-request (connection
                           method params
                           &rest args
                           &key
                           deferred timeout
                           cancel-on-quit
                           cancel-on-input
                           cancel-on-input-retval)
  "Make a request to CONNECTION, synchronously wait for a reply.
CONNECTION, METHOD, PARAMS, DEFERRED and TIMEOUT are interpreted as in
`jsonrpc-async-request', which see.

This function has two exit modes: local and non-local.  Except for
CANCEL-ON-INPUT, explained below, the only normal local exit occurs when
the remote endpoint succeeds, in which case a JSONRPC result object is
returned.  A remote endpoint error or a local timeout cause a non-local
exit with a `jsonrpc-error' condition.

A user quit (`'C-g'/`keyboard-quit') causes a non-local exit with a
`quit' condition.  A non-nil CANCEL-ON-QUIT must be a function of a
single argument, ID, which identifies the request as specified in the
JSONRPC 2.0 spec.  Callers may use this function to issue a cancel
notification to the endpoint, thus preventing it from continuing to work
on the request.

If CANCEL-ON-INPUT is non-nil and any type of user input is detected
while waiting for a response `jsonrpc-request' locally exits
immediately, returning CANCEL-ON-INPUT-RETVAL.  CANCEL-ON-INPUT can also
be a function with the same semantics as CANCEL-ON-QUIT.  Since the a
`C-g'/`keyboard-quit' also counts as user input, CANCEL-ON-INPUT
nullifies the effect of CANCEL-ON-QUIT.

On either cancellation scenario, any future remote endpoint replies
to the original request (normal or error) are ignored."
  (let* ((tag (funcall (if (fboundp 'gensym) 'gensym 'cl-gensym)
                       "jsonrpc-request-catch-tag"))
         id-and-timer
         canceled
         (throw-on-input nil)
         retval)
    (unwind-protect
        (catch tag
          (setq
           id-and-timer
           (apply
            #'jsonrpc--async-request-1
            connection method params
            :sync-request t
            :success-fn (lambda (result)
                          (unless canceled
                            (setq retval `(done ,result))
                            (throw tag nil)))
            :error-fn
            (jsonrpc-lambda
                (&key code message data)
              (unless canceled
                (setq retval `(error (jsonrpc-error-code . ,code)
                                     (jsonrpc-error-message . ,message)
                                     (jsonrpc-error-data . ,data)))
                (throw tag nil)))
            :timeout-fn
            (lambda ()
              (unless canceled
                (setq retval '(error (jsonrpc-error-message . "Timed out")))
                (throw tag nil)))
            `(,@(when (plist-member args :deferred) `(:deferred ,deferred))
              ,@(when (plist-member args :timeout) `(:timeout  ,timeout)))))
          (cond (cancel-on-input
                 (unwind-protect
                     (let ((inhibit-quit t) (inhibit-redisplay t))
                       (while (sit-for 30 t)))
                   (setq canceled t))
                 (when (functionp cancel-on-input)
                   (funcall cancel-on-input (car id-and-timer)))
                 (setq retval `(canceled ,cancel-on-input-retval)))
                (t (let ((inhibit-quit nil))
                     (while t (accept-process-output nil 30))))))
      ;; In normal operation, continuations for error/success is
      ;; handled by `jsonrpc--continue'.  Timeouts also remove
      ;; the continuation...
      (pcase-let* ((`(,id ,_) id-and-timer))
        ;; ...but we still have to guard against exist explicit
        ;; user-quit (C-g) or the `cancel-on-input' case, so
        ;; discard the continuation.
        (jsonrpc--remove connection id (list deferred (current-buffer)))
        ;; Furthermore, assume a nil `retval' is a quit from
        ;; `accept-process-output' (either "soft" or "hard," like a
        ;; double C-g C-g on TTY terminals)
        (unless retval
          (when cancel-on-quit (funcall cancel-on-quit id)))
        ;; ...finally, whatever may have happened to this sync
        ;; request, it might have been holding up any outer
        ;; "anxious" continuations.  The following ensures we
        ;; call them.
        (jsonrpc--continue connection `(:local ,id))))
    (cond ((eq 'error (car retval))
           (signal 'jsonrpc-error
                   (cons
                    (format "request id=%s failed:" (car id-and-timer))
                    (cdr retval)))))
    (cadr retval)))