{"library":"proper-lockfile","title":"Inter-Process Lockfile Utility","description":"proper-lockfile is a robust JavaScript utility for managing inter-process and inter-machine file locks across local and network file systems. Currently at version 4.1.2, it is actively maintained with updates released as needed. Its core design uses an atomic `mkdir` strategy for lockfile creation, which is more reliable than `open` with `O_EXCL` flags, especially on network file systems (NFS) where `O_EXCL` is prone to race conditions. The library differentiates itself by constantly updating the lockfile's `mtime` (modified time) to accurately check for staleness, a significant improvement over `ctime` (creation time) for long-running processes. Furthermore, it incorporates mechanisms to detect when a lockfile might be compromised due to failed updates or unexpected delays, enhancing overall reliability compared to alternatives.","language":"javascript","status":"active","last_verified":"Sun Apr 19","install":{"commands":["npm install proper-lockfile"],"cli":null},"imports":["import { lock } from 'proper-lockfile';","import { unlock } from 'proper-lockfile';","import { check } from 'proper-lockfile';"],"auth":{"required":false,"env_vars":[]},"quickstart":{"code":"import { lock, unlock } from 'proper-lockfile';\nimport { promises as fs } from 'fs';\nimport path from 'path';\n\nconst filePath = path.join(process.cwd(), 'my-resource.txt');\nconst lockFileOptions = {\n  stale: 15000, // Consider lock stale after 15 seconds\n  update: 5000, // Update mtime every 5 seconds\n  retries: {\n    retries: 5,\n    factor: 2,\n    minTimeout: 1000,\n    maxTimeout: 10000,\n    randomize: true,\n  },\n  onCompromised: (err) => {\n    console.error('Lock was compromised:', err.message);\n    // Implement critical error handling here, e.g., exit process\n    process.exit(1);\n  },\n};\n\nasync function accessResourceWithLock() {\n  let release;\n  try {\n    // Ensure the target file exists before trying to lock it\n    await fs.writeFile(filePath, 'Initial content.', { flag: 'a+' });\n\n    console.log('Attempting to acquire lock...');\n    release = await lock(filePath, lockFileOptions);\n    console.log('Lock acquired. Performing sensitive operation...');\n\n    // Simulate work\n    await new Promise(resolve => setTimeout(resolve, Math.random() * 3000 + 1000));\n    await fs.appendFile(filePath, `\\nAccessed at ${new Date().toISOString()} by process ${process.pid}`);\n\n    console.log('Sensitive operation complete. Releasing lock...');\n  } catch (error) {\n    console.error('Failed to acquire or release lock:', error.message);\n    if (error.code === 'ELOCKED') {\n      console.warn('File is already locked by another process.');\n    }\n  } finally {\n    if (release) {\n      try {\n        await release();\n        console.log('Lock released successfully.');\n      } catch (error) {\n        console.error('Error releasing lock:', error.message);\n      }\n    } else {\n        // If lock was never acquired, or release failed (e.g. compromised), ensure cleanup.\n        // In a real scenario, you might also attempt `unlock(filePath)` here if `release` failed\n        // but only if you are confident it's safe to force-unlock.\n        console.log('No release function available or lock acquisition failed. No explicit release needed/possible.');\n    }\n  }\n}\n\naccessResourceWithLock();\n","lang":"typescript","description":"Demonstrates how to acquire, use, and release an inter-process lock on a file using asynchronous functions, including error handling and retry options. It also shows basic file system interaction.","tag":null,"tag_description":null,"last_tested":null,"results":[]},"compatibility":null}