Транзакции в Query
В @ydbjs/query есть два удобных метода: begin и transaction.
begin(options?, fn)— создаёт транзакцию, выполняетfn(tx, signal)и коммитит. В случае ошибки откатывает.transaction(options?, fn)— алиасbegin.
Опции:
isolation?: 'serializableReadWrite' | 'snapshotReadOnly'— уровень изоляции транзакции (по умолчаниюserializableReadWrite).idempotent?: boolean— включает повторные попытки при условно‑повторяемых ошибках. Важно обеспечивать идемпотентность бизнес‑операции.
signal: AbortSignal внутри колбэка позволяет отменять долгие операции.
Базовое использование
ts
const result = await sql.begin(async (tx) => {
await tx`UPDATE users SET active = false WHERE ...`
return await tx`SELECT * FROM users WHERE active = false`
})Опции изоляции и идемпотентности
ts
await sql.begin(
{
isolation: 'snapshotReadOnly',
idempotent: true,
},
async (tx) => {
return await tx`SELECT COUNT(*) FROM users`
}
)Интеграция с Topic (без using)
При работе в рамках sql.transaction(...) используйте tx‑aware клиенты Topic без using/явного закрытия:
ts
import { createTopicTxReader } from '@ydbjs/topic/reader'
import { createTopicTxWriter } from '@ydbjs/topic/writer'
await sql.transaction(async (tx, signal) => {
const reader = createTopicTxReader(tx, driver, {
topic: '/Root/my-topic',
consumer: 'svc-a',
})
for await (const batch of reader.read({ signal })) {
// ...
}
const writer = createTopicTxWriter(tx, driver, {
topic: '/Root/my-topic',
producer: 'p1',
})
writer.write(new TextEncoder().encode('message'))
})Reader регистрирует updateOffsetsInTransaction в tx.onCommit, Writer — flush в tx.onCommit. Ручное закрытие внутри транзакции не требуется.
Таймауты и повторные попытки
- Таймауты задавайте на уровне запроса или обработчика.
- Повторные попытки см. «Продвинутое → Повторные попытки и идемпотентность».
Лучшие практики
- Держите транзакции короткими — минимизируйте блокировки и вероятность конфликтов.
- Для операций чтения используйте
snapshotReadOnlyпри возможности. - Идемпотентные операции упрощают повторные попытки; применяйте ключи идемпотентности, если нужно.
- Не смешивайте тяжёлые Topic‑операции и большие SQL‑чтения в одной транзакции без необходимости.