diff options
| author | João Távora | 2018-06-30 19:06:43 +0100 |
|---|---|---|
| committer | João Távora | 2018-06-30 19:46:06 +0100 |
| commit | 8af26410a91c3c9679bb0281ddd71f0dd77ec97c (patch) | |
| tree | 05d2780906fb17ccaaacf953393c15365c7abe05 /doc/lispref | |
| parent | 852395bab71cb7032692f3c95e1e4b81a884b66b (diff) | |
| download | emacs-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.texi | 187 |
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 | |||
| 5140 | The @code{jsonrpc} library implements the @acronym{JSONRPC} | ||
| 5141 | specification, version 2.0, as it is described in | ||
| 5142 | @uref{http://www.jsonrpc.org/}. As the name suggests, JSONRPC is a | ||
| 5143 | generic @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 | |||
| 5150 | Quoting from the @uref{http://www.jsonrpc.org/, spec}, JSONRPC "is | ||
| 5151 | transport agnostic in that the concepts can be used within the same | ||
| 5152 | process, over sockets, over http, or in many various message passing | ||
| 5153 | environments." | ||
| 5154 | |||
| 5155 | To model this agnosticism, the @code{jsonrpc} library uses objects of | ||
| 5156 | a @code{jsonrpc-connection} class, which represent a connection the | ||
| 5157 | remote JSON endpoint (for details on Emacs's object system, | ||
| 5158 | @pxref{Top,EIEIO,,eieio,EIEIO}). In modern object-oriented parlance, | ||
| 5159 | this class is ``abstract'', i.e. the actual class of a useful | ||
| 5160 | connection object used is always a subclass of it. Nevertheless, we | ||
| 5161 | can define two distinct API's around the @code{jsonrpc-connection} | ||
| 5162 | class: | ||
| 5163 | |||
| 5164 | @enumerate | ||
| 5165 | |||
| 5166 | @item A user interface for building JSONRPC applications | ||
| 5167 | |||
| 5168 | In this scenario, the JSONRPC application instantiates | ||
| 5169 | @code{jsonrpc-connection} objects of one of its concrete subclasses | ||
| 5170 | using @code{make-instance}. To initiate a contact to the remote | ||
| 5171 | endpoint, 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 | ||
| 5174 | contacts, which generally come in asynchronously, the instantiation | ||
| 5175 | should include @code{:request-dispatcher} and | ||
| 5176 | @code{:notification-dispatcher} initargs, which are both functions of | ||
| 5177 | 3 arguments: the connection object; a symbol naming the JSONRPC method | ||
| 5178 | invoked remotely; and a JSONRPC "params" object. | ||
| 5179 | |||
| 5180 | The function passed as @code{:request-dispatcher} is responsible for | ||
| 5181 | handling the remote endpoint's requests, which expect a reply from the | ||
| 5182 | local endpoint (in this case, the program you're building). Inside | ||
| 5183 | that function, you may either return locally (normally) or non-locally | ||
| 5184 | (error). A local return value must be a Lisp object serializable as | ||
| 5185 | JSON (@pxref{Parsing JSON}). This determines a success response, and | ||
| 5186 | the object is forwarded to the server as the JSONRPC "result" object. | ||
| 5187 | A non-local return, achieved by calling the function | ||
| 5188 | @code{jsonrpc-error}, causes an error response to be sent to the | ||
| 5189 | server. The details of the accompanying JSONRPC "error" are filled | ||
| 5190 | out with whatever was passed to @code{jsonrpc-error}. A non-local | ||
| 5191 | return triggered by an unexpected error of any other type also causes | ||
| 5192 | an error response to be sent (unless you have set | ||
| 5193 | @code{debug-on-error}, in which case this should land you in the | ||
| 5194 | debugger, @pxref{Error Debugging}). | ||
| 5195 | |||
| 5196 | @item A inheritance interface for building JSONRPC transport implementations | ||
| 5197 | |||
| 5198 | In this scenario, @code{jsonrpc-connection} is subclassed to implement | ||
| 5199 | a different underlying transport strategy (for details on how to | ||
| 5200 | subclass, @pxref{Inheritance,Inheritance,,eieio}). Users of the | ||
| 5201 | application-building interface can then instantiate objects of this | ||
| 5202 | concrete class (using the @code{make-instance} function) and connect | ||
| 5203 | to JSONRPC endpoints using that strategy. | ||
| 5204 | |||
| 5205 | This API has mandatory and optional parts. | ||
| 5206 | |||
| 5207 | To allow its users to initiate JSONRPC contacts (notifications or | ||
| 5208 | requests) or reply to endpoint requests, the method | ||
| 5209 | @code{jsonrpc-connection-send} must be implemented for the subclass. | ||
| 5210 | |||
| 5211 | Likewise, for handling the three types of remote contacts (requests, | ||
| 5212 | notifications and responses to local requests) the transport | ||
| 5213 | implementation must arrange for the function | ||
| 5214 | @code{jsonrpc-connection-receive} to be called after noticing a new | ||
| 5215 | JSONRPC message on the wire (whatever that "wire" may be). | ||
| 5216 | |||
| 5217 | Finally, and optionally, the @code{jsonrpc-connection} subclass should | ||
| 5218 | implement @code{jsonrpc-shutdown} and @code{jsonrpc-running-p} if | ||
| 5219 | these concepts apply to the transport. If they do, then any system | ||
| 5220 | resources (e.g. processes, timers, etc..) used listen for messages on | ||
| 5221 | the wire should be released in @code{jsonrpc-shutdown}, i.e. they | ||
| 5222 | should 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 | |||
| 5229 | For convenience, the @code{jsonrpc} library comes built-in with a | ||
| 5230 | @code{jsonrpc-process-connection} transport implementation that can | ||
| 5231 | talk to local subprocesses (using the standard input and standard | ||
| 5232 | output); or TCP hosts (using sockets); or any other remote endpoint | ||
| 5233 | that Emacs's process object can represent (@pxref{Processes}). | ||
| 5234 | |||
| 5235 | Using this transport, the JSONRPC messages are encoded on the wire as | ||
| 5236 | plain text and prefaced by some basic HTTP-style enveloping headers, | ||
| 5237 | such as ``Content-Length''. | ||
| 5238 | |||
| 5239 | For an example of an application using this transport scheme on top of | ||
| 5240 | JSONRPC, see the | ||
| 5241 | @uref{https://microsoft.github.io/language-server-protocol/specification, | ||
| 5242 | Language Server Protocol}. | ||
| 5243 | |||
| 5244 | Along 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 | ||
| 5247 | initargs as keyword-value pairs to @code{make-instance}: | ||
| 5248 | |||
| 5249 | @table @code | ||
| 5250 | @item :process | ||
| 5251 | Value must be a live process object or a function of no arguments | ||
| 5252 | producing one such object. If passed a process object, that is | ||
| 5253 | expected to contain an pre-established connection; otherwise, the | ||
| 5254 | function is called immediately after the object is made. | ||
| 5255 | |||
| 5256 | @item :on-shutdown | ||
| 5257 | Value must be a function of a single argument, the | ||
| 5258 | @code{jsonrpc-process-connection} object. The function is called | ||
| 5259 | after the underlying process object has been deleted (either | ||
| 5260 | deliberately by @code{jsonrpc-shutdown} or unexpectedly, because of | ||
| 5261 | some external cause). | ||
| 5262 | @end table | ||
| 5263 | |||
| 5264 | @node JSONRPC JSON object format | ||
| 5265 | @subsection JSON object format | ||
| 5266 | |||
| 5267 | JSON objects are exchanged as Lisp plists (@pxref{Parsing JSON}): | ||
| 5268 | JSON-compatible plists are handed to the dispatcher functions and, | ||
| 5269 | likewise, JSON-compatible plists should be given to | ||
| 5270 | @code{jsonrpc-notify}, @code{jsonrpc-request} and | ||
| 5271 | @code{jsonrpc-async-request}. | ||
| 5272 | |||
| 5273 | To facilitate handling plists, this library make liberal use of | ||
| 5274 | @code{cl-lib} library and suggests (but doesn't force) its clients to | ||
| 5275 | do the same. A macro @code{jsonrpc-lambda} can be used to create a | ||
| 5276 | lambda 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 | |||
| 5292 | In many @acronym{RPC} situations, synchronization between the two | ||
| 5293 | communicating endpoints is a matter of correctly designing the RPC | ||
| 5294 | application: when synchronization is needed, requests (which are | ||
| 5295 | blocking) should be used; when it isn't, notifications should suffice. | ||
| 5296 | However, when Emacs acts as one of these endpoints, asynchronous | ||
| 5297 | events (e.g. timer- or process-related) may be triggered while there | ||
| 5298 | is still uncertainty about the state of the remote endpoint. | ||
| 5299 | Furthermore, acting on these events may only sometimes demand | ||
| 5300 | synchronization, depending on the event's specific nature. | ||
| 5301 | |||
| 5302 | The @code{:deferred} keyword argument to @code{jsonrpc-request} and | ||
| 5303 | @code{jsonrpc-async-request} is designed to let the caller indicate | ||
| 5304 | that the specific request needs synchronization and its actual | ||
| 5305 | issuance may be delayed to the future, until some condition is | ||
| 5306 | satisfied. Specifying @code{:deferred} for a request doesn't mean it | ||
| 5307 | @emph{will} be delayed, only that it @emph{can} be. If the request | ||
| 5308 | isn't sent immediately, @code{jsonrpc} will make renewed efforts to | ||
| 5309 | send it at certain key times during communication, such as when | ||
| 5310 | receiving or sending other messages to the endpoint. | ||
| 5311 | |||
| 5312 | Before any attempt to send the request, the application-specific | ||
| 5313 | conditions are checked. Since the @code{jsonrpc} library can't known | ||
| 5314 | what these conditions are, the programmer may use the | ||
| 5315 | @code{jsonrpc-connection-ready-p} generic function (@pxref{Generic | ||
| 5316 | Functions}) to specify them. The default method for this function | ||
| 5317 | returns @code{t}, but you can add overriding methods that return | ||
| 5318 | @code{nil} in some situations, based on the arguments passed to it, | ||
| 5319 | which are the @code{jsonrpc-connection} object (@pxref{JSONRPC | ||
| 5320 | Overview}) and whichever value you passed as the @code{:deferred} | ||
| 5321 | keyword argument. | ||
| 5135 | 5322 | ||
| 5136 | @node Atomic Changes | 5323 | @node Atomic Changes |
| 5137 | @section Atomic Change Groups | 5324 | @section Atomic Change Groups |