aboutsummaryrefslogtreecommitdiffstats
path: root/doc/lispref
diff options
context:
space:
mode:
authorJoão Távora2018-06-30 19:06:43 +0100
committerJoão Távora2018-06-30 19:46:06 +0100
commit8af26410a91c3c9679bb0281ddd71f0dd77ec97c (patch)
tree05d2780906fb17ccaaacf953393c15365c7abe05 /doc/lispref
parent852395bab71cb7032692f3c95e1e4b81a884b66b (diff)
downloademacs-8af26410a91c3c9679bb0281ddd71f0dd77ec97c.tar.gz
emacs-8af26410a91c3c9679bb0281ddd71f0dd77ec97c.zip
Add lisp/jsonrpc.el
* doc/lispref/text.texi (Text): Add JSONRPC. (JSONRPC): New node. * etc/NEWS (New Modes and Packages in Emacs 27.1): Mention jsonrpc.el * lisp/jsonrpc.el: New file. * test/lisp/jsonrpc-tests.el: New file.
Diffstat (limited to 'doc/lispref')
-rw-r--r--doc/lispref/text.texi187
1 files changed, 187 insertions, 0 deletions
diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi
index 94cd87acf71..5e8601083e5 100644
--- a/doc/lispref/text.texi
+++ b/doc/lispref/text.texi
@@ -62,6 +62,7 @@ the character after point.
62* GnuTLS Cryptography:: Cryptographic algorithms imported from GnuTLS. 62* GnuTLS Cryptography:: Cryptographic algorithms imported from GnuTLS.
63* Parsing HTML/XML:: Parsing HTML and XML. 63* Parsing HTML/XML:: Parsing HTML and XML.
64* Parsing JSON:: Parsing and generating JSON values. 64* Parsing JSON:: Parsing and generating JSON values.
65* JSONRPC:: JSON Remote Procedure Call protocol
65* Atomic Changes:: Installing several buffer changes atomically. 66* Atomic Changes:: Installing several buffer changes atomically.
66* Change Hooks:: Supplying functions to be run when text is changed. 67* Change Hooks:: Supplying functions to be run when text is changed.
67@end menu 68@end menu
@@ -5132,6 +5133,192 @@ doesn't move point. The arguments @var{args} are interpreted as in
5132@code{json-parse-string}. 5133@code{json-parse-string}.
5133@end defun 5134@end defun
5134 5135
5136@node JSONRPC
5137@section JSONRPC communication
5138@cindex JSON remote procedure call protocol
5139
5140The @code{jsonrpc} library implements the @acronym{JSONRPC}
5141specification, version 2.0, as it is described in
5142@uref{http://www.jsonrpc.org/}. As the name suggests, JSONRPC is a
5143generic @code{Remote Procedure Call} protocol designed around
5144@acronym{JSON} objects, which you can convert to and from Lisp objects
5145(@pxref{Parsing JSON}).
5146
5147@node JSONRPC Overview
5148@subsection Overview
5149
5150Quoting from the @uref{http://www.jsonrpc.org/, spec}, JSONRPC "is
5151transport agnostic in that the concepts can be used within the same
5152process, over sockets, over http, or in many various message passing
5153environments."
5154
5155To model this agnosticism, the @code{jsonrpc} library uses objects of
5156a @code{jsonrpc-connection} class, which represent a connection the
5157remote JSON endpoint (for details on Emacs's object system,
5158@pxref{Top,EIEIO,,eieio,EIEIO}). In modern object-oriented parlance,
5159this class is ``abstract'', i.e. the actual class of a useful
5160connection object used is always a subclass of it. Nevertheless, we
5161can define two distinct API's around the @code{jsonrpc-connection}
5162class:
5163
5164@enumerate
5165
5166@item A user interface for building JSONRPC applications
5167
5168In this scenario, the JSONRPC application instantiates
5169@code{jsonrpc-connection} objects of one of its concrete subclasses
5170using @code{make-instance}. To initiate a contact to the remote
5171endpoint, the JSONRPC application passes this object to the functions
5172@code{jsonrpc-notify'}, @code{jsonrpc-request} and
5173@code{jsonrpc-async-request}. For handling remotely initiated
5174contacts, which generally come in asynchronously, the instantiation
5175should include @code{:request-dispatcher} and
5176@code{:notification-dispatcher} initargs, which are both functions of
51773 arguments: the connection object; a symbol naming the JSONRPC method
5178invoked remotely; and a JSONRPC "params" object.
5179
5180The function passed as @code{:request-dispatcher} is responsible for
5181handling the remote endpoint's requests, which expect a reply from the
5182local endpoint (in this case, the program you're building). Inside
5183that function, you may either return locally (normally) or non-locally
5184(error). A local return value must be a Lisp object serializable as
5185JSON (@pxref{Parsing JSON}). This determines a success response, and
5186the object is forwarded to the server as the JSONRPC "result" object.
5187A non-local return, achieved by calling the function
5188@code{jsonrpc-error}, causes an error response to be sent to the
5189server. The details of the accompanying JSONRPC "error" are filled
5190out with whatever was passed to @code{jsonrpc-error}. A non-local
5191return triggered by an unexpected error of any other type also causes
5192an error response to be sent (unless you have set
5193@code{debug-on-error}, in which case this should land you in the
5194debugger, @pxref{Error Debugging}).
5195
5196@item A inheritance interface for building JSONRPC transport implementations
5197
5198In this scenario, @code{jsonrpc-connection} is subclassed to implement
5199a different underlying transport strategy (for details on how to
5200subclass, @pxref{Inheritance,Inheritance,,eieio}). Users of the
5201application-building interface can then instantiate objects of this
5202concrete class (using the @code{make-instance} function) and connect
5203to JSONRPC endpoints using that strategy.
5204
5205This API has mandatory and optional parts.
5206
5207To allow its users to initiate JSONRPC contacts (notifications or
5208requests) or reply to endpoint requests, the method
5209@code{jsonrpc-connection-send} must be implemented for the subclass.
5210
5211Likewise, for handling the three types of remote contacts (requests,
5212notifications and responses to local requests) the transport
5213implementation must arrange for the function
5214@code{jsonrpc-connection-receive} to be called after noticing a new
5215JSONRPC message on the wire (whatever that "wire" may be).
5216
5217Finally, and optionally, the @code{jsonrpc-connection} subclass should
5218implement @code{jsonrpc-shutdown} and @code{jsonrpc-running-p} if
5219these concepts apply to the transport. If they do, then any system
5220resources (e.g. processes, timers, etc..) used listen for messages on
5221the wire should be released in @code{jsonrpc-shutdown}, i.e. they
5222should only be needed while @code{jsonrpc-running-p} is non-nil.
5223
5224@end enumerate
5225
5226@node Process-based JSONRPC connections
5227@subsection Process-based JSONRPC connections
5228
5229For convenience, the @code{jsonrpc} library comes built-in with a
5230@code{jsonrpc-process-connection} transport implementation that can
5231talk to local subprocesses (using the standard input and standard
5232output); or TCP hosts (using sockets); or any other remote endpoint
5233that Emacs's process object can represent (@pxref{Processes}).
5234
5235Using this transport, the JSONRPC messages are encoded on the wire as
5236plain text and prefaced by some basic HTTP-style enveloping headers,
5237such as ``Content-Length''.
5238
5239For an example of an application using this transport scheme on top of
5240JSONRPC, see the
5241@uref{https://microsoft.github.io/language-server-protocol/specification,
5242Language Server Protocol}.
5243
5244Along with the mandatory @code{:request-dispatcher} and
5245@code{:notification-dispatcher} initargs, users of the
5246@code{jsonrpc-process-connection} class should pass the following
5247initargs as keyword-value pairs to @code{make-instance}:
5248
5249@table @code
5250@item :process
5251Value must be a live process object or a function of no arguments
5252producing one such object. If passed a process object, that is
5253expected to contain an pre-established connection; otherwise, the
5254function is called immediately after the object is made.
5255
5256@item :on-shutdown
5257Value must be a function of a single argument, the
5258@code{jsonrpc-process-connection} object. The function is called
5259after the underlying process object has been deleted (either
5260deliberately by @code{jsonrpc-shutdown} or unexpectedly, because of
5261some external cause).
5262@end table
5263
5264@node JSONRPC JSON object format
5265@subsection JSON object format
5266
5267JSON objects are exchanged as Lisp plists (@pxref{Parsing JSON}):
5268JSON-compatible plists are handed to the dispatcher functions and,
5269likewise, JSON-compatible plists should be given to
5270@code{jsonrpc-notify}, @code{jsonrpc-request} and
5271@code{jsonrpc-async-request}.
5272
5273To facilitate handling plists, this library make liberal use of
5274@code{cl-lib} library and suggests (but doesn't force) its clients to
5275do the same. A macro @code{jsonrpc-lambda} can be used to create a
5276lambda for destructuring a JSON-object like in this example:
5277
5278@example
5279(jsonrpc-async-request
5280 myproc :frobnicate `(:foo "trix")
5281 :success-fn (jsonrpc-lambda (&key bar baz &allow-other-keys)
5282 (message "Server replied back with %s and %s!"
5283 bar baz))
5284 :error-fn (jsonrpc-lambda (&key code message _data)
5285 (message "Sadly, server reports %s: %s"
5286 code message)))
5287@end example
5288
5289@node JSONRPC deferred requests
5290@subsection Deferred requests
5291
5292In many @acronym{RPC} situations, synchronization between the two
5293communicating endpoints is a matter of correctly designing the RPC
5294application: when synchronization is needed, requests (which are
5295blocking) should be used; when it isn't, notifications should suffice.
5296However, when Emacs acts as one of these endpoints, asynchronous
5297events (e.g. timer- or process-related) may be triggered while there
5298is still uncertainty about the state of the remote endpoint.
5299Furthermore, acting on these events may only sometimes demand
5300synchronization, depending on the event's specific nature.
5301
5302The @code{:deferred} keyword argument to @code{jsonrpc-request} and
5303@code{jsonrpc-async-request} is designed to let the caller indicate
5304that the specific request needs synchronization and its actual
5305issuance may be delayed to the future, until some condition is
5306satisfied. Specifying @code{:deferred} for a request doesn't mean it
5307@emph{will} be delayed, only that it @emph{can} be. If the request
5308isn't sent immediately, @code{jsonrpc} will make renewed efforts to
5309send it at certain key times during communication, such as when
5310receiving or sending other messages to the endpoint.
5311
5312Before any attempt to send the request, the application-specific
5313conditions are checked. Since the @code{jsonrpc} library can't known
5314what these conditions are, the programmer may use the
5315@code{jsonrpc-connection-ready-p} generic function (@pxref{Generic
5316Functions}) to specify them. The default method for this function
5317returns @code{t}, but you can add overriding methods that return
5318@code{nil} in some situations, based on the arguments passed to it,
5319which are the @code{jsonrpc-connection} object (@pxref{JSONRPC
5320Overview}) and whichever value you passed as the @code{:deferred}
5321keyword argument.
5135 5322
5136@node Atomic Changes 5323@node Atomic Changes
5137@section Atomic Change Groups 5324@section Atomic Change Groups