Перейти к содержимому
ColliePWA

10/Documentation

Протокол durable (экспериментально)

Что передаётся между Collie и durable agent, руководство для разработчика: маршруты, hello и эпоха, жизненный цикл запроса и идентификаторы запросов, сокетный и токенный транспорты, лимиты и правила версионирования, со ссылкой на WIRE.md для точных правил

Экспериментальная. Сетевой протокол может измениться или функция может быть удалена в последующем минорном релизе. В Версии и информативное приветствие описано, как изменения доходят до вас.

Сетевой протокол durable — это способ взаимодействия Collie с durable-агентом. На этой странице он описан для разработчика, который создаёт durable-агента без SDK или хочет знать, что именно делает SDK. Точные правила приведены в WIRE.md, и если эта страница расходится с тем файлом, верным считается WIRE.md. Durable SDK берёт на себя всю работу с протоколом.

Что передаётся по сети

Collie подключается, а durable agent слушает; каждый обмен представляет собой один HTTP-запрос с телом в формате JSON.

Durable agent слушает приватный Unix-сокет или доступен через TLS по URL (Транспорты). Collie опрашивает его: здесь нет push-уведомлений, WebSocket и потоков. Каждый путь начинается с /session/v1 — это фиксированное имя, а не версия. Каждый вызов, кроме первого hello, передаёт версию в заголовке X-Collie-Session. Тело запроса представляет собой один JSON-объект размером не более 64 КиБ, а пустое тело POST читается как {}.

метод и путьдействиелимит ответа
GET /helloИмя durable agent, диапазон версий, эпоха, готовность и возможности16 КиБ
GET /snapshotРазметка: рабочие пространства, вкладки, панели с их состоянием, шаг диалога, открытые запросы и стартеры. Передаёт ETag и возвращает 304, если ничего не изменилось4 МиБ
GET /pane/:id/events?after=N&epoch=EСобытия панели после курсора8 МиБ
POST /pane/:id/answerОтвет на запрос16 КиБ
POST /pane/:id/sendТекст для панели, чтобы направить текущий шаг диалога или дождаться следующего16 КиБ
POST /pane/:id/abortОстановить текущий шаг диалога16 КиБ
POST /pane/:id/actionНажатие на одну из кнопок на панели инструментов16 КиБ
POST /renameНовый заголовок для рабочей области или вкладки16 КиБ
POST /closeЗакрыть панель, вкладку или рабочее пространство16 КиБ
POST /starter/:idЗапустить стартер. В ответе возвращается имя новой панели16 КиБ
GET /conversations?after=C&limit=NДиалоги durable agent, открытые и закрытые, сначала новые1 МиБ
GET /conversation/:id/items?after=C&limit=NЭлементы одного диалога, сначала старые8 МиБ
POST /reopenСнова открыть закрытый диалог16 КиБ

Каждая ошибка представляет собой тело JSON с code, например 409 stale или 404 no-such-pane. Любой другой путь возвращает 404 not-found. Ответ, превышающий лимит, не читается, а результат POST-запроса с оборванным ответом считается неизвестным (Идентификаторы запросов).

Приветствие и эпоха

hello указывает, чем является durable agent, а эпоха указывает, с каким именно его запуском взаимодействует Collie.

поле в helloчто содержит
serviceСтрого collie-durable. Без этого Collie считает durable agent другим сервером и больше ничего не вызывает
protocolДиапазон поддерживаемых durable agent версий протокола, { min, max }. На сегодня { min: 1, max: 1 }
host.nameСобственное имя durable agent, только отображаемый текст, не более 64 байт
epochНовое и случайное значение при каждом запуске durable agent, не менее 128 бит, никогда не используется повторно
readyЗначение false, пока durable agent компонует свои панели после запуска
capsВозможности durable agent, каждая в виде логического значения. Отсутствующая возможность считается false

