Add debug logging to cache lookup
This commit is contained in:
21
README.md
21
README.md
@@ -36,9 +36,12 @@ Interactive docs: http://localhost:8100/docs
|
||||
| POST | `/runs` | Start a rendering run |
|
||||
| GET | `/runs` | List all runs |
|
||||
| GET | `/runs/{run_id}` | Get run status |
|
||||
| DELETE | `/runs/{run_id}` | Delete a run |
|
||||
| GET | `/cache` | List cached content hashes |
|
||||
| GET | `/cache/{hash}` | Download cached content |
|
||||
| DELETE | `/cache/{hash}` | Delete cached content |
|
||||
| POST | `/cache/import?path=` | Import local file to cache |
|
||||
| POST | `/cache/upload` | Upload file to cache |
|
||||
| GET | `/assets` | List known assets |
|
||||
|
||||
### Start a run
|
||||
@@ -55,6 +58,24 @@ curl -X POST http://localhost:8100/runs \
|
||||
curl http://localhost:8100/runs/{run_id}
|
||||
```
|
||||
|
||||
### Delete a run
|
||||
|
||||
```bash
|
||||
curl -X DELETE http://localhost:8100/runs/{run_id} \
|
||||
-H "Authorization: Bearer <token>"
|
||||
```
|
||||
|
||||
Note: Failed runs can always be deleted. Completed runs can only be deleted if their outputs haven't been published to L2.
|
||||
|
||||
### Delete cached content
|
||||
|
||||
```bash
|
||||
curl -X DELETE http://localhost:8100/cache/{hash} \
|
||||
-H "Authorization: Bearer <token>"
|
||||
```
|
||||
|
||||
Note: Items that are inputs/outputs of runs, or published to L2, cannot be deleted.
|
||||
|
||||
## Storage
|
||||
|
||||
- **Cache**: `~/.artdag/cache/` (content-addressed files)
|
||||
|
||||
@@ -243,33 +243,46 @@ class L1CacheManager:
|
||||
|
||||
def get_by_content_hash(self, content_hash: str) -> Optional[Path]:
|
||||
"""Get cached file path by content_hash."""
|
||||
logger.info(f"get_by_content_hash({content_hash[:16]}...) - cache_dir={self.cache_dir}, nodes_dir={self.cache.cache_dir}")
|
||||
|
||||
# Check index first (new cache structure)
|
||||
node_id = self._content_index.get(content_hash)
|
||||
if node_id:
|
||||
logger.info(f" Found in content_index: node_id={node_id[:16]}...")
|
||||
path = self.cache.get(node_id)
|
||||
if path and path.exists():
|
||||
logger.info(f" Found via index: {path}")
|
||||
return path
|
||||
logger.info(f" Index entry but path not found: {path}")
|
||||
|
||||
# For uploads, node_id == content_hash, so try direct lookup
|
||||
# This works even if cache index hasn't been reloaded
|
||||
logger.info(f" Trying direct lookup with content_hash as node_id...")
|
||||
path = self.cache.get(content_hash)
|
||||
logger.info(f" cache.get({content_hash[:16]}...) returned: {path}")
|
||||
if path and path.exists():
|
||||
logger.info(f" Found via direct lookup: {path}")
|
||||
self._content_index[content_hash] = content_hash
|
||||
self._save_content_index()
|
||||
return path
|
||||
|
||||
# Scan cache entries (fallback for new structure)
|
||||
logger.info(f" Trying find_by_content_hash...")
|
||||
entry = self.cache.find_by_content_hash(content_hash)
|
||||
if entry and entry.output_path.exists():
|
||||
logger.info(f" Found via scan: {entry.output_path}")
|
||||
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
|
||||
logger.info(f" Checking legacy path: {legacy_path}, exists={legacy_path.exists()}")
|
||||
if legacy_path.exists() and legacy_path.is_file():
|
||||
logger.info(f" Found at legacy location: {legacy_path}")
|
||||
return legacy_path
|
||||
|
||||
logger.info(f" NOT FOUND anywhere")
|
||||
return None
|
||||
|
||||
def has_content(self, content_hash: str) -> bool:
|
||||
|
||||
36
server.py
36
server.py
@@ -280,6 +280,42 @@ async def root():
|
||||
return HOME_HTML
|
||||
|
||||
|
||||
@app.get("/debug/cache/{content_hash}")
|
||||
async def debug_cache(content_hash: str):
|
||||
"""Debug endpoint to check cache status for a content hash."""
|
||||
import os
|
||||
|
||||
result = {
|
||||
"content_hash": content_hash,
|
||||
"cache_dir": str(cache_manager.cache_dir),
|
||||
"nodes_dir": str(cache_manager.cache.cache_dir),
|
||||
"in_content_index": content_hash in cache_manager._content_index,
|
||||
"node_id_from_index": cache_manager._content_index.get(content_hash),
|
||||
}
|
||||
|
||||
# Check various locations
|
||||
locations = {
|
||||
"legacy_direct": cache_manager.cache_dir / content_hash,
|
||||
"nodes_dir": cache_manager.cache.cache_dir / content_hash,
|
||||
}
|
||||
|
||||
for name, path in locations.items():
|
||||
result[f"{name}_path"] = str(path)
|
||||
result[f"{name}_exists"] = path.exists()
|
||||
if path.exists() and path.is_dir():
|
||||
result[f"{name}_contents"] = [f.name for f in path.iterdir()]
|
||||
|
||||
# Check if artdag cache has it
|
||||
result["artdag_cache_get"] = str(cache_manager.cache.get(content_hash))
|
||||
|
||||
# Check via cache_manager
|
||||
found_path = cache_manager.get_by_content_hash(content_hash)
|
||||
result["cache_manager_path"] = str(found_path) if found_path else None
|
||||
result["has_content"] = cache_manager.has_content(content_hash)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@app.post("/runs", response_model=RunStatus)
|
||||
async def create_run(request: RunRequest, username: str = Depends(get_required_user)):
|
||||
"""Start a new rendering run. Requires authentication."""
|
||||
|
||||
Reference in New Issue
Block a user