diff --git a/cache_manager.py b/cache_manager.py index 5f4f3fa..24c798a 100644 --- a/cache_manager.py +++ b/cache_manager.py @@ -243,25 +243,25 @@ class L1CacheManager: def get_by_content_hash(self, content_hash: str) -> Optional[Path]: """Get cached file path by content_hash.""" - # Check index first + # Check index first (new cache structure) node_id = self._content_index.get(content_hash) if node_id: path = self.cache.get(node_id) - if path: + if path and path.exists(): return path - # Check legacy directory - legacy_path = self.legacy_dir / content_hash - if legacy_path.exists(): - return legacy_path - - # Scan cache entries (fallback) + # Scan cache entries (fallback for new structure) entry = self.cache.find_by_content_hash(content_hash) - if entry: + if entry and entry.output_path.exists(): self._content_index[content_hash] = entry.node_id self._save_content_index() return entry.output_path + # Check legacy location (files stored directly as CACHE_DIR/{content_hash}) + legacy_path = self.cache_dir / content_hash + if legacy_path.exists() and legacy_path.is_file(): + return legacy_path + return None def has_content(self, content_hash: str) -> bool: diff --git a/server.py b/server.py index 256a15f..c6a4cd1 100644 --- a/server.py +++ b/server.py @@ -161,24 +161,16 @@ def cache_file(source: Path, node_type: str = "output") -> str: Copy file to cache using L1CacheManager, return content hash. Uses artdag's Cache internally for proper tracking. - Also creates a symlink in legacy location for backward compatibility. """ cached = cache_manager.put(source, node_type=node_type) - - # Create symlink in legacy location for backward compatibility - legacy_path = CACHE_DIR / cached.content_hash - if not legacy_path.exists(): - try: - legacy_path.symlink_to(cached.path) - except (OSError, FileExistsError): - # Symlink failed, try copy - import shutil - if not legacy_path.exists(): - shutil.copy2(cached.path, legacy_path) - return cached.content_hash +def get_cache_path(content_hash: str) -> Optional[Path]: + """Get the path for a cached file by content_hash.""" + return cache_manager.get_by_content_hash(content_hash) + + @app.get("/api") async def api_info(): """Server info (JSON).""" @@ -456,14 +448,14 @@ async def run_detail(run_id: str, request: Request): # Build media HTML for input/output media_html = "" - has_input = run.inputs and (CACHE_DIR / run.inputs[0]).exists() - has_output = run.status == "completed" and run.output_hash and (CACHE_DIR / run.output_hash).exists() + has_input = run.inputs and cache_manager.has_content(run.inputs[0]) + has_output = run.status == "completed" and run.output_hash and cache_manager.has_content(run.output_hash) if has_input or has_output: media_html = '
Content not found: {content_hash}
' return HTMLResponse(render_page("Not Found", content, current_user, active_tab="cache"), status_code=404) @@ -1001,8 +977,8 @@ async def ui_cache_meta_form(content_hash: str, request: Request): pin_reason = meta.get("pin_reason", "") # Detect media type for publish - cache_path = CACHE_DIR / content_hash - media_type = detect_media_type(cache_path) if cache_path.exists() else "unknown" + cache_path = get_cache_path(content_hash) + media_type = detect_media_type(cache_path) if cache_path else "unknown" asset_type = "video" if media_type == "video" else "image" # Origin radio checked states @@ -1404,8 +1380,8 @@ async def list_cache( html_parts = [] for item in items_page: content_hash = item["hash"] - cache_path = CACHE_DIR / content_hash - media_type = detect_media_type(cache_path) + cache_path = get_cache_path(content_hash) + media_type = detect_media_type(cache_path) if cache_path else "unknown" # Format size size = item["size"] @@ -1509,11 +1485,9 @@ async def discard_cache(content_hash: str, username: str = Depends(get_required_ - Cannot delete inputs/outputs of activities (runs) - Cannot delete pinned items """ - # Check if content exists (in cache_manager or legacy location) + # Check if content exists if not cache_manager.has_content(content_hash): - cache_path = CACHE_DIR / content_hash - if not cache_path.exists(): - raise HTTPException(404, "Content not found") + raise HTTPException(404, "Content not found") # Check ownership user_hashes = get_user_cache_hashes(username) @@ -1535,8 +1509,8 @@ async def discard_cache(content_hash: str, username: str = Depends(get_required_ success, msg = cache_manager.delete_by_content_hash(content_hash) if not success: # Fallback to legacy deletion - cache_path = CACHE_DIR / content_hash - if cache_path.exists(): + cache_path = get_cache_path(content_hash) + if cache_path and cache_path.exists(): cache_path.unlink() # Clean up legacy metadata files @@ -1564,9 +1538,7 @@ async def ui_discard_cache(content_hash: str, request: Request): # Check if content exists if not cache_manager.has_content(content_hash): - cache_path = CACHE_DIR / content_hash - if not cache_path.exists(): - return '