fix(sessions): skip durable fsync for session store

This commit is contained in:
Peter Steinberger
2026-05-07 12:31:18 +01:00
parent 01dd593cfd
commit 897bac5b8c
3 changed files with 27 additions and 1 deletions

View File

@@ -10,6 +10,7 @@ Docs: https://docs.openclaw.ai
- Discord/voice: keep TTS playback running when another user starts speaking, ignore new capture during playback to avoid feedback loops, and downgrade expected receive-stream aborts to verbose diagnostics.
- Telegram: treat successful same-chat `message` tool outbound sends during an inbound telegram turn as delivered when deciding whether to emit the rewritten silent reply fallback (#78685). Thanks @neeravmakwana.
- Gateway/tasks: reconcile stale CLI run-context tasks whose live run context disappeared even when a child session row remains, and apply the default bounded reload deferral timeout to channel hot reloads so stale task records cannot block Discord/Slack/Telegram reloads forever.
- Gateway/sessions: keep session-store index writes atomic while skipping durable fsync inside the writer lock, reducing cron and channel-turn starvation on slow filesystems. Fixes #73655. Thanks @mmartoccia.
- Discord/voice: make `openclaw channels capabilities --channel discord --target channel:<id>` and `channels status --probe` audit voice-channel permissions, including auto-join targets, so missing Connect/Speak/Read Message History permissions show up before `/vc join`.
- Channels CLI: make `openclaw channels list` channel-only — drop the `Auth providers (OAuth + API keys)` block (use `openclaw models auth list`), drop the per-provider usage/quota fetch and the `--no-usage` flag (use `openclaw status` or `openclaw models list`), add `--all` to surface bundled-unconfigured, catalog-not-installed, and catalog-installed-but-unconfigured channels, and render explicit `installed` / `configured` / `enabled` tags per row plus an `origin` + `installed` field in JSON. Fixes WeCom-class catalog channels disappearing from `--all` when installed on disk but not yet configured. (#78456) Thanks @sliverp.
- CLI/cron: add computed `status` field to `cron list --json` and `cron show <id> --json` output, mirroring the human-readable status column (disabled/running/ok/error/skipped/idle) so external tooling can determine job state without re-deriving it from raw state fields. (#78701) Thanks @aweiker.

View File

@@ -337,6 +337,31 @@ describe("session store writer queue", () => {
writeSpy.mockRestore();
});
it("keeps session store writes atomic while skipping durable fsync inside the writer lock", async () => {
const key = "agent:main:no-fsync";
const { storePath } = await makeTmpStore({
[key]: { sessionId: "s-no-fsync", updatedAt: Date.now(), counter: 0 },
});
const writeSpy = vi.spyOn(jsonFiles, "writeTextAtomic");
await updateSessionStore(
storePath,
async (store) => {
const entry = store[key] as Record<string, unknown>;
entry.counter = 1;
},
{ skipMaintenance: true },
);
expect(writeSpy).toHaveBeenCalledTimes(1);
expect(writeSpy).toHaveBeenCalledWith(
storePath,
expect.any(String),
expect.objectContaining({ durable: false, mode: 0o600 }),
);
writeSpy.mockRestore();
});
it("multiple consecutive errors do not permanently poison the queue", async () => {
const key = "agent:main:multi-err";
const { storePath } = await makeTmpStore({

View File

@@ -499,7 +499,7 @@ async function writeSessionStoreAtomic(params: {
store: Record<string, SessionEntry>;
serialized: string;
}): Promise<void> {
await writeTextAtomic(params.storePath, params.serialized, { mode: 0o600 });
await writeTextAtomic(params.storePath, params.serialized, { durable: false, mode: 0o600 });
updateSessionStoreWriteCaches({
storePath: params.storePath,
store: params.store,