
Security News
GitHub Actions Adds cache-mode to Limit Cache Poisoning Risk
GitHub Actions now supports cache-mode, a least-privilege control on the Actions cache aimed at the cache poisoning technique behind recent compromises.
nextfile-js
Advanced tools
Atomic file-based locking with retry, TTL, heartbeat, PID tracking, stale detection, and multi-strategy support
Atomic file-based locking with retry, TTL, heartbeat, PID tracking, stale detection, and multi-strategy support.
npm install nextfile
import { withLock, lock, lockSync } from 'nextfile';
// Wrap a function in a lock (auto-released)
await withLock('/tmp/my-resource', async () => {
// only one process runs this at a time
});
// Manual acquire / release
const handle = await lock('/tmp/my-resource');
try {
// critical section
} finally {
await handle.release();
}
// Synchronous API
const { release } = lockSync('/tmp/my-resource');
release();
| Feature | Description |
|---|---|
| Atomic writes | Uses hard-link strategy — no partial writes |
| Multiple adapters | fs, atomic, mkdir, symlink |
| Multiple strategies | exclusive, shared, advisory, optimistic |
| TTL | Locks auto-expire after a configurable duration |
| Heartbeat | Refreshes lock timestamps to prevent false stale detection |
| PID tracking | Detects orphaned locks from dead processes |
| Stale detection | By age, PID liveness, or TTL expiry |
| Retry + backoff | linear, exponential, fibonacci, jitter |
| AbortSignal | Cancel acquisition at any point |
| Sync API | lockSync, unlockSync, checkSync |
| Events | Typed event system for monitoring |
| Hooks | Lifecycle hooks: beforeLock, afterLock, etc. |
| Middleware | Compose option transformers |
| CLI | lock, unlock, status, list, cleanup |
| TypeScript | 100% typed, strict mode |
| ESM + CJS | Dual package |
lock(path, options?) → Promise<LockHandle>Acquire a lock. Retries with backoff on conflict.
const handle = await lock('/tmp/resource', {
retries: 10,
retryBackoff: 'exponential',
ttl: 30_000,
heartbeatInterval: 5_000,
removeStale: true,
});
await handle.release();
withLock(path, fn, options?) → Promise<T>Acquire, run fn, release — even on error.
const result = await withLock('/tmp/resource', async () => {
return computeSomething();
});
lockSync(path, options?) → { lockPath, release }Synchronous lock (no retry, no heartbeat).
checkLock(path) → Promise<LockFile>Inspect a lock without acquiring it.
isLocked(path) → Promise<boolean>Returns true if a non-stale lock exists.
cleanupLocks(dir, options?) → Promise<CleanupResult>Remove stale lock files from a directory.
| Option | Type | Default | Description |
|---|---|---|---|
retries | number | 5 | Max retry attempts |
retryDelay | number | 100 | Base delay in ms |
retryBackoff | string | 'exponential' | Backoff strategy |
retryMaxDelay | number | 5000 | Max delay cap in ms |
timeout | number | 60000 | Total acquisition timeout |
ttl | number | null | Lock TTL in ms |
heartbeatInterval | number | 5000 | Heartbeat refresh interval |
staleAge | number | 30000 | Age threshold for stale detection |
removeStale | boolean | false | Auto-remove stale locks |
strategy | string | 'exclusive' | Lock strategy |
adapter | string | 'atomic' | File-system adapter |
signal | AbortSignal | — | Cancellation signal |
meta | object | {} | Arbitrary metadata stored in lock file |
# Acquire a lock
nextfile lock /tmp/resource --ttl 30000
# Release a lock
nextfile unlock /tmp/resource
# Check status
nextfile status /tmp/resource --json
# List all locks in a directory
nextfile list --dir /tmp --recursive --table
# Clean up stale locks
nextfile cleanup --dir /tmp --stale-age 60000 --dry-run
| Adapter | Atomic | Cross-platform | Notes |
|---|---|---|---|
atomic (default) | ✅ | ✅ | Hard-link strategy |
fs | ❌ | ✅ | Simple wx flag write |
mkdir | ✅ | ✅ | mkdir is atomic on most FS |
symlink | ✅ | ⚠️ Unix only | Symlink as lock token |
import { globalEmitter } from 'nextfile';
globalEmitter.on('acquired', (event) => {
console.log('Lock acquired:', event.lockPath, 'after', event.elapsed, 'ms');
});
globalEmitter.on('stale', (event) => {
console.warn('Stale lock detected:', event.lockPath);
});
import { addBeforeLockHook, addAfterLockHook } from 'nextfile';
addBeforeLockHook(async (path, lockPath, options) => {
console.log(`About to lock ${path}`);
});
addAfterLockHook(async (handle) => {
console.log(`Acquired lock on ${handle.path}, PID ${handle.data.pid}`);
});
import { withLoggingMiddleware, withRetryMiddleware, composeMiddleware } from 'nextfile';
const middleware = composeMiddleware(withLoggingMiddleware, withRetryMiddleware);
const handle = await lock('/tmp/resource', middleware({}));
MIT © nextfile contributors
FAQs
Atomic file-based locking with retry, TTL, heartbeat, PID tracking, stale detection, and multi-strategy support
We found that nextfile-js demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
GitHub Actions now supports cache-mode, a least-privilege control on the Actions cache aimed at the cache poisoning technique behind recent compromises.

Company News
Allow myself to introduce... myself.

Research
/Security News
A Twitch browser extension on Chrome and Firefox forwards users’ live OAuth session tokens through proxies controlled by a Russian bot service.