fix(trigger): tolerate unsupported directory fsync

This commit is contained in:
Xubin Ren
2026-07-02 13:32:46 +08:00
parent 661ab00656
commit fd9e57703c
2 changed files with 42 additions and 1 deletions
+6 -1
View File
@@ -2,6 +2,7 @@
from __future__ import annotations from __future__ import annotations
import errno
import json import json
import os import os
import secrets import secrets
@@ -402,7 +403,11 @@ class LocalTriggerStore:
with suppress(PermissionError): with suppress(PermissionError):
fd = os.open(str(path.parent), os.O_RDONLY) fd = os.open(str(path.parent), os.O_RDONLY)
try: try:
os.fsync(fd) try:
os.fsync(fd)
except OSError as exc:
if exc.errno != errno.EINVAL:
raise
finally: finally:
os.close(fd) os.close(fd)
except BaseException: except BaseException:
+36
View File
@@ -1,7 +1,9 @@
from __future__ import annotations from __future__ import annotations
import asyncio import asyncio
import errno
import json import json
import os
from contextlib import suppress from contextlib import suppress
from pathlib import Path from pathlib import Path
@@ -60,6 +62,40 @@ def test_trigger_store_allows_multiple_triggers_per_session(tmp_path: Path) -> N
assert first.id != second.id assert first.id != second.id
def test_trigger_store_atomic_write_ignores_unsupported_directory_fsync(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""Shared folders may allow opening directories but reject directory fsync."""
store = LocalTriggerStore(tmp_path)
real_open = os.open
real_fsync = os.fsync
directory_fds: set[int] = set()
def fake_open(path: str, flags: int, *args: object, **kwargs: object) -> int:
fd = real_open(path, flags, *args, **kwargs)
if Path(path).name == "triggers":
directory_fds.add(fd)
return fd
def fake_fsync(fd: int) -> None:
if fd in directory_fds:
raise OSError(errno.EINVAL, "Invalid argument")
real_fsync(fd)
monkeypatch.setattr(os, "open", fake_open)
monkeypatch.setattr(os, "fsync", fake_fsync)
trigger = store.create(
name="Shared folder safe",
channel="websocket",
chat_id="chat-1",
session_key="websocket:chat-1",
)
assert store.get(trigger.id) is not None
def test_enqueue_rejects_disabled_trigger(tmp_path: Path) -> None: def test_enqueue_rejects_disabled_trigger(tmp_path: Path) -> None:
store = LocalTriggerStore(tmp_path) store = LocalTriggerStore(tmp_path)
trigger = store.create( trigger = store.create(