feat(wordcloud): 收口在途开发(布局/存储/前端)+ R4 WCD 生产任务(jobs wcd_file)与生产订单列表
This commit is contained in:
@@ -1,10 +1,17 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
from .schemas import JobPaths
|
||||
|
||||
|
||||
_JOB_ID_RE = re.compile(r"^[0-9a-f]{32,}$")
|
||||
|
||||
|
||||
class Storage:
|
||||
def __init__(self, base_dir: Path) -> None:
|
||||
self.base_dir = base_dir
|
||||
@@ -25,3 +32,70 @@ class Storage:
|
||||
excel_path=input_dir / "names.xlsx",
|
||||
config_path=root / "config.json",
|
||||
)
|
||||
|
||||
def job_root(self, job_id: str) -> Path:
|
||||
return self.base_dir / job_id
|
||||
|
||||
def job_dir_size(self, job_id: str) -> int:
|
||||
root = self.job_root(job_id)
|
||||
if not root.exists():
|
||||
return 0
|
||||
total = 0
|
||||
for dirpath, _, filenames in os.walk(root):
|
||||
for filename in filenames:
|
||||
try:
|
||||
total += os.path.getsize(os.path.join(dirpath, filename))
|
||||
except OSError:
|
||||
continue
|
||||
return total
|
||||
|
||||
def job_dir_info(self, job_id: str) -> dict | None:
|
||||
root = self.job_root(job_id)
|
||||
if not root.is_dir():
|
||||
return None
|
||||
try:
|
||||
mtime = root.stat().st_mtime
|
||||
except OSError:
|
||||
return None
|
||||
return {
|
||||
"job_id": job_id,
|
||||
"path": str(root),
|
||||
"size_bytes": self.job_dir_size(job_id),
|
||||
"age_days": round(max(0.0, time.time() - mtime) / 86400.0, 2),
|
||||
}
|
||||
|
||||
def list_job_ids(self) -> list[str]:
|
||||
if not self.base_dir.exists():
|
||||
return []
|
||||
return [
|
||||
item.name
|
||||
for item in self.base_dir.iterdir()
|
||||
if item.is_dir() and _JOB_ID_RE.match(item.name)
|
||||
]
|
||||
|
||||
def stale_job_dirs(
|
||||
self,
|
||||
referenced_job_ids: set[str],
|
||||
exclude_job_ids: set[str] | None = None,
|
||||
max_age_days: float | None = None,
|
||||
) -> list[dict]:
|
||||
exclude = exclude_job_ids or set()
|
||||
result: list[dict] = []
|
||||
for job_id in self.list_job_ids():
|
||||
if job_id in referenced_job_ids or job_id in exclude:
|
||||
continue
|
||||
info = self.job_dir_info(job_id)
|
||||
if not info:
|
||||
continue
|
||||
if max_age_days is not None and info["age_days"] < max_age_days:
|
||||
continue
|
||||
result.append(info)
|
||||
return sorted(result, key=lambda item: item["size_bytes"], reverse=True)
|
||||
|
||||
def remove_job_dir(self, job_id: str) -> int:
|
||||
root = self.job_root(job_id)
|
||||
if not root.exists():
|
||||
return 0
|
||||
size = self.job_dir_size(job_id)
|
||||
shutil.rmtree(root, ignore_errors=True)
|
||||
return size
|
||||
|
||||
Reference in New Issue
Block a user