Перейти к содержанию

IPFS: асинхронное закрепление у поставщика

Удалённый хранитель часто принимает запрос на закрепление и продолжает работу после ответа. Для библиотеки это обычная асинхронная задача, которой нужен собственный журнал. В уроке построим переходы запроса и увидим, почему успешный HTTP-ответ о создании задачи не означает готовность выпуска.

Пример не обращается к поставщику и не использует токены. IPFS Pinning Service API изучен как опубликованная совместимая спецификация; её репозиторий архивирован, поэтому не называем её активно развивающимся универсальным будущим стандартом. Конкретный поставщик должен отдельно подтвердить поддержку.

Запрос и ресурс задачи

Клиент передаёт CID, понятное имя и допустимые вспомогательные данные. Поставщик возвращает идентификатор задачи и её состояние. Внутренний сервис библиотеки сохраняет результат, чтобы продолжить наблюдение после перезапуска.

{
  "releaseId": "course-17-edition-1",
  "provider": "storage-a",
  "requestId": "RETURNED_REQUEST_ID",
  "cid": "ROOT_CID",
  "state": "queued"
}

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

Состояния опубликованной модели включают ожидание, закрепление, успех и отказ. Адаптер преобразует их в внутренние категории, сохраняя исходное значение. Если поставщик ввёл новое состояние, приложение не считает его автоматически успехом только потому, что ответ содержит непустой JSON.

Конечный успех

После pinned хранитель сообщает завершённое закрепление. Это основание для следующего этапа сверки доступности. До этого queued или pinning не позволяют редакции уверенно объявить реплику полной.

Если задача завершилась отказом, сохраняем причину и решаем, допустим ли повтор. Причина может относиться к недоступным исходным блокам, ограничениям аккаунта или неправильному запросу. Простое многократное создание задач не исправляет отсутствующий полный источник данных.

В библиотечном журнале успех связывается с точным корнем и выпуском. Если задача относится к другому CID, её завершение не заполняет статус нашей редакции. Сверяем и идентичность, и принадлежность аккаунту, и доступный состав.

Повтор после неизвестного результата

Запрос может дойти до поставщика, а ответ потеряться. Тогда сервис не знает, создана ли задача. Повтор без стратегии может создать несколько записей. Если API предоставляет подходящий поиск или идемпотентный механизм, адаптер использует его по документации; нельзя придумывать заголовок, который сервер не поддерживает.

Для собственной модели сохраняем корреляцию намерения до внешнего вызова. Затем фиксируем полученный идентификатор. После сбоя сверяем известный выпуск по доступному API и осторожно определяем, какую задачу считать основной. Дубликаты удаляются только по явному процессу, чтобы не потерять нужную копию.

Не считаем имя задачи уникальным криптографическим идентификатором. Два запроса могут иметь одно название. Надёжная связь использует CID, идентификатор поставщика и возвращённый идентификатор ресурса.

Полномочия токена

Токен хранения находится на сервере. Браузер читателя не получает право создавать, перечислять или удалять задачи произвольного аккаунта. Публичный статус курса возвращается через прикладной маршрут с минимальными сведениями.

Для оператора полезны ограниченные полномочия и отдельный профиль тестовых действий, когда исполнение будет разрешено. Токен не записывается в URL, Markdown или журнал ошибки. В примерах здесь вообще нет его значения, даже фиктивного похожего секрета.

Если поставщик меняет способ авторизации, адаптер обновляется отдельно от модели выпуска. Идентичность данных не зависит от токена, а возможность выполнить административную операцию зависит. Это ещё одна причина разделять хранение, содержание и доступ к управлению.

Опрос и ограничения

Не нужно опрашивать каждую задачу непрерывно. Сервис задаёт ограниченную частоту, задержку повторов и общий срок наблюдения. Тайм-аут задачи по внутренней политике означает, что готовность не подтверждена за нужное время, а не обязательно физическое удаление блоков.

Если API поддерживает уведомления, их подлинность и повторяемость проверяются по его документации. Уведомление является сигналом для обновления состояния, но не поводом принимать неподписанные публичные сообщения как административное решение. Повторный сигнал не создаёт ещё одну реплику.

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

Потерян ответ на создание задачи

Внутренний сервис сохранил намерение закрепить корень первой редакции, отправил запрос и потерял соединение до ответа. У поставщика задача могла уже появиться. Локальная запись теперь имеет состояние неизвестного результата; это отличается от подтверждённого отказа создать ресурс. Если сразу послать десять новых запросов, приложение может получить несколько задач и запутаться при последующем удалении старых закреплений.

Адаптер использует только реально предусмотренную поставщиком процедуру сверки. Например, поддерживаемый поиск по CID и сохранённым вспомогательным данным может помочь обнаружить ресурс. Совпадение одного имени не является достаточным признаком, если имена не уникальны. Полученный кандидат сопоставляется с аккаунтом, точным корнем и нашим намерением. Нельзя объявлять любую найденную задачу доказательством нового независимого хранения.

Если идемпотентный ключ существует в конкретном API, его значение и семантика фиксируются по документации этой реализации. Если его нет, собственная корреляция библиотеки всё равно полезна, но не создаёт обещания однократного внешнего действия. Журнал отражает такую границу честно. Для удаления дубликата нужна уверенность, что оставшаяся задача действительно удерживает нужный выпуск; автоматическая уборка всех одноимённых ресурсов слишком груба.

Опрос также связан с идентичностью ресурса. Ответ pinned для другого requestId или корня не переводит наше намерение в успех. Новый неподдерживаемый статус сохраняется как исходное значение и требует корректного разбора адаптером. После восстановления связи сервис продолжает наблюдение той же задачи, а не начинает новое редакционное объявление. В будущем эту модель можно реализовать устойчивым журналом с ограниченными повторами. Пока сохранены только исходники и ожидаемые переходы: ни один реальный запрос не создавался, а окончательные значения идентификаторов остаются незаполненными.

Завершение выпуска

Объявление читателю происходит после требуемых стадий. Если библиотека допускает ранний анонс, страница сообщает, что материалы ещё готовятся к выдаче. Не превращаем промежуточный ответ API в текст «архив доступен навсегда».

Официальная модель опубликована в Pinning Service API и руководстве IPFS. Результат урока — устойчивый журнал асинхронной задачи. В дальнейшем он пригодится при смене поставщика и восстановлении, сохраняя различие намерения, завершения и реального получения данных.

Оглавление серии