dv-platform 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dv_platform-0.1.0/PKG-INFO +327 -0
- dv_platform-0.1.0/README.md +305 -0
- dv_platform-0.1.0/backend/app/__init__.py +1 -0
- dv_platform-0.1.0/backend/app/config.py +28 -0
- dv_platform-0.1.0/backend/app/db.py +55 -0
- dv_platform-0.1.0/backend/app/engine.py +342 -0
- dv_platform-0.1.0/backend/app/main.py +62 -0
- dv_platform-0.1.0/backend/app/models.py +170 -0
- dv_platform-0.1.0/backend/app/routers/__init__.py +1 -0
- dv_platform-0.1.0/backend/app/routers/audit.py +28 -0
- dv_platform-0.1.0/backend/app/routers/auth.py +81 -0
- dv_platform-0.1.0/backend/app/routers/datasets.py +266 -0
- dv_platform-0.1.0/backend/app/routers/storage_objects.py +96 -0
- dv_platform-0.1.0/backend/app/routers/tokens.py +53 -0
- dv_platform-0.1.0/backend/app/routers/versions.py +192 -0
- dv_platform-0.1.0/backend/app/schemas.py +237 -0
- dv_platform-0.1.0/backend/app/security.py +143 -0
- dv_platform-0.1.0/backend/app/storage.py +217 -0
- dv_platform-0.1.0/cli/dv/__init__.py +2 -0
- dv_platform-0.1.0/cli/dv/cli.py +467 -0
- dv_platform-0.1.0/cli/dv/client.py +63 -0
- dv_platform-0.1.0/cli/dv/config.py +112 -0
- dv_platform-0.1.0/cli/dv/server.py +355 -0
- dv_platform-0.1.0/cli/dv/transfer.py +213 -0
- dv_platform-0.1.0/dv_platform.egg-info/PKG-INFO +327 -0
- dv_platform-0.1.0/dv_platform.egg-info/SOURCES.txt +30 -0
- dv_platform-0.1.0/dv_platform.egg-info/dependency_links.txt +1 -0
- dv_platform-0.1.0/dv_platform.egg-info/entry_points.txt +3 -0
- dv_platform-0.1.0/dv_platform.egg-info/requires.txt +16 -0
- dv_platform-0.1.0/dv_platform.egg-info/top_level.txt +2 -0
- dv_platform-0.1.0/pyproject.toml +43 -0
- dv_platform-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dv-platform
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Git-like dataset version management platform: FastAPI backend + dv CLI, single pip install
|
|
5
|
+
Requires-Python: >=3.10
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: fastapi>=0.115
|
|
8
|
+
Requires-Dist: uvicorn[standard]>=0.30
|
|
9
|
+
Requires-Dist: sqlalchemy>=2.0
|
|
10
|
+
Requires-Dist: pydantic>=2.7
|
|
11
|
+
Requires-Dist: pydantic-settings>=2.3
|
|
12
|
+
Requires-Dist: python-multipart>=0.0.9
|
|
13
|
+
Requires-Dist: PyJWT>=2.8
|
|
14
|
+
Requires-Dist: python-dotenv>=1.0
|
|
15
|
+
Requires-Dist: boto3>=1.34
|
|
16
|
+
Requires-Dist: typer>=0.12
|
|
17
|
+
Requires-Dist: rich>=13
|
|
18
|
+
Requires-Dist: httpx>=0.27
|
|
19
|
+
Provides-Extra: test
|
|
20
|
+
Requires-Dist: pytest>=8; extra == "test"
|
|
21
|
+
Requires-Dist: httpx>=0.27; extra == "test"
|
|
22
|
+
|
|
23
|
+
# 数据集版本管理平台(Dataset Version Platform)
|
|
24
|
+
|
|
25
|
+
> 一个“类 Git”的数据集版本管理平台:**内容寻址存储(CAS)+ 控制面/数据面分离 + 引用计数 GC**。
|
|
26
|
+
> 本仓库按照《数据集版本管理平台-技术路线.md》实现,覆盖里程碑 **M1 ~ M4**(并包含 M5 的 diff 等基础能力)。
|
|
27
|
+
|
|
28
|
+
## 核心特性(对照技术路线需求)
|
|
29
|
+
|
|
30
|
+
| # | 需求 | 实现 |
|
|
31
|
+
|---|------|------|
|
|
32
|
+
| 1 | 数据集版本管理与控制(类 Git) | Blob/Tree/Commit 三对象模型、提交历史、分支、标签、diff、append-only 回滚 |
|
|
33
|
+
| 2 | 不同版本存云端、可恢复 | 对象存储 + 不可变提交 + 任意版本检出(零拷贝) |
|
|
34
|
+
| 3 | 命令行上传 | `dv add/commit/push`,上传前按 sha256 去重(跳过已存在 blob) |
|
|
35
|
+
| 4 | 命令行快速下载 | `dv pull/fetch/clone/checkout`,多线程并行下载 + sha256 校验 |
|
|
36
|
+
| 5 | Web 展示数据集/版本/下载命令 | 数据集列表/详情、版本历史、文件清单/目录树、一键复制下载命令卡片 |
|
|
37
|
+
| 6 | Web 端删除数据集并同步清理云端存储 | 删除接口 + blob 引用计数 + 物理删除对象,共享文件不误删 |
|
|
38
|
+
| 7 | 数据集最小化保存在 Web 端 | 控制面只存元数据(哈希/清单/大小),文件内容全部在对象存储 |
|
|
39
|
+
|
|
40
|
+
## 总体架构
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
┌─────────────┐ ┌─────────────┐
|
|
44
|
+
│ Web UI │ │ CLI (dv) │
|
|
45
|
+
│ (React+AntD)│ │ (Typer) │
|
|
46
|
+
└──────┬──────┘ └──────┬──────┘
|
|
47
|
+
▼ ▼
|
|
48
|
+
┌──────────────────────────────────────┐
|
|
49
|
+
│ 控制面 Control Plane (FastAPI) │
|
|
50
|
+
│ ├─ 认证/鉴权: JWT + API Token │
|
|
51
|
+
│ ├─ 数据集/版本/分支/标签 CRUD │
|
|
52
|
+
│ ├─ 版本引擎: commit/tree/blob │
|
|
53
|
+
│ ├─ 预签名 URL 签发(上传/下载) │
|
|
54
|
+
│ ├─ 存储清理: 引用计数 + 删除 GC │
|
|
55
|
+
│ └─ 审计日志 │
|
|
56
|
+
│ 元数据库: PostgreSQL / SQLite(开发) │
|
|
57
|
+
└───────────────┬──────────────────────┘
|
|
58
|
+
▼
|
|
59
|
+
┌──────────────────────────────────────┐
|
|
60
|
+
│ 数据面 Data Plane │
|
|
61
|
+
│ 对象存储: 本地盘(开发) / MinIO / S3 │
|
|
62
|
+
│ objects/<sha256> 内容寻址,跨版本去重│
|
|
63
|
+
└──────────────────────────────────────┘
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
- **控制面只走元数据,数据面直连对象存储**:大文件不经过应用服务器。
|
|
67
|
+
- **Blob 引用计数**:同一 blob 被多个数据集引用时 `ref_count > 1`;删除数据集只对 `ref_count` 归零的 blob 做物理删除。
|
|
68
|
+
|
|
69
|
+
## 目录结构
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
backend/ FastAPI 后端(版本引擎、存储适配、RBAC、审计、删除 GC)
|
|
73
|
+
app/
|
|
74
|
+
engine.py 版本引擎:hash/tree/commit/ref_count/删除
|
|
75
|
+
storage.py 存储适配:LocalStorage(本地盘)+ S3Storage(MinIO/OSS/COS/S3)
|
|
76
|
+
routers/ auth / tokens / datasets / versions / storage / audit
|
|
77
|
+
tests/ pytest 集成测试(7 个用例,覆盖核心流程)
|
|
78
|
+
cli/ dv 命令行(Typer + httpx + rich)
|
|
79
|
+
dv/cli.py 全部子命令
|
|
80
|
+
dv/transfer.py 并行上传/下载、sha256 扫描与校验
|
|
81
|
+
web/ React + TypeScript + Vite + AntD 前端
|
|
82
|
+
scripts/ demo_seed.py 演示数据;get_token.py 等
|
|
83
|
+
docker-compose.yml Postgres + MinIO + backend
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## 快速开始(开发环境)
|
|
87
|
+
|
|
88
|
+
### 1. 后端
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
python -m venv .venv
|
|
92
|
+
.venv\Scripts\pip install -r backend/requirements.txt # Windows
|
|
93
|
+
# 或 source .venv/bin/pip install -r backend/requirements.txt # Linux/macOS
|
|
94
|
+
|
|
95
|
+
cd backend
|
|
96
|
+
..\.venv\Scripts\python -m uvicorn app.main:app --port 8000
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
首次启动自动建库。访问:
|
|
100
|
+
- Web UI: http://localhost:8000
|
|
101
|
+
- API 文档: http://localhost:8000/docs
|
|
102
|
+
- 健康检查: http://localhost:8000/api/v1/health
|
|
103
|
+
|
|
104
|
+
默认管理员账号由 `/api/v1/auth/bootstrap` 创建(用户名 `admin`,密码来自 `DV_FIRST_ADMIN_PASSWORD`,默认 `admin123`)。
|
|
105
|
+
也可以 POST `/api/v1/auth/register` 注册新用户(第一个注册用户为 admin)。
|
|
106
|
+
|
|
107
|
+
### 2. 加载演示数据(可选)
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
.venv\Scripts\python scripts\demo_seed.py
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### 3. CLI
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
.venv\Scripts\pip install -e ./cli # 安装 dv 命令
|
|
117
|
+
|
|
118
|
+
dv login --token <API_TOKEN> --url http://localhost:8000
|
|
119
|
+
dv create default/my-dataset --visibility public
|
|
120
|
+
cd workdir
|
|
121
|
+
dv init default/my-dataset
|
|
122
|
+
dv add ./images ./labels.csv
|
|
123
|
+
dv status
|
|
124
|
+
dv commit -m "v1: 初始数据"
|
|
125
|
+
dv push # 上传新 blob(去重)+ 创建云端版本
|
|
126
|
+
dv log
|
|
127
|
+
dv tag v1.0
|
|
128
|
+
dv diff v1 HEAD
|
|
129
|
+
dv rollback v1 -m "回滚到 v1"
|
|
130
|
+
dv fetch default/my-dataset v1.0 -o ./data
|
|
131
|
+
dv clone default/my-dataset -o ./copy
|
|
132
|
+
dv ls --version v1.0
|
|
133
|
+
dv dataset delete default/my-dataset --yes
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
API Token 可在 Web 端或 `POST /api/v1/tokens` 创建(CLI 用长期 Token,Web 用 JWT)。
|
|
137
|
+
|
|
138
|
+
### 4. Web UI
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
cd web
|
|
142
|
+
npm install
|
|
143
|
+
npm run build # 构建到 web/dist,后端自动挂载
|
|
144
|
+
# 开发模式(热更新,代理 /api 到 :8000):
|
|
145
|
+
npm run dev # http://localhost:5173
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## API 一览(节选)
|
|
149
|
+
|
|
150
|
+
| 方法 | 路径 | 说明 |
|
|
151
|
+
|------|------|------|
|
|
152
|
+
| POST | /api/v1/auth/login · register · bootstrap | 认证 |
|
|
153
|
+
| POST/GET/DELETE | /api/v1/tokens | API Token 管理(CLI) |
|
|
154
|
+
| POST | /api/v1/datasets | 创建数据集 |
|
|
155
|
+
| GET | /api/v1/datasets | 数据集列表(搜索/分页) |
|
|
156
|
+
| GET | /api/v1/datasets/{id} | 数据集详情 |
|
|
157
|
+
| **DELETE** | **/api/v1/datasets/{id}** | **删除数据集:元数据 + 引用计数归零对象的物理删除,返回释放字节** |
|
|
158
|
+
| GET | /api/v1/datasets/{id}/storage-info | 删除前影响范围(版本数/占用/共享 blob) |
|
|
159
|
+
| POST | /api/v1/datasets/{id}/presign/upload | 上传意向:哈希清单 → 仅返回缺失 blob 的预签名 URL(去重) |
|
|
160
|
+
| POST | /api/v1/datasets/{id}/commits | 创建版本(校验声明哈希均已存在) |
|
|
161
|
+
| GET | /api/v1/datasets/{id}/commits | 版本历史 |
|
|
162
|
+
| GET | /api/v1/datasets/{id}/versions/{ref}/manifest | 版本文件清单 |
|
|
163
|
+
| GET | /api/v1/datasets/{id}/versions/{ref}/presign/download | 版本下载预签名 URL 列表 |
|
|
164
|
+
| GET | /api/v1/datasets/{id}/versions/{ref}/download-command | 下载命令(Web 展示用) |
|
|
165
|
+
| GET | /api/v1/datasets/{id}/tree/{ref} | 目录树浏览 |
|
|
166
|
+
| GET | /api/v1/datasets/{id}/diff?base=&head= | 版本差异 |
|
|
167
|
+
| POST | /api/v1/datasets/{id}/rollback | 回滚(append-only 新提交) |
|
|
168
|
+
| POST/GET/DELETE | /api/v1/datasets/{id}/tags · branches | 标签 / 分支 |
|
|
169
|
+
| GET | /api/v1/datasets/{id}/stats | 存储统计 |
|
|
170
|
+
| GET | /api/v1/audit/logs | 审计日志(admin) |
|
|
171
|
+
|
|
172
|
+
`ref` 支持:tag 名、分支名、`HEAD`/`latest`、`vN` 序号、commit 哈希(前缀)。
|
|
173
|
+
|
|
174
|
+
## 存储后端切换
|
|
175
|
+
|
|
176
|
+
默认 `DV_STORAGE_BACKEND=local`(本地盘模拟对象存储,预签名 URL 为 HMAC 签名 API URL)。
|
|
177
|
+
切换到 S3 兼容对象存储(MinIO/OSS/COS/AWS S3):
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
DV_STORAGE_BACKEND=s3 \
|
|
181
|
+
DV_S3_ENDPOINT=http://localhost:9000 \
|
|
182
|
+
DV_S3_BUCKET=datasets \
|
|
183
|
+
DV_S3_ACCESS_KEY=... \
|
|
184
|
+
DV_S3_SECRET_KEY=... \
|
|
185
|
+
.venv\Scripts\python -m uvicorn app.main:app --port 8000
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
CLI/Web 代码路径完全一致(都走预签名 URL 直传/直下)。
|
|
189
|
+
|
|
190
|
+
## Docker Compose(Postgres + MinIO + 后端)
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
# 先构建前端(把 web/dist 打进镜像)
|
|
194
|
+
cd web && npm install && npm run build && cd ..
|
|
195
|
+
|
|
196
|
+
docker compose up -d --build
|
|
197
|
+
# Web/API: http://localhost:8000 MinIO 控制台: http://localhost:9001
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## 测试
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
.venv\Scripts\python -m pytest backend/tests -q
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
覆盖:认证/Token、数据集 CRUD、上传去重、提交/标签/diff/回滚、下载校验、
|
|
207
|
+
**RBAC(非 owner 删除返回 403)**、**跨数据集共享 blob 的引用计数与删除 GC**、物理对象释放。
|
|
208
|
+
|
|
209
|
+
## 里程碑对照
|
|
210
|
+
|
|
211
|
+
- ✅ M1 版本引擎 + CLI:三对象模型、add/commit/log/tag/rollback、本地盘对象存储、控制面只存元数据
|
|
212
|
+
- ✅ M2 云存储:S3 适配 + 预签名直传直下 + 去重 + 并发下载(分片/断点续传留作增强)
|
|
213
|
+
- ✅ M3 Web UI v1:列表/详情/版本历史/文件清单/目录树/下载命令卡片,元数据驱动渲染
|
|
214
|
+
- ✅ M4 平台化:删除 + 引用计数 + 存储同步清理、RBAC、Token、审计、存储统计
|
|
215
|
+
- 🔜 M5 进阶:分片断点续传、Merkle 分层树、软删除回收站、Webhooks、SDK
|
|
216
|
+
|
|
217
|
+
## 关键设计说明
|
|
218
|
+
|
|
219
|
+
- **最小化存储**:数据库只存哈希/清单/大小,文件内容永不入库;相同内容全平台只存一份。
|
|
220
|
+
- **删除原子性**:元数据删除与引用计数更新在同一事务;物理删除失败可由 `gc_jobs` 兜底重试。
|
|
221
|
+
- **完整性**:上传 PUT 时校验 `sha256(body)==key`;下载后校验 sha256。
|
|
222
|
+
- **安全**:私有桶 + 短时效预签名 URL(默认 15 分钟)+ 数据集级 RBAC + 全量审计。
|
|
223
|
+
## 前端界面(ModelScope 风格)
|
|
224
|
+
|
|
225
|
+
Web 界面参考 ModelScope 社区风格设计:
|
|
226
|
+
|
|
227
|
+
- 顶部品牌导航 + 「新建数据集」入口 + 用户菜单
|
|
228
|
+
- 首页:渐变 Hero 搜索区 + 数据集卡片网格(彩色图标、描述、版本/文件/大小标签、可见性徽标、更新时间)
|
|
229
|
+
- 详情页:头部大图标 + 统计条(版本/文件/大小/最新版本/更新时间)+ **复制下载命令** 卡片 + 删除入口(owner)
|
|
230
|
+
- 标签页:数据集介绍(自动渲染 README.md)、文件(左侧目录树 + 文件表 + 单文件下载)、版本历史、标签、分支、版本差异
|
|
231
|
+
- 登录页:渐变品牌背景 + 居中卡片
|
|
232
|
+
|
|
233
|
+
构建:`cd web && npm run build`(产物 `web/dist`,由后端自动托管)。
|
|
234
|
+
UI 冒烟测试:`scripts/ui_check.py`、`scripts/ui_check2.py`(Playwright,自动登录并检查列表/详情/文件/版本/diff/删除弹窗)。
|
|
235
|
+
页面截图:`scripts/ui_check.py` 运行后输出到 `.shots/`。
|
|
236
|
+
|
|
237
|
+
## 下载进度
|
|
238
|
+
|
|
239
|
+
- **CLI**:`dv push / pull / fetch / clone / checkout` 均显示 rich 进度条——字节进度、文件数、当前文件、传输速度与剩余时间;下载按流式分块实时刷新,且断点续传(已存在且哈希匹配的文件自动跳过)。可用 `--no-progress` 关闭。
|
|
240
|
+
- **Web 详情页**:新增「下载全部(ZIP)」按钮,弹窗实时显示百分比、当前文件与已下载文件数,完成后打包为 `<数据集名>.zip` 下载。
|
|
241
|
+
|
|
242
|
+
## 账号注册 与 Token 管理
|
|
243
|
+
|
|
244
|
+
- **注册**:登录页有「立即注册」入口(用户名/邮箱/密码/确认密码),第一个注册用户自动成为管理员;注册成功即自动登录。
|
|
245
|
+
- **Web Token 管理**(导航栏「Token 管理」):创建 Token(名称 + 过期时间:永不过期/7/30/90/365 天)、列表展示过期时间与最近使用、吊销;明文仅在创建弹窗显示一次,可一键复制。
|
|
246
|
+
- **CLI**:`dv token create --name X [--expires 2027-01-01T00:00:00]`、`dv token list`、`dv token revoke <id>`。
|
|
247
|
+
- 所有 API 响应均带 `Cache-Control: no-store`,前端请求亦禁用缓存,保证列表变更即时可见。
|
|
248
|
+
|
|
249
|
+
## README 展示(ModelScope 风格)
|
|
250
|
+
|
|
251
|
+
- 每个数据集详情页**默认展示 README.md**(「数据集介绍」标签页),风格对齐 ModelScope:
|
|
252
|
+
- GitHub 风格 Markdown 渲染:标题锚点链接、表格、代码块语法高亮(highlight.js)、引用块、任务列表、分隔线
|
|
253
|
+
- 相对路径图片自动解析为数据集内文件的预签名 URL(支持懒加载)
|
|
254
|
+
- 外部链接新窗口打开
|
|
255
|
+
- 支持 README 中的原生 HTML(rehype-raw)
|
|
256
|
+
- 头部有 `README.md` 标识与「下载 README.md」按钮
|
|
257
|
+
- 无 README 时展示引导空态(含 `dv add README.md && dv commit ... && dv push` 示例)
|
|
258
|
+
|
|
259
|
+
## 打包安装为 Python 库(推荐部署方式)
|
|
260
|
+
|
|
261
|
+
仓库根目录的 `pyproject.toml` 把 **后端(`backend/app`)** 与 **CLI(`cli/dv`)** 打包成
|
|
262
|
+
**一个发行版 `dv-platform`**,`pip install` 后即可得到两个命令:
|
|
263
|
+
|
|
264
|
+
| 命令 | 作用 |
|
|
265
|
+
|------|------|
|
|
266
|
+
| `dv` | 数据集版本管理 CLI(不变) |
|
|
267
|
+
| `dv-server` | 启动/管理后端服务(前台或后台守护进程) |
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
# 在仓库根目录(含 pyproject.toml)
|
|
271
|
+
pip install . # 或开发模式: pip install -e .
|
|
272
|
+
pip install ".[test]" # 可选:测试依赖
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
> 如果环境里以前用 `pip install -e ./cli` 装过旧版 `dv-cli`,先执行 `pip uninstall dv-cli`,
|
|
276
|
+
> 避免与新版 `dv-platform` 里的 `dv` 包/`dv` 命令冲突。
|
|
277
|
+
|
|
278
|
+
### 快速开始
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
# 1) 后台启动服务(默认数据目录 ~/.dvserver,监听 0.0.0.0:8000)
|
|
282
|
+
dv-server start
|
|
283
|
+
dv-server status
|
|
284
|
+
|
|
285
|
+
# 自定义端口 / 数据目录 / 前台运行
|
|
286
|
+
dv-server start --port 9000 --data-dir D:\dvdata
|
|
287
|
+
dv-server run --host 127.0.0.1 --port 8000 # 前台(Ctrl+C 停止)
|
|
288
|
+
dv-server stop --port 9000
|
|
289
|
+
dv-server restart
|
|
290
|
+
dv-server logs --tail 50
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
需要开机自启时,可把 `dv-server start` 加入 Windows 任务计划程序(开机触发)或 systemd 单元。
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
# 2) 首次创建管理员账号(admin / admin123,见数据目录 .env 可改)
|
|
297
|
+
# http://127.0.0.1:8000/docs -> POST /api/v1/auth/bootstrap
|
|
298
|
+
# 或
|
|
299
|
+
# Web UI http://127.0.0.1:8000 (若构建了前端并以 DV_WEB_DIST 指向 web/dist)
|
|
300
|
+
|
|
301
|
+
# 3) CLI 使用
|
|
302
|
+
dv login --token <API_TOKEN> --url http://127.0.0.1:8000
|
|
303
|
+
dv create team/my-dataset
|
|
304
|
+
dv clone team/my-dataset -o ./data
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### `dv-server` 数据目录(data dir)
|
|
308
|
+
|
|
309
|
+
所有可变数据(SQLite `dv.db`、本地对象存储 `./storage`、`.env`、PID、日志)都落在
|
|
310
|
+
**数据目录**内,因此服务可放在任意位置、完全自包含:
|
|
311
|
+
|
|
312
|
+
- `run`(前台):默认使用当前目录;
|
|
313
|
+
- `start/stop/status/restart/logs`(守护进程):默认 `~/.dvserver`(可用 `DV_SERVER_DIR` 或 `--data-dir` 覆盖)。
|
|
314
|
+
|
|
315
|
+
首次 `start` 会自动生成 `.env`(含随机 `DV_JWT_SECRET`,重启后凭据保持有效)。
|
|
316
|
+
生产建议:`DV_DATABASE_URL` 换 PostgreSQL、`DV_STORAGE_BACKEND=s3` 指向 MinIO/OSS/S3,
|
|
317
|
+
并把 `DV_PUBLIC_BASE_URL` 设为客户端可达的地址(预签名 URL 以此为基准)。
|
|
318
|
+
|
|
319
|
+
### 多客户端并发上传/下载
|
|
320
|
+
|
|
321
|
+
- 上传/下载走预签名 URL(S3 后端直连对象存储,完全不经过应用进程);
|
|
322
|
+
- 本地后端(`DV_STORAGE_BACKEND=local`)的 PUT/GET 已改为**流式收发**:上传边收边写临时文件
|
|
323
|
+
并校验 sha256 后原子改名,下载用 `FileResponse` 流式返回,多客户端并发传大文件不会把文件整体载入内存;
|
|
324
|
+
- SQLite(开发默认)开启 WAL + `busy_timeout=30000`,且每个事务以 `BEGIN IMMEDIATE` 开始,
|
|
325
|
+
多个客户端同时上传相同 blob(去重竞态)或同时向同一数据集 push 时不会出现
|
|
326
|
+
“database is locked”/重复版本号/丢更新;
|
|
327
|
+
- 同一台机器多客户端并行传输建议保持 `--workers 1`;要横向扩容请换 PostgreSQL + S3 再加大 workers。
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
# 数据集版本管理平台(Dataset Version Platform)
|
|
2
|
+
|
|
3
|
+
> 一个“类 Git”的数据集版本管理平台:**内容寻址存储(CAS)+ 控制面/数据面分离 + 引用计数 GC**。
|
|
4
|
+
> 本仓库按照《数据集版本管理平台-技术路线.md》实现,覆盖里程碑 **M1 ~ M4**(并包含 M5 的 diff 等基础能力)。
|
|
5
|
+
|
|
6
|
+
## 核心特性(对照技术路线需求)
|
|
7
|
+
|
|
8
|
+
| # | 需求 | 实现 |
|
|
9
|
+
|---|------|------|
|
|
10
|
+
| 1 | 数据集版本管理与控制(类 Git) | Blob/Tree/Commit 三对象模型、提交历史、分支、标签、diff、append-only 回滚 |
|
|
11
|
+
| 2 | 不同版本存云端、可恢复 | 对象存储 + 不可变提交 + 任意版本检出(零拷贝) |
|
|
12
|
+
| 3 | 命令行上传 | `dv add/commit/push`,上传前按 sha256 去重(跳过已存在 blob) |
|
|
13
|
+
| 4 | 命令行快速下载 | `dv pull/fetch/clone/checkout`,多线程并行下载 + sha256 校验 |
|
|
14
|
+
| 5 | Web 展示数据集/版本/下载命令 | 数据集列表/详情、版本历史、文件清单/目录树、一键复制下载命令卡片 |
|
|
15
|
+
| 6 | Web 端删除数据集并同步清理云端存储 | 删除接口 + blob 引用计数 + 物理删除对象,共享文件不误删 |
|
|
16
|
+
| 7 | 数据集最小化保存在 Web 端 | 控制面只存元数据(哈希/清单/大小),文件内容全部在对象存储 |
|
|
17
|
+
|
|
18
|
+
## 总体架构
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
┌─────────────┐ ┌─────────────┐
|
|
22
|
+
│ Web UI │ │ CLI (dv) │
|
|
23
|
+
│ (React+AntD)│ │ (Typer) │
|
|
24
|
+
└──────┬──────┘ └──────┬──────┘
|
|
25
|
+
▼ ▼
|
|
26
|
+
┌──────────────────────────────────────┐
|
|
27
|
+
│ 控制面 Control Plane (FastAPI) │
|
|
28
|
+
│ ├─ 认证/鉴权: JWT + API Token │
|
|
29
|
+
│ ├─ 数据集/版本/分支/标签 CRUD │
|
|
30
|
+
│ ├─ 版本引擎: commit/tree/blob │
|
|
31
|
+
│ ├─ 预签名 URL 签发(上传/下载) │
|
|
32
|
+
│ ├─ 存储清理: 引用计数 + 删除 GC │
|
|
33
|
+
│ └─ 审计日志 │
|
|
34
|
+
│ 元数据库: PostgreSQL / SQLite(开发) │
|
|
35
|
+
└───────────────┬──────────────────────┘
|
|
36
|
+
▼
|
|
37
|
+
┌──────────────────────────────────────┐
|
|
38
|
+
│ 数据面 Data Plane │
|
|
39
|
+
│ 对象存储: 本地盘(开发) / MinIO / S3 │
|
|
40
|
+
│ objects/<sha256> 内容寻址,跨版本去重│
|
|
41
|
+
└──────────────────────────────────────┘
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
- **控制面只走元数据,数据面直连对象存储**:大文件不经过应用服务器。
|
|
45
|
+
- **Blob 引用计数**:同一 blob 被多个数据集引用时 `ref_count > 1`;删除数据集只对 `ref_count` 归零的 blob 做物理删除。
|
|
46
|
+
|
|
47
|
+
## 目录结构
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
backend/ FastAPI 后端(版本引擎、存储适配、RBAC、审计、删除 GC)
|
|
51
|
+
app/
|
|
52
|
+
engine.py 版本引擎:hash/tree/commit/ref_count/删除
|
|
53
|
+
storage.py 存储适配:LocalStorage(本地盘)+ S3Storage(MinIO/OSS/COS/S3)
|
|
54
|
+
routers/ auth / tokens / datasets / versions / storage / audit
|
|
55
|
+
tests/ pytest 集成测试(7 个用例,覆盖核心流程)
|
|
56
|
+
cli/ dv 命令行(Typer + httpx + rich)
|
|
57
|
+
dv/cli.py 全部子命令
|
|
58
|
+
dv/transfer.py 并行上传/下载、sha256 扫描与校验
|
|
59
|
+
web/ React + TypeScript + Vite + AntD 前端
|
|
60
|
+
scripts/ demo_seed.py 演示数据;get_token.py 等
|
|
61
|
+
docker-compose.yml Postgres + MinIO + backend
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 快速开始(开发环境)
|
|
65
|
+
|
|
66
|
+
### 1. 后端
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
python -m venv .venv
|
|
70
|
+
.venv\Scripts\pip install -r backend/requirements.txt # Windows
|
|
71
|
+
# 或 source .venv/bin/pip install -r backend/requirements.txt # Linux/macOS
|
|
72
|
+
|
|
73
|
+
cd backend
|
|
74
|
+
..\.venv\Scripts\python -m uvicorn app.main:app --port 8000
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
首次启动自动建库。访问:
|
|
78
|
+
- Web UI: http://localhost:8000
|
|
79
|
+
- API 文档: http://localhost:8000/docs
|
|
80
|
+
- 健康检查: http://localhost:8000/api/v1/health
|
|
81
|
+
|
|
82
|
+
默认管理员账号由 `/api/v1/auth/bootstrap` 创建(用户名 `admin`,密码来自 `DV_FIRST_ADMIN_PASSWORD`,默认 `admin123`)。
|
|
83
|
+
也可以 POST `/api/v1/auth/register` 注册新用户(第一个注册用户为 admin)。
|
|
84
|
+
|
|
85
|
+
### 2. 加载演示数据(可选)
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
.venv\Scripts\python scripts\demo_seed.py
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### 3. CLI
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
.venv\Scripts\pip install -e ./cli # 安装 dv 命令
|
|
95
|
+
|
|
96
|
+
dv login --token <API_TOKEN> --url http://localhost:8000
|
|
97
|
+
dv create default/my-dataset --visibility public
|
|
98
|
+
cd workdir
|
|
99
|
+
dv init default/my-dataset
|
|
100
|
+
dv add ./images ./labels.csv
|
|
101
|
+
dv status
|
|
102
|
+
dv commit -m "v1: 初始数据"
|
|
103
|
+
dv push # 上传新 blob(去重)+ 创建云端版本
|
|
104
|
+
dv log
|
|
105
|
+
dv tag v1.0
|
|
106
|
+
dv diff v1 HEAD
|
|
107
|
+
dv rollback v1 -m "回滚到 v1"
|
|
108
|
+
dv fetch default/my-dataset v1.0 -o ./data
|
|
109
|
+
dv clone default/my-dataset -o ./copy
|
|
110
|
+
dv ls --version v1.0
|
|
111
|
+
dv dataset delete default/my-dataset --yes
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
API Token 可在 Web 端或 `POST /api/v1/tokens` 创建(CLI 用长期 Token,Web 用 JWT)。
|
|
115
|
+
|
|
116
|
+
### 4. Web UI
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
cd web
|
|
120
|
+
npm install
|
|
121
|
+
npm run build # 构建到 web/dist,后端自动挂载
|
|
122
|
+
# 开发模式(热更新,代理 /api 到 :8000):
|
|
123
|
+
npm run dev # http://localhost:5173
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## API 一览(节选)
|
|
127
|
+
|
|
128
|
+
| 方法 | 路径 | 说明 |
|
|
129
|
+
|------|------|------|
|
|
130
|
+
| POST | /api/v1/auth/login · register · bootstrap | 认证 |
|
|
131
|
+
| POST/GET/DELETE | /api/v1/tokens | API Token 管理(CLI) |
|
|
132
|
+
| POST | /api/v1/datasets | 创建数据集 |
|
|
133
|
+
| GET | /api/v1/datasets | 数据集列表(搜索/分页) |
|
|
134
|
+
| GET | /api/v1/datasets/{id} | 数据集详情 |
|
|
135
|
+
| **DELETE** | **/api/v1/datasets/{id}** | **删除数据集:元数据 + 引用计数归零对象的物理删除,返回释放字节** |
|
|
136
|
+
| GET | /api/v1/datasets/{id}/storage-info | 删除前影响范围(版本数/占用/共享 blob) |
|
|
137
|
+
| POST | /api/v1/datasets/{id}/presign/upload | 上传意向:哈希清单 → 仅返回缺失 blob 的预签名 URL(去重) |
|
|
138
|
+
| POST | /api/v1/datasets/{id}/commits | 创建版本(校验声明哈希均已存在) |
|
|
139
|
+
| GET | /api/v1/datasets/{id}/commits | 版本历史 |
|
|
140
|
+
| GET | /api/v1/datasets/{id}/versions/{ref}/manifest | 版本文件清单 |
|
|
141
|
+
| GET | /api/v1/datasets/{id}/versions/{ref}/presign/download | 版本下载预签名 URL 列表 |
|
|
142
|
+
| GET | /api/v1/datasets/{id}/versions/{ref}/download-command | 下载命令(Web 展示用) |
|
|
143
|
+
| GET | /api/v1/datasets/{id}/tree/{ref} | 目录树浏览 |
|
|
144
|
+
| GET | /api/v1/datasets/{id}/diff?base=&head= | 版本差异 |
|
|
145
|
+
| POST | /api/v1/datasets/{id}/rollback | 回滚(append-only 新提交) |
|
|
146
|
+
| POST/GET/DELETE | /api/v1/datasets/{id}/tags · branches | 标签 / 分支 |
|
|
147
|
+
| GET | /api/v1/datasets/{id}/stats | 存储统计 |
|
|
148
|
+
| GET | /api/v1/audit/logs | 审计日志(admin) |
|
|
149
|
+
|
|
150
|
+
`ref` 支持:tag 名、分支名、`HEAD`/`latest`、`vN` 序号、commit 哈希(前缀)。
|
|
151
|
+
|
|
152
|
+
## 存储后端切换
|
|
153
|
+
|
|
154
|
+
默认 `DV_STORAGE_BACKEND=local`(本地盘模拟对象存储,预签名 URL 为 HMAC 签名 API URL)。
|
|
155
|
+
切换到 S3 兼容对象存储(MinIO/OSS/COS/AWS S3):
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
DV_STORAGE_BACKEND=s3 \
|
|
159
|
+
DV_S3_ENDPOINT=http://localhost:9000 \
|
|
160
|
+
DV_S3_BUCKET=datasets \
|
|
161
|
+
DV_S3_ACCESS_KEY=... \
|
|
162
|
+
DV_S3_SECRET_KEY=... \
|
|
163
|
+
.venv\Scripts\python -m uvicorn app.main:app --port 8000
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
CLI/Web 代码路径完全一致(都走预签名 URL 直传/直下)。
|
|
167
|
+
|
|
168
|
+
## Docker Compose(Postgres + MinIO + 后端)
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
# 先构建前端(把 web/dist 打进镜像)
|
|
172
|
+
cd web && npm install && npm run build && cd ..
|
|
173
|
+
|
|
174
|
+
docker compose up -d --build
|
|
175
|
+
# Web/API: http://localhost:8000 MinIO 控制台: http://localhost:9001
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## 测试
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
.venv\Scripts\python -m pytest backend/tests -q
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
覆盖:认证/Token、数据集 CRUD、上传去重、提交/标签/diff/回滚、下载校验、
|
|
185
|
+
**RBAC(非 owner 删除返回 403)**、**跨数据集共享 blob 的引用计数与删除 GC**、物理对象释放。
|
|
186
|
+
|
|
187
|
+
## 里程碑对照
|
|
188
|
+
|
|
189
|
+
- ✅ M1 版本引擎 + CLI:三对象模型、add/commit/log/tag/rollback、本地盘对象存储、控制面只存元数据
|
|
190
|
+
- ✅ M2 云存储:S3 适配 + 预签名直传直下 + 去重 + 并发下载(分片/断点续传留作增强)
|
|
191
|
+
- ✅ M3 Web UI v1:列表/详情/版本历史/文件清单/目录树/下载命令卡片,元数据驱动渲染
|
|
192
|
+
- ✅ M4 平台化:删除 + 引用计数 + 存储同步清理、RBAC、Token、审计、存储统计
|
|
193
|
+
- 🔜 M5 进阶:分片断点续传、Merkle 分层树、软删除回收站、Webhooks、SDK
|
|
194
|
+
|
|
195
|
+
## 关键设计说明
|
|
196
|
+
|
|
197
|
+
- **最小化存储**:数据库只存哈希/清单/大小,文件内容永不入库;相同内容全平台只存一份。
|
|
198
|
+
- **删除原子性**:元数据删除与引用计数更新在同一事务;物理删除失败可由 `gc_jobs` 兜底重试。
|
|
199
|
+
- **完整性**:上传 PUT 时校验 `sha256(body)==key`;下载后校验 sha256。
|
|
200
|
+
- **安全**:私有桶 + 短时效预签名 URL(默认 15 分钟)+ 数据集级 RBAC + 全量审计。
|
|
201
|
+
## 前端界面(ModelScope 风格)
|
|
202
|
+
|
|
203
|
+
Web 界面参考 ModelScope 社区风格设计:
|
|
204
|
+
|
|
205
|
+
- 顶部品牌导航 + 「新建数据集」入口 + 用户菜单
|
|
206
|
+
- 首页:渐变 Hero 搜索区 + 数据集卡片网格(彩色图标、描述、版本/文件/大小标签、可见性徽标、更新时间)
|
|
207
|
+
- 详情页:头部大图标 + 统计条(版本/文件/大小/最新版本/更新时间)+ **复制下载命令** 卡片 + 删除入口(owner)
|
|
208
|
+
- 标签页:数据集介绍(自动渲染 README.md)、文件(左侧目录树 + 文件表 + 单文件下载)、版本历史、标签、分支、版本差异
|
|
209
|
+
- 登录页:渐变品牌背景 + 居中卡片
|
|
210
|
+
|
|
211
|
+
构建:`cd web && npm run build`(产物 `web/dist`,由后端自动托管)。
|
|
212
|
+
UI 冒烟测试:`scripts/ui_check.py`、`scripts/ui_check2.py`(Playwright,自动登录并检查列表/详情/文件/版本/diff/删除弹窗)。
|
|
213
|
+
页面截图:`scripts/ui_check.py` 运行后输出到 `.shots/`。
|
|
214
|
+
|
|
215
|
+
## 下载进度
|
|
216
|
+
|
|
217
|
+
- **CLI**:`dv push / pull / fetch / clone / checkout` 均显示 rich 进度条——字节进度、文件数、当前文件、传输速度与剩余时间;下载按流式分块实时刷新,且断点续传(已存在且哈希匹配的文件自动跳过)。可用 `--no-progress` 关闭。
|
|
218
|
+
- **Web 详情页**:新增「下载全部(ZIP)」按钮,弹窗实时显示百分比、当前文件与已下载文件数,完成后打包为 `<数据集名>.zip` 下载。
|
|
219
|
+
|
|
220
|
+
## 账号注册 与 Token 管理
|
|
221
|
+
|
|
222
|
+
- **注册**:登录页有「立即注册」入口(用户名/邮箱/密码/确认密码),第一个注册用户自动成为管理员;注册成功即自动登录。
|
|
223
|
+
- **Web Token 管理**(导航栏「Token 管理」):创建 Token(名称 + 过期时间:永不过期/7/30/90/365 天)、列表展示过期时间与最近使用、吊销;明文仅在创建弹窗显示一次,可一键复制。
|
|
224
|
+
- **CLI**:`dv token create --name X [--expires 2027-01-01T00:00:00]`、`dv token list`、`dv token revoke <id>`。
|
|
225
|
+
- 所有 API 响应均带 `Cache-Control: no-store`,前端请求亦禁用缓存,保证列表变更即时可见。
|
|
226
|
+
|
|
227
|
+
## README 展示(ModelScope 风格)
|
|
228
|
+
|
|
229
|
+
- 每个数据集详情页**默认展示 README.md**(「数据集介绍」标签页),风格对齐 ModelScope:
|
|
230
|
+
- GitHub 风格 Markdown 渲染:标题锚点链接、表格、代码块语法高亮(highlight.js)、引用块、任务列表、分隔线
|
|
231
|
+
- 相对路径图片自动解析为数据集内文件的预签名 URL(支持懒加载)
|
|
232
|
+
- 外部链接新窗口打开
|
|
233
|
+
- 支持 README 中的原生 HTML(rehype-raw)
|
|
234
|
+
- 头部有 `README.md` 标识与「下载 README.md」按钮
|
|
235
|
+
- 无 README 时展示引导空态(含 `dv add README.md && dv commit ... && dv push` 示例)
|
|
236
|
+
|
|
237
|
+
## 打包安装为 Python 库(推荐部署方式)
|
|
238
|
+
|
|
239
|
+
仓库根目录的 `pyproject.toml` 把 **后端(`backend/app`)** 与 **CLI(`cli/dv`)** 打包成
|
|
240
|
+
**一个发行版 `dv-platform`**,`pip install` 后即可得到两个命令:
|
|
241
|
+
|
|
242
|
+
| 命令 | 作用 |
|
|
243
|
+
|------|------|
|
|
244
|
+
| `dv` | 数据集版本管理 CLI(不变) |
|
|
245
|
+
| `dv-server` | 启动/管理后端服务(前台或后台守护进程) |
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
# 在仓库根目录(含 pyproject.toml)
|
|
249
|
+
pip install . # 或开发模式: pip install -e .
|
|
250
|
+
pip install ".[test]" # 可选:测试依赖
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
> 如果环境里以前用 `pip install -e ./cli` 装过旧版 `dv-cli`,先执行 `pip uninstall dv-cli`,
|
|
254
|
+
> 避免与新版 `dv-platform` 里的 `dv` 包/`dv` 命令冲突。
|
|
255
|
+
|
|
256
|
+
### 快速开始
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
# 1) 后台启动服务(默认数据目录 ~/.dvserver,监听 0.0.0.0:8000)
|
|
260
|
+
dv-server start
|
|
261
|
+
dv-server status
|
|
262
|
+
|
|
263
|
+
# 自定义端口 / 数据目录 / 前台运行
|
|
264
|
+
dv-server start --port 9000 --data-dir D:\dvdata
|
|
265
|
+
dv-server run --host 127.0.0.1 --port 8000 # 前台(Ctrl+C 停止)
|
|
266
|
+
dv-server stop --port 9000
|
|
267
|
+
dv-server restart
|
|
268
|
+
dv-server logs --tail 50
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
需要开机自启时,可把 `dv-server start` 加入 Windows 任务计划程序(开机触发)或 systemd 单元。
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
# 2) 首次创建管理员账号(admin / admin123,见数据目录 .env 可改)
|
|
275
|
+
# http://127.0.0.1:8000/docs -> POST /api/v1/auth/bootstrap
|
|
276
|
+
# 或
|
|
277
|
+
# Web UI http://127.0.0.1:8000 (若构建了前端并以 DV_WEB_DIST 指向 web/dist)
|
|
278
|
+
|
|
279
|
+
# 3) CLI 使用
|
|
280
|
+
dv login --token <API_TOKEN> --url http://127.0.0.1:8000
|
|
281
|
+
dv create team/my-dataset
|
|
282
|
+
dv clone team/my-dataset -o ./data
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### `dv-server` 数据目录(data dir)
|
|
286
|
+
|
|
287
|
+
所有可变数据(SQLite `dv.db`、本地对象存储 `./storage`、`.env`、PID、日志)都落在
|
|
288
|
+
**数据目录**内,因此服务可放在任意位置、完全自包含:
|
|
289
|
+
|
|
290
|
+
- `run`(前台):默认使用当前目录;
|
|
291
|
+
- `start/stop/status/restart/logs`(守护进程):默认 `~/.dvserver`(可用 `DV_SERVER_DIR` 或 `--data-dir` 覆盖)。
|
|
292
|
+
|
|
293
|
+
首次 `start` 会自动生成 `.env`(含随机 `DV_JWT_SECRET`,重启后凭据保持有效)。
|
|
294
|
+
生产建议:`DV_DATABASE_URL` 换 PostgreSQL、`DV_STORAGE_BACKEND=s3` 指向 MinIO/OSS/S3,
|
|
295
|
+
并把 `DV_PUBLIC_BASE_URL` 设为客户端可达的地址(预签名 URL 以此为基准)。
|
|
296
|
+
|
|
297
|
+
### 多客户端并发上传/下载
|
|
298
|
+
|
|
299
|
+
- 上传/下载走预签名 URL(S3 后端直连对象存储,完全不经过应用进程);
|
|
300
|
+
- 本地后端(`DV_STORAGE_BACKEND=local`)的 PUT/GET 已改为**流式收发**:上传边收边写临时文件
|
|
301
|
+
并校验 sha256 后原子改名,下载用 `FileResponse` 流式返回,多客户端并发传大文件不会把文件整体载入内存;
|
|
302
|
+
- SQLite(开发默认)开启 WAL + `busy_timeout=30000`,且每个事务以 `BEGIN IMMEDIATE` 开始,
|
|
303
|
+
多个客户端同时上传相同 blob(去重竞态)或同时向同一数据集 push 时不会出现
|
|
304
|
+
“database is locked”/重复版本号/丢更新;
|
|
305
|
+
- 同一台机器多客户端并行传输建议保持 `--workers 1`;要横向扩容请换 PostgreSQL + S3 再加大 workers。
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Dataset Version Management Platform - backend package."""
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""Application settings (env-prefixed with DV_)."""
|
|
2
|
+
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Settings(BaseSettings):
|
|
6
|
+
model_config = SettingsConfigDict(env_prefix="DV_", env_file=".env", extra="ignore")
|
|
7
|
+
|
|
8
|
+
app_name: str = "Dataset Version Platform"
|
|
9
|
+
database_url: str = "sqlite:///./dv.db"
|
|
10
|
+
storage_backend: str = "local" # local | s3
|
|
11
|
+
storage_root: str = "./storage" # local backend object root
|
|
12
|
+
s3_endpoint: str = "http://localhost:9000"
|
|
13
|
+
s3_bucket: str = "datasets"
|
|
14
|
+
s3_access_key: str = ""
|
|
15
|
+
s3_secret_key: str = ""
|
|
16
|
+
s3_region: str = "us-east-1"
|
|
17
|
+
presign_ttl: int = 900 # seconds (15 min)
|
|
18
|
+
jwt_secret: str = "dev-secret-change-me-0123456789abcdef0123456789"
|
|
19
|
+
jwt_algorithm: str = "HS256"
|
|
20
|
+
jwt_expire_minutes: int = 10080 # 7 days
|
|
21
|
+
public_base_url: str = "http://localhost:8000"
|
|
22
|
+
web_dist: str = "" # optional: absolute path to a built web/dist to serve
|
|
23
|
+
first_admin_password: str = "admin123"
|
|
24
|
+
chunk_size: int = 8 * 1024 * 1024 # 8MB reference chunk for docs
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
settings = Settings()
|
|
28
|
+
|