From f9f726c0c1c58aeac51f7ea4cbc138720bd37c31 Mon Sep 17 00:00:00 2001 From: xiaoen <2768753269@qq.com> Date: Wed, 4 Mar 2026 19:21:34 +0800 Subject: [PATCH] fix(memory): fsync appended message for consistent durability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit addMsg now calls f.Sync() before f.Close(), matching the durability guarantee of writeMeta and rewriteJSONL (both use WriteFileAtomic with fsync). Without this, a power loss could leave the appended line in the kernel page cache only — lost on reboot. --- pkg/memory/jsonl.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/pkg/memory/jsonl.go b/pkg/memory/jsonl.go index efd4347c0..e12e2c5ab 100644 --- a/pkg/memory/jsonl.go +++ b/pkg/memory/jsonl.go @@ -236,11 +236,19 @@ func (s *JSONLStore) addMsg(sessionKey string, msg providers.Message) error { return fmt.Errorf("memory: open jsonl for append: %w", err) } _, writeErr := f.Write(line) - closeErr := f.Close() if writeErr != nil { + f.Close() return fmt.Errorf("memory: append message: %w", writeErr) } - if closeErr != nil { + // Flush to physical storage before closing. This matches the + // durability guarantee of writeMeta and rewriteJSONL (which use + // WriteFileAtomic with fsync). Without Sync, a power loss could + // leave the append in the kernel page cache only — lost on reboot. + if syncErr := f.Sync(); syncErr != nil { + f.Close() + return fmt.Errorf("memory: sync jsonl: %w", syncErr) + } + if closeErr := f.Close(); closeErr != nil { return fmt.Errorf("memory: close jsonl: %w", closeErr) }