Files
junhong_cmp_fiber/.planning/codebase/ARCHITECTURE.md

11 KiB
Raw Blame History

Architecture

Analysis Date: 2026-03-27

Pattern Overview

Overall: 双进程分层单体API + Worker核心代码按 Handler → Service → Store → Model 组织。

Key Characteristics:

  • HTTP 入口与异步任务入口分离:cmd/api/main.go 负责 Fiber APIcmd/worker/main.go 负责 Asynq Worker 与轮询调度。
  • 依赖集中在 internal/bootstrap/ 组装,再分发给 internal/routes/internal/handler/internal/task/
  • 数据访问主要走 internal/store/postgres/*.go,模型与 DTO 分别位于 internal/model/*.gointernal/model/dto/*.go
  • 路由注册统一经过 internal/routes/registry.goRegister(),同时驱动 Fiber 路由与 OpenAPI 元数据。
  • 多租户与权限控制主要依赖认证上下文 + Store 层显式过滤函数,而不是数据库外键或 ORM 关联。

Layers

Entrypoint / Composition Layer:

  • Purpose: 进程启动、基础设施初始化、依赖装配、生命周期管理。
  • Location: cmd/api/main.go, cmd/worker/main.go, internal/bootstrap/*.go
  • Contains: 配置加载、日志、数据库、Redis、队列、对象存储、Gateway 客户端、Bootstrap 编排。
  • Depends on: pkg/config, pkg/database, pkg/logger, pkg/queue, pkg/storage, internal/bootstrap
  • Used by: 整个应用进程。

Routing / Transport Layer:

  • Purpose: 路由域划分、认证挂载、HTTP 入参与响应封装、OpenAPI 文档注册。
  • Location: internal/routes/*.go, internal/handler/**/*.go
  • Contains: RegisterRoutesWithDoc() 总入口、Admin/Auth/Personal 域路由、Fiber Handler。
  • Depends on: internal/bootstrap.Handlers, internal/bootstrap.Middlewares, pkg/openapi, pkg/response
  • Used by: cmd/api/main.go

Service Layer:

  • Purpose: 业务规则、权限判断、事务编排、幂等、异步任务提交、跨模块协作。
  • Location: internal/service/**/*.go
  • Contains: 账号、订单、套餐、轮询、设备、卡、认证、充值、佣金等服务。
  • Depends on: internal/store/postgres, pkg/errors, pkg/middleware, pkg/queue, pkg/wechat, gorm.DB, redis.Client
  • Used by: Handler 层、Worker Bootstrap、Task Handler。

