first add

This commit is contained in:
2025-10-13 21:05:00 +08:00
parent c7744836e9
commit d71163df00
29 changed files with 144656 additions and 37 deletions

View File

@@ -0,0 +1,2 @@

View File

@@ -0,0 +1,56 @@
from __future__ import annotations
from typing import Dict, List, Optional
from pathlib import Path
import docker
from ..core.config import settings
class DockerRunner:
"""通过 docker.sock 在宿主机运行容器的轻量封装。"""
def __init__(self) -> None:
# 依赖 /var/run/docker.sock 已在 docker-compose 挂载至 worker 容器
self.client = docker.from_env()
def run(
self,
image: Optional[str],
command: List[str],
workdir: Path,
mounts: Dict[Path, str],
env: Optional[Dict[str, str]] = None,
platform: Optional[str] = None,
detach: bool = False,
remove: bool = True,
) -> str:
"""
运行容器并返回容器日志(非 detach或容器 IDdetach
mounts: {host_path: container_path}
"""
image_to_use = image or settings.DOCKER_IMAGE
platform_to_use = platform or settings.DOCKER_PLATFORM
volumes = {str(host): {"bind": container, "mode": "rw"} for host, container in mounts.items()}
container = self.client.containers.run(
image=image_to_use,
command=command,
working_dir=str(workdir),
volumes=volumes,
environment=env or {},
platform=platform_to_use,
detach=detach,
remove=remove if not detach else False,
)
if detach:
return container.id
# 同步模式:等待并返回日志
result_bytes = container.logs(stream=False)
return result_bytes.decode("utf-8", errors="ignore")

View File

@@ -0,0 +1,45 @@
from pathlib import Path
from typing import List, Dict
import shutil
from fastapi import UploadFile
from ..core.config import settings
class WorkspaceManager:
def __init__(self) -> None:
self.base_path = Path(settings.WORKSPACE_BASE_PATH)
self.base_path.mkdir(parents=True, exist_ok=True)
def create_workspace(self, job_id: str) -> Dict[str, Path]:
root = self.base_path / job_id
input_dir = root / "inputs"
logs_dir = root / "logs"
results_dir = root / "results"
for d in [root, input_dir, logs_dir, results_dir]:
d.mkdir(parents=True, exist_ok=True)
return {"root": root, "inputs": input_dir, "logs": logs_dir, "results": results_dir}
def save_input_files(self, job_id: str, files: List[UploadFile]) -> List[dict]:
ws = self.create_workspace(job_id)
saved: List[dict] = []
for f in files:
dst = ws["inputs"] / f.filename
with dst.open("wb") as out:
out.write(f.file.read())
saved.append({"filename": f.filename, "path": str(dst)})
return saved
def cleanup_workspace(self, job_id: str, keep_results: bool = False) -> None:
root = self.base_path / job_id
if not root.exists():
return
if keep_results:
# 仅清理 inputs 和 logs
for name in ["inputs", "logs"]:
p = root / name
if p.exists():
shutil.rmtree(p, ignore_errors=True)
else:
shutil.rmtree(root, ignore_errors=True)