import { createHash } from "node:crypto"; import type { CollectionAdvisoryLockService } from "./CollectionAdvisoryLockService.types"; import type { PrismaDatabaseClient } from "../persistence/PrismaDatabaseClient"; export class PostgresCollectionAdvisoryLockService implements CollectionAdvisoryLockService { constructor(private readonly prismaClient: PrismaDatabaseClient) {} async withLock(key: string, fn: () => Promise): Promise { const lockId = this.keyToLockId(key); await this.prismaClient.$executeRawUnsafe(`SELECT pg_advisory_lock(${lockId})`); try { return await fn(); } finally { await this.prismaClient.$executeRawUnsafe(`SELECT pg_advisory_unlock(${lockId})`); } } private keyToLockId(key: string): bigint { const hash = createHash("sha256").update(key).digest(); const high = hash.readUInt32BE(0); const low = hash.readUInt32BE(4); const unsigned = BigInt(high) * BigInt(0x100000000) + BigInt(low); const maxSigned = BigInt("9223372036854775807"); if (unsigned > maxSigned) { return unsigned - BigInt("18446744073709551616"); } return unsigned; } }