Практическое руководство для разработчиков
Idempotency key video API: как не создать дублирующие задачи
Повторный клик, обрыв сети или timeout не означают, что видео-задача не была создана. Если каждый повтор сразу отправлять в video API, одна пользовательская операция превратится в несколько затратных заданий. Idempotency key связывает намерение приложения с одной внутренней записью и позволяет безопасно показать уже созданную задачу. RussiaAPI — независимый сторонний gateway: конкретные параметры и статусы видео-моделей нужно сверять по текущему каталогу и документации, а не угадывать по старому примеру.
RUSSIAAPI_API_KEY на сервере; не передавайте внешние ключи, cookie, пароли, коды подтверждения или лишние персональные данные.Разделите запрос пользователя и задачу поставщика
Начните с внутренней операции: пользователь нажимает «создать видео», сервер проверяет сессию, права на исходные материалы, лимит и бюджет, затем создаёт строку со статусом pending. В ней есть собственный случайный ключ идемпотентности, ID пользователя или tenant и отпечаток допустимого payload. Только после успешного резервирования сервер отправляет один запрос gateway и сохраняет возвращённый task ID, если он предусмотрен текущим контрактом.
Ключ не должен быть API-ключом, подписью callback или значением, которое можно предсказать. Лучше использовать случайный UUID, сгенерированный сервером для одного подтверждённого действия. Если пользователь повторяет запрос с тем же идентификатором операции, ваш backend возвращает существующее состояние вместо новой отправки. Не полагайтесь на имя файла или один и тот же prompt: это не всегда однозначно и может нечаянно объединить разные работы.
Определите границы ключа и отпечатка
Привязывайте ключ к пользователю, продукту и короткому периоду хранения, который соответствует вашему сценарию. Один и тот же ключ от другого tenant нельзя считать совпадением. Для защиты от ошибочного повторного использования храните хеш нормализованного payload: выбранной модели, разрешённого источника, параметров формата и версии вашего маршрута. Сам исходный prompt, приватный URL изображения и токен доступа не обязаны попадать в таблицу идемпотентности.
При поступлении одинакового ключа есть три ясных результата. Если запись ещё pending, верните 202 и внутренний operation ID. Если задача создана или готова, верните её текущее безопасное представление. Если ключ совпадает, а отпечаток другой, верните 409 и попросите клиент создать новое действие. Это лучше, чем молча запускать второе видео или отдавать чужой результат. Проверку прав на контент дополняет чек-лист прав для video API.
Серверный пример с транзакцией
Ниже пример Node.js 18+ показывает логику маршрута. Функции findOperation, createOperation и saveProviderTask реализуются вашим хранилищем в транзакции с уникальным индексом по tenantId + key. В URL и поле model нет обещания доступности конкретной модели: перед запуском сверьте актуальный video-контракт RussiaAPI. Ключ сервиса остаётся только в окружении backend-процесса.
export async function createVideoOperation({ tenantId, input, key }) {
if (!tenantId || !key || key.length > 128) return { status: 400, body: { error: 'invalid_request' } };
const fingerprint = await sha256(JSON.stringify({ model: input.model, format: input.format, source: input.sourceId }));
const existing = await findOperation(tenantId, key);
if (existing && existing.fingerprint !== fingerprint) return { status: 409, body: { error: 'idempotency_conflict' } };
if (existing) return { status: 202, body: { operationId: existing.id, status: existing.status } };
const operation = await createOperation({ tenantId, key, fingerprint, status: 'pending' });
const response = await fetch('https://russiaapi.com/v1/video/generations', {
method: 'POST',
headers: { authorization: `Bearer ${process.env.RUSSIAAPI_API_KEY}`, 'content-type': 'application/json' },
body: JSON.stringify({ model: input.model, source_id: input.sourceId, format: input.format }),
signal: AbortSignal.timeout(15_000)
});
if (!response.ok) return { status: 503, body: { operationId: operation.id, error: 'video_submission_pending_review' } };
const data = await response.json();
await saveProviderTask(operation.id, data.id); // validate current provider response schema first
return { status: 202, body: { operationId: operation.id, status: 'submitted' } };
}Если сеть оборвалась после отправки, не делайте бесконечный retry вслепую. Сначала прочитайте внутреннюю операцию и её безопасный статус; при наличии task ID продолжайте polling или callback-обработку. Если контракт поставщика поддерживает собственный заголовок идемпотентности, используйте его только после проверки документации, но не заменяйте им внутреннюю таблицу: именно она связывает результат с пользователем и вашим бюджетом.
Обработайте timeout и callback
Timeout означает неопределённость, а не гарантированную неудачу. Пометьте попытку как «проверяется», сохраните время и внутренний request ID, если он есть, затем поставьте контролируемую задачу проверки. Для асинхронных видео-операций callback должен проверять подпись по документированному механизму, дедуплицировать event ID и обновлять запись только для ожидаемого состояния. Не отдавайте браузеру внешний callback URL, заголовки или временную ссылку результата без проверки владельца.
Polling и webhook — способы получить статус, но не способы создавать новую работу. Установите конечный срок ожидания и понятное состояние для оператора: например, «требует ручной проверки» вместо бесконечного pending. Обрабатывайте 429 и 5xx по ограниченной политике, не переотправляя удачную операцию. Для выбора уведомления смотрите сравнение polling и webhook, а для длительных задач — асинхронную генерацию видео.
Не смешивайте идемпотентность и доступ
Idempotency key защищает от дублей, но не подтверждает право пользователя на операцию. Перед каждым чтением и выдачей статуса проверяйте tenant и роль. Отдельно ограничивайте число незавершённых задач, размер входа и свой расходный лимит. Случайный ключ не следует помещать в публичный лог или URL, если по нему можно узнать состояние чужой работы. Для браузера безопаснее вернуть короткий внутренний ID и запросить статус на авторизованном маршруте.
Не используйте этот механизм для обхода правил поставщиков, региональных ограничений или прав на материалы. Если операция недоступна, ваш продукт должен сообщить об этом честно и не искать альтернативные пути. RussiaAPI не является официальным сервисом производителя модели, а совместимый формат не даёт автоматического права на любую функцию.
Чек-лист перед запуском
- Внутренний ключ создаётся сервером, привязан к tenant и защищён уникальным индексом.
- Повтор с тем же ключом возвращает состояние операции, а не создаёт новую видео-задачу.
- Ключ с другим payload даёт понятный 409; ключ не содержит и не раскрывает секреты.
- Timeout и callback обновляют одну внутреннюю запись через контролируемые состояния.
- Выдача статуса и результата проверяет владельца, срок доступа и правила контента.
Протестируйте два одновременных клика, повтор после сетевой ошибки, разный payload с тем же ключом и callback-дубликат. Только после этих сценариев включайте реальную нагрузку. Это полезнее, чем проверять один удачный ответ в браузере.
Проверьте сценарий в RussiaAPI
Создайте собственный тестовый ключ в консоли, проверьте текущий каталог моделей и выполните минимальный server-side тест на синтетических данных. Расширяйте доступ и нагрузку только после измеримой проверки.
Открыть консоль RussiaAPIFAQ
Кто генерирует idempotency key?
Предпочтительно сервер вашего приложения после проверки пользователя и входа. Клиент может передать случайный идентификатор операции, но сервер всё равно должен проверить tenant, длину, срок действия и уникальность в хранилище.
Нужно ли повторять видео-запрос после timeout?
Не автоматически. Timeout оставляет неопределённость: сначала прочитайте внутреннюю операцию, проверьте сохранённый task ID или контролируемый статус. Повтор разрешается только по вашей ограниченной политике и после проверки контракта.
Можно ли по ключу выдавать результат видео?
Нет. Ключ идемпотентности не заменяет авторизацию. Перед статусом, скачиванием или временной ссылкой сервер подтверждает владельца операции, доступ tenant и срок действия результата.