fix(sync): autopass device-file on restart and new invite
CI / Build & Test (push) Successful in 4m46s
CI / Build & Test (push) Successful in 4m46s
- Remove autopass dir before createSyncInvite/pairWithInvite so Corestore gets a fresh device-file (device-file throws when inode/mtime changes) - Await sync/rdp/holesail cleanup on host shutdown so corestore closes before process exit - Reset initPromise on init failure so Create invite can retry after removing corrupt autopass dir
This commit is contained in:
@@ -126,12 +126,15 @@ async function handleMessageAsync(send, msg) {
|
||||
|
||||
function cleanup() {
|
||||
if (_scheduledBackupTimer) { clearTimeout(_scheduledBackupTimer); _scheduledBackupTimer = null; }
|
||||
syncManager.cleanup().catch(() => {});
|
||||
httpsProxy.stop(() => {});
|
||||
connectProxy.stop(() => {});
|
||||
sshManager.cleanup();
|
||||
rdpManager.cleanup().catch(() => {});
|
||||
holesailManager.cleanup().catch(() => {});
|
||||
return Promise.all([
|
||||
syncManager.cleanup().catch(() => {}),
|
||||
rdpManager.cleanup().catch(() => {}),
|
||||
holesailManager.cleanup().catch(() => {})
|
||||
]).then(() => {
|
||||
httpsProxy.stop(() => {});
|
||||
connectProxy.stop(() => {});
|
||||
sshManager.cleanup();
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { handleMessage: handleMessageAsync, cleanup };
|
||||
|
||||
@@ -71,19 +71,23 @@ const messenger = createMessenger({
|
||||
},
|
||||
});
|
||||
|
||||
function shutdown() {
|
||||
async function shutdown() {
|
||||
removePidFile();
|
||||
cleanup();
|
||||
try {
|
||||
const c = cleanup();
|
||||
if (c && typeof c.then === 'function') await c;
|
||||
} catch (_) {}
|
||||
messenger.destroy();
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
process.on('exit', () => {
|
||||
removePidFile();
|
||||
cleanup();
|
||||
const c = cleanup();
|
||||
if (c && typeof c.then === 'function') c.catch(() => {});
|
||||
});
|
||||
process.on('SIGTERM', shutdown);
|
||||
process.on('SIGINT', shutdown);
|
||||
process.on('SIGTERM', () => { shutdown().catch(() => process.exit(1)); });
|
||||
process.on('SIGINT', () => { shutdown().catch(() => process.exit(1)); });
|
||||
|
||||
process.on('unhandledRejection', (reason) => {
|
||||
logErr('unhandledRejection: ' + (reason && (reason.stack || reason.message || reason)));
|
||||
|
||||
@@ -127,6 +127,26 @@ async function closeSyncForBackup() {
|
||||
await closePass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the autopass directory so a new Corestore can be created with a fresh device-file.
|
||||
* The device-file package throws "Invalid device file, was modified" if inode/mtime changes
|
||||
* (e.g. after restart or when reusing the same path for a new identity). Used before
|
||||
* createSyncInvite and pairWithInvite so we start with a clean store.
|
||||
*/
|
||||
function removeAutopassDir() {
|
||||
const autopassPath = getAutopassPath();
|
||||
if (!autopassPath) return;
|
||||
try {
|
||||
if (fs.existsSync(autopassPath)) {
|
||||
fs.rmSync(autopassPath, { recursive: true });
|
||||
}
|
||||
} catch (e) {
|
||||
if (e.code !== 'ENOENT' && process.stderr) {
|
||||
process.stderr.write('[sync-manager] removeAutopassDir: ' + e.message + '\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function ensureInitialized() {
|
||||
if (initPromise) return initPromise;
|
||||
initPromise = (async () => {
|
||||
@@ -148,6 +168,7 @@ async function ensureInitialized() {
|
||||
if (process.stderr) process.stderr.write('[sync-manager] init failed: ' + e.message + '\n');
|
||||
store = null;
|
||||
pass = null;
|
||||
initPromise = null; // allow retry on next getSyncStatus (e.g. after Create invite clears autopass dir)
|
||||
}
|
||||
})();
|
||||
await initPromise;
|
||||
@@ -352,6 +373,7 @@ async function getSyncStatus() {
|
||||
async function createSyncInvite() {
|
||||
if (!storageDir) return { ok: false, error: 'Storage path not set' };
|
||||
await closePass();
|
||||
removeAutopassDir();
|
||||
clearIdentity();
|
||||
try {
|
||||
const Corestore = require('corestore');
|
||||
@@ -379,6 +401,7 @@ async function createSyncInvite() {
|
||||
async function pairWithInvite(invite) {
|
||||
if (!storageDir || !invite || typeof invite !== 'string') return { ok: false, error: 'Storage path and invite required' };
|
||||
await closePass();
|
||||
removeAutopassDir();
|
||||
clearIdentity();
|
||||
try {
|
||||
const Corestore = require('corestore');
|
||||
|
||||
Reference in New Issue
Block a user