* Acquire the state lock via atomic mkdir of a lock directory. Retries up to * LOCK_RETRIES times at LOCK_RETRY_MS intervals. A lock older than * LOCK_STALE_MS by mtime is considered abandoned and removed.
()
| 181 | * LOCK_STALE_MS by mtime is considered abandoned and removed. |
| 182 | */ |
| 183 | function acquireLock() { |
| 184 | if (!fs.existsSync(PLANNING_DIR)) { |
| 185 | fs.mkdirSync(PLANNING_DIR, { recursive: true }); |
| 186 | } |
| 187 | for (let attempt = 0; attempt < LOCK_RETRIES; attempt++) { |
| 188 | try { |
| 189 | fs.mkdirSync(LOCK_PATH); |
| 190 | return true; |
| 191 | } catch (err) { |
| 192 | if (err.code !== 'EEXIST') throw err; |
| 193 | try { |
| 194 | const stat = fs.statSync(LOCK_PATH); |
| 195 | if (Date.now() - stat.mtimeMs > LOCK_STALE_MS) { |
| 196 | fs.rmdirSync(LOCK_PATH); |
| 197 | continue; |
| 198 | } |
| 199 | } catch { |
| 200 | // Lock vanished between mkdir and stat; retry immediately. |
| 201 | continue; |
| 202 | } |
| 203 | sleepMs(LOCK_RETRY_MS); |
| 204 | } |
| 205 | } |
| 206 | return false; |
| 207 | } |
| 208 | |
| 209 | function releaseLock() { |
| 210 | try { |