Collie сначала вызывает hello без заголовка версии, выбирает наибольшую поддерживаемую обеими сторонами версию и передаёт её во всех последующих вызовах. Пока ready равно false, каждый маршрут, кроме hello, возвращает 503 starting, а на телефоне отображается, что durable agent запускается. Durable agent выставляет ready только после того, как все диалоги снова отображены и каждый открытый ask создан повторно, поэтому при перезапуске никогда не отображается незавершённая разметка.

ETag снимка равен "<epoch>-<rev>". Значение rev увеличивается при каждом изменении, видимом для читателя, поэтому ответ 304 почти ничего не стоит для durable agent. Новая эпоха сообщает Collie, что durable agent перезапустился. Collie продолжает показывать имеющиеся панели, пока не считает новый снимок. Затем он считывает каждую панель со старым курсором и получает всё текущее представление панели в одном ответе.

Одно неудачное чтение после успешного сохраняет последний снимок на время этого опроса. Два сбоя подряд показывают durable agent как недоступный. Путь к сокету, не прошедший проверку прав доступа, становится недоступным сразу.

Запросы и ответы

Ask представляет собой карточку с вопросом; он открыт от события ask в durable agent до события ask-closed.

состояниекто задаётчто отображает телефон
ОткрытDurable agent создаёт ask. Панель показывает waiting, пока открыт хотя бы один askКарточка в разделе «Требуется ваш ответ» с именем durable agent и оставшимся временем, если у запроса задано expiresAt
ИзменёнDurable agent изменяет ask на месте, и его revision увеличиваетсяКарточка перерисовывается. Нажатие на старую форму возвращает 409 stale, а на карточке появляется сообщение: «Этот запрос изменился. Прочитайте его снова, затем выберите ответ».
ПринятТелефон отправляет ответ, и durable agent закрывает ask со статусом by: "phone"Карточка исчезает, а инструмент запускается или отклоняется в соответствии с выбранным вариантом
Решено в durable agentDurable agent закрывает ask самостоятельно, decidedBy: "program". Остановка шага засчитываетсяСтрока в чате, начинающаяся со слов «Решено в durable agent», с заголовком запроса
Время истеклоВремя превысило expiresAt, decidedBy: "timeout"Строка в чате, начинающаяся со слов «Время истекло до получения ответа», с заголовком запроса

Нажатие, совершённое после принятия решения, возвращает 409 decided с первым результатом, и ничего не запускается. Затем на карточке отображается, кто принял решение первым: «Решено в durable agent.», «Время истекло до получения ответа.» или после повторного нажатия «Ответ уже дан. Эта карточка исчезнет при следующем обновлении.». Запрос, о котором durable agent больше не знает, возвращает 200 too-late. Тогда на карточке отображается: «Не принят. Вопрос может появиться снова через минуту.», поскольку после перезапуска durable agent может создать его повторно с тем же идентификатором.

правилопочему
Идентификатор запроса представляет собой хеш идентификатора панели и идентификатора вызова инструментаТот же вызов инструмента, созданный после перезапуска, имеет тот же идентификатор, поэтому отправленный после перезапуска ответ будет доставлен
Карточка permission формируется из имени инструмента и его аргументов, но никогда из слов моделиМодель, желающая получить утвердительный ответ, описала бы вызов в выгодном свете
Durable agent за TLS не должен предлагать allow-alwaysТокен служит единственной точкой контроля, поэтому один ответ от его владельца пропустит все последующие вызовы
Телефон не предлагает allow-always на карточке, слова в которой были урезаны или удалены, либо если в ней не указан инструментПользователь не видит, что именно покрывает разрешение
expiresAt задаётся по стандарту ISO 8601 с указанием временной зоныПосле него судьбу запроса решает timeout, и снимок больше не показывает его как открытый
Durable agent хранит результаты как минимум последних 500 разрешённых запросов на панельЗапоздалое нажатие возвращает decided и исходный результат, а не обычный too-late

