UNPKG

syncguard

Version:

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

44 lines (43 loc) 1.91 kB
/* SPDX-FileCopyrightText: 2025-present Kriasoft */ /* SPDX-License-Identifier: MIT */ import { withRetries } from "../retry.js"; /** * Creates a release operation for Firestore backend */ export function createReleaseOperation(db, locksCollection, config) { return async (lockId) => { return withRetries(async () => { // First, find the document by querying for lockId to get the key const querySnapshot = await locksCollection .where("lockId", "==", lockId) .limit(1) .get(); if (querySnapshot.empty) { return false; } const doc = querySnapshot.docs[0]; const data = doc.data(); // Use transaction for atomic ownership verification and deletion const result = await db.runTransaction(async (trx) => { // Use the exact document reference from the query to avoid TOCTOU issues const docRef = doc.ref; const currentDoc = await trx.get(docRef); // Handle race condition: document might have been deleted between query and transaction if (!currentDoc.exists) { // Document was deleted between query and transaction - treat as success // since our lockId was found initially but document no longer exists return true; } const currentData = currentDoc.data(); // Verify ownership by lockId - this is critical for safety if (currentData.lockId !== lockId) { // Document exists but lockId changed - another lock took this key return false; } trx.delete(docRef); return true; }); return result; }, config); }; }