refactor(core): optimize performance, fix concurrency and clean up AGENTS.md design violations

- Concurrency: Added lock protection to WebSocket writes, fixed timer leaks, and prevented config cache listener context leaks.
- Performance: Added memory cache in ObservabilityBufferStore, periodic cleaning in CH Deduplicator, and buffered ZIP batch download writes.
- Design: Introduced Redis caching for OAuth session/tokens, sanitized raw DB error messages, segregated handlers and logics, and standard CAP response envelopes.
This commit is contained in:
ryan
2026-06-20 09:09:02 +08:00
parent 5bed2bae9f
commit b3a55d4ab5
25 changed files with 668 additions and 364 deletions
+10
View File
@@ -18,6 +18,16 @@ sidebar: false
### 变更
- 优化认证性能:引入 Redis 与本地二级缓存缓存 Token 数据库查询和用户 Active 状态,并在用户注销或用户状态修改/删除时进行缓存失效清理。
- 重构用户与令牌管理:完成 User 控制器和 AccessToken 控制器的 Handler 和数据库操作逻辑的层级解耦(移入 `logics.go`),并统一对数据库异常进行脱敏封装,避免底层数据库错误泄露。
- 优化观测数据缓存:`ObservabilityBufferStore` 引入内存缓存,避免每次心跳时从磁盘重复读取和解析 JSON 缓存文件。
- 优化 ClickHouse 写入去重效率:`dedupSet` 的 `markIfNew` 改为定期清理过期 Key,避免在高并发指标入队时同步遍历整个 Map。
- 优化大文件打包下载:`BatchDownloadFiles` 批量打包 ZIP 下载流中引入 `bufio.Writer` 缓冲写入,避免直接向网络 Socket 进行无缓冲碎片化写入。
- 优化 Pages 静态部署切换性能:在支持的系统与文件系统下,优先通过软链接(Symlink)进行 Pages deployments 目录快速切换,失败时自动退回到全量目录复制(Copy)。
### 修复
- 修复 CAP 模块路由错误响应:将 CAP 接口中的所有直接 JSON 错误响应改造为统一的 `response.Abort*` 抛出并挂载到中间件统一写出 JSON,保证全局 `{ "error_msg": "...", "data": null }` 信封规范。
### 移除
+55 -31
View File
@@ -49,13 +49,25 @@ const docTemplate = `{
"200": {
"description": "成功返回 PoW 难题",
"schema": {
"$ref": "#/definitions/cap.ChallengeResponse"
"allOf": [
{
"$ref": "#/definitions/response.Any"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.ChallengeResponse"
}
}
}
]
}
},
"500": {
"description": "内部服务错误",
"schema": {
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse"
"$ref": "#/definitions/response.Any"
}
}
}
@@ -89,19 +101,31 @@ const docTemplate = `{
"200": {
"description": "核销成功,返回 X-Cap-Token",
"schema": {
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse"
"allOf": [
{
"$ref": "#/definitions/response.Any"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse"
}
}
}
]
}
},
"400": {
"description": "参数错误或核销失败",
"schema": {
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse"
"$ref": "#/definitions/response.Any"
}
},
"500": {
"description": "内部服务错误",
"schema": {
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse"
"$ref": "#/definitions/response.Any"
}
}
}
@@ -13057,32 +13081,6 @@ const docTemplate = `{
}
}
},
"cap.ChallengeResponse": {
"type": "object",
"properties": {
"challenge": {
"type": "object",
"properties": {
"c": {
"type": "integer"
},
"d": {
"type": "integer"
},
"s": {
"type": "integer"
}
}
},
"expires": {
"description": "ms timestamp",
"type": "integer"
},
"token": {
"type": "string"
}
}
},
"cap.challengeRequest": {
"type": "object",
"properties": {
@@ -13580,6 +13578,32 @@ const docTemplate = `{
}
}
},
"github_com_Rain-kl_Wavelet_internal_apps_cap.ChallengeResponse": {
"type": "object",
"properties": {
"challenge": {
"type": "object",
"properties": {
"c": {
"type": "integer"
},
"d": {
"type": "integer"
},
"s": {
"type": "integer"
}
}
},
"expires": {
"description": "ms timestamp",
"type": "integer"
},
"token": {
"type": "string"
}
}
},
"github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse": {
"type": "object",
"properties": {
+55 -31
View File
@@ -42,13 +42,25 @@
"200": {
"description": "成功返回 PoW 难题",
"schema": {
"$ref": "#/definitions/cap.ChallengeResponse"
"allOf": [
{
"$ref": "#/definitions/response.Any"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.ChallengeResponse"
}
}
}
]
}
},
"500": {
"description": "内部服务错误",
"schema": {
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse"
"$ref": "#/definitions/response.Any"
}
}
}
@@ -82,19 +94,31 @@
"200": {
"description": "核销成功,返回 X-Cap-Token",
"schema": {
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse"
"allOf": [
{
"$ref": "#/definitions/response.Any"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse"
}
}
}
]
}
},
"400": {
"description": "参数错误或核销失败",
"schema": {
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse"
"$ref": "#/definitions/response.Any"
}
},
"500": {
"description": "内部服务错误",
"schema": {
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse"
"$ref": "#/definitions/response.Any"
}
}
}
@@ -13050,32 +13074,6 @@
}
}
},
"cap.ChallengeResponse": {
"type": "object",
"properties": {
"challenge": {
"type": "object",
"properties": {
"c": {
"type": "integer"
},
"d": {
"type": "integer"
},
"s": {
"type": "integer"
}
}
},
"expires": {
"description": "ms timestamp",
"type": "integer"
},
"token": {
"type": "string"
}
}
},
"cap.challengeRequest": {
"type": "object",
"properties": {
@@ -13573,6 +13571,32 @@
}
}
},
"github_com_Rain-kl_Wavelet_internal_apps_cap.ChallengeResponse": {
"type": "object",
"properties": {
"challenge": {
"type": "object",
"properties": {
"c": {
"type": "integer"
},
"d": {
"type": "integer"
},
"s": {
"type": "integer"
}
}
},
"expires": {
"description": "ms timestamp",
"type": "integer"
},
"token": {
"type": "string"
}
}
},
"github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse": {
"type": "object",
"properties": {
+32 -22
View File
@@ -240,23 +240,6 @@ definitions:
- max_size_mb
- ttl_minutes
type: object
cap.ChallengeResponse:
properties:
challenge:
properties:
c:
type: integer
d:
type: integer
s:
type: integer
type: object
expires:
description: ms timestamp
type: integer
token:
type: string
type: object
cap.challengeRequest:
properties:
scope:
@@ -585,6 +568,23 @@ definitions:
version:
type: string
type: object
github_com_Rain-kl_Wavelet_internal_apps_cap.ChallengeResponse:
properties:
challenge:
properties:
c:
type: integer
d:
type: integer
s:
type: integer
type: object
expires:
description: ms timestamp
type: integer
token:
type: string
type: object
github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse:
properties:
error:
@@ -3945,11 +3945,16 @@ paths:
"200":
description: 成功返回 PoW 难题
schema:
$ref: '#/definitions/cap.ChallengeResponse'
allOf:
- $ref: '#/definitions/response.Any'
- properties:
data:
$ref: '#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.ChallengeResponse'
type: object
"500":
description: 内部服务错误
schema:
$ref: '#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse'
$ref: '#/definitions/response.Any'
summary: 生成人机验证难题
tags:
- cap
@@ -3971,15 +3976,20 @@ paths:
"200":
description: 核销成功,返回 X-Cap-Token
schema:
$ref: '#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse'
allOf:
- $ref: '#/definitions/response.Any'
- properties:
data:
$ref: '#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse'
type: object
"400":
description: 参数错误或核销失败
schema:
$ref: '#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse'
$ref: '#/definitions/response.Any'
"500":
description: 内部服务错误
schema:
$ref: '#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse'
$ref: '#/definitions/response.Any'
summary: 校验人机验证解答
tags:
- cap