33.32.1 概述

引自 规范,JSONRPC“与传输层无关, 相关概念可在同一进程内、套接字、HTTP 或多种消息传递环境中使用”。

为体现这种传输无关性,jsonrpc 库使用 jsonrpc-connection 类的对象, 表示与远程 JSON 端点的连接(有关 Emacs 对象系统的详情, see EIEIO in EIEIO)。 在现代面向对象术语中,该类是“抽象类”,即:一个可用的连接对象, 其实际类始终是 jsonrpc-connection 的子类。 尽管如此,我们仍可以围绕 jsonrpc-connection 类定义两套独立的 API:

  1. 用于构建 JSONRPC 应用的 API

    在这种场景下,一个基于 JSONRPC 的新应用会选择 jsonrpc-connection 的一个具体子类, 该子类为端点间交换的 JSONRPC 消息提供传输层支持。

    应用通过 make-instance 创建该子类的对象。 为发起与远程端点的通信,应用会将该对象传入 jsonrpc-notifyjsonrpc-requestjsonrpc-async-request 等函数。

    为处理通常异步到达的、由远程发起的通信, make-instance 初始化时应设置 :request-dispatcher:notification-dispatcher 这两个 EIEIO 关键字参数。二者均为接收三个参数的函数: 连接对象、远程调用的 JSONRPC 方法名符号、以及 JSONRPC params 对象。

    作为 :request-dispatcher 传入的函数, 负责处理远程端点的请求——这类请求期望本地端点(即你正在构建的应用)给出回复。 在该函数内部,你可以正常返回(普通返回)或非本地返回(抛出错误)。 两种退出方式都会通过传输层向远程端点的请求发送回复。

    普通返回表示成功响应,返回值必须是可序列化为 JSON 的 Lisp 对象(see 解析和生成 JSON 值)。 该结果会作为 JSONRPC result 对象发送给服务端。 通过调用 jsonrpc-error 实现的非本地返回, 会向服务端发送错误响应。附带的 JSONRPC error 对象的详细信息, 由传入 jsonrpc-error 的参数填充。 由其他类型意外错误触发的非本地返回,同样会发送错误响应 (除非你已设置 debug-on-error,此时会调用 Lisp 调试器,see 发生错误时进入调试器)。

    可以使用 jsonrpc 库构建基于“类 JSONRPC”传输协议的应用。 这类协议与 JSONRPC 相似但不完全相同,例如 DAP(调试适配器协议)。 这类协议同样定义请求、响应与通知消息,但格式与 JSONRPC 略有差异。 泛化函数 jsonrpc-convert-to-endpointjsonrpc-convert-from-endpoint 可用于定制 JSONRPC 内部表示与端点所接受格式之间的转换(see 泛型函数)。

  2. 用于构建 JSONRPC 传输层的 API

    在这种场景下,jsonrpc-connection 被继承以实现不同的底层传输策略 (有关子类化的详情,参见 Inheritance)。 应用构建接口的使用者可实例化该具体类(通过 make-instance 函数), 并使用该策略连接到 JSONRPC 端点。 内置的传输层实现可参见 基于进程的 JSONRPC 连接

    该 API 包含必选与可选部分。

    为允许使用者发起 JSONRPC 通信(通知或请求)或回复端点请求, 新的传输层实现必须为新子类提供 jsonrpc-connection-send 泛化函数的特化版本(see 泛型函数)。 该泛化函数会由 jsonrpc-requestjsonrpc-notify 等原语自动调用。 该特化版本应确保参数列表中描述的消息,通过新传输层用于与端点通信的底层通信机制(即 “线路(wire)”)发送。 该 “线路(wire)” 可以是网络套接字、串行接口、HTTP 连接等。

    同样,为处理三类远程通信(请求、通知、对本地请求的响应), 传输层实现应在 “线路(wire)” 上检测到可构造 JSONRPC(或类 JSONRPC)消息的数据后, 从 Elisp 中调用 jsonrpc-connection-receive 函数。

    最后(可选),如果相关概念适用于该传输层, jsonrpc-connection 子类应对 jsonrpc-shutdownjsonrpc-running-p 泛化函数添加特化实现。 jsonrpc-shutdown 的特化版本应确保释放用于在线路上监听消息的系统资源 (例如进程、定时器等)。 jsonrpc-running-p 的特化版本应判断这些资源是否仍处于活跃状态, 或已(通过 jsonrpc-shutdown 或其他方式)释放。