import { acquireDatabaseLock, releaseDatabaseLock, getDatabaseLock, } from "../../utils/local-data-store/database-lock.js"; import { logger } from "../reporting-service/index.js"; export class SQLiteCoordinator { private static readonly LOCK_TIMEOUT_MS = 30_000; // 30 seconds private static readonly LOCK_RETRY_INTERVAL_MS = 1_000; // 1 second /** * Performs startup checks to ensure no stale locks exist * Should be called when the application starts */ static async performStartupCheck(): Promise { const currentLock = getDatabaseLock(); if (currentLock.isLocked) { logger.warn( `Found existing lock held by ${currentLock.lockedBy}, releasing for clean startup` ); releaseDatabaseLock(currentLock.lockedBy); } } /** * Attempts to acquire the database lock * @param processName Name of the process requesting the lock * @returns true if lock was acquired, false if database is already locked */ private static async tryAcquireLock(processName: string): Promise { return acquireDatabaseLock(processName); } /** * Executes a database operation with proper locking * @param processName Name of the process executing the operation * @param operation The operation to execute * @returns The result of the operation */ static async executeWithLock( processName: string, operation: () => Promise ): Promise { const startTime = Date.now(); // Try to acquire the lock with timeout while (Date.now() - startTime < this.LOCK_TIMEOUT_MS) { if (await this.tryAcquireLock(processName)) { try { // Execute the operation const result = await operation(); return result; } finally { // Always release the lock releaseDatabaseLock(processName); } } // Wait before retrying await new Promise((resolve) => setTimeout(resolve, this.LOCK_RETRY_INTERVAL_MS) ); } throw new Error( `Failed to acquire database lock after ${this.LOCK_TIMEOUT_MS}ms` ); } /** * Checks if the database is currently available for operations * @returns true if the database is available, false if locked */ static isAvailable(): boolean { const lock = getDatabaseLock(); return !lock.isLocked; } }