durable-objects
Этот скилл посвящён Cloudflare Durable Objects и приложениям на edge, которым нужны координация и состояние. Он предназначен для chat rooms, multiplayer-игр, совместных документов, бронирований, inventory, turn-based сценариев, multi-tenant SaaS, постоянных WebSocket-соединений, realtime-уведомлений и планируемой работы на уровне отдельной сущности. Durable Object рассматривается как место для координации, сильной согласованности, хранения состояния конкретного объекта, persistent connections и per-entity scheduled work. При этом скилл прямо отделяет такой случай от stateless request handling, где достаточно обычного Worker, от задач с максимальной глобальной распределённостью и от независимых high-fan-out запросов. Выбор технологии поэтому должен начинаться с природы состояния и координации, а не с желания использовать один и тот же runtime для любого запроса. Для маршрутизации скилл рекомендует детерминированный getByName(): одинаковый вход должен вести к одному и тому же экземпляру Durable Object. В качестве альтернатив показаны idFromString() для уже сохранённого ID и newUniqueId() для нового уникального ID, когда соответствие нужно хранить отдельно. Архитектура моделируется вокруг coordination atoms: обычно один объект соответствует комнате, игре или пользователю, а единый глобальный объект для всех запросов считается bottleneck. Для хранения состояния используется SQLite; в конфигурации wrangler нужно связать namespace с классом и указать new_sqlite_classes в migration. Критическое состояние нельзя оставлять только в памяти, потому что объект может быть вытеснен или процесс может завершиться. Правило persist first, cache second означает: сначала запись в storage, затем обновление in-memory представления. Инициализация схемы выполняется в конструкторе, а blockConcurrencyWhile() используется для setup схемы, чтобы конкурирующая работа не увидела незавершённое создание таблиц. Скилл предупреждает не держать этот блок на каждом запросе и не переносить его через fetch или внешний I/O, иначе падает пропускная способность. Для нового RPC-стиля предлагаются методы класса Durable Object вместо fetch()-обработчика, если compatibility date соответствует требованиям API. SQL-хранилище вызывается синхронно через ctx.storage.sql.exec(), а KV-операции выполняются асинхронно. Связанные storage writes не следует разделять await, если это разрушает требуемую атомарность. Alarm у каждого Durable Object один: setAlarm() заменяет существующий alarm, обработчик alarm() выполняет отложенную работу и при необходимости ставит следующий срок, а deleteAlarm() отменяет расписание. Такой контракт нужно учитывать при проектировании нескольких видов задач для одной сущности. В списке анти-паттернов отдельно отмечены единый глобальный объект, blockConcurrencyWhile() на каждом request, важные данные только в памяти, await между связанными storage writes и попытка держать блокировку во время внешнего вызова. Для проверки скилл показывает Vitest с @cloudflare/vitest-pool-workers, namespace из cloudflare:test и вызов stub.getByName() в тесте. Он также направляет разработчика к официальным страницам Cloudflare по Durable Objects, API, best practices и примерам, потому что детали API и конфигурации могут устаревать. Это руководство по границам состояния, routing, storage, RPC, alarm и тестированию, а не готовая реализация конкретного Worker.
Для чего подходит
- Разработка stateful Cloudflare-сервисов
- Работа с Durable Objects и SQLite
- Тестирование WebSocket и alarm-сценариев
Установка
Сначала прочитайте SKILL.md и scripts в исходном репозитории. Затем выполните команду в каталоге проекта:
npx skills add https://github.com/cloudflare/skills/tree/main/skills/durable-objects