Commit d82d4fb9 authored by Eli Zaretskii's avatar Eli Zaretskii

Improve documentation of JSONRPC

* doc/lispref/text.texi (JSONRPC Overview)
(Process-based JSONRPC connections)
(JSONRPC JSON object format): Fix wording and markup.  Add
indexing.
parent 2475687d
Pipeline #1265 failed with stage
in 58 minutes and 12 seconds
......@@ -5197,11 +5197,12 @@ the value if contains a valid JSON object; otherwise it signals the
@node JSONRPC
@section JSONRPC communication
@cindex JSON remote procedure call protocol
@cindex JSONRPC
The @code{jsonrpc} library implements the @acronym{JSONRPC}
specification, version 2.0, as it is described in
@uref{http://www.jsonrpc.org/}. As the name suggests, JSONRPC is a
generic @code{Remote Procedure Call} protocol designed around
generic @dfn{Remote Procedure Call} protocol designed around
@acronym{JSON} objects, which you can convert to and from Lisp objects
(@pxref{Parsing JSON}).
......@@ -5220,81 +5221,96 @@ transport agnostic in that the concepts can be used within the same
process, over sockets, over http, or in many various message passing
environments."
@findex jsonrpc-connection
To model this agnosticism, the @code{jsonrpc} library uses objects of
a @code{jsonrpc-connection} class, which represent a connection the
a @code{jsonrpc-connection} class, which represent a connection to a
remote JSON endpoint (for details on Emacs's object system,
@pxref{Top,EIEIO,,eieio,EIEIO}). In modern object-oriented parlance,
this class is ``abstract'', i.e. the actual class of a useful
connection object used is always a subclass of it. Nevertheless, we
can define two distinct API's around the @code{jsonrpc-connection}
class:
this class is ``abstract'', i.e.@: the actual class of a useful
connection object is always a subclass of @code{jsonrpc-connection}.
Nevertheless, we can define two distinct APIs around the
@code{jsonrpc-connection} class:
@cindex JSONRPC application interfaces
@enumerate
@item A user interface for building JSONRPC applications
@findex :request-dispatcher
@findex :notification-dispatcher
@findex jsonrpc-notify
@findex jsonrpc-request
@findex jsonrpc-async-request
In this scenario, the JSONRPC application selects a concrete subclass
of @code{jsonrpc-connection}, and proceeds to create objects of that
subclass using @code{make-instance}. To initiate a contact to the
remote endpoint, the JSONRPC application passes this object to the
functions @code{jsonrpc-notify'}, @code{jsonrpc-request} and
functions @code{jsonrpc-notify}, @code{jsonrpc-request}, and/or
@code{jsonrpc-async-request}. For handling remotely initiated
contacts, which generally come in asynchronously, the instantiation
should include @code{:request-dispatcher} and
@code{:notification-dispatcher} initargs, which are both functions of
3 arguments: the connection object; a symbol naming the JSONRPC method
invoked remotely; and a JSONRPC "params" object.
invoked remotely; and a JSONRPC @code{params} object.
@findex jsonrpc-error
The function passed as @code{:request-dispatcher} is responsible for
handling the remote endpoint's requests, which expect a reply from the
local endpoint (in this case, the program you're building). Inside
that function, you may either return locally (normally) or non-locally
(error). A local return value must be a Lisp object serializable as
JSON (@pxref{Parsing JSON}). This determines a success response, and
the object is forwarded to the server as the JSONRPC "result" object.
A non-local return, achieved by calling the function
@code{jsonrpc-error}, causes an error response to be sent to the
server. The details of the accompanying JSONRPC "error" are filled
out with whatever was passed to @code{jsonrpc-error}. A non-local
return triggered by an unexpected error of any other type also causes
an error response to be sent (unless you have set
@code{debug-on-error}, in which case this should land you in the
debugger, @pxref{Error Debugging}).
that function, you may either return locally (a normal return) or
non-locally (an error return). A local return value must be a Lisp
object that can be serialized as JSON (@pxref{Parsing JSON}). This
determines a success response, and the object is forwarded to the
server as the JSONRPC @code{result} object. A non-local return,
achieved by calling the function @code{jsonrpc-error}, causes an error
response to be sent to the server. The details of the accompanying
JSONRPC @code{error} are filled out with whatever was passed to
@code{jsonrpc-error}. A non-local return triggered by an unexpected
error of any other type also causes an error response to be sent
(unless you have set @code{debug-on-error}, in which case this calls
the Lisp debugger, @pxref{Error Debugging}).
@item A inheritance interface for building JSONRPC transport implementations
In this scenario, @code{jsonrpc-connection} is subclassed to implement
a different underlying transport strategy (for details on how to
subclass, @pxref{Inheritance,Inheritance,,eieio}). Users of the
subclass, see @ref{Inheritance,Inheritance,,eieio}.). Users of the
application-building interface can then instantiate objects of this
concrete class (using the @code{make-instance} function) and connect
to JSONRPC endpoints using that strategy.
This API has mandatory and optional parts.
@findex jsonrpc-connection-send
To allow its users to initiate JSONRPC contacts (notifications or
requests) or reply to endpoint requests, the method
@code{jsonrpc-connection-send} must be implemented for the subclass.
requests) or reply to endpoint requests, the subclass must have an
implementation of the @code{jsonrpc-connection-send} method.
@findex jsonrpc-connection-receive
Likewise, for handling the three types of remote contacts (requests,
notifications and responses to local requests) the transport
notifications, and responses to local requests), the transport
implementation must arrange for the function
@code{jsonrpc-connection-receive} to be called after noticing a new
JSONRPC message on the wire (whatever that "wire" may be).
@findex jsonrpc-shutdown
@findex jsonrpc-running-p
Finally, and optionally, the @code{jsonrpc-connection} subclass should
implement @code{jsonrpc-shutdown} and @code{jsonrpc-running-p} if
these concepts apply to the transport. If they do, then any system
resources (e.g. processes, timers, etc..) used listen for messages on
the wire should be released in @code{jsonrpc-shutdown}, i.e. they
should only be needed while @code{jsonrpc-running-p} is non-nil.
implement the @code{jsonrpc-shutdown} and @code{jsonrpc-running-p}
methods if these concepts apply to the transport. If they do, then
any system resources (e.g.@: processes, timers, etc.) used to listen for
messages on the wire should be released in @code{jsonrpc-shutdown},
i.e.@: they should only be needed while @code{jsonrpc-running-p} is
non-nil.
@end enumerate
@node Process-based JSONRPC connections
@subsection Process-based JSONRPC connections
@cindex JSONRPC process-based connections
For convenience, the @code{jsonrpc} library comes built-in with a
@findex jsonrpc-process-connection
For convenience, the @code{jsonrpc} library comes with a built-in
@code{jsonrpc-process-connection} transport implementation that can
talk to local subprocesses (using the standard input and standard
output); or TCP hosts (using sockets); or any other remote endpoint
......@@ -5309,6 +5325,7 @@ JSONRPC, see the
@uref{https://microsoft.github.io/language-server-protocol/specification,
Language Server Protocol}.
@cindex JSONRPC connection initargs
Along with the mandatory @code{:request-dispatcher} and
@code{:notification-dispatcher} initargs, users of the
@code{jsonrpc-process-connection} class should pass the following
......@@ -5317,29 +5334,32 @@ initargs as keyword-value pairs to @code{make-instance}:
@table @code
@item :process
Value must be a live process object or a function of no arguments
producing one such object. If passed a process object, that is
expected to contain an pre-established connection; otherwise, the
producing one such object. If passed a process object, the object is
expected to contain a pre-established connection; otherwise, the
function is called immediately after the object is made.
@item :on-shutdown
Value must be a function of a single argument, the
@code{jsonrpc-process-connection} object. The function is called
after the underlying process object has been deleted (either
deliberately by @code{jsonrpc-shutdown} or unexpectedly, because of
deliberately by @code{jsonrpc-shutdown}, or unexpectedly, because of
some external cause).
@end table
@node JSONRPC JSON object format
@subsection JSON object format
@subsection JSONRPC JSON object format
@cindex JSONRPC object format
JSON objects are exchanged as Lisp plists (@pxref{Parsing JSON}):
JSON-compatible plists are handed to the dispatcher functions and,
likewise, JSON-compatible plists should be given to
@code{jsonrpc-notify}, @code{jsonrpc-request} and
JSONRPC JSON objects are exchanged as Lisp plists (@pxref{Property
Lists}): JSON-compatible plists are handed to the dispatcher functions
and, likewise, JSON-compatible plists should be given to
@code{jsonrpc-notify}, @code{jsonrpc-request}, and
@code{jsonrpc-async-request}.
To facilitate handling plists, this library make liberal use of
@code{cl-lib} library and suggests (but doesn't force) its clients to
@findex jsonrpc-lambda
To facilitate handling plists, this library makes liberal use of
@code{cl-lib} library (@pxref{Top,cl-lib,,cl,Common Lisp Extensions
for GNU Emacs Lisp}) and suggests (but doesn't force) its clients to
do the same. A macro @code{jsonrpc-lambda} can be used to create a
lambda for destructuring a JSON-object like in this example:
......@@ -5355,7 +5375,8 @@ lambda for destructuring a JSON-object like in this example:
@end example
@node JSONRPC deferred requests
@subsection Deferred requests
@subsection Deferred JSONRPC requests
@cindex JSONRPC deferred requests
In many @acronym{RPC} situations, synchronization between the two
communicating endpoints is a matter of correctly designing the RPC
......@@ -5367,6 +5388,7 @@ is still uncertainty about the state of the remote endpoint.
Furthermore, acting on these events may only sometimes demand
synchronization, depending on the event's specific nature.
@findex :deferred@r{, JSONRPC keyword}
The @code{:deferred} keyword argument to @code{jsonrpc-request} and
@code{jsonrpc-async-request} is designed to let the caller indicate
that the specific request needs synchronization and its actual
......@@ -5377,9 +5399,10 @@ isn't sent immediately, @code{jsonrpc} will make renewed efforts to
send it at certain key times during communication, such as when
receiving or sending other messages to the endpoint.
@findex jsonrpc-connection-ready-p
Before any attempt to send the request, the application-specific
conditions are checked. Since the @code{jsonrpc} library can't known
what these conditions are, the programmer may use the
conditions are checked. Since the @code{jsonrpc} library can't know
what these conditions are, the program can use the
@code{jsonrpc-connection-ready-p} generic function (@pxref{Generic
Functions}) to specify them. The default method for this function
returns @code{t}, but you can add overriding methods that return
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment