33.32.1 Обзор

Цитируя спецификацию, JSONRPC «не зависит от транспорта, поскольку эти концепции могут использоваться в одном и том же процессе, по сокетам, по http или в различных средах обмена сообщениями».

Чтобы смоделировать эту независимость от транспорта, библиотека jsonrpc использует объекты класса jsonrpc-connection, которые представляют соединение с удаленной конечной точкой JSON (подробности о системе объектов Emacs см. в EIEIO в EIEIO). В современной объектно-ориентированной терминологии этот класс «абстрактен», то есть фактический класс полезного объекта соединения всегда является подклассом jsonrpc-connection. Тем не менее, мы можем определить два отдельных API вокруг класса jsonrpc-connection:

  1. API для создания приложений JSONRPC

    В этом сценарии новое приложение, основанное на JSONRPC, выбирает конкретный подкласс jsonrpc-connection, который предоставляет транспорт для обмена сообщениями JSONRPC между конечными точками.

    Приложение создает объекты этого подкласса с помощью make-instance. Чтобы инициировать контакт с удаленной конечной точкой, приложение передает этот объект в такие функции, как jsonrpc-notify, jsonrpc-request или jsonrpc-async-request.

    Для обработки контактов, инициированных удаленно, которые обычно поступают асинхронно, инстанцирование с помощью make-instance должно инициализировать ключевые аргументы EIEIO :request-dispatcher и :notification-dispatcher. Оба они являются функциями с 3 аргументами: объект соединения; символ, называющий вызываемый удаленно метод JSONRPC; и объект params JSONRPC.

    Функция, переданная как :request-dispatcher, отвечает за обработку запросов удаленной конечной точки, которые ожидают ответа от локальной конечной точки (в данном случае, от создаваемого вами приложения). Внутри этой функции вы можете либо вернуть локально (обычный возврат), либо нелокально (выбросить ошибку). Оба выхода из диспетчера запросов приводят к отправке ответа на запрос удаленной конечной точки через транспорт.

    Обычный возврат определяет ответ об успехе, и возвращаемое значение должно быть объектом Lisp, который может быть сериализован в JSON (см. Парсинг и генерация значений JSON). Результат пересылается на сервер как объект result JSONRPC. Нелокальный возврат, достигаемый вызовом функции jsonrpc-error, вызывает отправку ответа об ошибке на сервер. Детали сопровождающего объекта error JSONRPC заполняются тем, что было передано в jsonrpc-error. Нелокальный возврат, вызванный неожиданной ошибкой любого другого типа, также вызывает отправку ответа об ошибке (если вы не установили debug-on-error, в этом случае вызывается отладчик Lisp, см. Вход в отладчик при ошибке).

    Возможно использовать библиотеку jsonrpc для создания приложений на основе протоколов транспорта, которые можно описать как «квази-JSONRPC». Они похожи, но не совсем идентичны JSONRPC, например, DAP (Debug Adapter Protocol). Эти протоколы также определяют сообщения запроса, ответа и уведомления, но формат не совсем такой же, как в JSONRPC. Универсальные функции jsonrpc-convert-to-endpoint и jsonrpc-convert-from-endpoint могут быть настроены для преобразования между внутренней репрезентацией JSONRPC и тем, что принимает конечная точка (см. Универсальные функции).

  2. API для создания транспортных механизмов JSONRPC

    В этом сценарии jsonrpc-connection подклассируется для реализации другой базовой стратегии транспорта (подробности о том, как подклассировать, см. (eieio)Inheritance). Пользователи интерфейса создания приложений могут затем инстанцировать объекты этого конкретного класса (используя функцию make-instance) и подключаться к конечным точкам JSONRPC, используя эту стратегию. См. Соединения JSONRPC на основе процессов для встроенной реализации транспорта.

    Этот API имеет обязательные и необязательные части.

    Чтобы позволить его пользователям инициировать контакты JSONRPC (уведомления или запросы) или отвечать на запросы конечной точки, новая реализация транспорта должна снабдить универсальную функцию jsonrpc-connection-send специализацией для нового подкласса (см. Универсальные функции). Эта универсальная функция вызывается автоматически примитивами, такими как jsonrpc-request и jsonrpc-notify. Специализация должна гарантировать, что сообщение, описанное в списке аргументов, отправляется через любой базовый коммуникационный механизм (также называемый «провод»), который использует новый транспорт для связи с конечными точками. Этот «провод» может быть сетевым сокетом, последовательным интерфейсом, HTTP-соединением и т. д.

    Точно так же, для обработки трех типов удаленных контактов (запросы, уведомления и ответы на локальные запросы) реализация транспорта должна обеспечить вызов функции jsonrpc-connection-receive из Elisp после обнаружения данных на «проводе», которые могут быть использованы для создания сообщения JSONRPC (или квази-JSONRPC).

    Наконец, и опционально, подкласс jsonrpc-connection должен добавить специализации к универсальным функциям jsonrpc-shutdown и jsonrpc-running-p, если эти концепции применимы к транспорту. Специализация jsonrpc-shutdown должна обеспечить освобождение любых системных ресурсов (например, процессов, таймеров и т. д.), используемых для прослушивания сообщений на «проводе». Специализация jsonrpc-running-p должна указывать, активны ли эти ресурсы или они уже были освобождены (через jsonrpc-shutdown или иным образом).