Повторные попытки и идемпотентность
Как устроены ретраи в SDK и когда включать идемпотентность.
Обзор политики ретраев
Ретраи реализованы пакетом @ydbjs/retry с разумными значениями по умолчанию:
- Мгновенный повтор для
BAD_SESSION,SESSION_EXPIRED,ABORTED. - Экспоненциальная задержка для
OVERLOADEDи gRPCRESOURCE_EXHAUSTED(начиная с 1000 мс). - Экспоненциальная задержка для остальных ретраебельных случаев (начиная с 10 мс).
- Бюджет попыток по умолчанию бесконечный; ограничьте через
budget.
Ретраи запросов зависят от флага идемпотентности:
- Всегда повторяются:
ABORTED,OVERLOADED,UNAVAILABLE,BAD_SESSION,SESSION_BUSY. - Условные (только с
.idempotent(true)):SESSION_EXPIRED,UNDETERMINED,TIMEOUT.
См. реализацию: packages/retry/src/index.ts и packages/query/src/query.ts.
Пометка одиночного вызова как идемпотентного
ts
await sql`UPDATE counters SET v = v + 1 WHERE id = ${id}`
.idempotent(true)
.timeout(3000)Внутри sql.begin/sql.transaction пометка на уровне одного вызова игнорируется; настраивайте идемпотентность на уровне транзакции и делайте бизнес‑логику идемпотентной (например, через ключи идемпотентности).
Кастомизация стратегии ретраев
ts
import { retry, defaultRetryConfig, strategies } from '@ydbjs/retry'
await retry(
{
...defaultRetryConfig,
budget: 5,
strategy: strategies.exponential(200),
},
async (signal) => {
return await sql`SELECT 1`.signal(signal)
}
)Topic streaming
Topic reader/writer переподнимают соединение при сбоях и пересоздают очередь команд. Для writer можно настраивать retryConfig; обеспечивайте идемпотентность продюсера через producerId + seqNo.
Рекомендации
- Предпочитайте идемпотентные операции и используйте ключи идемпотентности в сценариях at‑least‑once.
- Ставьте явные таймауты, чтобы ограничивать «хвосты» по времени.
- Логируйте ретраи через
on('retry')и включайтеDEBUG=ydbjs:*на стендах.