Reclaim stale script lock after crash (v1.3.1)
The single-tab lock was only released in beforeunload, so a browser crash or power-cut left the localStorage key behind and the script exited on every subsequent load until site data was cleared. Treat a lock not refreshed within 90s as dead and take it over, and add a 30s heartbeat so a live instance keeps its lock fresh. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
31
cams.user.js
31
cams.user.js
@@ -1,7 +1,7 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name cams
|
// @name cams
|
||||||
// @namespace http://tampermonkey.net/
|
// @namespace http://tampermonkey.net/
|
||||||
// @version 1.3.0
|
// @version 1.3.1
|
||||||
// @description Set maxDockedCamsForUser, keep-alive, and multi-poke
|
// @description Set maxDockedCamsForUser, keep-alive, and multi-poke
|
||||||
// @author You
|
// @author You
|
||||||
// @match https://chat.fabswingers.com/*
|
// @match https://chat.fabswingers.com/*
|
||||||
@@ -223,18 +223,37 @@
|
|||||||
localStorage.setItem(KEEPALIVE_SETTINGS_KEY, JSON.stringify(keepAliveSettings));
|
localStorage.setItem(KEEPALIVE_SETTINGS_KEY, JSON.stringify(keepAliveSettings));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to acquire lock
|
// Try to acquire lock.
|
||||||
const lockValue = Date.now().toString();
|
// The lock value is a timestamp that a live instance refreshes on a heartbeat.
|
||||||
|
// If a crash / power-cut kills the tab, beforeunload never fires and the key is
|
||||||
|
// left behind; a new load treats a lock older than LOCK_STALE_MS as dead and
|
||||||
|
// takes over, instead of exiting forever (which required clearing site data).
|
||||||
|
const LOCK_STALE_MS = 90 * 1000; // reclaim a lock not refreshed within 90s
|
||||||
|
const LOCK_HEARTBEAT_MS = 30 * 1000; // refresh our lock every 30s while alive
|
||||||
|
let ourLockValue = Date.now().toString();
|
||||||
|
|
||||||
if (localStorage.getItem(LOCK_KEY)) {
|
const existingLock = localStorage.getItem(LOCK_KEY);
|
||||||
|
if (existingLock) {
|
||||||
|
const lockAge = Date.now() - parseInt(existingLock, 10);
|
||||||
|
if (isNaN(lockAge) || lockAge < LOCK_STALE_MS) {
|
||||||
console.log('MaxDockedCams: Another instance already running, exiting');
|
console.log('MaxDockedCams: Another instance already running, exiting');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
console.log(`MaxDockedCams: Reclaiming stale lock (${Math.round(lockAge / 1000)}s old)`);
|
||||||
|
}
|
||||||
|
|
||||||
localStorage.setItem(LOCK_KEY, lockValue);
|
localStorage.setItem(LOCK_KEY, ourLockValue);
|
||||||
|
|
||||||
|
// Keep our lock fresh so a live instance is never mistaken for a crashed one.
|
||||||
|
setInterval(function() {
|
||||||
|
if (localStorage.getItem(LOCK_KEY) === ourLockValue) {
|
||||||
|
ourLockValue = Date.now().toString();
|
||||||
|
localStorage.setItem(LOCK_KEY, ourLockValue);
|
||||||
|
}
|
||||||
|
}, LOCK_HEARTBEAT_MS);
|
||||||
|
|
||||||
window.addEventListener('beforeunload', function() {
|
window.addEventListener('beforeunload', function() {
|
||||||
if (localStorage.getItem(LOCK_KEY) === lockValue) {
|
if (localStorage.getItem(LOCK_KEY) === ourLockValue) {
|
||||||
localStorage.removeItem(LOCK_KEY);
|
localStorage.removeItem(LOCK_KEY);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
2
meta.js
2
meta.js
@@ -1,7 +1,7 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name cams
|
// @name cams
|
||||||
// @namespace http://tampermonkey.net/
|
// @namespace http://tampermonkey.net/
|
||||||
// @version 1.3.0
|
// @version 1.3.1
|
||||||
// @description Set maxDockedCamsForUser, keep-alive, and multi-poke
|
// @description Set maxDockedCamsForUser, keep-alive, and multi-poke
|
||||||
// @author You
|
// @author You
|
||||||
// @match https://chat.fabswingers.com/*
|
// @match https://chat.fabswingers.com/*
|
||||||
|
|||||||
Reference in New Issue
Block a user