Store Layer:

  • Purpose: SQL 查询、分页、显式数据权限过滤、缓存辅助、事务基础能力。
  • Location: internal/store/store.go, internal/store/options.go, internal/store/postgres/*.go
  • Contains: 每个聚合的 PostgreSQL Store例如 internal/store/postgres/account_store.go, internal/store/postgres/order_store.go
  • Depends on: gorm, redis, pkg/middleware/data_scope.go
  • Used by: Service 层、部分 Handler 组装期专用读模型。

Model Layer:

  • Purpose: 持久化模型、DTO、常量化状态值、表名映射。
  • Location: internal/model/*.go, internal/model/dto/*.go
  • Contains: model.Account, model.Order, model.Shop, model.PollingConfig 以及请求/响应 DTO。
  • Depends on: GORM tags、标准库类型。
  • Used by: Store、Service、Handler、OpenAPI 生成。

Task / Worker Layer:

  • Purpose: Asynq 任务处理、轮询调度、定时任务、批处理导入。
  • Location: internal/task/*.go, internal/polling/*.go, pkg/queue/*.go
  • Contains: pkg/queue/handler.go 任务注册器、internal/task/polling_handler.gointernal/task/order_expire.gointernal/polling/scheduler.go
  • Depends on: Worker bootstrap 产出的 stores/services、Redis、Asynq、Gateway。
  • Used by: cmd/worker/main.go

Data Flow

API Request Flow:

  1. cmd/api/main.go 创建 Fiber 应用并注册 Recover、RequestID、访问日志、压缩中间件。
  2. internal/routes/routes.go 将请求分发到 /api/auth/api/admin/api/c/v1/api/callback 四个域。
  3. pkg/middleware/auth.gointernal/middleware/personal_auth 将用户信息写入 Fiber Locals 和标准 context.Context
  4. Handler 解析 DTO 并调用 Service例如 internal/handler/admin/account.gointernal/service/account/service.go
  5. Service 调用一个或多个 Store必要时使用 db.WithContext(ctx).Transaction(...) 编排事务,例如 internal/service/order/service.go
  6. Store 在查询中显式调用 pkg/middleware/data_scope.go 的过滤函数,例如 internal/store/postgres/account_store.gointernal/store/postgres/order_store.go
  7. Handler 通过 pkg/response/response.go 返回统一响应;异常交由 internal/middleware.ErrorHandler 处理。

Worker Flow:

  1. cmd/worker/main.go 初始化 PostgreSQL、Redis、Asynq Client、对象存储、Gateway。
  2. internal/bootstrap/worker.go 调用 initWorkerStores()initWorkerServices(),生成 queue.WorkerBootstrapResult
  3. pkg/queue/handler.go 基于 Bootstrap 结果注册导入、轮询、佣金、超时取消、告警、清理等任务处理器。
  4. internal/polling/scheduler.go 独立运行轮询调度循环:从 Redis Sorted Set / List 取卡片,再投递到 Asynq。
  5. cmd/worker/main.go 还额外创建 Asynq Scheduler注册 TaskTypeOrderExpireTaskTypeAlertCheckTaskTypeDataCleanup
  6. 具体任务处理器调用 Service 或直接使用 Store/DB 更新状态,例如 internal/task/order_expire.goorder.Service.CancelExpiredOrders()

State Management:

  • HTTP 侧状态主要放在 PostgreSQL请求态身份与数据权限范围放在 context.Context
  • 高速状态、Token、轮询队列、并发信号量、下级店铺缓存放在 Redispkg/auth/token.gointernal/polling/scheduler.gointernal/store/postgres/shop_store.go
  • 异步处理采用 Redis-backed Asynq 队列,由 pkg/queue/client.go 提交、pkg/queue/server.go 消费。

Key Abstractions

BootstrapResult / WorkerBootstrapResult:

  • Purpose: 启动期依赖编排结果。
  • Examples: internal/bootstrap/bootstrap.go, internal/bootstrap/worker.go
  • Pattern: 显式依赖注入,不使用外部 DI 框架。

Handlers / Middlewares 容器:

  • Purpose: 路由注册时的装配清单。
  • Examples: internal/bootstrap/types.go, internal/bootstrap/handlers.go, internal/bootstrap/middlewares.go
  • Pattern: 结构体聚合所有已构造的 Handler 与 Middleware。

RouteSpec + Register():

  • Purpose: 单次声明同时完成真实路由注册和 OpenAPI 元数据注册。
  • Examples: internal/routes/registry.go, internal/routes/account.go, internal/routes/personal.go
  • Pattern: 代码即文档DTO 驱动文档生成。

QueryOptions:

  • Purpose: Store 通用分页与排序选项。
  • Examples: internal/store/options.go, internal/service/account/service.go, internal/service/order/service.go
  • Pattern: Service 先构造查询选项,再下传到 Store。

UserContextInfo + Data Scope Filters:

  • Purpose: 承载用户身份与可管理店铺范围,并在 Store 查询时执行过滤。
  • Examples: pkg/middleware/auth.go, pkg/middleware/data_scope.go, internal/store/postgres/shop_store.go
  • Pattern: 中间件预计算 SubordinateShopIDsStore 按字段类型显式调用 ApplyShopFilter / ApplyEnterpriseFilter / ApplySellerShopFilter

Entry Points

API Main:

  • Location: cmd/api/main.go
  • Triggers: go run cmd/api/main.go、API 容器启动。
  • Responsibilities: 加载配置、初始化基础设施、执行 bootstrap.Bootstrap()、创建 Fiber、注册中间件和路由、生成运行时 OpenAPI 文件 logs/openapi.yaml

Worker Main:

  • Location: cmd/worker/main.go
  • Triggers: go run cmd/worker/main.go、Worker 容器启动。
  • Responsibilities: 初始化 Worker 依赖、执行 bootstrap.BootstrapWorker()、启动 Asynq Worker、启动轮询调度器和 Asynq Scheduler、优雅关闭。

OpenAPI Generation CLI:

  • Location: cmd/gendocs/main.go
  • Triggers: 手动执行文档生成。
  • Responsibilities: 通过 openapi.BuildDocHandlers() + routes.RegisterRoutesWithDoc() 输出 docs/admin-openapi.yaml

Routing Strategy

Domain Split:

  • /api/auth:统一后台/H5 认证,见 internal/routes/auth.go
  • /api/admin:管理后台业务域,见 internal/routes/admin.go
  • /api/c/v1:个人客户端域,见 internal/routes/personal.go
  • /api/callback:支付回调,无认证,见 internal/routes/order.gointernal/handler/callback/payment.go

Registration Style:

  • 所有 HTTP 接口使用 internal/routes/registry.goRegister(),文档规范见 docs/api-documentation-guide.md
  • internal/routes/admin.go 以 handler 是否为 nil 决定是否挂载模块,便于文档生成和裁剪。
  • internal/routes/personal.go 明确区分公开路由与认证路由,并依赖注册顺序确保公开接口不被 Use() 拦截。

Error Handling

Strategy: 统一错误码 + 全局 Fiber ErrorHandler。

Patterns:

  • Handler 层只做参数解析与转发,返回 pkg/errors 中的 AppError,如 internal/handler/admin/account.go
  • Service 层封装业务错误,不直接向外泄露底层错误文本,如 internal/service/account/service.gointernal/service/order/service.go
  • Worker 任务记录结构化日志,并将可重试与不可重试逻辑写在处理器内部,如 internal/task/order_expire.gointernal/task/polling_handler.go

Cross-Cutting Concerns

Logging:

  • pkg/logger/logger.go 初始化 App/Access 日志;pkg/logger/middleware.go 记录完整请求/响应摘要。

Validation:

  • Fiber BodyParser / QueryParser + validator.v10,示例见 internal/handler/auth/handler.go

Authentication:

  • 后台/H5 使用 Redis Token + pkg/middleware/auth.go;个人客户使用单独中间件,由 internal/bootstrap/middlewares.go 创建。

OpenAPI:

  • 路由元数据写在 RouteSpec;文档生成器依赖 cmd/api/docs.gocmd/gendocs/main.gopkg/openapi/handlers.go 三处手工维护 Handler 清单。

Persistence Rules:

  • 模型显式声明 TableName() 与字段列名,如 internal/model/account.go, internal/model/order.go, internal/model/shop.go
  • 数据库结构通过 migrations/*.sql 管理,pkg/database/postgres.go 明确禁用自动建表。

Architectural Deviations

README / 规范与当前实现存在的偏差:

  • README.mdopenspec/config.yaml 多处描述“GORM Callback 自动注入数据权限过滤”,但当前 internal/bootstrap/bootstrap.go 第 67 行明确写明“数据权限过滤已移至 Store 层显式调用 ApplyXxxFilter 函数”。当前保留的 GORM Callback 只有 pkg/gorm/callback.go 中的创建人/更新人自动填充。
  • internal/bootstrap/handlers.go 为客户端场景直接新建多个 Store 和一个 client_order Service而不是完全只消费 services 聚合;这说明 Handler 装配阶段存在读模型/适配层级的额外拼装。
  • internal/task/polling_handler.go 在首次实名激活流程中先构造 Asynq 任务,但实际通过 Redis List RPush 提交,文件内注释明确写出“实际应该通过依赖注入 asynq.Client”这是 Worker 流程中的特殊机制与待收敛点。

Architecture analysis: 2026-03-27