Запрос бывает одного из четырёх типов: permission, choice, text или form. У каждого своя структура ответа, описанная рядом с Вопросы в SDK.

Идентификаторы запросов

Каждое действие с телефона содержит идентификатор запроса, поэтому оно выполняется не более одного раза.

Телефон генерирует по одному идентификатору запроса на каждое намерение, а Collie записывает собственную квитанцию перед дальнейшей передачей идентификатора. Durable agent хранит как минимум 500 последних идентификаторов своей эпохи. Повтор завершённого идентификатора снова получает первый ответ с replayed: true и ничего не запускает. Тот же идентификатор с другим телом запроса возвращает 409 request-id-reused.

Collie никогда не повторяет POST самостоятельно. Запрос POST, завершившийся по тайм-ауту, потерявший соединение или получивший ответ 5xx, имеет неизвестный результат. В поле ответа на карточке появляется сообщение "Not sure the answer arrived. Try again sends it once more.", а кнопка Try again отправляет тот же идентификатор запроса, поэтому память durable agent отвечает на повтор.

Повторная попытка, которая застаёт запрос закрытым или ход переданным, не может определить, прошёл ли первый запрос. В этом случае Collie возвращает телефону ответ "maybe applied", карточка сообщает "May already be applied. Check the chat.", и действие больше никогда не отправляется в третий раз.

Транспорты

Durable agent использует один из двух транспортов: приватный сокет на машине Collie или TLS с токеном.

Байты в обоих случаях одинаковы: маршруты, тела запросов, заголовок версии, ETag и коды ошибок. Различается лишь то, кому разрешён доступ к durable agent.

через сокетправило
ПутьАбсолютный, не более 103 байт. Обе стороны считывают его из COLLIE_DURABLE_SOCKET
Режимы доступаСокет создаётся с режимом 0600 в папке с режимом 0700. Durable agent удаляет устаревший файл сокета перед началом прослушивания
Обход путиПеред каждым подключением Collie проверяет каждую часть пути с помощью lstat. Ни одна из частей не является символической ссылкой. Папка сокета принадлежит вам и имеет режим 0700. Ни одна папка выше по дереву не доступна для записи группе или остальным пользователям, за исключением папок со sticky bit, таких как /tmp. Сокет принадлежит вам, без прав для группы или остальных пользователей
Ошибки обхода путиCollie не подключается и помечает durable agent как недоступный, указывая socket-not-private и часть пути, вызвавшую сбой
ТокенНет. Приватный сокет сам служит точкой контроля
Кто может действоватьЛюбой процесс вашего пользователя. Durable agent может отклонять собственные дочерние процессы с кодом 403 caller-refused
Тайм-ауты1000 мс для hello, snapshot и events. 3000 мс для answer, send, stop, action, rename или close. 30000 мс для starter
Как часто Collie отправляет запросыКаждую 1 с, пока телефон активен, иначе каждые 3 с. Если durable agent недоступен, опрос выполняется один раз за интервал
СистемыLinux и macOS. В Windows нет сокетного транспорта
через TLSправило
URLhttps://, либо http://127.0.0.1:<port> или http://localhost:<port> для локального теста. Не более 2048 байт, без имени пользователя и пароля, без query и фрагмента. Collie добавляет к нему /session/v1
ТокенНе менее 32 байт, печатные символы ASCII без пробелов. Collie отправляет Authorization: Bearer <token> при каждом запросе, включая hello
Проверка durable agentСначала токен, до версии, hello и ready, сравнение за константное время. При отсутствии или неверном токене возвращается только 401 { "code": "unauthorized" } и ничего больше
ПеренаправленияCollie не переходит по перенаправлениям. Код 3xx передаётся наверх как статус, поэтому токен никогда не попадёт на другой хост
ETagПрокси, сжимающий ответ, может ослабить тег до W/"<epoch>-<rev>". Обе стороны сравнивают его без префикса W/
ОтказКод 401 или 403 отмечает durable agent как недоступный с token-refused
Тайм-ауты5000 мс на каждое чтение и запись, так как уснувший durable agent может запускаться с нуля. 30000 мс для starter
Как часто Collie отправляет запросыКаждые 2 с, пока открыто на телефоне, иначе каждые 10 с. Durable agent, который недоступен или вернул отказ, опрашивается не чаще одного раза в 10 с

