fix(scanner): offload persisted-cache hydration from the event loop

This commit is contained in:
Will Miao
2026-08-25 17:38:09 +08:00
parent c83b26b556
commit cdb044cb45
4 changed files with 204 additions and 73 deletions
@@ -236,24 +236,33 @@ class DownloadedVersionHistoryService:
return
async with self._lock:
conn = self._get_conn()
conn.executemany(
"""
INSERT INTO downloaded_model_versions (
model_type, version_id, model_id, first_seen_at, last_seen_at,
source, last_file_path, last_library_name, is_deleted_override
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 0)
ON CONFLICT(model_type, version_id) DO UPDATE SET
model_id = COALESCE(excluded.model_id, downloaded_model_versions.model_id),
last_seen_at = excluded.last_seen_at,
source = excluded.source,
last_file_path = COALESCE(excluded.last_file_path, downloaded_model_versions.last_file_path),
last_library_name = COALESCE(excluded.last_library_name, downloaded_model_versions.last_library_name),
is_deleted_override = 0
""",
payload,
)
conn.commit()
# The connection is created with check_same_thread=False and all
# access is serialized by self._lock, so the executemany upsert +
# commit can run in the default executor without blocking the
# event loop on large hydration payloads.
loop = asyncio.get_running_loop()
await loop.run_in_executor(None, self._mark_downloaded_bulk_sync, payload)
def _mark_downloaded_bulk_sync(self, payload: Sequence[tuple[object, ...]]) -> None:
"""Synchronous executemany upsert + commit; runs in a worker thread."""
conn = self._get_conn()
conn.executemany(
"""
INSERT INTO downloaded_model_versions (
model_type, version_id, model_id, first_seen_at, last_seen_at,
source, last_file_path, last_library_name, is_deleted_override
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 0)
ON CONFLICT(model_type, version_id) DO UPDATE SET
model_id = COALESCE(excluded.model_id, downloaded_model_versions.model_id),
last_seen_at = excluded.last_seen_at,
source = excluded.source,
last_file_path = COALESCE(excluded.last_file_path, downloaded_model_versions.last_file_path),
last_library_name = COALESCE(excluded.last_library_name, downloaded_model_versions.last_library_name),
is_deleted_override = 0
""",
payload,
)
conn.commit()
async def mark_as_deleted(self, model_type: str, version_id: int) -> None:
normalized_type = _normalize_model_type(model_type)