docs: add T-553 cmhub timeout tuning
This commit is contained in:
@@ -48,7 +48,7 @@
|
|||||||
| 更新蝦皮(③) | 按批次/店铺/状态筛选;可先「检查本轮更新」确认范围;点击「开始更新」后弹窗确认,确认后对当前筛选出的已生成任务按每批最大条数分批更新蝦皮商品,逐条换标题+封面并点「更新」提交线上;普通正式更新不再受测试商品 ID 限制,可批量更新真实商品;可按状态=失败重试 | P0 |
|
| 更新蝦皮(③) | 按批次/店铺/状态筛选;可先「检查本轮更新」确认范围;点击「开始更新」后弹窗确认,确认后对当前筛选出的已生成任务按每批最大条数分批更新蝦皮商品,逐条换标题+封面并点「更新」提交线上;普通正式更新不再受测试商品 ID 限制,可批量更新真实商品;可按状态=失败重试 | P0 |
|
||||||
| 检查本轮更新 / 运行日志 / 多账号并行(③/⑤) | ③ 提供「检查本轮更新」按钮,不打开 Shopee、不提交、不改任务状态,只显示当前筛选范围、店铺分布、预计分批和会更新字段;点击「检查本轮更新」或「开始更新」时清空③界面旧日志,只显示本轮检查/更新日志;真实更新写运行日志;可在⑤开启多账号并行,同账号内仍串行 | V2 已接入,检查按钮已接入 |
|
| 检查本轮更新 / 运行日志 / 多账号并行(③/⑤) | ③ 提供「检查本轮更新」按钮,不打开 Shopee、不提交、不改任务状态,只显示当前筛选范围、店铺分布、预计分批和会更新字段;点击「检查本轮更新」或「开始更新」时清空③界面旧日志,只显示本轮检查/更新日志;真实更新写运行日志;可在⑤开启多账号并行,同账号内仍串行 | V2 已接入,检查按钮已接入 |
|
||||||
| 结果存储与回写 | 各阶段结果实时存 SQLite;该文件全部完成后把旧/新数据+状态批量回写原 Excel | P0 |
|
| 结果存储与回写 | 各阶段结果实时存 SQLite;该文件全部完成后把旧/新数据+状态批量回写原 Excel | P0 |
|
||||||
| 设置(⑤) | AI 模型管理(下拉+新增/删除/详情/测试连接,至少各一个文本+图像模型);标题/图片大模型角色选择;分辨率(512/1k/2k/4k,普通默认 cmhub 模式下只控制生图尺寸,返回超时只读展示实际口径:标题 600 秒 / 图片 650 秒;direct 兼容路径仍按分辨率映射);并发/重试/jpg质量,其中 cmhub 生图请求与图片下载实际并发最大 5,超过后内部限流且运行日志展示实际并发;图片目录/Chrome 路径/端口;设置页采用居中内容区、适度左右留白和响应式三列表单,长字段跨列显示;点击「保存设置」成功后弹轻量提示框 | P0 |
|
| 设置(⑤) | AI 模型管理(下拉+新增/删除/详情/测试连接,至少各一个文本+图像模型);标题/图片大模型角色选择;分辨率(512/1k/2k/4k,普通默认 cmhub 模式下只控制生图尺寸,返回超时只读展示实际口径:标题 600 秒 / 图片 900 秒;direct 兼容路径仍按分辨率映射);并发/重试/jpg质量,其中 cmhub 生图请求与图片下载实际并发最大 5,超过后内部限流且运行日志展示实际并发;图片目录/Chrome 路径/端口;设置页采用居中内容区、适度左右留白和响应式三列表单,长字段跨列显示;点击「保存设置」成功后弹轻量提示框 | P0 |
|
||||||
| 首次引导保护 | 未配账号、对应账号 Chrome 未启动或未登录时,① ③ 执行按钮禁用/执行前拦截并提示去④;③ 不自动打开缺失账号 Chrome,必须中止本轮更新 | P0 |
|
| 首次引导保护 | 未配账号、对应账号 Chrome 未启动或未登录时,① ③ 执行按钮禁用/执行前拦截并提示去④;③ 不自动打开缺失账号 Chrome,必须中止本轮更新 | P0 |
|
||||||
|
|
||||||
### 后续迭代
|
### 后续迭代
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ T-538 后统一数据根为 `data/`:打包版默认 `<exe目录>/data`,源
|
|||||||
"base_url": "",
|
"base_url": "",
|
||||||
"title_alias": "",
|
"title_alias": "",
|
||||||
"image_alias": "",
|
"image_alias": "",
|
||||||
"connect_timeout": 10,
|
"connect_timeout": 66,
|
||||||
"check_balance_before_batch": false
|
"check_balance_before_batch": false
|
||||||
},
|
},
|
||||||
"title_concurrency": 4,
|
"title_concurrency": 4,
|
||||||
@@ -143,7 +143,7 @@ T-538 后统一数据根为 `data/`:打包版默认 `<exe目录>/data`,源
|
|||||||
- `default_text_model` / `default_image_model`:仅 direct 内部兼容模式下引用 `ai_models.json` 里的模型名(标题用文本模型、封面用图像模型);普通 cmhub 模式不读取这些模型定义,⑤设置页不再展示标题/图片模型角色下拉。
|
- `default_text_model` / `default_image_model`:仅 direct 内部兼容模式下引用 `ai_models.json` 里的模型名(标题用文本模型、封面用图像模型);普通 cmhub 模式不读取这些模型定义,⑤设置页不再展示标题/图片模型角色下拉。
|
||||||
- `generate_cover`:②「开始生成」时是否调用图片模型生成新封面;默认 `false`,避免用户无意产生图片生成成本。该字段只控制 AI 生成阶段,不等同于 ③ 的 `allow_cover_update`。
|
- `generate_cover`:②「开始生成」时是否调用图片模型生成新封面;默认 `false`,避免用户无意产生图片生成成本。该字段只控制 AI 生成阶段,不等同于 ③ 的 `allow_cover_update`。
|
||||||
- `resolution`:当前分辨率,下拉 `512 / 1k / 2k / 4k`。
|
- `resolution`:当前分辨率,下拉 `512 / 1k / 2k / 4k`。
|
||||||
- `resolution_timeouts`:direct 内部兼容路径使用的分辨率 → **等待大模型返回超时(秒)** 映射。普通默认 `cmhub` 模式下,分辨率只控制生图尺寸;⑤设置页「返回超时」只读展示实际等待口径:标题 600 秒 / 图片 650 秒,不再随分辨率切换显示 180/240/360/600。
|
- `resolution_timeouts`:direct 内部兼容路径使用的分辨率 → **等待大模型返回超时(秒)** 映射。普通默认 `cmhub` 模式下,分辨率只控制生图尺寸;⑤设置页「返回超时」只读展示实际等待口径:标题 600 秒 / 图片 900 秒,不再随分辨率切换显示 180/240/360/600。
|
||||||
- direct 内部兼容模式模型本身的定义(url/key/类型/连接超时…)在 `data/config/ai_models.json`,见 5.1b。
|
- direct 内部兼容模式模型本身的定义(url/key/类型/连接超时…)在 `data/config/ai_models.json`,见 5.1b。
|
||||||
- 密钥不在 `config.json`:cmhub API Key 存于 `data/config/cmhub.json`;direct 内部兼容模式每个模型的 `api_key` 存于 `data/config/ai_models.json`。两者均本地明文保存、保存/变更时弹窗提示、UI 打码、gitignore、不入日志/导出。
|
- 密钥不在 `config.json`:cmhub API Key 存于 `data/config/cmhub.json`;direct 内部兼容模式每个模型的 `api_key` 存于 `data/config/ai_models.json`。两者均本地明文保存、保存/变更时弹窗提示、UI 打码、gitignore、不入日志/导出。
|
||||||
|
|
||||||
@@ -402,7 +402,7 @@ data/images/<batch_id>/<slug>/<task_id>_<item_id>_new.<ext> # AI 生成的新
|
|||||||
1. **并发生成标题**:线程池大小 = `title_concurrency`,调 `gen_title(标题提示词, old_title)` → new_title。默认 `backend=cmhub`,调用 `POST /api/v1/generate/title` 并使用 `title_alias`;`backend=direct` 仅内部兼容时使用 `default_text_model`。
|
1. **并发生成标题**:线程池大小 = `title_concurrency`,调 `gen_title(标题提示词, old_title)` → new_title。默认 `backend=cmhub`,调用 `POST /api/v1/generate/title` 并使用 `title_alias`;`backend=direct` 仅内部兼容时使用 `default_text_model`。
|
||||||
2. **若②勾选「生成封面图片(成本较高)」**:接着并发生成图片,线程池大小 = `image_concurrency`,调 `gen_cover(封面提示词, old_cover_path, resolution, jpg_quality)` → 新图存 `data/images/<batch_id>/<slug>/<task_id>_<item_id>_new.jpg`。默认 `backend=cmhub`,调用 `POST /api/v1/generate/image`,拿 `image_url` 后立即安全下载并转本地 JPEG;`backend=direct` 仅内部兼容时使用 `default_image_model`。
|
2. **若②勾选「生成封面图片(成本较高)」**:接着并发生成图片,线程池大小 = `image_concurrency`,调 `gen_cover(封面提示词, old_cover_path, resolution, jpg_quality)` → 新图存 `data/images/<batch_id>/<slug>/<task_id>_<item_id>_new.jpg`。默认 `backend=cmhub`,调用 `POST /api/v1/generate/image`,拿 `image_url` 后立即安全下载并转本地 JPEG;`backend=direct` 仅内部兼容时使用 `default_image_model`。
|
||||||
- T-545 已实现:cmhub 模式下不再直接按用户填写的 `image_concurrency` 全量打到网关;实际生图请求并发 = `min(image_concurrency, 5)`。拿到 `image_url` 后交给独立下载/保存线程池,下载线程数量与实际生图请求并发一致,同样最大 5。这样批量时“下一批生图请求”和“上一批图片下载/保存”可以流水线并行,但不会对 cmhub 生图接口或 `/media/generated/images/*.png` 静态下载打出超过 5 的并发。direct 兼容路径暂不改变。
|
- T-545 已实现:cmhub 模式下不再直接按用户填写的 `image_concurrency` 全量打到网关;实际生图请求并发 = `min(image_concurrency, 5)`。拿到 `image_url` 后交给独立下载/保存线程池,下载线程数量与实际生图请求并发一致,同样最大 5。这样批量时“下一批生图请求”和“上一批图片下载/保存”可以流水线并行,但不会对 cmhub 生图接口或 `/media/generated/images/*.png` 静态下载打出超过 5 的并发。direct 兼容路径暂不改变。
|
||||||
- cmhub 生图连接超时取 `ai.cmhub.connect_timeout`;生图请求和随后 `image_url` 下载的读取等待统一固定 650 秒,读超时不自动重发,避免重复扣点。下载层最多安全重试 3 次,只复用同一个 `image_url`,不重新请求 cmhub 生图;下载总耗时超过 20 秒时写“图片下载较慢”警告。`backend=direct` 兼容路径仍按模型 `timeout_seconds` 或 `resolution_timeouts[resolution]`(512→180/1k→240/2k→360/4k→600)取返回超时。
|
- cmhub 生图连接超时取 `ai.cmhub.connect_timeout`(默认 66 秒);生图请求和随后 `image_url` 下载的读取等待统一固定 900 秒,读超时不自动重发,避免重复扣点。下载层最多安全重试 3 次,只复用同一个 `image_url`,不重新请求 cmhub 生图;下载总耗时超过 20 秒时写“图片下载较慢”警告。`backend=direct` 兼容路径仍按模型 `timeout_seconds` 或 `resolution_timeouts[resolution]`(512→180/1k→240/2k→360/4k→600)取返回超时。
|
||||||
- T-548 已实现:cmhub 图片下载后端新增 `ai.cmhub.download_with_curl`(`auto`/`true`/`false`,默认 `auto`)。Windows 且检测到系统 curl 时优先用 curl 下载,否则或 curl 执行失败时回退 requests;生成、models、balance 仍走共享 requests Session。curl 下载前仍执行公网 URL 校验;URL 写入临时 curl 配置文件并通过 `-K` 传入,避免带 token 的 `image_url` 出现在进程命令行;`use_system_proxy=false` 时 curl 加 `--noproxy "*"`。
|
- T-548 已实现:cmhub 图片下载后端新增 `ai.cmhub.download_with_curl`(`auto`/`true`/`false`,默认 `auto`)。Windows 且检测到系统 curl 时优先用 curl 下载,否则或 curl 执行失败时回退 requests;生成、models、balance 仍走共享 requests Session。curl 下载前仍执行公网 URL 校验;URL 写入临时 curl 配置文件并通过 `-K` 传入,避免带 token 的 `image_url` 出现在进程命令行;`use_system_proxy=false` 时 curl 加 `--noproxy "*"`。
|
||||||
- cmhub 返回的完整 `image_url` 默认只在内存中临时用于下载,不写入 `tasks` 或 `run_log_events`。本机调试时可设置环境变量 `CMSHOPEE_DEBUG_CMHUB_IMAGE_URL=1`,②本轮可见运行日志会显示脱敏后的 URL 调试行,且该行不持久化到 SQLite。
|
- cmhub 返回的完整 `image_url` 默认只在内存中临时用于下载,不写入 `tasks` 或 `run_log_events`。本机调试时可设置环境变量 `CMSHOPEE_DEBUG_CMHUB_IMAGE_URL=1`,②本轮可见运行日志会显示脱敏后的 URL 调试行,且该行不持久化到 SQLite。
|
||||||
3. **若未勾选生成封面**:标题成功后立即写 `new_title`,`new_cover_path=NULL`,不渲染封面提示词、不调用 `gen_cover()`、不创建本地新封面文件。
|
3. **若未勾选生成封面**:标题成功后立即写 `new_title`,`new_cover_path=NULL`,不渲染封面提示词、不调用 `gen_cover()`、不创建本地新封面文件。
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
> **v3.3 修订(2026-07-04,产品收口)**:普通用户后续默认使用 `cmhub` 网关;⑤设置页去掉「AI 后端」label 和 direct/cmhub 下拉,直接展示 cmhub 网关配置。`direct` 代码和 `config/ai_models.json` 保留为内部兼容/手工回滚路径,但普通 UI 不提供切换入口;保存设置固定写 `ai.backend=cmhub`,允许先保存不完整 cmhub 配置,②生成时再提示去⑤补齐 Base URL/API Key/别名。已同步 T-529。
|
> **v3.3 修订(2026-07-04,产品收口)**:普通用户后续默认使用 `cmhub` 网关;⑤设置页去掉「AI 后端」label 和 direct/cmhub 下拉,直接展示 cmhub 网关配置。`direct` 代码和 `config/ai_models.json` 保留为内部兼容/手工回滚路径,但普通 UI 不提供切换入口;保存设置固定写 `ai.backend=cmhub`,允许先保存不完整 cmhub 配置,②生成时再提示去⑤补齐 Base URL/API Key/别名。已同步 T-529。
|
||||||
> **v3.4 修订(2026-07-07,T-538 路径收敛)**:打包版和源码运行的用户数据统一落在 `data/` 下;本文早期提到的 `config.json`、`config/ai_models.json`、`config/cmhub.json`、`images/`,当前默认路径分别为 `data/config.json`、`data/config/ai_models.json`、`data/config/cmhub.json`、`data/images/`。文件名和 schema 不变,旧布局由启动迁移逻辑处理。
|
> **v3.4 修订(2026-07-07,T-538 路径收敛)**:打包版和源码运行的用户数据统一落在 `data/` 下;本文早期提到的 `config.json`、`config/ai_models.json`、`config/cmhub.json`、`images/`,当前默认路径分别为 `data/config.json`、`data/config/ai_models.json`、`data/config/cmhub.json`、`data/images/`。文件名和 schema 不变,旧布局由启动迁移逻辑处理。
|
||||||
> **v3.4 核对(2026-07-06,刷新别名 notfound)**:核对对接文档 §4.4 与 cmhub `ModelsView` 路由,确认 cmshopee `GET /api/v1/models` + Bearer 请求**已达标**;「notfound」为 404,根因是 Base URL 带多余 `/api(/v1)` 路径(双拼)或所连实例未部署 `/api/v1/models`(见 `docs/troubleshooting.md`)。**T-530 已落地**:保存/请求前规整 Base URL 到网关根,HTTP 404 映射为 `not_found` 并给出中文排障提示。
|
> **v3.4 核对(2026-07-06,刷新别名 notfound)**:核对对接文档 §4.4 与 cmhub `ModelsView` 路由,确认 cmshopee `GET /api/v1/models` + Bearer 请求**已达标**;「notfound」为 404,根因是 Base URL 带多余 `/api(/v1)` 路径(双拼)或所连实例未部署 `/api/v1/models`(见 `docs/troubleshooting.md`)。**T-530 已落地**:保存/请求前规整 Base URL 到网关根,HTTP 404 映射为 `not_found` 并给出中文排障提示。
|
||||||
|
> **v3.5 修订(2026-07-08,T-553 待实现)**:cmhub 生图稳定性口径调整为连接超时默认 66 秒、生图请求和 `image_url` 下载读取等待统一 900 秒,与线上 Nginx/Gunicorn 的长等待窗口对齐;生图读超时仍不自动重发,避免重复扣点。
|
||||||
|
|
||||||
## 1. 背景与目标
|
## 1. 背景与目标
|
||||||
|
|
||||||
@@ -30,7 +31,7 @@
|
|||||||
| 生图请求 | `images_edits` multipart 或 vision chat | `{prompt, model:别名, image_base64?/image_url?, resolution?, aspect_ratio?, parameters?}` |
|
| 生图请求 | `images_edits` multipart 或 vision chat | `{prompt, model:别名, image_base64?/image_url?, resolution?, aspect_ratio?, parameters?}` |
|
||||||
| 生图响应 | 直接返回 image bytes | `{image_url, ...}` → 需再下载 |
|
| 生图响应 | 直接返回 image bytes | `{image_url, ...}` → 需再下载 |
|
||||||
| 错误 | HTTP error 文本 | `{error:{code,message}}`:`insufficient_points`(402)/`upstream_error`(502)/`rate_limited`(429)/`unauthorized`(401)/`account_disabled`(403)/`bad_request`(400)/`model_not_allowed`/`no_pricing_rule` |
|
| 错误 | HTTP error 文本 | `{error:{code,message}}`:`insufficient_points`(402)/`upstream_error`(502)/`rate_limited`(429)/`unauthorized`(401)/`account_disabled`(403)/`bad_request`(400)/`model_not_allowed`/`no_pricing_rule` |
|
||||||
| 超时 | 按 `resolution_timeouts` | 生图同步且慢;当前 cmshopee 生图请求和图片下载读取等待统一固定 650s,不再按分辨率变化;生图读超时仍不自动重发 |
|
| 超时 | 按 `resolution_timeouts` | 生图同步且慢;T-553 目标为 cmshopee 生图请求和图片下载读取等待统一固定 900s,不再按分辨率变化;生图读超时仍不自动重发 |
|
||||||
| 幂等 | 直连一次成功一次 | **非幂等、无幂等键**:客户端超时 ≠ 未扣点,读超时后不可无脑重发 |
|
| 幂等 | 直连一次成功一次 | **非幂等、无幂等键**:客户端超时 ≠ 未扣点,读超时后不可无脑重发 |
|
||||||
|
|
||||||
关键差异(决定改造点):
|
关键差异(决定改造点):
|
||||||
@@ -57,7 +58,7 @@
|
|||||||
"base_url": "https://<cmhub>", // 网关根地址,请求时拼 /api/v1/...
|
"base_url": "https://<cmhub>", // 网关根地址,请求时拼 /api/v1/...
|
||||||
"title_alias": "title-standard", // 生文能力别名
|
"title_alias": "title-standard", // 生文能力别名
|
||||||
"image_alias": "image-hd", // 生图能力别名
|
"image_alias": "image-hd", // 生图能力别名
|
||||||
"connect_timeout": 10,
|
"connect_timeout": 66,
|
||||||
"check_balance_before_batch": false
|
"check_balance_before_batch": false
|
||||||
},
|
},
|
||||||
// 现有字段保留:resolution / jpg_quality / *_concurrency / retry /
|
// 现有字段保留:resolution / jpg_quality / *_concurrency / retry /
|
||||||
@@ -96,7 +97,7 @@
|
|||||||
旧封面必传(改图类),复用现有 `_image_data_url(old_cover_path)` 生成 base64。
|
旧封面必传(改图类),复用现有 `_image_data_url(old_cover_path)` 生成 base64。
|
||||||
- `resolution` 归一为**大写** `512/1K/2K/4K`(cmshopee 内部用小写 `1k`,发请求前转 `1K`);`aspect_ratio` 默认 `1:1`(Shopee 封面)。
|
- `resolution` 归一为**大写** `512/1K/2K/4K`(cmshopee 内部用小写 `1k`,发请求前转 `1K`);`aspect_ratio` 默认 `1:1`(Shopee 封面)。
|
||||||
- **响应**:拿 `image_url` → **新增一步下载**该图字节(cmhub 自家对象存储公网 URL)→ 交给现有 `_save_jpeg(image_bytes, out_path, resolution, quality)` 落盘。下载 helper 必须校验 URL scheme 只允许 `http/https`,拒绝内网/回环/本机地址,并校验域名解析后的 IP 仍不属于内网/回环/本机地址,设置超时和大小上限;生成后**立即下载**(对象存储 URL 可能有有效期)。`points_cost`/`points_balance`/`call_id` 同样通过事件回调传播,不改变 `gen_cover` 返回值。
|
- **响应**:拿 `image_url` → **新增一步下载**该图字节(cmhub 自家对象存储公网 URL)→ 交给现有 `_save_jpeg(image_bytes, out_path, resolution, quality)` 落盘。下载 helper 必须校验 URL scheme 只允许 `http/https`,拒绝内网/回环/本机地址,并校验域名解析后的 IP 仍不属于内网/回环/本机地址,设置超时和大小上限;生成后**立即下载**(对象存储 URL 可能有有效期)。`points_cost`/`points_balance`/`call_id` 同样通过事件回调传播,不改变 `gen_cover` 返回值。
|
||||||
- **超时(关键)**:生图同步且慢。当前 cmshopee 的 cmhub 生图请求和随后 `image_url` 下载读取等待统一固定 650 秒,不再按分辨率变化,绝不用 30s/60s 调生图——否则客户端超时但服务端仍在算并扣点(见 §4.4 幂等)。
|
- **超时(关键)**:生图同步且慢。T-553 目标为 cmshopee 的 cmhub 连接超时默认 66 秒,生图请求和随后 `image_url` 下载读取等待统一固定 900 秒,不再按分辨率变化,绝不用 30s/60s 调生图——否则客户端超时但服务端仍在算并扣点(见 §4.4 幂等)。
|
||||||
- **并发(T-545 已实现)**:最近实测 `/media/generated/images/*.png` 下载链路在 10 并发下明显慢且有连接失败。cmhub 模式下采用内置保护:实际生图请求并发 = `min(ai.image_concurrency, 5)`;下载/保存使用独立线程池,线程数与实际生图请求并发一致,同样最大 5;不新增用户可见配置项。运行日志必须同时显示用户设置和实际并发,避免用户误解设置 10 就会对 cmhub 打 10 并发。下载失败记为该任务失败,不得重新调用生图接口导致重复扣点;读超时仍按 §4.4 的非幂等规则处理。
|
- **并发(T-545 已实现)**:最近实测 `/media/generated/images/*.png` 下载链路在 10 并发下明显慢且有连接失败。cmhub 模式下采用内置保护:实际生图请求并发 = `min(ai.image_concurrency, 5)`;下载/保存使用独立线程池,线程数与实际生图请求并发一致,同样最大 5;不新增用户可见配置项。运行日志必须同时显示用户设置和实际并发,避免用户误解设置 10 就会对 cmhub 打 10 并发。下载失败记为该任务失败,不得重新调用生图接口导致重复扣点;读超时仍按 §4.4 的非幂等规则处理。
|
||||||
- **下载后端(T-548 已实现)**:cmhub 生成/models/balance 仍走共享 requests Session;仅 `image_url` 图片下载可按 `ai.cmhub.download_with_curl` 选择系统 curl。默认 `auto` 在 Windows 且检测到系统 curl 时优先 curl,非 Windows、无 curl 或 curl 失败自动回退 requests。curl 调用前仍做公网 URL 校验,用 `-K` 临时配置文件传 URL,避免 token 出现在进程命令行;`use_system_proxy=false` 时加 `--noproxy "*"`。
|
- **下载后端(T-548 已实现)**:cmhub 生成/models/balance 仍走共享 requests Session;仅 `image_url` 图片下载可按 `ai.cmhub.download_with_curl` 选择系统 curl。默认 `auto` 在 Windows 且检测到系统 curl 时优先 curl,非 Windows、无 curl 或 curl 失败自动回退 requests。curl 调用前仍做公网 URL 校验,用 `-K` 临时配置文件传 URL,避免 token 出现在进程命令行;`use_system_proxy=false` 时加 `--noproxy "*"`。
|
||||||
|
|
||||||
@@ -116,7 +117,7 @@ cmhub 返回结构化 `{error:{code}}`。映射层**按 `code` 优先分支**(
|
|||||||
|
|
||||||
**幂等与超时——生图重试必须特别处理(会亏钱)**:cmhub 生成接口**非幂等、无幂等键**,客户端超时 ≠ 未扣点。
|
**幂等与超时——生图重试必须特别处理(会亏钱)**:cmhub 生成接口**非幂等、无幂等键**,客户端超时 ≠ 未扣点。
|
||||||
|
|
||||||
- **生图(`gen_cover`)**:**读超时后绝不自动重发**——服务端可能已算完并扣点,重发 = 重复扣点。首选办法是把读超时设够大(§4.3,当前固定 650s)从源头避免歧义;只对**连接超时**(请求根本没送达服务端)安全重试。
|
- **生图(`gen_cover`)**:**读超时后绝不自动重发**——服务端可能已算完并扣点,重发 = 重复扣点。首选办法是把读超时设够大(§4.3,T-553 目标固定 900s)从源头避免歧义;只对**连接超时**(请求根本没送达服务端)安全重试。
|
||||||
- **生文(`gen_title`)**:秒级返回、点数低,读超时重试风险小,但仍建议同样区分连接超时/读超时;重试次数可小。
|
- **生文(`gen_title`)**:秒级返回、点数低,读超时重试风险小,但仍建议同样区分连接超时/读超时;重试次数可小。
|
||||||
- 只对 `502`/`429`/**连接**超时重试;`402/401/403/400`/读超时立即失败。现状 `_call_with_retry` 是**一刀切重试**,cmhub 模式必须替换为这套区分策略。
|
- 只对 `502`/`429`/**连接**超时重试;`402/401/403/400`/读超时立即失败。现状 `_call_with_retry` 是**一刀切重试**,cmhub 模式必须替换为这套区分策略。
|
||||||
- `insufficient_points` 是新的用户可见态:② 生成页应弹明确提示并引导去网页端充值,不当普通失败淹没在计数里。
|
- `insufficient_points` 是新的用户可见态:② 生成页应弹明确提示并引导去网页端充值,不当普通失败淹没在计数里。
|
||||||
@@ -177,7 +178,7 @@ cmhub 返回结构化 `{error:{code}}`。映射层**按 `code` 优先分支**(
|
|||||||
3. ~~`resolution` 取值~~ **已解决**:`512/1K/2K/4K`(大写 K),默认 `1K`;cmshopee 小写值发请求前归一。
|
3. ~~`resolution` 取值~~ **已解决**:`512/1K/2K/4K`(大写 K),默认 `1K`;cmshopee 小写值发请求前归一。
|
||||||
4. ~~`aspect_ratio`~~ **已解决**:默认 `1:1`,Shopee 封面用 `1:1`。
|
4. ~~`aspect_ratio`~~ **已解决**:默认 `1:1`,Shopee 封面用 `1:1`。
|
||||||
5. **`image_url` 有效期(按最坏处理)**:对象存储 URL 可能过期——本设计已是**生成后立即下载落盘**,无需长期持有。
|
5. **`image_url` 有效期(按最坏处理)**:对象存储 URL 可能过期——本设计已是**生成后立即下载落盘**,无需长期持有。
|
||||||
6. ~~超时上限~~ **已解决**:当前 cmshopee 生图请求和图片下载读取等待统一固定 650s。
|
6. ~~超时上限~~ **已解决**:T-553 目标为 cmshopee 生图请求和图片下载读取等待统一固定 900s,连接超时默认 66s。
|
||||||
7. **Base URL / API Key 形态**:域名待部署方提供;Key 形如 `sk_cmhub_xxx`,仅网页端生成时显示一次——⑤设置需提示用户从网页端复制粘贴,本地保存。
|
7. **Base URL / API Key 形态**:域名待部署方提供;Key 形如 `sk_cmhub_xxx`,仅网页端生成时显示一次——⑤设置需提示用户从网页端复制粘贴,本地保存。
|
||||||
|
|
||||||
## 10. 落地拆分与任务顺序
|
## 10. 落地拆分与任务顺序
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
---
|
||||||
|
id: T-553
|
||||||
|
title: cmhub 生图超时口径调优(连接 66 秒,读取 900 秒)
|
||||||
|
phase: 7
|
||||||
|
deps: [T-535, T-545, T-547, T-548]
|
||||||
|
status: TODO
|
||||||
|
created: 2026-07-08
|
||||||
|
---
|
||||||
|
|
||||||
|
## 问题 / 背景
|
||||||
|
|
||||||
|
cmhub 生图偶发超时或连接失败。当前桌面端口径是:
|
||||||
|
|
||||||
|
- `ai.cmhub.connect_timeout` 默认 `10` 秒,慢网络、服务端连接队列或代理环境下容易过早报「连接 cmhub 超时」。
|
||||||
|
- cmhub 生图请求和随后 `image_url` 下载的读取等待固定 `650` 秒。如果 cmhub 线上 Nginx/Gunicorn 允许请求等待到 `900` 秒,桌面端会先于服务端超时,产生“服务端仍在生成或已扣点,本地先失败”的歧义。
|
||||||
|
- 生图是非幂等接口,读超时后不能自动重发,否则可能重复扣点。
|
||||||
|
|
||||||
|
cmhub 项目侧建议:桌面端连接超时提高到 60/120 秒量级;生图 read timeout 与线上 Nginx/Gunicorn 对齐到 900 秒。本项目第一版取中间偏保守值:连接超时默认 `66` 秒,生图读取等待 `900` 秒。
|
||||||
|
|
||||||
|
## 方案
|
||||||
|
|
||||||
|
1. **cmhub 连接超时默认改为 66 秒**
|
||||||
|
- `DEFAULT_CONFIG.ai.cmhub.connect_timeout` 从 `10` 改为 `66`。
|
||||||
|
- `cmhub_config()` 对缺失值使用 `66`。
|
||||||
|
- ⑤设置页 cmhub「连接超时(秒)」默认值改为 `66`,范围仍保持 `1..3600`。
|
||||||
|
- 兼容旧配置:如果旧 `data/config.json` 中该值缺失或仍是旧默认 `10`,迁到 `66`,确保已安装用户升级后也生效;若用户明确配置了其它正整数,保留用户配置。用户确实需要更短连接超时时,仍可在⑤设置页手工改小并保存。
|
||||||
|
|
||||||
|
2. **cmhub 生图读取等待改为 900 秒**
|
||||||
|
- `CMHUB_IMAGE_READ_TIMEOUT_SECONDS` 从 `650` 改为 `900`。
|
||||||
|
- 生图请求 `POST /api/v1/generate/image` 的 `read_timeout` 使用 `900`。
|
||||||
|
- 随后的 `image_url` 下载读取等待、curl `--max-time` 同步使用 `900`,保持现有统一口径。
|
||||||
|
- ⑤设置页「返回超时」只读展示改为「标题 600 秒 / 图片 900 秒」。
|
||||||
|
|
||||||
|
3. **保持非幂等安全边界**
|
||||||
|
- 生图读超时仍不可自动重发;只允许连接超时、`rate_limited`、`upstream_error` 按现有规则处理。
|
||||||
|
- 下载失败仍只复用已返回的同一个 `image_url` 做下载层重试,不重新调用 cmhub 生图接口。
|
||||||
|
- 不把图片并发默认值调高;用户排障时仍建议先把图片并发降到 1 或 2,稳定后再试 3。
|
||||||
|
|
||||||
|
## 验收要点
|
||||||
|
|
||||||
|
- 新默认配置中 `ai.cmhub.connect_timeout == 66`。
|
||||||
|
- ⑤设置页 cmhub 连接超时默认显示 `66`。
|
||||||
|
- cmhub 生图请求 timeout 为 `(connect_timeout, 900)`。
|
||||||
|
- cmhub 图片下载 requests timeout 为 `(connect_timeout, 900)`。
|
||||||
|
- curl 下载参数 `--max-time` 为 `900`。
|
||||||
|
- ⑤设置页「返回超时」显示「标题 600 秒 / 图片 900 秒」。
|
||||||
|
- 生图读超时仍不自动重发;相关单测继续覆盖“不重复扣点”的行为。
|
||||||
|
- 更新 `docs/04-architecture.md`、`docs/cmhub-integration-design.md`、`docs/02-requirements.md` 的超时口径。
|
||||||
|
|
||||||
|
## 边界(不改什么)
|
||||||
|
|
||||||
|
只改 cmhub 连接超时默认值、生图读取等待常量、⑤设置页显示文案、相关单测和文档;不改 cmhub API 协议、Base URL/Key/别名配置结构、标题读取等待 600 秒、图片并发上限 5、下载线程池语义、DB、Excel、Shopee/CDP 更新流程,也不增加生图读超时重试。
|
||||||
Reference in New Issue
Block a user