UNPKG

redis-smq-common

Version:

Provides essential components and utilities shared across RedisSMQ packages.

64 lines 2.77 kB
import { WatchedKeysChangedError, WatchTransactionMaxRetriesExceeded, } from './errors/index.js'; import { CallbackEmptyReplyError } from '../errors/index.js'; export function withWatchTransaction(client, attemptFn, callback, options) { const maxAttempts = options?.maxAttempts ?? 3; const doAttempt = (attemptNo) => { if (attemptNo > maxAttempts) { const err = options?.makeRetryExceededError?.() ?? new WatchTransactionMaxRetriesExceeded(); return callback(err); } const watch = (keys, cb) => { const arr = Array.isArray(keys) ? keys : [keys]; if (arr.length === 0) return cb(); client.watch(arr, (err) => { if (err && options?.onWatchError) options.onWatchError(err); cb(err || null); }); }; attemptFn(client, watch, (attemptErr, result) => { if (attemptErr) { return client.unwatch(() => callback(attemptErr)); } if (!result || !result.multi) { return client.unwatch(() => callback(new CallbackEmptyReplyError({ message: 'Invalid attempt result. Expected a result object with a "multi" key.', }))); } result.multi.exec((execErr, execRes) => { if (execErr) { if (execErr instanceof WatchedKeysChangedError) { options?.onRetry?.(attemptNo, maxAttempts); return client.unwatch(() => { const backoff = options?.backoff ?? ((n) => n * 1000); const delay = backoff(attemptNo); if (delay && delay > 0) { setTimeout(() => doAttempt(attemptNo + 1), delay); } else { doAttempt(attemptNo + 1); } }); } if (options?.onExecError) options.onExecError(execErr); return client.unwatch(() => callback(execErr)); } if (result.afterExec) { try { result.afterExec(execRes ?? []); } catch (e) { const err = e instanceof Error ? e : new Error(String(e)); return callback(err); } } callback(null, execRes); }); }); }; doAttempt(1); } //# sourceMappingURL=with-watch-transaction.js.map