feat(wordcloud): 收口在途开发(布局/存储/前端)+ R4 WCD 生产任务(jobs wcd_file)与生产订单列表
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Inspect and optionally clean stale job directories.
|
||||
|
||||
Default mode is a safe dry-run that reports reclaimable bytes. Pass --apply to
|
||||
actually remove unreferenced job directories.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
from .metadata_store import MetadataStore
|
||||
from .storage import Storage
|
||||
|
||||
|
||||
BACKEND_ROOT = Path(__file__).resolve().parents[1]
|
||||
PROJECT_ROOT = BACKEND_ROOT
|
||||
WORKSPACE_DIR = PROJECT_ROOT / "service_workspace"
|
||||
ASSETS_DIR = PROJECT_ROOT / "service_assets"
|
||||
METADATA_DIR = PROJECT_ROOT / "service_metadata"
|
||||
|
||||
|
||||
def read_asset_meta(path: Path) -> dict:
|
||||
try:
|
||||
return json.loads(path.read_text(encoding="utf-8"))
|
||||
except Exception:
|
||||
return {}
|
||||
|
||||
|
||||
def referenced_job_ids() -> set[str]:
|
||||
refs: set[str] = set()
|
||||
for meta_path in ASSETS_DIR.glob("*/*/meta.json"):
|
||||
job_id = read_asset_meta(meta_path).get("job_id") or ""
|
||||
if job_id:
|
||||
refs.add(job_id)
|
||||
return refs
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--max-age-days", type=float, default=0)
|
||||
parser.add_argument("--apply", action="store_true", help="Actually delete stale job directories")
|
||||
parser.add_argument("--json", type=Path, default=None, help="Write JSON report")
|
||||
args = parser.parse_args()
|
||||
|
||||
store = MetadataStore(METADATA_DIR / "app.db")
|
||||
storage = Storage(WORKSPACE_DIR)
|
||||
known_job_ids = store.job_ids() if store.db_path.exists() else set()
|
||||
referenced = referenced_job_ids()
|
||||
stale = storage.stale_job_dirs(
|
||||
referenced_job_ids=referenced,
|
||||
exclude_job_ids=known_job_ids,
|
||||
max_age_days=args.max_age_days,
|
||||
)
|
||||
|
||||
reclaimable = sum(item["size_bytes"] for item in stale)
|
||||
report = {
|
||||
"scanned_at": datetime.now(timezone.utc).isoformat(),
|
||||
"job_dir_count": len(storage.list_job_ids()),
|
||||
"referenced_job_ids": len(referenced),
|
||||
"known_job_ids": len(known_job_ids),
|
||||
"stale_job_count": len(stale),
|
||||
"reclaimable_bytes": reclaimable,
|
||||
"max_age_days": args.max_age_days,
|
||||
"apply": args.apply,
|
||||
"stale_jobs": stale[:200],
|
||||
}
|
||||
|
||||
print(json.dumps(report, ensure_ascii=False, indent=2))
|
||||
if args.json:
|
||||
args.json.write_text(json.dumps(report, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
|
||||
if args.apply:
|
||||
freed = 0
|
||||
for item in stale:
|
||||
freed += storage.remove_job_dir(item["job_id"])
|
||||
store.delete_job(item["job_id"])
|
||||
print(f"freed_bytes={freed}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user