# geMoldInsight 后端模块化重构蓝图 > 目标:在**同一 Git 仓库**、**同一数据库**前提下,将当前代码结构整理为**可独立部署的多模块架构**,明确 gemold、inventory、frontend 的边界与演进路径。本文档是后续实施的权威蓝图,不是历史记录。 --- ## 1. 背景与目标 当前项目已经从早期单体演进为“双应用 + 共享层”的形态: - 业务模块:`src/moldinsight/`、`src/inventory/` - 共享层:`src/shared/` - 部署入口:`src/entrypoints/moldinsight.py`、`src/entrypoints/inventory.py` - 前端工程:`frontend/` 从代码现状看,`moldinsight` 与 `inventory` 已基本无直接互引,说明模块边界已经初步形成;但同时,数据库模型、认证、配置、应用工厂等仍集中在 `shared/`,导致当前更接近“**模块化中的单体**”,而不是“**可独立部署的模块化单体**”。 本次蓝图的目标不是拆库、拆仓、微服务化,而是: 1. 保持**单仓库(monorepo)** 2. 保持**单数据库** 3. 将后端正式整理为多个模块: - **gemold**(模具分析 / moldinsight) - **inventory**(进销存) - **identity / platform**(共享基础设施与认证) 4. 保持前端为**独立模块工程**,并增强其对多部署模式的兼容 5. 支持三种部署模式: - **unified**:gemold + inventory 同时部署 - **gemold-only**:仅部署 gemold - **inventory-only**:仅部署 inventory --- ## 2. 范围与非目标 ### 2.1 本次蓝图覆盖范围 - 后端模块边界 - 共享层职责重新定义 - 单数据库下的模型归属与表所有权 - 独立部署模式设计 - 前端 API 边界强化策略 - 分阶段迁移路径 - 风险与验证方法 ### 2.2 非目标 本蓝图**不包含**以下方向: - 多 Git 仓库拆分 - 多数据库拆分 - 分布式微服务重构 - 全量 DDD 重写 - 全量前端重构 - 事件驱动或消息总线主导的跨服务通信改造 换句话说,目标架构是: > **单仓库 + 单数据库 + 多模块 + 可独立部署的 modular monolith** 而不是微服务系统。 --- ## 3. 当前架构快照 ### 3.1 后端现状 当前核心目录结构如下: ```text src/ entrypoints/ moldinsight.py inventory.py shared/ app_factory.py config/ database/ models/ services/ utils/ moldinsight/ api/ core/ services/ storage/ inventory/ api/ schemas/ services/ ``` 其中: - [app_factory.py](../src/shared/app_factory.py) 已统一 CORS、日志中间件、startup/shutdown、认证路由、健康检查与 SPA fallback。 - [moldinsight.py](../src/entrypoints/moldinsight.py) 与 [inventory.py](../src/entrypoints/inventory.py) 已提供独立入口。 - [database.py](../src/shared/models/database.py) 同时包含 identity、moldinsight、inventory 三类模型,是当前最强耦合点。 ### 3.2 前端现状 前端已是独立 Vite/Vue 工程: ```text frontend/ src/ modules/ moldinsight/ inventory/ login/ users/ home/ router/ shared/ stores/ types/ ``` 特点: - 已按页面/业务模块组织 - 已有共享 API 层雏形:[api-client.ts](../frontend/src/shared/api-client.ts) - 已接入 OpenAPI 生成类型:[api.ts](../frontend/src/types/api.ts) - 当前仍有大量相对路径 `/api/...` 与 raw `fetch()` 的同源假设 ### 3.3 现状判断 当前架构可概括为: > **HTTP 入口已分离,业务代码已分组,但平台层与数据层仍共享。** 因此,它适合继续朝“可独立部署的模块化单体”演进,而不适合直接跳到微服务。 --- ## 4. 目标架构:可独立部署的模块化单体 ### 4.1 架构原则 目标态采用以下原则: 1. **组合优先于复制**:不同部署模式通过组合不同模块得到,而不是复制多套代码。 2. **平台与业务分离**:`platform` 只承载技术性共享能力,不继续承载业务逻辑。 3. **模块所有权清晰**:每张表、每条 API、每个服务类都应有明确归属。 4. **单数据库但显式边界**:允许共享 DB,但不允许“共享数据库 = 没有边界”。 5. **统一前端,兼容多后端部署形态**:前端继续是一套工程,通过 API client 适配 unified / split deployment。 ### 4.2 架构定位 目标架构不是“多个服务各自拥有数据库”的微服务,而是: - 同一个仓库 - 同一个数据库 - 多个模块 - 多个部署入口 - 同一套迁移历史 - 同一套共享基础设施能力 这是一种适合当前项目阶段的**治理性重构**,而不是组织级拆分。 --- ## 5. 目标目录结构 以下结构是**目标态**,不要求一次性到位: ```text src/ platform/ app/ app_factory.py lifecycle.py middleware/ config/ auth/ database/ engine.py session.py migrations/ observability/ contracts/ api/ events/ shared_kernel/ types/ exceptions/ utils/ modules/ moldinsight/ application/ services/ use_cases/ domain/ models/ policies/ repositories/ infrastructure/ persistence/ storage/ adapters/ interfaces/ api/ schemas/ module.py inventory/ application/ services/ use_cases/ domain/ models/ policies/ repositories/ infrastructure/ persistence/ adapters/ interfaces/ api/ schemas/ module.py identity/ application/ domain/ infrastructure/ interfaces/ module.py compositions/ unified_app.py gemold_app.py inventory_app.py legacy/ main.py ``` ### 5.1 当前目录到目标目录的映射 | 当前路径 | 目标路径 | 说明 | |---|---|---| | `src/shared/*` | `src/platform/*` | 共享基础设施重新命名与归位 | | `src/moldinsight/*` | `src/modules/moldinsight/*` | gemold 业务模块 | | `src/inventory/*` | `src/modules/inventory/*` | inventory 业务模块 | | `src/entrypoints/*` | `src/compositions/*` | 部署组合层 | | `src/main.py` | `src/legacy/main.py` | 过渡期兼容入口 | ### 5.2 为什么要引入 `compositions/` 当前 [entrypoints/](../src/entrypoints/) 已经承担“部署入口”角色,但语义更偏“启动文件”。 引入 `compositions/` 的意义是明确: - 它不是业务模块 - 它不是平台能力 - 它是“**按部署模式装配模块**”的组合层 例如: - `gemold_app.py`:平台 + identity + moldinsight - `inventory_app.py`:平台 + identity + inventory - `unified_app.py`:平台 + identity + moldinsight + inventory --- ## 6. 模块职责边界 ### 6.1 platform `platform` 是技术共享层,只承载**跨模块公共基础设施能力**。 #### 归属范围 - app factory / middleware / 生命周期 - config - 数据库 engine / session / Alembic 接线 - auth / JWT / 权限 - 日志 / request_id / observability - 通用 contracts / utilities #### 可复用现有实现 - [app_factory.py](../src/shared/app_factory.py) - [settings.py](../src/shared/config/settings.py) - [database.py](../src/shared/database/database.py) - [auth_service.py](../src/shared/services/auth_service.py) - [auth_routes.py](../src/shared/services/auth_routes.py) #### 规则 `platform` 不得继续吸收业务规则代码,否则新的 `platform` 会变成旧的 `shared`。 --- ### 6.2 moldinsight(gemold) `moldinsight` 模块负责模具分析、几何处理和分析结果生命周期。 #### 归属范围 - 上传、任务、历史、批量分析、成本估算、CAM、分析结果 - 几何分析、特征检测、模具方案、报告 - RustFS / 对象存储接入 - Celery 异步处理链路 #### 可复用现有实现 - [moldinsight/api/__init__.py](../src/moldinsight/api/__init__.py) - [processing_service.py](../src/moldinsight/services/processing_service.py) - [task_query_service.py](../src/moldinsight/services/task_query_service.py) - [moldinsight/core/](../src/moldinsight/core/) - [celery_app.py](../src/celery_app.py) - [celery_tasks.py](../src/celery_tasks.py) --- ### 6.3 inventory `inventory` 模块负责 ERP / 进销存类业务流程。 #### 归属范围 - 产品、物料、供应商、客户、仓库 - 库存、库存流水 - 销售订单、采购订单、财务、采购建议 - BOM / 采购需求推导 #### 可复用现有实现 - [inventory/api/__init__.py](../src/inventory/api/__init__.py) - [inventory_service.py](../src/inventory/services/inventory_service.py) - [sales_order_service.py](../src/inventory/services/sales_order_service.py) - [purchase_order_service.py](../src/inventory/services/purchase_order_service.py) - [finance_service.py](../src/inventory/services/finance_service.py) --- ### 6.4 identity `identity` 负责用户、角色、权限与认证授权。 #### 归属范围 - User / Role / Permission - 登录、鉴权、管理员接口 - 统一授权能力 在物理目录上,identity 可以先靠近 platform;但逻辑上应从一开始就被视为独立边界,而不是“moldinsight 的一部分”或“inventory 的一部分”。 --- ## 7. 允许的依赖方向 这是本蓝图最重要的治理规则之一。 ### 7.1 依赖规则 ```text compositions -> platform compositions -> modules/* platform -> 不依赖业务模块 modules/*/interfaces -> modules/*/application modules/*/application -> modules/*/domain modules/*/infrastructure -> modules/*/domain modules/*/interfaces -> platform modules/*/infrastructure -> platform ``` ### 7.2 跨模块约束 - `inventory` 不能直接 import `moldinsight.api` / `moldinsight.services` - `moldinsight` 不能直接 import `inventory.api` / `inventory.services` - `platform` 不得依赖任一业务模块 - 跨模块协作只能通过: - 显式 contract / query service - composition wiring - 受控的共享数据库引用 ### 7.3 当前代码与规则的差距 从代码检查看,当前 `moldinsight` 与 `inventory` 基本没有直接互引,这说明上述规则在业务代码层**已经接近成立**。 当前主要问题集中在: - [database.py](../src/shared/models/database.py) 集中承载所有 ORM 模型 - [app_factory.py](../src/shared/app_factory.py) 同时知道通用平台逻辑与 moldinsight 专属 startup 行为 因此,后续实施的重点不是“切断业务模块互引”,而是“**把共享层与数据层的边界拉直**”。 --- ## 8. 单数据库下的模型与表归属策略 ### 8.1 核心原则 数据库继续保持为**一个 PostgreSQL 数据库**,但代码中的模型归属必须显式化。 也就是说: > **数据库不拆,模型归属要拆。** ### 8.2 当前最强耦合点 当前 [database.py](../src/shared/models/database.py) 同时包含: - identity / 平台相关模型 - moldinsight 业务模型 - inventory 业务模型 这会带来两个问题: 1. 代码层看不出模型所有权 2. 开发者更容易跨模块直接访问整套 ORM 图谱 因此,后续实施应优先将这个文件按归属拆分。 ### 8.3 推荐表归属矩阵 #### platform / identity-owned - users - roles - permissions - user_roles - role_permissions - (可选)system_logs #### moldinsight-owned - stp_files - geometry_data - mesh_data - html_files - processing_tasks - mold_cavity_data - feature_detections - design_recommendations - analysis_metrics #### inventory-owned - products - product_materials - material_price_history - material_suppliers - suppliers - customers - warehouses - inventory - stock_movements - purchase_orders - purchase_order_items - sales_orders - sales_order_items - finance_transactions - finance_allocations ### 8.4 目标代码形态 推荐逐步演进到: ```text platform/database/base.py modules/identity/infrastructure/persistence/models.py modules/moldinsight/infrastructure/persistence/models.py modules/inventory/infrastructure/persistence/models.py ``` 同时保持: - 同一个 SQLAlchemy `Base` - 同一个 metadata - 同一条 Alembic 历史链 - 同一个数据库连接 ### 8.5 跨模块 FK 的处理策略 当前存在真实跨模块业务桥: - `STPFile.product_id -> Product.id` 这是合理的,因为它反映了真实业务关系:模具分析结果可以创建成品,并与 inventory 中的产品建立连接。 原则上允许保留这类稳定 FK,但应遵守: 1. 跨模块 FK 是**业务桥**,不是“任意跨模块查询”的许可 2. 模块之间应逐步通过 query service / repository contract 暴露需要的读取能力 3. 避免一个模块直接依赖另一个模块的整套 ORM 图谱 --- ## 9. 部署模式设计 本项目必须支持三种部署模式。 ### 9.1 unified #### 组成 - platform + identity + moldinsight + inventory #### 适用场景 - 本地开发 - 小团队部署 - 集成环境 - 一体化业务场景 #### 说明 新的 unified 组合层应接替旧 [main.py](../src/main.py) 的语义,但应通过 `compositions/unified_app.py` 的方式实现,而不是继续维持旧单体式入口。 --- ### 9.2 gemold-only #### 组成 - platform + identity + moldinsight #### 适用场景 - 仅开放模具分析能力 - 分析服务独立扩容 - 单独部署算法/文件处理能力 #### 说明 - 只暴露 gemold 路由 - 可保留对共享数据库中 `products` 的受控引用 - RustFS / Celery 等专属基础设施只在该模式启用 当前入口基线: - [moldinsight.py](../src/entrypoints/moldinsight.py) --- ### 9.3 inventory-only #### 组成 - platform + identity + inventory #### 适用场景 - 仅提供 ERP / 进销存能力 - 不需要模具分析链路的后台场景 #### 说明 - 只暴露 inventory 路由 - 不要求启动 RustFS 等 moldinsight 专属基础设施 当前入口基线: - [inventory.py](../src/entrypoints/inventory.py) --- ### 9.4 当前共享工厂的边界问题 需要特别指出:当前 [app_factory.py](../src/shared/app_factory.py) 通过 `mount_html=True` 分支初始化 RustFS,这说明共享工厂仍然知道 moldinsight 模块专属基础设施。 这意味着: - `shared` / `platform` 还不够纯 - 模块专属 startup hook 还没有完全从平台层剥离 后续实施时,这应是**优先解决的问题之一**: > app factory 只负责通用平台装配;模块专属生命周期应由 module hook 或 composition layer 决定。 --- ## 10. 前端 API 边界策略 ### 10.1 设计原则 前端已经是独立工程,不需要再拆目录或拆仓。后续重点应放在: - 强化域 API 边界 - 消除对单一同源 `/api/...` 的强依赖 - 兼容 unified / split deployment ### 10.2 当前可复用基础 当前前端已经具备良好基础: - 域客户端入口:[api-client.ts](../frontend/src/shared/api-client.ts) - 生成类型:[api.ts](../frontend/src/types/api.ts) - 模块目录:[frontend/src/modules/moldinsight/](../frontend/src/modules/moldinsight/) 与 [frontend/src/modules/inventory/](../frontend/src/modules/inventory/) 因此,后续策略应是“**边界强化**”,不是“前端重写”。 ### 10.3 建议的客户端边界 应继续收敛为: - `authApi` - `moldinsightApi` - `inventoryApi` 并要求: - 页面/组件尽量不直接写裸 `/api/...` 字符串 - multipart upload / download / export 也尽量通过域客户端封装 - 统一利用 OpenAPI 生成类型,而不是额外维护平行手写类型 ### 10.4 支持两类部署配置 #### unified 模式 - `VITE_API_BASE_URL` #### split 模式 - `VITE_AUTH_API_BASE_URL` - `VITE_MOLDINSIGHT_API_BASE_URL` - `VITE_INVENTORY_API_BASE_URL` 客户端实现上应支持: - unified 下三个 client 指向同一个 base URL - split 下各 client 指向不同服务 ### 10.5 capability-aware UI 在 gemold-only 或 inventory-only 部署模式下,前端不应假设所有模块总是存在。 因此建议: - 后端通过 `/health` 或单独 capability endpoint 暴露已启用模块信息 - 前端根据 capability 隐藏未部署模块入口或禁用对应页面 这样可避免“前端路由还在,但后端根本没部署”的硬失败场景。 --- ## 11. 分阶段迁移计划 ### Phase 0:蓝图冻结 目标:冻结目标结构与边界规则,防止迁移过程中继续长出新的耦合。 动作: - 确认模块边界 - 确认依赖规则 - 确认三种部署模式 - 确认 shared/platform 的使用边界 --- ### Phase 1:组合层标准化 目标:将部署模式从“若干入口脚本”升级为“正式的 composition layer”。 动作: - 将 `entrypoints/*` 升级为 `compositions/*` - 定义 `unified_app.py` / `gemold_app.py` / `inventory_app.py` - 将 module-specific startup hooks 从通用 app factory 中迁出 重点问题: - 当前 `mount_html -> RustFS connect` 属于模块专属逻辑,必须从 shared factory 中剥离 --- ### Phase 2:platform 与业务代码分治 目标:把“共享基础设施”从“共享杂项”中真正分离出来。 动作: - 从 `shared` 语义切换到更清晰的 `platform` - 归位 config / auth / db / observability / utils - 禁止新业务逻辑继续沉积到 `shared` --- ### Phase 3:ORM 按归属拆分 目标:解决当前最大的代码耦合源。 动作: - 拆分 [database.py](../src/shared/models/database.py) - 保持单 Base / 单 Alembic / 单 DB - 先完成代码层归属拆分,再处理更深层的业务隔离 这是整个重构中最关键的一步。 --- ### Phase 4:模块内部继续分层 目标:让每个模块内部的“路由 / 服务 / 领域 / 基础设施”边界更清晰。 动作: - inventory:从现有 service 层继续向 `application / domain / infrastructure / interfaces` 拉开 - moldinsight:逐步理顺 `api / services / core / storage` 的边界 原则: - 不要求一步完成 DDD 化 - 先把层次职责清楚,再考虑更纯粹的领域对象抽象 --- ### Phase 5:建立跨模块集成规则 目标:把当前 ad hoc 跨表访问逐步收敛成显式桥接能力。 动作: - 定义跨模块 query services / repository contracts - 明确“从分析创建成品”等桥接能力的正式入口 - 收敛直接穿透跨模块 ORM 图谱的做法 重点桥接场景: - `STPFile.product_id` - [product_routes.py](../src/inventory/api/product_routes.py) 中的“按 task 创建产品”逻辑 --- ### Phase 6:前端边界加固 目标:让前端真正适配 unified / split deployment。 动作: - 强制域 API client 收口 - 支持 per-module base URL - 支持 capability-aware UI - 减少页面中裸 `fetch('/api/...')` --- ### Phase 7:部署与文档收尾 目标:使架构蓝图与部署事实一致。 动作: - 固化 unified / gemold-only / inventory-only 部署说明 - 更新 README / deployment docs / frontend docs - 明确旧入口、旧 Dockerfile、旧部署说明的地位(兼容 / 历史 / 废弃) --- ## 12. 风险与缓解措施 ### 风险 1:共享模型文件继续隐藏领域归属 **现象**:所有模型集中在 [database.py](../src/shared/models/database.py) **风险**:边界无法落实,任何模块都能自然跨领域访问 **缓解**: - 先产出表归属矩阵 - 再拆 ORM 文件 - 拆归属优先于改业务逻辑 --- ### 风险 2:`shared` 继续变成杂物间 **风险**:shared/platform 成为“不知道放哪就放这里”的位置 **缓解**: - 以 `platform` 重新定义共享层 - 明确只有技术性共享能力可进入 platform - 代码 review 中禁止新增业务逻辑进入 platform --- ### 风险 3:模块专属启动逻辑继续留在 app factory **现象**:当前 `mount_html` 分支控制 RustFS 连接 **风险**:平台层继续了解业务模块内部基础设施 **缓解**: - module lifecycle hook - composition 层控制模块 startup/shutdown - 通用 app factory 保持纯平台化 --- ### 风险 4:独立部署后,前端仍假设所有模块存在 **风险**:前端路由可见,但后端未部署,造成运行时错误 **缓解**: - capability metadata - feature gating - 前端按模块部署形态动态隐藏入口 --- ### 风险 5:单数据库导致开发者随意跨模块查表 **风险**:虽然数据库未拆,但代码边界被绕开 **缓解**: - 表归属规则文档化 - code review 要求说明跨模块访问理由 - 逐步通过 query services 收口 --- ### 风险 6:大爆炸式目录迁移导致 import churn **风险**:一次性移动所有目录,修改面过大,回归成本高 **缓解**: - 分阶段迁移 - 保留兼容 import 过渡层 - 先稳定组合层与模型层,再做深层目录调整 --- ## 13. 验证清单 ### 13.1 结构验证 - `platform` 不 import 业务模块 - `moldinsight` / `inventory` 无直接 api/services 互引 - ORM 文件已按归属拆分,或至少表归属矩阵已文档化并被遵守 ### 13.2 运行验证 #### unified - 两类路由都能正常挂载 - 统一 health / auth / request-id 机制生效 #### gemold-only - inventory 路由未挂载 - gemold 路由可用 - RustFS / Celery 等专属依赖正常初始化 #### inventory-only - moldinsight 路由未挂载 - inventory 路由可用 - 不依赖 moldinsight 专属基础设施即可启动 ### 13.3 数据验证 - 三种部署模式使用同一 migration head - 单数据库中的跨模块 FK 保持有效 - Alembic 无分叉历史 ### 13.4 前端验证 - unified 模式下,一个 base URL 即可跑通 - split 模式下,各模块 base URL 可独立配置 - 未部署模块能被隐藏或优雅失败 --- ## 14. 文档联动更新计划 本蓝图批准后,以下文档应逐步对齐: - [EVOLUTION_ROADMAP.md](./EVOLUTION_ROADMAP.md) - [LINUX_SETUP.md](./deployment/LINUX_SETUP.md) - [DEPLOY_PORT.md](./deployment/DEPLOY_PORT.md) - [PORT_CONFIG.md](./deployment/PORT_CONFIG.md) - [PORT_REFACTOR_SUMMARY.md](./deployment/PORT_REFACTOR_SUMMARY.md) - `README.md` - `frontend/README.md` 其中需要特别注意: - `README.md` 当前仍主要描述旧单体结构,与当前实际代码已有明显漂移。 - 本文档应作为“当前目标架构”的权威蓝图,路线图与部署文档随后对齐。 --- ## 15. 附录:实施热点文件 以下文件是后续实际重构时最关键的热点: ### 平台与组合层 - [app_factory.py](../src/shared/app_factory.py) - [settings.py](../src/shared/config/settings.py) - [database.py](../src/shared/database/database.py) - [init_db.py](../src/shared/database/init_db.py) - [moldinsight.py](../src/entrypoints/moldinsight.py) - [inventory.py](../src/entrypoints/inventory.py) - [main.py](../src/main.py) ### 模型与边界 - [database.py](../src/shared/models/database.py) - [product_routes.py](../src/inventory/api/product_routes.py) ### gemold 模块 - [moldinsight/api/__init__.py](../src/moldinsight/api/__init__.py) - [processing_service.py](../src/moldinsight/services/processing_service.py) - [task_query_service.py](../src/moldinsight/services/task_query_service.py) ### inventory 模块 - [inventory/api/__init__.py](../src/inventory/api/__init__.py) - [inventory_service.py](../src/inventory/services/inventory_service.py) - [sales_order_service.py](../src/inventory/services/sales_order_service.py) - [purchase_order_service.py](../src/inventory/services/purchase_order_service.py) - [finance_service.py](../src/inventory/services/finance_service.py) ### 前端边界 - [api-client.ts](../frontend/src/shared/api-client.ts) - [api.ts](../frontend/src/types/api.ts) ### 演进与部署参考 - [EVOLUTION_ROADMAP.md](./EVOLUTION_ROADMAP.md) - [docker-compose.yml](../docker-compose.yml) --- ## 16. 最终结论 本项目当前最适合的演进路径不是微服务,而是: > **单仓库 + 单数据库 + 多模块 + 可独立部署的 modular monolith** 它既能保留当前业务闭环(模具分析 → 成品 → BOM → 销售/采购/库存),又能逐步降低共享层和模型层的结构耦合。 后续实施时,应优先按以下顺序推进: 1. 固化组合层(deployment composition) 2. 纯化 platform/shared 边界 3. 拆分共享 ORM 文件 4. 再继续模块内部细分层次 5. 最后收口前端 API 与部署文档 这条路径风险最低、收益最大,也最符合当前代码现状与团队演进成本。