Skip to content

Commit a701e2d

Browse files
committed
perf: debounce settings writes by 1s
Batch frequent settings.json updates into async non-blocking writes to reduce sync disk churn during active chat traffic.
1 parent fe651de commit a701e2d

File tree

1 file changed

+25
-1
lines changed

1 file changed

+25
-1
lines changed

packages/config/local/settings.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as fs from "fs";
22
import * as path from "path";
33
import * as os from "os";
4+
import { writeFile } from "fs/promises";
45
import {
56
setChannelCwd as setChannelCwdInConfig,
67
} from "./ode";
@@ -16,6 +17,7 @@ const homedir = typeof os.homedir === "function" ? os.homedir : () => "";
1617
const ODE_CONFIG_DIR = join(homedir(), ".config", "ode");
1718
const SETTINGS_FILE = join(ODE_CONFIG_DIR, "settings.json");
1819
const AGENTS_DIR = join(ODE_CONFIG_DIR, "agents");
20+
const SETTINGS_SAVE_DEBOUNCE_MS = 1000;
1921

2022
export interface ChannelSettings {
2123
threadSessions: Record<string, string>; // threadId -> sessionId
@@ -34,6 +36,9 @@ export interface Settings {
3436
}
3537

3638
let cachedSettings: Settings | null = null;
39+
let pendingSettingsWriteTimer: ReturnType<typeof setTimeout> | null = null;
40+
let pendingSettingsSnapshot: Settings | null = null;
41+
let settingsWriteChain: Promise<void> = Promise.resolve();
3742

3843
function ensureDataDir(): void {
3944
if (!existsSync(ODE_CONFIG_DIR)) {
@@ -95,7 +100,26 @@ export function saveSettings(settings: Settings): void {
95100
...settings,
96101
channels: normalizedChannels,
97102
};
98-
writeFileSync(SETTINGS_FILE, JSON.stringify(cachedSettings, null, 2));
103+
104+
pendingSettingsSnapshot = structuredClone(cachedSettings);
105+
if (pendingSettingsWriteTimer) {
106+
clearTimeout(pendingSettingsWriteTimer);
107+
pendingSettingsWriteTimer = null;
108+
}
109+
110+
pendingSettingsWriteTimer = setTimeout(() => {
111+
pendingSettingsWriteTimer = null;
112+
const snapshot = pendingSettingsSnapshot;
113+
if (!snapshot) return;
114+
pendingSettingsSnapshot = null;
115+
const payload = JSON.stringify(snapshot, null, 2);
116+
settingsWriteChain = settingsWriteChain
117+
.catch(() => undefined)
118+
.then(async () => {
119+
await writeFile(SETTINGS_FILE, payload, "utf-8");
120+
})
121+
.catch(() => undefined);
122+
}, SETTINGS_SAVE_DEBOUNCE_MS);
99123
}
100124

101125
export function getPendingRestartMessages(): PendingRestartMessage[] {

0 commit comments

Comments
 (0)