UNPKG

syncguard

Version:

Functional TypeScript library for distributed locking across microservices. Prevents race conditions with Redis, PostgreSQL, Firestore, and custom backends. Features automatic lock management, timeout handling, and extensible architecture.

35 lines (34 loc) 1.71 kB
// SPDX-FileCopyrightText: 2025-present Kriasoft // SPDX-License-Identifier: MIT import { LockError, makeStorageKey, normalizeAndValidateKey, } from "../../common/backend.js"; import { TIME_TOLERANCE_MS } from "../../common/time-predicates.js"; import { checkAborted, mapRedisError } from "../errors.js"; import { IS_LOCKED_SCRIPT } from "../scripts.js"; /** * Creates isLocked operation using Lua script for atomicity. * Script checks expiration and optionally cleans up with safety guard. * @see ../scripts.ts for IS_LOCKED_SCRIPT implementation */ export function createIsLockedOperation(redis, config) { return async (opts) => { try { // Pre-dispatch abort check (ioredis does not accept AbortSignal) checkAborted(opts.signal); const normalizedKey = normalizeAndValidateKey(opts.key); const REDIS_LIMIT_BYTES = 1000; const RESERVE_BYTES = 26; // ":id:" (4 bytes) + 22-char lockId const lockKey = makeStorageKey(config.keyPrefix, normalizedKey, REDIS_LIMIT_BYTES, RESERVE_BYTES); // Prefer cached command (ioredis) over eval for better performance const scriptResult = redis.checkLock ? await redis.checkLock(lockKey, config.keyPrefix, TIME_TOLERANCE_MS.toString(), config.cleanupInIsLocked.toString()) : (await redis.eval(IS_LOCKED_SCRIPT, 1, lockKey, config.keyPrefix, TIME_TOLERANCE_MS.toString(), config.cleanupInIsLocked.toString())); return scriptResult === 1; } catch (error) { if (error instanceof LockError) { throw error; } throw mapRedisError(error); } }; }