DocHub/docs/superpowers/specs/2026-08-01-dochub-design.md
2026-08-01 00:22:16 +08:00

7.6 KiB
Raw Blame History

DocHub 设计文档

背景与目标

小团队10 人以下)需要一个基于 MinIO 的文档管理系统,支持:

  • 浏览 MinIO 中存储的文档(主要是 Markdown / HTML图片为次要内容
  • 全文内容检索(不只是文件名搜索)
  • 在线编辑文档内容并保存
  • 上传新文档

无需用户登录和权限管理(内部工具,信任团队内所有成员)。

技术栈

选型 理由
前端 React + Vite + Monaco Editor Monaco 提供代码级编辑体验(语法高亮、查找替换),适合 Markdown/HTML 源码编辑
后端 Python + FastAPI 团队熟悉度高,异步 IO 足够应对 MinIO/Meilisearch 网络调用瓶颈生态利于后续扩展文档解析、AI 摘要等)
存储 MinIO独立部署 S3 兼容对象存储,文档内容和元数据(大小/时间/路径)都存在这里,不引入额外数据库
检索 Meilisearch 轻量、内置中文分词、MIT 协议、Docker 一条命令部署,检索延迟低

明确不引入的组件:

  • 关系型数据库(内容和元数据用 MinIO 承载,索引用 Meilisearch 承载,当前需求下够用)
  • 用户认证/权限系统(团队内部工具,暂不需要)

架构

                    ┌─────────────┐
        HTTPS       │   nginx     │
     ───────────▶   │ (反向代理)  │
                    └──────┬──────┘
                           │
              ┌────────────┼────────────┐
              ▼            ▼            ▼
        app.domain    api.domain   minio.domain(可选)
              │            │
      ┌───────▼───────┐ ┌──▼──────────────┐
      │  React 前端    │ │  FastAPI 后端     │
      │  Vite + Monaco│ │  (Python)        │
      └───────────────┘ └───┬──────────┬───┘
                             │          │
                    S3 API   │          │  REST API
                             ▼          ▼
                    ┌─────────────┐ ┌──────────────┐
                    │   MinIO     │ │ Meilisearch  │
                    │ (独立部署)   │ │ (与后端同机)  │
                    └─────────────┘ └──────────────┘

部署形态:两套独立的 docker-compose各自独立生命周期

  • minio/docker-compose.yml — 仅 MinIO独立服务器或独立栈长期稳定运行可被其他项目复用
  • app/docker-compose.yml — frontend + backend + meilisearch可整体重启/升级而不影响已存储的数据

两套 compose 之间通过共享 Docker 网络或宿主机 IP 通信(后端配置 MinIO endpoint 即可,代码不感知部署形态差异,因为走的是标准 S3 API

域名与端口:通过 nginx 反向代理 + 子域名区分服务,无需在域名上绑定端口:

app.domain      → React 前端
api.domain      → FastAPI 后端
minio.domain    → MinIO 控制台(可选对外)

Meilisearch 仅供后端内网访问,不对外暴露子域名。

数据流

上传文档

前端上传文件 → 后端 PUT 到 MinIO
  → 后端解析内容Markdown/HTML 转纯文本)
  → 推送索引到 Meilisearch
  → 返回成功

浏览文件列表

前端请求文件树 → 后端调用 MinIO ListObjects → 返回文件夹/文件结构

查看/编辑文档

点击文件 → 后端从 MinIO GetObject 取内容 → 前端 Monaco Editor 加载展示
保存编辑 → 后端覆盖写入 MinIO → 同步更新 Meilisearch 索引

全局搜索

输入关键词 → 后端转发查询到 Meilisearch
  → 返回匹配文档(含高亮片段)
  → 前端展示结果列表,点击跳转到对应文档

删除文档

后端从 MinIO 删除对象 → 同步从 Meilisearch 删除对应索引

关键决策:索引更新采用后端同步处理,即写完 MinIO 后立即在同一请求中更新 Meilisearch 索引,不引入 MinIO webhook 异步机制。理由:团队规模小、写入量低,同步更新逻辑更简单、更容易保证一致性,避免维护额外的 webhook 消费者服务。

模块设计

前端React + Vite + Monaco Editor

组件 职责
FileExplorer 左侧文件树,展示文件夹/文件,支持点击导航
DocumentViewer/Editor 主区域,用 Monaco 加载文档内容,支持编辑与保存
SearchBar 顶部全局搜索框输入即查debounce
SearchResults 搜索结果列表,展示高亮匹配片段,点击跳转对应文档
UploadButton 拖拽或选择文件上传
apiClient 封装对后端的 fetch 调用documents CRUD + search是前端与后端之间的唯一边界

后端FastAPI

API 层:

接口 方法 职责
/api/documents GET 列出文件树(基于 MinIO ListObjects
/api/documents/{key} GET 读取单个文档内容
/api/documents/{key} PUT 创建/覆盖文档(写 MinIO + 更新索引)
/api/documents/{key} DELETE 删除文档(删 MinIO + 删索引)
/api/upload POST 处理文件上传multipart
/api/search GET 转发查询到 Meilisearch返回结果

内部模块划分(各模块单一职责,可独立测试):

  • minio_client.py — 封装 MinIO 操作list/get/put/delete只负责与 MinIO 交互,不含业务逻辑
  • search_client.py — 封装 Meilisearch 操作index/update/delete/search只负责与 Meilisearch 交互
  • document_service.py — 业务逻辑层,协调 minio_clientsearch_client(保存文档先写 MinIO 再更新索引;删除时顺序相反),并负责 Markdown/HTML 转纯文本供索引使用
  • routes/documents.pyroutes/search.py — API 路由层,只做参数校验和调用 service不直接触碰 MinIO/Meilisearch 客户端

依赖方向:routesdocument_serviceminio_client / search_client。上层不了解下层实现细节,替换 MinIO 为其他 S3 兼容存储或替换 Meilisearch 为其他搜索引擎时,只需改动对应的 client 模块。

错误处理

  • MinIO 写入成功但索引更新失败:记录日志,不阻塞用户操作(文档已保存成功),后续可手动触发全量重建索引
  • 请求的文档不存在:返回 404
  • 上传文件类型/大小校验:在后端 document_service 层做校验(限制非文档类型或超大文件),拒绝时返回明确错误信息

测试策略

  • 后端pytest 测试 document_service 业务逻辑mock minio_clientsearch_client,覆盖保存/删除时序、索引失败降级等场景
  • 前端:暂不强制要求自动化测试覆盖(小型内部工具,手动验证优先级更高)

部署资源参考

学习/小团队场景下DocHub 各服务的大致资源占用(供部署规划参考,非强制要求):

  • MinIO约 256-512MB 内存
  • Meilisearch约 512MB-1GB 内存(随索引文档量增长)
  • FastAPI 后端:约 256-512MB 内存
  • React/nginx 前端:约 128-256MB 内存

4 核 / 4GB 内存足以运行 DocHub 全部服务;若与其他自建服务(如 Gitea、数据库共享同一台机器建议预留合计 8GB 以上内存。