mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-09-30 06:16:37 +08:00
refactor(core): align with cordis spatiotemporal composability architecture
- Purify core micro-kernel by removing context hardcoded helpers and reverse dependencies - Eliminate init() side effects in infra plugins with reversible lifecycle disposal - Completely isolate plugins by removing cross-plugin imports and using core/contracts - Introduce TaskService and RiskControlService contracts for unified cross-plugin APIs - Regenerate Swagger documentation and update developer guide matrix - Achieve 0 violations in check_cordis_architecture.sh and 100% test pass
This commit is contained in:
@@ -67,8 +67,9 @@ func (p *Plugin) Apply(ctx *core.Context) error {
|
||||
```go
|
||||
// 1. 插件 A (提供者 plugins/user) 将服务注入 Context
|
||||
func (p *UserPlugin) Apply(ctx *core.Context) error {
|
||||
userSvc := NewUserServiceImpl(ctx.DB())
|
||||
ctx.Provide[contracts.UserService](userSvc)
|
||||
dbSvc, _ := core.Inject[contracts.DBService](ctx)
|
||||
userSvc := NewUserServiceImpl(dbSvc)
|
||||
core.Provide[contracts.UserService](ctx, userSvc)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -611,7 +612,7 @@ Wavelet/
|
||||
|
||||
每个插件在 `Apply(ctx *core.Context)` 时,都可以无缝调用微内核暴露的以下标准能力:
|
||||
|
||||
| 扩展点方法 | 返回类型 | 功能说明 | 适用场景 |
|
||||
| 扩展点/能力方法 | 返回类型 | 功能说明 | 适用场景 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `ctx.Router()` | `RouterExtension` | 声明 HTTP 路由、前缀分组与挂载中间件,支持 `Unregister` / `UnregisterByID` | 暴露 API 接口、Web 控制台 |
|
||||
| `ctx.Task()` | `TaskExtension` | 注册 Asynq 异步任务消费处理器,支持 `Unregister` | 耗时后台任务、异步消息发送 |
|
||||
@@ -619,15 +620,15 @@ Wavelet/
|
||||
| `ctx.Migrations()` | `MigrationExtension`| 注册插件专属的 Goose SQL 迁移嵌入系统,支持 `Unregister` | 自建数据表、版本升级 |
|
||||
| `ctx.Events()` | `EventBus` | 强类型领域事件总线(支持 `Emit`, `Waterfall`, `Parallel`, `Serial`) | 跨插件完全解耦通知与状态同步 |
|
||||
| `ctx.Settings()` | `SettingExtension` | 声明动态可配置项(支持热更新),支持 `Unregister` | 业务参数配置、管理台可调节参数 |
|
||||
| `ctx.DB()` | `contracts.DBService` | 获取受事务与 Trace 保护的数据库连接与 GORM 实例 | 数据持久化 CRUD |
|
||||
| `ctx.Cache()` | `contracts.CacheService` | 三层穿透缓存(RAM L1 + Redis L2 + PubSub 广播)| 高频读数据性能加速 |
|
||||
| `ctx.DistLock()` | `DistLockService` | 基于 Redis 的工业级分布式锁 | 防并发超卖、防重复执行 |
|
||||
| `ctx.Logger()` | `Logger` | 携带链路 TraceID 的结构化日志记录器 | 业务日志打印与审计 |
|
||||
| `ctx.Storage()` | `contracts.StorageService` | 统一对象存储读写引擎 | 文件摄取、图片持久化 |
|
||||
| `ctx.Fork()` | `*Context` | 创建继承父级容器并隔离局部副作用的子上下文 | 局部 Fiber、请求域隔离 |
|
||||
| `core.Provide[T]`| `void` | 向全局 IoC 容器注册强类型服务(自动挂载 `OnDispose` 逆操作) | 暴露自身能力给其他插件消费 |
|
||||
| `core.Inject[T]` | `(T, error)` | 从全局 IoC 容器中按类型获取服务实例 | 消费其他插件暴露的服务 |
|
||||
| `core.When[T]` | `void` | 响应式监听服务注入(当服务一旦就绪立即触发回调) | 解决插件装载时序竞争与延迟初始化 |
|
||||
| `core.Has[T]` | `bool` | 判断指定服务类型当前是否已在容器中注册 | 探测环境能力与条件装载 |
|
||||
| `core.Using[T]` | `error` | 响应式声明依赖,当服务就绪时执行回调 | 声明前置依赖关系 |
|
||||
| `ctx.Using(func(T))` | `error` | 响应式声明依赖,当服务就绪时执行回调 | 声明前置依赖关系 |
|
||||
| `core.Inject[contracts.DBService]` | `(DBService, error)` | 获取受事务与 Trace 保护的数据库连接与 GORM 实例 | 数据持久化 CRUD |
|
||||
| `core.Inject[contracts.CacheService]` | `(CacheService, error)` | 三层穿透缓存(RAM L1 + Redis L2 + PubSub 广播)| 高频读数据性能加速 |
|
||||
| `core.Inject[contracts.StorageService]` | `(StorageService, error)` | 统一对象存储读写引擎 | 文件摄取、图片持久化 |
|
||||
| `core.Inject[contracts.TaskService]` | `(TaskService, error)` | 后台任务下发、重试与调度管理契约 | 任务下发与定时调度管理 |
|
||||
| `core.Inject[contracts.RiskControlService]` | `(RiskControlService, error)` | 访问日志查询、聚合分析与存储引擎管理契约 | 审计日志与安全分析 |
|
||||
|
||||
|
||||
+83
-68
@@ -264,7 +264,7 @@ const docTemplate = `{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/diskcache.Status"
|
||||
"$ref": "#/definitions/disk.Status"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2156,7 +2156,7 @@ const docTemplate = `{
|
||||
"data": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/driver_asynq_worker.TaskMeta"
|
||||
"$ref": "#/definitions/contracts.TaskMetaDTO"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4696,6 +4696,9 @@ const docTemplate = `{
|
||||
"status": {
|
||||
"type": "integer"
|
||||
},
|
||||
"trace_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"user_agent": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -5026,7 +5029,60 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"diskcache.Status": {
|
||||
"contracts.TaskMetaDTO": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"category": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"display_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"max_retry": {
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/contracts.TaskParamDTO"
|
||||
}
|
||||
},
|
||||
"queue": {
|
||||
"type": "string"
|
||||
},
|
||||
"schedule": {
|
||||
"type": "string"
|
||||
},
|
||||
"timeout": {
|
||||
"$ref": "#/definitions/time.Duration"
|
||||
}
|
||||
}
|
||||
},
|
||||
"contracts.TaskParamDTO": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"default": {},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"disk.Status": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"base_path": {
|
||||
@@ -5049,71 +5105,6 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"driver_asynq_worker.TaskMeta": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"asynq_task": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"max_retry": {
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/driver_asynq_worker.TaskParam"
|
||||
}
|
||||
},
|
||||
"queue": {
|
||||
"type": "string"
|
||||
},
|
||||
"retryable": {
|
||||
"description": "是否支持手动重试",
|
||||
"type": "boolean"
|
||||
},
|
||||
"supports_time": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"driver_asynq_worker.TaskParam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description": {
|
||||
"description": "描述",
|
||||
"type": "string"
|
||||
},
|
||||
"label": {
|
||||
"description": "显示名称",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "参数键名",
|
||||
"type": "string"
|
||||
},
|
||||
"placeholder": {
|
||||
"description": "占位符",
|
||||
"type": "string"
|
||||
},
|
||||
"required": {
|
||||
"description": "是否必填",
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"description": "类型:string, text, number, boolean",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"handler.batchDownloadRequest": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -5535,6 +5526,30 @@ const docTemplate = `{
|
||||
"example": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"time.Duration": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"enum": [
|
||||
-9223372036854775808,
|
||||
9223372036854775807,
|
||||
1,
|
||||
1000,
|
||||
1000000,
|
||||
1000000000,
|
||||
60000000000,
|
||||
3600000000000
|
||||
],
|
||||
"x-enum-varnames": [
|
||||
"minDuration",
|
||||
"maxDuration",
|
||||
"Nanosecond",
|
||||
"Microsecond",
|
||||
"Millisecond",
|
||||
"Second",
|
||||
"Minute",
|
||||
"Hour"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securityDefinitions": {
|
||||
|
||||
@@ -1,171 +1,120 @@
|
||||
# Cordis Architecture Refactor Implementation Plan
|
||||
# Cordis 架构重构实施计划 (Cordis Architecture Refactor Implementation Plan)
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Refactor Wavelet backend to strictly conform to Cordis meta-framework principles: full revertible effects, space composability via per-plugin scoped context fork, 4-semantic typed event bus, elimination of package-level infra globals, and strict single-owner principle across domain plugins.
|
||||
**Goal:** 依据 Cordis 时空可组合性元框架,彻底消除 Wavelet 后端的包级静态单例、`init()` 隐式副作用建连以及跨插件私有实现依赖,实现微内核纯洁化与契约驱动解耦。
|
||||
|
||||
**Architecture:**
|
||||
1. Microkernel core (`core/`): Implement `Waterfall`, `Parallel`, `Serial` event dispatch, per-plugin Scoped Context (`ctx.Fork()`), revertible extension points (`extpoints`), and `ctx.DB()` / `ctx.Cache()` contract helpers.
|
||||
2. Contracts (`core/contracts/`): Expand `UserService` & `AuthService` with administration and token revocation interfaces; define typed domain events.
|
||||
3. Domain Plugins (`plugins/domain/`): Implement user/auth contract additions; refactor `admin` plugin to completely remove cross-plugin internal package imports and direct SQL operations on other plugins' tables.
|
||||
1. 移除 `backend/core/context.go` 中的特权服务快捷方法(`DB()` / `Cache()`)。
|
||||
2. 将 `infra/database` 与 `infra/cache` 的连接初始化移至 `Plugin.Apply(ctx)`,并在 `ctx.OnDispose` 中注册 LIFO 逆操作(Close)。
|
||||
3. 重构全部 8 个 Domain 业务插件(`auth`、`user`、`admin`、`cap`、`message_gateway`、`risk_control`、`system`、`upload`),彻底斩断对 `infra/database`、`infra/cache` 及其他插件内部包的直接 import,统一面向 `contracts.DBService` / `contracts.CacheService`。
|
||||
4. 清除 `admin` 等插件的包级全局变量。
|
||||
|
||||
**Tech Stack:** Go 1.23+, GORM, Gin, Goose, Cordis Paradigm.
|
||||
**Tech Stack:** Go 1.24+, GORM, Redis (go-redis/v9), Cordis micro-kernel, Goose migration.
|
||||
|
||||
## Global Constraints
|
||||
|
||||
- No direct cross-package imports between plugins (`plugins/domain/A` must NEVER import `plugins/domain/B` or `plugins/drivers/*`).
|
||||
- Single Owner Principle: Every database table is owned and operated exclusively by its owner plugin.
|
||||
- Microkernel purity: `core/` and `core/contracts/` must never import `gin`, `gorm`, `asynq`.
|
||||
- Tests must pass with `-race` enabled; temporary directories must use `t.TempDir()`.
|
||||
- Quality gates: `make code-check`, `make format`, `make swagger`.
|
||||
- 严禁任何业务插件跨包 import `Wavelet/plugins/infra/database` 或 `Wavelet/plugins/infra/cache`。
|
||||
- 严禁跨插件 import 私有实现包(如 `admin` import `risk_control/logstore`)。
|
||||
- 保持 `backend/pkg/util/` 绝对纯净,禁止导入 Web/数据库框架。
|
||||
- 重构后必须确保 `go test ./...`、`make code-check` 与 `make format` 全部 0 错误通过。
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Core EventBus 4 Dispatch Semantics
|
||||
### Task 1: 微内核纯洁化 (`backend/core/`)
|
||||
|
||||
**Files:**
|
||||
- Modify: `backend/core/events.go`
|
||||
- Test: `backend/core/events_test.go`
|
||||
|
||||
**Interfaces:**
|
||||
- Produces:
|
||||
- `(b *EventBus) Emit(ctx context.Context, topic string, payload any) error`
|
||||
- `(b *EventBus) Waterfall(ctx context.Context, topic string, initialPayload any) (any, error)`
|
||||
- `(b *EventBus) Parallel(ctx context.Context, topic string, payload any) error`
|
||||
- `(b *EventBus) Serial(ctx context.Context, topic string, payload any) error`
|
||||
|
||||
- [ ] **Step 1: Write tests for Waterfall, Parallel, and Serial dispatch semantics**
|
||||
- [ ] **Step 2: Run tests to verify they fail**
|
||||
- [ ] **Step 3: Implement Waterfall, Parallel, Serial methods on EventBus**
|
||||
- [ ] **Step 4: Run tests to verify they pass**
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
---
|
||||
|
||||
### Task 2: Core Scoped Context, Revertible ExtPoints & Contract Helpers
|
||||
|
||||
**Files:**
|
||||
- Modify: `backend/core/context.go`
|
||||
- Modify: `backend/core/app.go`
|
||||
- Modify: `backend/core/extpoints/router.go`
|
||||
- Modify: `backend/core/extpoints/task.go`
|
||||
- Modify: `backend/core/extpoints/schedule.go`
|
||||
- Modify: `backend/core/extpoints/setting.go`
|
||||
- Modify: `backend/core/extpoints/migration.go`
|
||||
- Modify: `backend/core/context.go:240-260`
|
||||
- Test: `backend/core/context_test.go`
|
||||
- Test: `backend/core/app_test.go`
|
||||
- Test: `backend/core/extpoints/extpoints_test.go`
|
||||
|
||||
**Interfaces:**
|
||||
- Produces:
|
||||
- `(c *Context) DB() contracts.DBService`
|
||||
- `(c *Context) Cache() contracts.CacheService`
|
||||
- `(r *RouterRegistry) Unregister(id uint64) bool`
|
||||
- `RouterExtension.Handle(...) Disposer` / `RouteDefinition` with disposer tracking
|
||||
- `App.ApplyPlugins()` forks scoped context per plugin: `p.Apply(a.ctx.Fork())`
|
||||
- Consumes: `core.Context`, `core.Inject`
|
||||
- Produces: 纯净无特权方法的 `core.Context`
|
||||
|
||||
- [ ] **Step 1: Write tests for Scoped Context Fork, LIFO Disposer, and Router Unregister**
|
||||
- [ ] **Step 2: Run tests to verify failure**
|
||||
- [ ] **Step 3: Implement Scoped Fork, Disposers, and Context DB/Cache helpers**
|
||||
- [ ] **Step 4: Update App.ApplyPlugins to fork a context for each plugin**
|
||||
- [ ] **Step 5: Run tests and verify all core tests pass**
|
||||
- [ ] **Step 6: Commit**
|
||||
- [ ] **Step 1: 编写/更新 Context 纯洁性测试**
|
||||
- [ ] **Step 2: 移除 `Context.DB()` 与 `Context.Cache()` 方法**
|
||||
- [ ] **Step 3: 运行 `go test ./backend/core/...` 验证通过**
|
||||
|
||||
---
|
||||
|
||||
### Task 3: Expand Service Contracts & Domain Events
|
||||
### Task 2: 基础设施插件生命周期可逆化 (`backend/plugins/infra/`)
|
||||
|
||||
**Files:**
|
||||
- Modify: `backend/core/contracts/user.go`
|
||||
- Modify: `backend/core/contracts/auth.go`
|
||||
- Modify: `backend/core/contracts/events.go`
|
||||
- Modify: `backend/plugins/infra/database/postgres.go`
|
||||
- Modify: `backend/plugins/infra/database/plugin.go`
|
||||
- Modify: `backend/plugins/infra/cache/redis.go`
|
||||
- Modify: `backend/plugins/infra/cache/plugin.go`
|
||||
- Test: `backend/plugins/infra/infra_test.go`
|
||||
|
||||
**Interfaces:**
|
||||
- Produces:
|
||||
- `AdminListUsersRequest`, `AdminCreateUserRequest`, `AdminUpdateUserRequest`
|
||||
- `UserService` admin methods (`AdminListUsers`, `AdminGetUser`, `AdminCreateUser`, `AdminUpdateUser`, `AdminUpdateUserStatus`, `AdminDeleteUser`)
|
||||
- `AuthService` token management methods (`RevokeToken`, `RevokeUserTokens`, `InvalidateCachedUser`, `InvalidateCachedToken`)
|
||||
- Standard event definitions (`EventUserUpdated`, `EventUserDeleted`, `EventUserStatusChanged`, `EventTokenRevoked`)
|
||||
- Consumes: `core.Plugin`, `contracts.DBService`, `contracts.CacheService`
|
||||
- Produces: `contracts.DBService` 与 `contracts.CacheService`(带 `ctx.OnDispose` 逆操作)
|
||||
|
||||
- [ ] **Step 1: Declare extended contracts and DTO types in core/contracts/**
|
||||
- [ ] **Step 2: Declare typed event constants and structs in core/contracts/events.go**
|
||||
- [ ] **Step 3: Verify core and core/contracts compile cleanly**
|
||||
- [ ] **Step 4: Commit**
|
||||
- [ ] **Step 1: 移除 `infra/database` 中的 `func init()` 及全局 `var db`,在 `Plugin.Apply` 中建连并注册 `ctx.OnDispose(sqlDB.Close)`**
|
||||
- [ ] **Step 2: 移除 `infra/cache` 中的 `func init()` 及全局 `var Redis`,在 `Plugin.Apply` 中建连并注册 `ctx.OnDispose(client.Close)`**
|
||||
- [ ] **Step 3: 运行 `go test ./backend/plugins/infra/...` 验证通过**
|
||||
|
||||
---
|
||||
|
||||
### Task 4: Implement Expanded Contracts in User & Auth Domain Plugins
|
||||
### Task 3: 核心 Domain 插件防线重塑(Auth & User 插件)
|
||||
|
||||
**Files:**
|
||||
- Modify: `backend/plugins/domain/user/service.go`
|
||||
- Modify: `backend/plugins/domain/user/plugin.go`
|
||||
- Modify: `backend/plugins/domain/user/user_test.go`
|
||||
- Modify: `backend/plugins/domain/auth/service.go`
|
||||
- Modify: `backend/plugins/domain/auth/plugin.go`
|
||||
- Modify: `backend/plugins/domain/auth/plugin_test.go`
|
||||
- Modify: `backend/plugins/domain/auth/*`
|
||||
- Modify: `backend/plugins/domain/user/*`
|
||||
- Test: `backend/plugins/domain/auth/plugin_test.go`
|
||||
- Test: `backend/plugins/domain/user/plugin_test.go`
|
||||
|
||||
**Interfaces:**
|
||||
- Implements: `contracts.UserService` full methods in `user` plugin.
|
||||
- Implements: `contracts.AuthService` full methods in `auth` plugin.
|
||||
- Subscribes: `auth` plugin subscribes to `EventUserStatusChanged` / `EventUserDeleted` to invalidate cache and revoke tokens.
|
||||
- Consumes: `contracts.DBService`, `contracts.CacheService`
|
||||
- Produces: `contracts.AuthService`, `contracts.UserService`
|
||||
|
||||
- [ ] **Step 1: Write unit tests for new UserService admin methods and AuthService revocation methods**
|
||||
- [ ] **Step 2: Run tests to verify failure**
|
||||
- [ ] **Step 3: Implement the methods in user and auth domain packages**
|
||||
- [ ] **Step 4: Run user and auth plugin tests and verify they pass**
|
||||
- [ ] **Step 5: Commit**
|
||||
- [ ] **Step 1: 移除 `auth` 插件中对 `Wavelet/plugins/infra/database` 和 `cache` 的 import,改用插件持有的 `contracts.DBService` 与 `contracts.CacheService`**
|
||||
- [ ] **Step 2: 移除 `user` 插件中对 `Wavelet/plugins/infra/database` 和 `cache` 的 import,改用 `contracts.DBService` 与 `contracts.CacheService`**
|
||||
- [ ] **Step 3: 运行 `go test ./backend/plugins/domain/auth/... ./backend/plugins/domain/user/...` 验证通过**
|
||||
|
||||
---
|
||||
|
||||
### Task 5: Refactor Admin Plugin (Eliminate Cross-Plugin Direct Imports & Table Ownership Violations)
|
||||
### Task 4: 业务 Domain 插件防线重塑(Cap, MessageGateway, RiskControl, System, Upload)
|
||||
|
||||
**Files:**
|
||||
- Modify: `backend/plugins/domain/admin/handlers_user.go`
|
||||
- Modify: `backend/plugins/domain/admin/handlers_auth_source.go`
|
||||
- Modify: `backend/plugins/domain/admin/handlers_config.go`
|
||||
- Modify: `backend/plugins/domain/admin/handlers_logs.go`
|
||||
- Modify: `backend/plugins/domain/admin/handlers_status.go`
|
||||
- Modify: `backend/plugins/domain/admin/handlers_tasks.go`
|
||||
- Modify: `backend/plugins/domain/admin/repository.go`
|
||||
- Modify: `backend/plugins/domain/admin/system_config_cache.go`
|
||||
- Modify: `backend/plugins/domain/admin/plugin.go`
|
||||
- Modify: `backend/plugins/domain/admin/plugin_test.go`
|
||||
- Modify: `backend/plugins/domain/cap/*`
|
||||
- Modify: `backend/plugins/domain/message_gateway/*`
|
||||
- Modify: `backend/plugins/domain/risk_control/*`
|
||||
- Modify: `backend/plugins/domain/system/*`
|
||||
- Modify: `backend/plugins/domain/upload/*`
|
||||
- Test: `backend/plugins/domain/domain_test.go`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: `contracts.UserService`, `contracts.AuthService`, `contracts.DBService`, `contracts.CacheService`, `ctx.DB()`, `ctx.Cache()`
|
||||
- Zero imports of `plugins/domain/auth`, `plugins/domain/risk_control`, `plugins/domain/cap`, `plugins/drivers/*`, `plugins/infra/database`
|
||||
- Consumes: `contracts.DBService`, `contracts.CacheService`
|
||||
|
||||
- [ ] **Step 1: Write integration tests for Admin handlers using mocked/injected contracts**
|
||||
- [ ] **Step 2: Refactor admin handlers to delegate user/auth operations to contracts**
|
||||
- [ ] **Step 3: Remove all cross-plugin direct package imports and illegal SQL DML**
|
||||
- [ ] **Step 4: Run admin plugin tests to verify passing**
|
||||
- [ ] **Step 5: Commit**
|
||||
- [ ] **Step 1: 改造 `cap`、`message_gateway`、`risk_control`、`system`、`upload` 插件,移除所有 `infra/database` 和 `infra/cache` 的直接 import**
|
||||
- [ ] **Step 2: 统一各插件内部 Repository / Service 的 DB / Cache 获取途径**
|
||||
- [ ] **Step 3: 运行各插件单测验证通过**
|
||||
|
||||
---
|
||||
|
||||
### Task 6: Clean up Domain & Infra Plugins Database / Cache Injections
|
||||
### Task 5: Admin 插件解耦与包级全局状态清除
|
||||
|
||||
**Files:**
|
||||
- Modify: `backend/plugins/domain/cap/...`
|
||||
- Modify: `backend/plugins/domain/message_gateway/...`
|
||||
- Modify: `backend/plugins/domain/risk_control/...`
|
||||
- Modify: `backend/plugins/domain/upload/...`
|
||||
- Modify: `backend/plugins/domain/system/...`
|
||||
- Modify: `backend/plugins/domain/admin/*`
|
||||
- Test: `backend/plugins/domain/admin/plugin_test.go`
|
||||
|
||||
- [ ] **Step 1: Audit and replace direct `database.DB(ctx)` calls with `ctx.DB()` / injected `contracts.DBService`**
|
||||
- [ ] **Step 2: Audit and replace direct `cache.Client()` calls with `ctx.Cache()` / injected `contracts.CacheService`**
|
||||
- [ ] **Step 3: Run domain plugins test suite**
|
||||
- [ ] **Step 4: Commit**
|
||||
**Interfaces:**
|
||||
- Consumes: `contracts.DBService`, `contracts.CacheService`, `contracts.UserService`, `contracts.AuthService`, `ctx.Tasks()`
|
||||
|
||||
- [ ] **Step 1: 移除 `admin` 插件中对 `risk_control/logstore`、`driver_asynq_worker`、`infra/storage/diskcache` 等私有包的直接 import**
|
||||
- [ ] **Step 2: 清除 `admin/plugin.go` 中的 `globalUserSvc`、`globalAuthSvc`、`globalCoreCtx` 等包级变量**
|
||||
- [ ] **Step 3: 运行 `go test ./backend/plugins/domain/admin/...` 验证通过**
|
||||
|
||||
---
|
||||
|
||||
### Task 7: Full Verification & Quality Gates
|
||||
### Task 6: 组装层对齐与全量质量门禁验证
|
||||
|
||||
**Files:**
|
||||
- All backend files
|
||||
- Modify: `backend/cmd/app.go`
|
||||
- Modify: `backend/cmd/*`
|
||||
|
||||
- [ ] **Step 1: Run full test suite with race detector: `go test -v -race ./backend/...`**
|
||||
- [ ] **Step 2: Run `make code-check`**
|
||||
- [ ] **Step 3: Run `make format`**
|
||||
- [ ] **Step 4: Run `make swagger`**
|
||||
- [ ] **Step 5: Final commit**
|
||||
- [ ] **Step 1: 检查并适配 `cmd/app.go` 及启动指令,确保 Goose 迁移与驱动正确接入新版 `DBService`**
|
||||
- [ ] **Step 2: 运行全局跨包 import 检查:`grep -r "Wavelet/plugins/infra/database" backend/plugins/domain/` 必须为空**
|
||||
- [ ] **Step 3: 运行全量单元测试与基准测试:`go test ./...`**
|
||||
- [ ] **Step 4: 运行质量门禁:`make code-check && make format`**
|
||||
|
||||
@@ -1,140 +1,84 @@
|
||||
# Cordis 架构对齐与系统重构设计规范 (Design Spec)
|
||||
# Cordis 架构重构设计规格书 (Cordis Architecture Refactor Design)
|
||||
|
||||
- **Date:** 2026-08-28
|
||||
- **Topic:** Cordis Architecture Alignment & Full System Refactor
|
||||
- **Status:** Approved
|
||||
**日期**: 2026-08-28
|
||||
**目标**: 依据 Cordis 时空可组合性元框架(Spatiotemporal Composability)哲学,重构 Wavelet 后端包结构、包职责与插件边界,消除全局静态单例与跨插件私有实现依赖,实现真正的可逆副作用与契约化隔离。
|
||||
|
||||
---
|
||||
|
||||
## 1. 目标与背景 (Goal & Background)
|
||||
## 1. 背景与核心设计原则
|
||||
|
||||
本项目遵循 **Cordis(时空可组合性元框架)** 的核心设计哲学:
|
||||
- **时间可组合性(Time Composability)**:所有对运行时环境的修改(扩展点挂载、事件订阅、服务注册、状态配置)均具备显式可逆操作(Revertible Effects),卸载时按 LIFO(后进先出)严格回收。
|
||||
- **空间可组合性(Space Composability)**:插件运行在独立的 Scoped Context 分支中,通过面向契约(`contracts`)与事件(`EventBus`)解耦,消除人工硬编码启动顺序与跨插件内部实现耦合。
|
||||
- **表单一所有者原则(Single Owner Principle)**:每张数据表由且仅由一个所有者插件维护,严禁旁路 DML 读写。
|
||||
|
||||
本规范定义微内核层、服务契约层、基础设施层与业务域插件的全量重构设计。
|
||||
Cordis 是一个面向时空可组合性的元框架,核心在于:
|
||||
1. **时间可组合性 (Temporal Composability / Revertible Effects)**:组件挂载到上下文时产生的任何副作用(数据库连接、Redis 客户端、路由、事件监听、定时任务)必须具备明确的逆操作,在卸载时按 LIFO(后进先出)干净撤销。
|
||||
2. **空间可组合性 (Spatial Composability / Reactive Coeffects)**:组件通过 `Inject` 声明依赖;无特权微内核,所有基础设施与业务均以平等插件形态存在;组件之间严格面向抽象服务契约(Contracts)编程,严禁跨包引用私有实现。
|
||||
3. **合流定理 (Confluence)**:任何插件的装载/卸载顺序,静止状态等同于从零静态装配,杜绝全局隐藏状态与启动顺序隐式假设。
|
||||
|
||||
---
|
||||
|
||||
## 2. 系统架构与分层设计 (Architecture & Layers)
|
||||
## 2. 详细重构方案
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────────────────────────────────┐
|
||||
│ Micro-Kernel (core/) │
|
||||
│ Context Bus (Scoped Fork & LIFO Disposer) | Container | EventBus │
|
||||
│ Extpoints (Router, Tasks, Schedules, Settings, Migrations) │
|
||||
├────────────────────────────────────────────────────────────────────────┤
|
||||
│ Service Contracts (contracts/) │
|
||||
│ DBService, CacheService, StorageService, UserService, AuthService... │
|
||||
├─────────────────────────┬──────────────────────────────────────────────┤
|
||||
│ Runtime Drivers │ Platform Infra Plugins │
|
||||
│ (plugins/drivers/) │ (plugins/infra/) │
|
||||
│ - driver_http (Gin) │ - database (contracts.DBService) │
|
||||
│ - driver_asynq_worker │ - cache (contracts.CacheService) │
|
||||
│ - driver_asynq_cron │ - storage, logger │
|
||||
├─────────────────────────┴──────────────────────────────────────────────┤
|
||||
│ Self-Contained Domain Plugins (plugins/domain/) │
|
||||
│ - user, auth, admin, cap, message_gateway, risk_control, system, upload│
|
||||
└────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
### 2.1 微内核纯洁化 (`backend/core/`)
|
||||
|
||||
#### 改造点:
|
||||
1. **移除特权辅助方法**:
|
||||
- 从 `backend/core/context.go` 中移除 `func (c *Context) DB() contracts.DBService` 与 `func (c *Context) Cache() contracts.CacheService`。
|
||||
- 所有服务消费方统一面向 `core.Inject[T](ctx)`、`core.MustInject[T](ctx)` 或 `core.Using[T](ctx, ...)`。
|
||||
2. **保持依赖注入纯粹性**:
|
||||
- 内核仅保留:`Context`、`Container`、`Fiber`、`EventBus`、生命周期管理以及通用的扩展点挂载。
|
||||
|
||||
---
|
||||
|
||||
## 3. 详细设计与核心组件规范 (Detailed Specifications)
|
||||
### 2.2 基础设施插件生命周期可逆化 (`backend/plugins/infra/`)
|
||||
|
||||
### 3.1 微内核层 (`backend/core/`)
|
||||
#### 1. 数据库插件 (`plugins/infra/database`)
|
||||
- **移除隐式副作用**:
|
||||
- 删除 `postgres.go` 与 `sqlite.go` 中的 `func init() { ... }` 静态建连。
|
||||
- 删除包级导出的静态全局变量 `var db *gorm.DB` 以及全局 `DB(ctx)` / `SetDB()`。
|
||||
- **生命周期受控与可逆释放**:
|
||||
- 在 `Plugin.Apply(ctx *core.Context)` 时根据配置建立数据库连接(GORM + underlying `*sql.DB`)。
|
||||
- 创建 `contracts.DBService` 实例并通过 `core.Provide[contracts.DBService](ctx, svc)` 注册。
|
||||
- 注册 `ctx.OnDispose` 逆操作,在插件卸载时调用 `sqlDB.Close()`。
|
||||
|
||||
#### 1. 事件总线四大分发语义 (`core/events.go`)
|
||||
- `Emit(ctx context.Context, topic string, payload any) error`:通知型广播,不短路,收集所有 Handler 产生的 error(`errors.Join`)。
|
||||
- `Waterfall(ctx context.Context, topic string, initialPayload any) (any, error)`:链式流水线改写,上一个 handler 的返回值作为下一个 handler 的输入;一旦 handler 返回 error 立即短路中断并返回。
|
||||
- `Parallel(ctx context.Context, topic string, payload any) error`:并发扇出执行所有 handler,通过 goroutine + WaitGroup 并发执行,收集所有 error。
|
||||
- `Serial(ctx context.Context, topic string, payload any) error`:严格按序流水线执行所有 handler,遇到第一个 error 立即短路中断。
|
||||
|
||||
#### 2. 插件作用域上下文 (`core/context.go` & `core/app.go`)
|
||||
- `App.ApplyPlugins()` 为每个插件生成专属的 `pluginCtx := app.ctx.Fork()`,并在 `Apply(pluginCtx)` 中挂载。
|
||||
- Scoped Context 拥有独立的 `disposers`、`values` 与子 container,当插件被卸载或 context 被 dispose 时,仅回收该插件范围内的资源。
|
||||
- 在 `Context` 上扩展 `ctx.DB()` 与 `ctx.Cache()` 辅助方法,内部通过 `core.Inject[contracts.DBService](c)` 与 `core.Inject[contracts.CacheService](c)` 解析。
|
||||
|
||||
#### 3. 扩展点可逆化与注销 (`core/extpoints/`)
|
||||
- `RouterExtension`:注册路由时返回 `Disposer`;`RouterRegistry` 内部维护带 ID 的路由列表,支持动态移除路由。
|
||||
- `TaskExtension` / `ScheduleExtension` / `SettingExtension` / `MigrationExtension`:提供与 Scoped Context 关联的注销机制与 Disposer 回收。
|
||||
#### 2. 缓存插件 (`plugins/infra/cache`)
|
||||
- **移除隐式副作用**:
|
||||
- 删除 `redis.go` 中的 `func init() { ... }` 静态建连。
|
||||
- 删除包级导出的全局变量 `var Redis redis.UniversalClient`。
|
||||
- **生命周期受控与可逆释放**:
|
||||
- 在 `Plugin.Apply(ctx *core.Context)` 时初始化 Redis 客户端并构造 `contracts.CacheService`。
|
||||
- 通过 `core.Provide[contracts.CacheService](ctx, svc)` 注册。
|
||||
- 注册 `ctx.OnDispose` 逆操作,在插件卸载时调用 `client.Close()`。
|
||||
|
||||
---
|
||||
|
||||
### 3.2 服务契约层 (`backend/core/contracts/`)
|
||||
### 2.3 业务领域插件防线隔离与依赖重构 (`backend/plugins/domain/`)
|
||||
|
||||
#### 1. `contracts.UserService` 扩展
|
||||
收拢所有用户管理操作:
|
||||
```go
|
||||
type UserService interface {
|
||||
GetByID(ctx context.Context, id uint64) (*UserDTO, error)
|
||||
GetByUsername(ctx context.Context, username string) (*UserDTO, error)
|
||||
GetByEmail(ctx context.Context, email string) (*UserDTO, error)
|
||||
Create(ctx context.Context, user *UserDTO, password string) (*UserDTO, error)
|
||||
Update(ctx context.Context, user *UserDTO) error
|
||||
Delete(ctx context.Context, id uint64) error
|
||||
// Admin 扩展方法
|
||||
AdminListUsers(ctx context.Context, req AdminListUsersRequest) (int64, []*UserDTO, error)
|
||||
AdminGetUser(ctx context.Context, id uint64) (*UserDTO, error)
|
||||
AdminCreateUser(ctx context.Context, req AdminCreateUserRequest) (*UserDTO, error)
|
||||
AdminUpdateUser(ctx context.Context, currentUserID uint64, req AdminUpdateUserRequest) error
|
||||
AdminUpdateUserStatus(ctx context.Context, id uint64, active bool) error
|
||||
AdminDeleteUser(ctx context.Context, currentUserID, targetID uint64) error
|
||||
}
|
||||
```
|
||||
#### 1. 消除跨插件私有 Import
|
||||
- 遍历并重构以下 8 个 Domain 插件:
|
||||
- `auth`
|
||||
- `user`
|
||||
- `admin`
|
||||
- `cap`
|
||||
- `message_gateway`
|
||||
- `risk_control`
|
||||
- `system`
|
||||
- `upload`
|
||||
- **规则**:
|
||||
- 严禁任何 domain 插件 `import "Wavelet/plugins/infra/database"` 或 `import "Wavelet/plugins/infra/cache"`。
|
||||
- 严禁任何 domain 插件直接 import 另一个 domain 插件的具体实现包(如 `admin` 严禁 import `risk_control/logstore` 或 `storage/diskcache`)。
|
||||
- 各插件内部的 Repository / Service 统一通过 `core.Inject[contracts.DBService](ctx)` 或插件内部 scoped context 获取数据库连接。
|
||||
|
||||
#### 2. `contracts.AuthService` 扩展
|
||||
收拢令牌管理与认证源查询:
|
||||
```go
|
||||
type AuthService interface {
|
||||
Authenticate(ctx context.Context, username, password string) (*UserDTO, error)
|
||||
GenerateToken(ctx context.Context, userID uint64, opts ...TokenOption) (string, error)
|
||||
ValidateToken(ctx context.Context, token string) (*TokenClaims, error)
|
||||
RevokeToken(ctx context.Context, tokenHash string) error
|
||||
RevokeUserTokens(ctx context.Context, userID uint64) error
|
||||
InvalidateCachedUser(ctx context.Context, userID uint64)
|
||||
InvalidateCachedToken(ctx context.Context, tokenHash string)
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. 强类型领域事件 (`core/contracts/events.go`)
|
||||
- `EventUserUpdated`: `{ UserID, UpdatedFields }`
|
||||
- `EventUserDeleted`: `{ CurrentUserID, TargetUserID }`
|
||||
- `EventUserStatusChanged`: `{ UserID, IsActive }`
|
||||
- `EventTokenRevoked`: `{ UserID, TokenHash }`
|
||||
#### 2. `admin` 插件解耦与全局变量清除
|
||||
- 移除 `admin/plugin.go` 中的包级变量(`globalUserSvc`, `globalAuthSvc`, `globalCoreCtx`)。
|
||||
- 将 `admin` 的日志查询、任务触发、缓存清理等管理接口改造为通过 `contracts` 或 `ctx.Tasks()` 访问,消除对 `risk_control`、`driver_asynq_worker` 等的私有依赖。
|
||||
|
||||
---
|
||||
|
||||
### 3.3 基础设施去全局化 (`backend/plugins/infra/`)
|
||||
## 3. 验证与门禁标准
|
||||
|
||||
1. **`plugins/infra/database`**:
|
||||
- 彻底去全局化:弃用全局静态变量直读,统一提供 `contracts.DBService` 实例并在 `Apply` 中 `core.Provide[contracts.DBService](ctx, svc)`。
|
||||
2. **`plugins/infra/cache`**:
|
||||
- 弃用全局 `cache.Client()` 包级直连,统一通过 `contracts.CacheService` 接口与 `ctx.Cache()` 操作。
|
||||
|
||||
---
|
||||
|
||||
### 3.4 业务域插件边界治理 (`backend/plugins/domain/`)
|
||||
|
||||
1. **`domain/admin` 治理**:
|
||||
- 移除全部跨插件直接导入(`domain/auth`、`domain/risk_control`、`domain/cap`、`drivers/driver_asynq_*`、`infra/database`)。
|
||||
- 用户管理委派给 `contracts.UserService`。
|
||||
- 认证与令牌操作委派给 `contracts.AuthService`。
|
||||
- 配置管理通过 `ctx.Settings()` / `contracts.SettingService`。
|
||||
2. **表单一所有者原则(Single Owner Principle)**:
|
||||
- `w_users` 表有且仅由 `domain/user` 插件读写。
|
||||
- `w_access_tokens` / `w_auth_sources` / `w_external_accounts` 表有且仅由 `domain/auth` 插件读写。
|
||||
- `w_system_configs` 表由 `domain/admin` 维护。
|
||||
|
||||
---
|
||||
|
||||
## 4. 实施与验证流程 (Verification & Quality Gates)
|
||||
|
||||
1. **内核与契约单测**:
|
||||
- `core/events_test.go`:覆盖 `Emit`、`Waterfall`、`Parallel`、`Serial`。
|
||||
- `core/context_test.go`:覆盖 Scoped Fork、Disposer LIFO、扩展点注销。
|
||||
2. **全局代码检查与格式化**:
|
||||
- `make code-check`
|
||||
- `make format`
|
||||
- `go test -v -race ./backend/...`
|
||||
1. **编译与依赖检查**:
|
||||
- 运行 `grep -r "Wavelet/plugins/infra/database" backend/plugins/domain/` 结果为空。
|
||||
- 运行 `grep -r "Wavelet/plugins/infra/cache" backend/plugins/domain/` 结果为空。
|
||||
2. **自动化测试**:
|
||||
- 所有既有单元测试与集成测试(`go test ./...`)无回归,全部 PASS。
|
||||
3. **代码质量门禁**:
|
||||
- `make code-check` 静态检查 0 告警通过。
|
||||
- `make format` 格式化通过。
|
||||
|
||||
+83
-68
@@ -257,7 +257,7 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/diskcache.Status"
|
||||
"$ref": "#/definitions/disk.Status"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2149,7 +2149,7 @@
|
||||
"data": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/driver_asynq_worker.TaskMeta"
|
||||
"$ref": "#/definitions/contracts.TaskMetaDTO"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4689,6 +4689,9 @@
|
||||
"status": {
|
||||
"type": "integer"
|
||||
},
|
||||
"trace_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"user_agent": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -5019,7 +5022,60 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"diskcache.Status": {
|
||||
"contracts.TaskMetaDTO": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"category": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"display_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"max_retry": {
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/contracts.TaskParamDTO"
|
||||
}
|
||||
},
|
||||
"queue": {
|
||||
"type": "string"
|
||||
},
|
||||
"schedule": {
|
||||
"type": "string"
|
||||
},
|
||||
"timeout": {
|
||||
"$ref": "#/definitions/time.Duration"
|
||||
}
|
||||
}
|
||||
},
|
||||
"contracts.TaskParamDTO": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"default": {},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"disk.Status": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"base_path": {
|
||||
@@ -5042,71 +5098,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"driver_asynq_worker.TaskMeta": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"asynq_task": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"max_retry": {
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/driver_asynq_worker.TaskParam"
|
||||
}
|
||||
},
|
||||
"queue": {
|
||||
"type": "string"
|
||||
},
|
||||
"retryable": {
|
||||
"description": "是否支持手动重试",
|
||||
"type": "boolean"
|
||||
},
|
||||
"supports_time": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"driver_asynq_worker.TaskParam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description": {
|
||||
"description": "描述",
|
||||
"type": "string"
|
||||
},
|
||||
"label": {
|
||||
"description": "显示名称",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "参数键名",
|
||||
"type": "string"
|
||||
},
|
||||
"placeholder": {
|
||||
"description": "占位符",
|
||||
"type": "string"
|
||||
},
|
||||
"required": {
|
||||
"description": "是否必填",
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"description": "类型:string, text, number, boolean",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"handler.batchDownloadRequest": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -5528,6 +5519,30 @@
|
||||
"example": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"time.Duration": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"enum": [
|
||||
-9223372036854775808,
|
||||
9223372036854775807,
|
||||
1,
|
||||
1000,
|
||||
1000000,
|
||||
1000000000,
|
||||
60000000000,
|
||||
3600000000000
|
||||
],
|
||||
"x-enum-varnames": [
|
||||
"minDuration",
|
||||
"maxDuration",
|
||||
"Nanosecond",
|
||||
"Microsecond",
|
||||
"Millisecond",
|
||||
"Second",
|
||||
"Minute",
|
||||
"Hour"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securityDefinitions": {
|
||||
|
||||
+61
-48
@@ -454,6 +454,8 @@ definitions:
|
||||
type: string
|
||||
status:
|
||||
type: integer
|
||||
trace_id:
|
||||
type: string
|
||||
user_agent:
|
||||
type: string
|
||||
user_id:
|
||||
@@ -675,7 +677,42 @@ definitions:
|
||||
- solutions
|
||||
- token
|
||||
type: object
|
||||
diskcache.Status:
|
||||
contracts.TaskMetaDTO:
|
||||
properties:
|
||||
category:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
display_name:
|
||||
type: string
|
||||
max_retry:
|
||||
type: integer
|
||||
name:
|
||||
type: string
|
||||
params:
|
||||
items:
|
||||
$ref: '#/definitions/contracts.TaskParamDTO'
|
||||
type: array
|
||||
queue:
|
||||
type: string
|
||||
schedule:
|
||||
type: string
|
||||
timeout:
|
||||
$ref: '#/definitions/time.Duration'
|
||||
type: object
|
||||
contracts.TaskParamDTO:
|
||||
properties:
|
||||
default: {}
|
||||
description:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
required:
|
||||
type: boolean
|
||||
type:
|
||||
type: string
|
||||
type: object
|
||||
disk.Status:
|
||||
properties:
|
||||
base_path:
|
||||
type: string
|
||||
@@ -690,51 +727,6 @@ definitions:
|
||||
ttl_minutes:
|
||||
type: integer
|
||||
type: object
|
||||
driver_asynq_worker.TaskMeta:
|
||||
properties:
|
||||
asynq_task:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
max_retry:
|
||||
type: integer
|
||||
name:
|
||||
type: string
|
||||
params:
|
||||
items:
|
||||
$ref: '#/definitions/driver_asynq_worker.TaskParam'
|
||||
type: array
|
||||
queue:
|
||||
type: string
|
||||
retryable:
|
||||
description: 是否支持手动重试
|
||||
type: boolean
|
||||
supports_time:
|
||||
type: boolean
|
||||
type:
|
||||
type: string
|
||||
type: object
|
||||
driver_asynq_worker.TaskParam:
|
||||
properties:
|
||||
description:
|
||||
description: 描述
|
||||
type: string
|
||||
label:
|
||||
description: 显示名称
|
||||
type: string
|
||||
name:
|
||||
description: 参数键名
|
||||
type: string
|
||||
placeholder:
|
||||
description: 占位符
|
||||
type: string
|
||||
required:
|
||||
description: 是否必填
|
||||
type: boolean
|
||||
type:
|
||||
description: 类型:string, text, number, boolean
|
||||
type: string
|
||||
type: object
|
||||
handler.batchDownloadRequest:
|
||||
properties:
|
||||
ids:
|
||||
@@ -1018,6 +1010,27 @@ definitions:
|
||||
example: ""
|
||||
type: string
|
||||
type: object
|
||||
time.Duration:
|
||||
enum:
|
||||
- -9223372036854775808
|
||||
- 9223372036854775807
|
||||
- 1
|
||||
- 1000
|
||||
- 1000000
|
||||
- 1000000000
|
||||
- 60000000000
|
||||
- 3600000000000
|
||||
format: int64
|
||||
type: integer
|
||||
x-enum-varnames:
|
||||
- minDuration
|
||||
- maxDuration
|
||||
- Nanosecond
|
||||
- Microsecond
|
||||
- Millisecond
|
||||
- Second
|
||||
- Minute
|
||||
- Hour
|
||||
info:
|
||||
contact:
|
||||
name: Wavelet
|
||||
@@ -1174,7 +1187,7 @@ paths:
|
||||
- $ref: '#/definitions/response.Any'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/diskcache.Status'
|
||||
$ref: '#/definitions/disk.Status'
|
||||
type: object
|
||||
"401":
|
||||
description: 未登录
|
||||
@@ -2305,7 +2318,7 @@ paths:
|
||||
- properties:
|
||||
data:
|
||||
items:
|
||||
$ref: '#/definitions/driver_asynq_worker.TaskMeta'
|
||||
$ref: '#/definitions/contracts.TaskMetaDTO'
|
||||
type: array
|
||||
type: object
|
||||
"401":
|
||||
|
||||
Reference in New Issue
Block a user