fix: stop settings.json from being wiped on launch
Electron main, ssh-manager, and the embedded web server all write the
same settings.json. readJsonFile/readJsonRoot silently coerced any read
failure (including mid-write parse errors) to {}, and writes were plain
fs.writeFile. A partial read during a concurrent write let the reader's
next read-modify-write overwrite the whole file with only the field it
just set — wiping projects, desktopDefaultHostId, and more. Next launch
showed the welcome chooser because defaultHostId was gone, and the
sidebar was empty because projects were gone.
- Switch all writers to atomic tmp+rename so readers never see partial
JSON.
- Add mutateSettingsRoot() in Electron main to serialize read-modify-
write pairs across its own call sites (hosts config, window state,
desktop port, ssh instances, vibrancy).
- Keep read-on-error returning {} to avoid crashing startup callers,
but log loudly now so we can catch it if it ever happens again.
- useProjectsStore: don't clobber a populated cache with empty incoming
settings. If settings ever do come back empty, the sidebar stays
intact until a real, non-empty sync lands.
This commit is contained in:
@@ -72,7 +72,12 @@ const readJsonRoot = (settingsFilePath) => {
|
||||
|
||||
const writeJsonRoot = async (settingsFilePath, root) => {
|
||||
await fsp.mkdir(path.dirname(settingsFilePath), { recursive: true });
|
||||
await fsp.writeFile(settingsFilePath, JSON.stringify(root, null, 2));
|
||||
// Atomic write: concurrent readers (main.mjs, web server) would otherwise
|
||||
// see partial JSON and readJsonRoot()'s catch would silently coerce to {},
|
||||
// causing the next read-modify-write to wipe the entire settings file.
|
||||
const tmp = `${settingsFilePath}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
||||
await fsp.writeFile(tmp, JSON.stringify(root, null, 2));
|
||||
await fsp.rename(tmp, settingsFilePath);
|
||||
};
|
||||
|
||||
const defaultTrue = () => true;
|
||||
|
||||
Reference in New Issue
Block a user