Upload via GUI (16 Dateien)
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
// lock.js — soft lock so the second PC gets warned instead of silently
|
||||
// overwriting the other PC's work. This is advisory, not a hard database lock:
|
||||
// sql.js rewrites the whole .db file on every save, so if both PCs really did
|
||||
// write at the same time, the last save wins. The heartbeat file makes that
|
||||
// situation visible before it happens instead of after.
|
||||
"use strict";
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const os = require("os");
|
||||
|
||||
const HEARTBEAT_MS = 10_000;
|
||||
const STALE_AFTER_MS = 30_000;
|
||||
|
||||
let lockPath = null;
|
||||
let heartbeatTimer = null;
|
||||
let myToken = null;
|
||||
|
||||
function readLock(dataFolder) {
|
||||
const p = path.join(dataFolder, ".fellakte.lock");
|
||||
if (!fs.existsSync(p)) return null;
|
||||
try {
|
||||
return JSON.parse(fs.readFileSync(p, "utf8"));
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether another PC currently looks active.
|
||||
* Returns { active:boolean, info } — info is the other host's lock contents when active.
|
||||
*/
|
||||
function checkOther(dataFolder) {
|
||||
const info = readLock(dataFolder);
|
||||
if (!info) return { active: false, info: null };
|
||||
const age = Date.now() - info.updatedAt;
|
||||
const isOther = info.host !== os.hostname() || info.pid !== process.pid;
|
||||
return { active: isOther && age < STALE_AFTER_MS, info };
|
||||
}
|
||||
|
||||
function acquire(dataFolder) {
|
||||
lockPath = path.join(dataFolder, ".fellakte.lock");
|
||||
myToken = { host: os.hostname(), pid: process.pid, updatedAt: Date.now() };
|
||||
fs.writeFileSync(lockPath, JSON.stringify(myToken));
|
||||
heartbeatTimer = setInterval(() => {
|
||||
myToken.updatedAt = Date.now();
|
||||
try {
|
||||
fs.writeFileSync(lockPath, JSON.stringify(myToken));
|
||||
} catch {
|
||||
// shared drive briefly unreachable — next tick will retry
|
||||
}
|
||||
}, HEARTBEAT_MS);
|
||||
}
|
||||
|
||||
function release() {
|
||||
if (heartbeatTimer) clearInterval(heartbeatTimer);
|
||||
heartbeatTimer = null;
|
||||
if (lockPath && fs.existsSync(lockPath)) {
|
||||
try {
|
||||
const current = readLock(path.dirname(lockPath));
|
||||
if (current && current.host === os.hostname() && current.pid === process.pid) {
|
||||
fs.unlinkSync(lockPath);
|
||||
}
|
||||
} catch {
|
||||
// best effort — a stale lock will simply age out after STALE_AFTER_MS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { checkOther, acquire, release };
|
||||
Reference in New Issue
Block a user