fix(session): tolerate unsupported directory fsync

This commit is contained in:
sunpengcheng05
2026-07-21 10:11:53 +08:00
committed by chengyongru
parent 9db0d9f3c9
commit 4a79cbb6e7
2 changed files with 50 additions and 3 deletions
+8 -3
View File
@@ -1,6 +1,7 @@
"""Session management for conversation history."""
import base64
import errno
import json
import os
import re
@@ -688,12 +689,16 @@ class SessionManager:
if fsync:
# fsync the directory so the rename is durable.
# On Windows, opening a directory with O_RDONLY raises
# PermissionError — skip the dir sync there (NTFS
# journals metadata synchronously).
# PermissionError; some shared filesystems allow the open but
# reject directory fsync with EINVAL.
with suppress(PermissionError):
fd = os.open(str(path.parent), os.O_RDONLY)
try:
os.fsync(fd)
try:
os.fsync(fd)
except OSError as exc:
if exc.errno != errno.EINVAL:
raise
finally:
os.close(fd)
except BaseException:
+42
View File
@@ -2,6 +2,8 @@
from __future__ import annotations
import errno
import os
import sys
from pathlib import Path
from unittest.mock import patch
@@ -55,6 +57,46 @@ class TestSaveFsync:
manager.save(session)
mock_fsync.assert_not_called()
def test_save_ignores_unsupported_directory_fsync(
self, manager: SessionManager
) -> None:
"""Shared filesystems may open directories but reject directory fsync."""
session = manager.get_or_create("test:unsupported-directory-fsync")
session.add_message("user", "hello")
directory_fd = 987654
with (
patch("nanobot.session.manager.os.open", return_value=directory_fd) as open_dir,
patch(
"nanobot.session.manager.os.fsync",
side_effect=[None, OSError(errno.EINVAL, "Invalid argument")],
),
patch("nanobot.session.manager.os.close") as close_dir,
):
manager.save(session, fsync=True)
assert manager._get_session_path(session.key).exists()
open_dir.assert_called_once_with(str(manager.sessions_dir), os.O_RDONLY)
close_dir.assert_called_once_with(directory_fd)
def test_save_propagates_other_directory_fsync_errors(
self, manager: SessionManager
) -> None:
"""Only EINVAL is an expected unsupported-directory-fsync result."""
session = manager.get_or_create("test:directory-fsync-io-error")
directory_fd = 987654
with (
patch("nanobot.session.manager.os.open", return_value=directory_fd),
patch(
"nanobot.session.manager.os.fsync",
side_effect=[None, OSError(errno.EIO, "I/O error")],
),
patch("nanobot.session.manager.os.close") as close_dir,
pytest.raises(OSError, match="I/O error"),
):
manager.save(session, fsync=True)
close_dir.assert_called_once_with(directory_fd)
class TestFlushAll:
"""Verify flush_all re-saves all cached sessions with fsync."""