chore: docs

This commit is contained in:
tao.chen
2026-09-02 10:10:41 +08:00
committed by tao.chen
parent ce7adce89c
commit ef0000ebe5
3 changed files with 440 additions and 259 deletions
+13 -146
View File
@@ -9,97 +9,16 @@
## 它做什么
| 能力 | 位置 |
|---|---|
| workspace 内 notebook 编辑,行级锁 | `backend/jupyter.py` + `scripts.is_locked` |
| Jupyter 鉴权路由(浏览器永远拿不到 runtime token | `nginx/default.conf` + `auth_request` + `backend/jupyter.py` |
| notebook / script / version / run_log 的对象存储(s3 / local 二选一) | `common/storage/` + `backend/scripts.py` |
| DAG 调度:节点、边、cron、手动触发、重试、快照 | `backend/schedules.py` + `backend/schedule_runs.py` + `schedule/`5 个模块) |
| DAG 执行走 MySQL Outbox(无 Redis,无进程内队列) | `schedule/orchestrator.py` + `schedule/worker.py` |
| 每个 workspace 一个 Jupyter 子进程池,配 asyncio 锁 | `runtime/process.py` |
| runtime 内 rclone FUSE 把 workspace 桶挂上来(s3 模式) | `runtime/mount.py` |
| 仅 MySQL 持久化(26 张表,软删除,无外键) | `common/db/models/` |
能力清单、组件图、容器表、存储布局、配置参考——**全部在 [`DEVELOP.md`](./DEVELOP.md)**
## 架构一览
- 系统整体架构([§Architecture](./DEVELOP.md#architecture)
- 18 张 MySQL 表的 Eventing 协作模式([§Eventing](./DEVELOP.md#eventing--outbox--inbox--business-tables)
- 代码目录布局([§Code layout](./DEVELOP.md#code-layout)
- 全部 26 个环境变量([§Configuration system](./DEVELOP.md#configuration-system)
- 写代码的约定([§Conventions](./DEVELOP.md#conventions)
- 加新表 / 新桶 / 新节点类型的步骤([§Common tasks](./DEVELOP.md#common-tasks)
```
┌────────────────────┐
│ Browser (SPA) │
└─────────┬──────────┘
│ HTTPS / WS
┌─────────▼──────────┐
│ Nginx (only :80) │ ← templates/default.conf
│ /api/ /jupyter/ /storage/
└────┬───────┬──────┘
│ │
┌──────────────┘ └─────────────┐
▼ ▼
┌──────────────────┐ ┌──────────────────────┐
│ FastAPI Backend │ │ Runtime (Jupyter) │
│ + /internal/v1 │ control │ - rclone FUSE mount │ (P0-1)
│ /objects │ token-Auth │ │
│ (storage) ├──────────────►│ - subprocess pool │
│ - DAG CRUD │ │ (per workspace) │
│ - script CRUD │ └──────────┬───────────┘
│ - auth_request │ │ FUSE / shared vol
│ - /api/v1/... │ ▼
└────┬──────┬──────┘ ┌──────────────────────┐
│ │ │ Object storage │
│ └──────── HTTP ───────►│ (s3: S3 service / │
▼ │ local: shared vol) │
┌────────────┐ │ 4 buckets per usage │
│ MySQL │◄───────── poll ─────│ │
│ - 26 tbls │ └──────────────────────┘
│ - outbox │
│ - jobstore │
└────┬───────┘
│ outbox poll
┌────┴──────────────────────────┐
│ Schedule Executor │
│ - CronScheduler (APScheduler) │
│ - DispatchOrchestrator │
│ - NodeExecutor (worker) │
│ - SchedulerService (facade) │
└───────────────────────────────┘
```
对象存储通过 `STORAGE_BACKEND`s3 | local)二选一。s3 模式下 4 个 purpose 命名桶
`workspace` / `version` / `run-log` / `trash`)是独立的 S3 bucketlocal 模式下
`LOCAL_STORAGE_BASE_DIR` 的子目录,通过 Docker volume `local-storage` 共享。
详见 `DEVELOP.md` §存储。
详细设计见 `ARCHITECTURE.md`。实现的偏离和近期重构记录在 `HANDOVER.md`
## 目录结构
```text
frontend/ React Router SPA
backend/ FastAPI:公开 API + 内部存储 API
runtime/ Jupyter 子进程管理 + rclone FUSE
schedule/ DAG 调度器(5 模块:context/scheduler/
orchestrator/worker/service
common/ 配置、SQLAlchemy 模型、存储 SDK、
outbox 事件、jobstore
migrations/ Alembic 基线 + 各特性 migration
nginx/ (仅概念 — 见下方「容器」一节)
scripts/ nginx-entrypoint.sh(模板渲染)
docker-compose.yml 4 服务 — web / backend / runtime / schedule
default.conf Nginx 模板(挂载,启动时渲染)
.env.example common.config.Settings 消费的所有环境变量
```
## 容器
| 服务 | 镜像 | 暴露 | 用途 |
|---|---|---|---|
| `web` | `nginx:alpine` | 宿主机 `:8888``:80` | SPA、`/api/` 反向代理、`/jupyter/{ws}/` auth_request 代理、`/storage/` S3 直通(仅 s3 模式) |
| `backend` | `Dockerfile` | 仅内网 | DAG CRUD、script CRUD、schedule 触发、`/api/v1/auth/jupyter``/internal/v1/objects` 服务间 RPC(共享 `INTERNAL_SERVICE_TOKEN` 鉴权,P0-1)|
| `runtime` | `Dockerfile` | 仅内网 | 每个 workspace 一个 Jupyter 子进程池、rclone FUSE 挂载 `workspace` 桶(s3 模式) |
| `schedule` | `Dockerfile` | 仅内网 | cron tick + DAG 执行(轮询 MySQL Outbox |
架构**故意只暴露一个宿主机端口**(网关);其他服务都在 Docker 内网。
这一点在 `docker-compose.yml` 里强制执行 — backend / runtime / schedule 都没有 `ports:`。在 P0-1 之前,backend 与 runtime 曾短暂地把 `8891` / `8892` 映射到宿主机;此映射已被删除,改用 `INTERNAL_SERVICE_TOKEN` 头对 `/internal/v1/*` 做服务间鉴权,见 `API.md §9`
`ARCHITECTURE.md` 现已并入 `DEVELOP.md``HANDOVER.md` 记录近期重构与待办事项。
## 快速启动
@@ -144,65 +63,13 @@ docker compose down
docker compose down -v
```
## 配置
所有环境变量在 `common/src/common/config.py` 里用 pydantic-settings 的 `Settings`
类一次性声明,外面套一层 `@lru_cache` 单例。新增环境变量:
1.`common/src/common/config.py``Settings` 里加字段(带合理 default,使 dev 启动不需要设)
2.`.env.example` 加一行带注释
3. 调用点用 `settings.<name>`,永远不要用 `os.environ["..."]`
完整环境变量列表和含义见 `DEVELOP.md`
## 存储布局
4 个 purpose 命名桶。从 `StorageObjects.usage_type` 到桶的映射由
**单一入口**`backend/storage_api.py:resolve_bucket`)决定:
| `usage_type` | 桶(环境变量) | 默认名 |
|---|---|---|
| `working_copy``public_script``data_resource``snapshot` | `S3_WORKSPACE_BUCKET` | `workspace` |
| `version_artifact` | `S3_VERSION_BUCKET` | `version` |
| `run_log``run_result` | `S3_RUN_LOG_BUCKET` | `run-log` |
| (软删除目标) | `S3_TRASH_BUCKET` | `trash` |
`STORAGE_BACKEND=s3` 模式下是 4 个独立 S3 桶。`STORAGE_BACKEND=local` 模式下
`LOCAL_STORAGE_BASE_DIR`(默认 `/data`)下的 4 个子目录:
```
/data/
├── workspace/ # S3_WORKSPACE_BUCKET
├── version/ # S3_VERSION_BUCKET
├── run_log/ # S3_RUN_LOG_BUCKET
└── trash/ # S3_TRASH_BUCKET
```
某个 workspace 的 `artifact_bucket` 列(非 NULL 时)覆盖该 workspace 的默认桶,
无视 `usage_type` — 适合把付费客户隔离到专属桶。
对象 key 是两层扁平路径 — `workspace_id` 加服务端签发的 `ulid`
```
<workspace_bucket>/<workspace_id>/<ulid>{.<ext>}
```
文件名、扩展名、MIME、逻辑路径都放在 `StorageObjects``Scripts` 行里,不进
object key — 重新组织存储不需要重写数据库。
Backend 代码从不写容器本地文件系统(`STORAGE_BACKEND=local` 模式除外,那里共享
`local-storage` volume 就是规范存储)。Schedule Executor 在 `tempfile.TemporaryDirectory()`
里暂存节点工件(自动清理)。只有 `runtime` 容器保留宿主 volume — s3 模式下 rclone FUSE
挂载需要;local 模式下是 no-op 透传。
## 文档
- `README.md`(本文)— 快速导读
- `ARCHITECTURE.md`设计图 + 简化历史
- `HANDOVER.md` — 实现偏离、近期重构、待办事项
- `DEVELOP.md` — 开发指南(环境变量、代码规约、常用操作)
- `CLAUDE.md` — agent 面向的本仓库规约
- [`DEVELOP.md`](./DEVELOP.md) — 权威文档:架构、代码布局、配置、约定、常用任务、测试、故障排查
- [`HANDOVER.md`](./HANDOVER.md)近期 commit / 实现偏离 / 待办事项
- [`API.md`](./API.md) — REST API 契约
- [`CLAUDE.md`](./CLAUDE.md) — agent 面向的本仓库规约
## 许可
内部。
内部。