Каждый таймаут задаёт предельный срок на весь обмен целиком, от подключения до последнего байта. Через TLS каждый опрос считается запросом, за который хостинг может списывать средства, включая 304.

Ограничения

Collie обрезает или отклоняет всё, что выходит за эти пределы, поэтому durable agent в их границах ничего не теряет.

параметрлимит
Рабочих пространств на снимок64
Вкладок на снимок256
Панелей на снимок256
Открытых запросов на панель50, сначала самые старые
Вариантов для permission6
Вариантов для choice и для поля выбора8
Полей для form6
Starter на снимок50
Кнопок belt на панель4, метка из 16 символов
ИдентификаторОт 1 до 128 байт, без управляющих символов, без пробелов, без /, ? и #
Тело запроса64 КиБ, иначе 413 too-large
Ответыhello — 16 КиБ, snapshot — 4 МиБ, events — 8 МиБ, conversations — 1 МиБ, items — 8 МиБ, POST — 16 КиБ
Событий на ответ1000. Отставший читатель получает текущее состояние, не более 2000 самых свежих элементов
Текст элемента user, reply, thinking или notice64 КиБ
Текст элемента markdown или code32 КиБ
Текст, отправляемый телефоном32 КиБ
Элемент linkТолько https://, не более 2048 символов
Страница истории100 диалогов или 1000 элементов
Курсор истории512 байт печатных символов ASCII, без пробелов

Строка, превышающая лимит, обрезается, а её управляющие и невидимые символы удаляются. Список, превышающий лимит, сохраняет первые записи. Страница истории, превышающая лимит, не читается вовсе.

Версии и информативное приветствие

Сейчас существует одна версия сетевого протокола, 1, и Collie использует 1..1.

Когда выйдет версия 2, Collie продолжит поддерживать версию 1 в течение одного минорного релиза, а следующий за ним минорный релиз прекратит её поддержку. Читатель игнорирует неизвестные ему поля, типы событий, разновидности элементов и коды. Поле, добавленное в рамках версии 1, такое как expiresAt или decidedBy, является необязательным. Новое обязательное поле, новое значение для старого поля или удалённое поле требуют новой версии.

Запрос неизвестного телефону типа отображается как запрос, на который нельзя ответить с телефона, без кнопок.

Если два диапазона не пересекаются, Collie больше ничего не читает от durable agent. Один раз за эпоху durable agent он отправляет ещё один hello, на этот раз со своей версией, чтобы durable agent мог зафиксировать несовпадение в своём журнале. Durable agent отвечает 409 incompatible с заголовком refusal, где указаны оба диапазона. Это информационное приветствие.

Collie записывает одну строку в журнал для каждого отклонённого диапазона, а collie doctor показывает оба диапазона. Домашний экран durable agent на телефоне выводит то же сообщение, например: «The durable agent speaks wire v2, this Collie speaks v1. Update Collie, or the agent's SDK.» Обновите устаревшую сторону.

Где найти точные правила

WIRE.md — это контракт со всеми структурами, кодами и правилами.

Решения, лежащие в его основе, зафиксированы в репозитории:

записьчто оно решает
ADR 0099Долговечный агент — это мультиплексор без экрана
ADR 0100Запрос передается как данные и получает ответ по id
ADR 0101Send и stop указывают ход, который видел телефон
ADR 0102Шаблоны запуска — это строки на странице «Создать»
ADR 0103Два транспорта
ADR 0104Долговечный агент — это сессия и выход из нее
ADR 0105SDK представляет собой npm-пакет

Редактировать эту страницу на GitHub

The rest of the documentation