MAX API v1.0.4 正式版:额度并发与结算一致性全面加固-计费零遗漏 · 并发零透支 · 结算零重放
[!IMPORTANT]
Claude/Anthropic 流式输出 token 计费回归已修复。 v1.0.4 曾在 Claude/Anthropic 流结束时正确解析顶层CompletionTokens,但生成最终BillingUsage快照时遗漏OutputTokens,导致用量日志中的completion_tokens可能为0,输出 token 也可能未进入实际结算。当前版本已补齐最终快照回填,并加入完整流式事件链回归测试。该问题按响应处理器而不是模型名称划分:Anthropic 原生、AWS Bedrock Claude、Vertex Claude 模式、Advanced Custom Anthropic Messages,以及通过
/v1/messages复用 Claude 流式处理器的兼容渠道都可能受影响。Claude 非流式请求以及原生 OpenAI Chat、OpenAI Responses、Gemini 路径未发现同类问题。历史受影响请求无法仅凭本地
completion_tokens=0恢复精确输出量,应优先结合上游 usage 或账单记录进行对账;根据响应文本重新分词只能作为估算。额度并发与结算一致性已完成正式版加固。 发布前复核确认并修复了用户/token 额度在 Redis 与数据库之间异步更新、并发扣减缺少余额条件、邀请奖励全字段覆盖,以及资金结算成功但 token 调整失败后被错误标记为已完成等问题。额度扣减现在以数据库条件写为最终判定;旧版预扣路径会在同一数据库事务中同时扣减用户与 token;Redis 通过共享单调代次、条件回填、实体删除清理和持续失效重试阻断旧快照或已撤销 token;结算会分别处理已确认的部分补偿与结果不明的补偿错误,后者不会自动重复非幂等资金操作。
v1.0.4 涉及计费结算、分阶段计费、GPT-5.6 缓存写入、异步任务、Responses 兼容、安全验证、数据库迁移和项目授权说明等关键变化。升级前建议在测试环境核对常用模型、缓存创建价格、任务类渠道、用户额度、反向代理和 access token 相关流程,并阅读最新版 README 中的授权要求。
生产数据库提醒:正式环境不建议使用 SQLite。 SQLite 仅适合本地体验、开发和小规模测试;并发请求、多实例部署、大量日志与用量数据、数据库迁移、备份恢复和长事务可能引发锁等待、写入阻塞、迁移耗时或失败,以及可用性和数据维护问题。正式环境请使用 MySQL ≥ 5.7.8 或 PostgreSQL ≥ 9.6,并配置可靠的备份与恢复方案。
[!NOTE]
本正式版草稿汇总 v1.0.4-preview.1 至 v1.0.4-preview.4 的主要更新,并补充正式发布前确认的授权政策、前端体验更新和 Claude/Anthropic 流式计费关键修复。
MAX API V1.0.4 Release Notes
GitHub 地址
https://github.com/MAX-API-Next/MAX-API/releases/tag/v1.0.4

Highlights
- Responses 跨协议兼容全面增强:完善 OpenAI Responses 与 Chat Completions 双向转换,覆盖普通响应、流式事件、工具调用、reasoning、usage 聚合,并新增 Gemini Responses 与 Advanced Custom 转换能力。
- 计费精度与表达能力升级:引入语义化
BillingUsage、tiered_expr分阶段计费和统一 quota 转换策略,扩展 OpenAI、Claude、Gemini 的缓存、图片、音频、reasoning 等细分用量,并补齐 GPT-5.6cache_write_tokens的跨协议结算以及 Claude/Anthropic 流式输出 token 的最终快照映射。 - 额度与结算并发安全补强:用户和 token 扣减改为数据库条件写,旧版预扣路径改为同库事务,Redis 使用跨节点单调版本栅栏拒绝旧快照回填,并为 token 撤销增加去重、指数退避和缓存 TTL 截止边界;BillingSession 分开处理已确认的部分补偿与结果不明的资金操作,避免自动重放非幂等补偿。
- 配置、缓存与身份约束继续收口:分组倍率注册配置与旧
GroupRatio入口共享同一运行时RWMap;指针型配置会在原对象上安全更新,坏 JSON 不会污染现值;用户缓存失效/删除、token 缓存删除、quota_data聚合键和 OAuth 身份唯一性都有更明确的迁移与重试边界。 - 异步任务进入通用计费阶段:新增任务 rate card 与通用计费框架,可按时长、分辨率、音频、媒体输入、图片数量和最终请求体进行预扣费与结算。
- 视频与多模态任务能力扩展:集中完善 Doubao Seedance、Ali/Kling/Wan、Gemini、Vertex、Vidu、Hailuo、Jimeng、Sora 等任务渠道的请求透传、动态计费、轮询和结果解析。
- 渠道与自动路由管理升级:支持
auto、auto:fast、auto:cheap等多条具名自动链路,并优化渠道抽屉、模型/分组倍率编辑、模型广场链路展示和 OAuth 回调配置提示。 - 账户敏感操作进一步加固:access token 改为 POST 生成并接入二次验证、禁缓存和双重限流;验证状态绑定当前用户,并支持 Passkey、2FA 或限定作用域的密码验证。
- 生产运行可靠性提升:完善优雅关闭、流式连接保护、Redis 原子更新、多节点任务归因、日志审计以及 SQLite、MySQL、PostgreSQL 老库兼容。
- 二次开发与授权说明完善:多语言 README 新增项目来源/社区鸣谢要求及临时商用授权说明,同时明确 One API MIT、New API AGPLv3 和本项目 AGPLv3 等既有开源义务仍需分别遵守。
New Features
- 新增
service/openaicompat兼容层和 Gemini Responses adaptor,支持 Responses 请求接入 Chat Completions 或 Gemini 上游。 - 新增
dto.BillingUsage协议用量快照,并在InputTokenDetails中支持cache_write_tokens,为格式转换后的原始协议语义、缓存写入量及 Claude/Anthropic 流式输出量结算提供统一载体。 - 新增
tiered_expr分阶段计费及可视化/表达式编辑能力,可按上下文长度、输入输出、缓存、图片、音频、请求参数、header 和时间条件组合价格规则。 - 新增通用任务请求构造、路径配置、结果解析和 rate card 计费模块;
Pass Through Body、模型映射与Param Override可组合使用。 - 豆包 Seedance 2.0 支持官方
content[]请求及safety_identifier、priority、generate_audio、ratio、resolution等参数,并按分辨率和视频输入动态计费。 - 新增多自动链路配置,每条链路可独立设置名称、启用状态、用户可见性和真实分组顺序。
- 用量聚合新增分组、令牌、渠道和节点维度,并补充 retry、empty retry、quota 区间等筛选能力。
- 管理端新增订阅重置、安全验证方式发现、OAuth 回调提示和更完整的渠道高级设置入口。
- Dashboard 新增运行状态摘要、真实加载失败提示和失败项重试入口,密钥、可用模型、额度与请求量状态更容易确认。
- 前端新增统一的安全富文本渲染链路,并为新增设置、日志、订阅和计费能力补齐多语言文案。
Major Improvements
- 任务提交会先生成最终上游请求,再执行计费;
Param Override修改后的时长、尺寸、媒体输入和 header 会同时作用于实际请求与费用计算。 - Playground 改善模型与分组选项恢复、聊天历史清理、选区处理、长文本输入和窄屏布局;
auto/auto:*自动链路会从用户完整模型集合加载选项,避免使用虚拟分组过滤后得到空列表。 - 服务关闭时会等待在途请求完成,超时后主动关闭连接,再执行 quota cache 落库与退出清理,降低重启期间的流式中断和数据丢失风险。
- 渠道表单、倍率编辑器和自动路由展示进一步统一校验与状态管理,复杂配置更易维护,也减少旧字段残留。
- 配置加载和导出路径进一步统一:
group_ratio_setting.group_ratio与旧GroupRatio指向同一运行时倍率表,UpdateConfigFromMap会原地更新指针型子配置,坏 JSON 会在校验失败后返回错误且不污染现有RWMap。 - 用户、token、订阅和兑换码的局部更新加强零值与并发保护;额度列升级为
bigint,管理端操作保持在 JavaScript 安全整数范围内。 - Redis 通用计数增量继续通过 Lua 保留 TTL 语义;用户/token 可用额度不再依赖 Redis 增量,而是以数据库条件更新为最终结果,并通过版本化失效重建缓存。用量日志和异步任务结算同时增强写入、回填与多节点归因。
- GPT-5.6
cache_write_tokens可在 Responses 非流式、流式、compact 和 Responses/Chat 转换中完整保留;结算时归一为缓存创建 token,并写入用量日志便于对账。 - 前端数据表改为按实际容器宽度切换桌面/移动布局,移动端支持批量操作;公共头部集中收纳 GitHub、语言和主题工具,并补充更多无障碍与多语言状态提示。
- 上游协议兼容性进一步扩展,完善 Claude/Gemini 工具调用、Ollama 非流式
tool_calls和 Wan2.7 图生视频input.media等请求响应格式。 - 上游错误响应、流式扫描、SSE ping、任务轮询和回调结算得到集中优化,异常请求对内存、连接和后台任务的影响更可控。
- 控制台与管理接口的全局 API 限流默认值由 180 秒内 180 次提升为 180 秒内 720 次,为管理端并发加载和连续操作保留更多余量;该调整只覆盖
/api/*及旧版 Dashboard 账单接口,模型中继/v1/*、Gemini/v1beta/*继续使用独立的模型请求限流。 - 管理端渠道测试补齐响应时间反馈:直接测试按钮与测试弹窗都会显示测试耗时,并把最新
response_time/test_time同步回渠道列表,便于管理员即时判断上游连通性和延迟。 - 模型定价图形化编辑器现在会区分保存快照与草稿快照;删除已保存模型时不会再被旧保存值回填,删除动作会立即从图形列表中生效,待保存后再落到配置。
- 用户/token 额度更新不再进入延迟批量落库路径;普通 token 通过
remain_quota >= amount条件保护并发下界,无限额度 token 继续保留原有不受余额限制的使用语义。 - Token 的
remain_quota/used_quota与用户额度统一为 64 位整数,并为 MySQL、PostgreSQL 老库补充bigint NOT NULL DEFAULT 0迁移;SQLite 继续使用兼容的类型亲和性与 AutoMigrate 路径。 - 数据看板 quota 缓存改为锁内快照、锁外落库;每批聚合数据会携带稳定快照 ID,并在
quota_data_snapshots中与累计更新同事务去重。数据库失败会保留原快照 ID 重新入队,提交结果不明确时重复执行也不会再次累加;看板刷盘和聚合键迁移现在共用跨数据库 operation lock,并使用短租约 heartbeat 持续续租,避免启动迁移扫描后被并发写入覆盖。 quota_data.aggregate_key迁移改为在保留唯一索引约束的前提下清理 stale key、合并旧 NULL/空聚合键记录、删除重复行并回填 survivor;迁移使用有界批量扫描、bigintscratch 表和跨库 set-based apply,后续 upsert 会命中迁移后的累计行,避免同一统计维度拆出并行记录。- 看板 flush 现在贯穿调用方
context与截止时间:关机保存不再仅停止等待一个仍在后台运行的 goroutine,本地 flush 串行锁、数据库 operation lock 获取和单条持久化事务都会响应取消;截止时间到达时,已摘取 snapshot 会在函数返回前按原SnapshotID重入队。单条持久化失败也会在保留失败项重试的同时向调用方返回非空错误,不再把“仅存在于内存中的待重试数据”报告为保存成功。 quota_data_operation_locks的创建、过期抢占和 heartbeat 续租统一使用数据库服务器时钟,并在同一 SQL 语句中计算当前时间与新过期时间;SQLite 使用strftime、MySQL 使用UNIX_TIMESTAMP()、PostgreSQL 使用CURRENT_TIMESTAMP,避免多节点主机时钟偏差导致仍有效的租约被提前抢占。tiered_expr编译缓存达到上限时只淘汰最早条目,不再全量清空;订阅资金源也改为严格使用调用方传入的预扣额度。- 用户/token 缓存回填增加 Redis 共享单调 generation 与
WATCH条件写;用户 group、status、role、name、setting 等窄字段也会在 DB 查询前捕获 generation。实体删除会同时清理 hash 与专属版本键;token 撤销删除失败后会按 HMAC 缓存键去重并在缓存 TTL 窗口内指数退避重试,执行中的旧任务也不能吞掉同一 token 的新删除请求。 - 用户设置保存、用户删除和 token 撤销的 Redis 缓存处理共用有界重试语义;用户删除的数据库事务已提交后,缓存删除失败会写入日志并登记删除重试,不再把已完成的删除操作返回为失败。
- 有限额度 token 的信任判断统一读取 Gin 中的
int64上下文值,避免 64 位额度升级后被误读为0并触发错误预扣。
Stability and Security
- 管理端模型拉取统一执行 SSRF 校验,默认可信代理范围收紧为 loopback,并加强真实客户端 IP 与关键验证接口的限流边界。
- 注册、邮箱绑定、充值回调和通知邮箱统一采用更严格的邮箱规范化与唯一性检查;验证码和密码重置流程强化一次性使用与并发占用语义。
- 富文本和 HTML 内容统一经过 sanitizer,公告、首页、关于页、法律文档等用户可见内容采用一致的安全渲染策略。
- MySQL 命名锁、老库字段迁移及 SQLite/PostgreSQL 差异路径得到补强,root 用户删除保护下沉到 model 层。
- 计费、日志审计和用户更新路径增加边界保护,降低异常数据、旧快照或极端额度对账务字段的影响。
- 渠道测试成功和失败提示统一携带渠道/模型上下文,多语言界面会明确区分“测试失败”和“未执行/未完成”状态;失败场景会保留上游错误码与错误摘要,减少管理员排查连接问题时的二次定位成本。
- 自定义 Footer HTML 复用统一 sanitizer,OAuth 登录回跳只接受同源站内路径;外部支付、预览和 OAuth 绑定窗口统一隔离
window.opener,并通过短时 OAuth state 标记维持绑定流程。 - Turnstile token 改由
X-Turnstile-Token请求头传递,避免进入 URL、浏览器历史和常规 query 日志;后端暂时保留 query 回退以兼容旧客户端。 - 浏览器端价格预估移除
new Function,改用受限表达式解释器;服务端header()/param()改用正向白名单,只开放明确的计价元数据,并拒绝整个请求、GJSON 查询/修饰符/通配符、未知 body 根和伪装认证 header。 - Setup 完成状态不再永久写入 localStorage,后端重置后刷新页面即可重新进入初始化流程;流式 Playground 状态改为响应式 state,未收到
[DONE]时即使 SSE 已关闭也会进入错误收尾,生产错误处理不再输出包含请求头的完整 Axios 对象。 - GitHub、Discord、OIDC、WeChat、Telegram 和 Linux DO 身份占用检查改为“存在任意匹配即占用”;即使老库中已经存在重复 OAuth 标识,也不会因为匹配行数大于 1 而错误放行新的绑定。唯一性查询的数据库错误会写入服务端日志,公开登录/绑定响应只返回本地化通用错误,不再暴露连接地址、表名或驱动信息。
- OAuth 身份唯一性现在同时由数据库迁移层兜底:启动时会把空字符串归一为 NULL,清理重复 GitHub、Discord、OIDC、WeChat、Telegram 和 LinuxDO 标识,并在支持的数据库上建立非空唯一约束,减少检查通过后并发写入重复身份的窗口。
- Redis 缓存失效/删除失败会进入带截止时间的进程内重试,并在到期后写入终态日志;用户删除已提交后,缓存删除失败只登记重试,不再把已完成的数据库删除包装成接口失败。
- 清理了 token 与用户缓存中已无调用的逐字段写入 helper,包括旧 token hash 字段写入入口和用户 group/role/email/name/setting/status setter;当前保留的窄字段回填均继续走 version fence,降低后续误接回旧 Redis 写法的风险。
Critical Fixes
- P0 — 修复 Claude/Anthropic 流式输出 token 未进入日志与结算:最终构造 Claude
BillingUsage时,会在上游快照缺少输出量的情况下,从已解析的CompletionTokens回填ClaudeUsage.OutputTokens;若上游已提供非零OutputTokens,则继续保留上游原值。 - 覆盖范围:所有最终由 Claude 流式响应处理器完成 usage 快照的请求,包括 Anthropic、AWS Bedrock Claude、Vertex Claude 模式、Advanced Custom Anthropic Messages,以及部分通过 Claude 协议接入的 Ali、DeepSeek、Moonshot、MiniMax、VolcEngine、Zhipu 等兼容路径。模型名称本身不是判断依据。
- 其他模型核查:Claude 非流式、OpenAI Chat、OpenAI Responses、Chat/Responses 双向转换、Gemini 原生流式/非流式及 Gemini 本地 usage 估算路径未发现同类问题。
- 历史对账:修复前已产生的异常日志无法仅凭本地
completion_tokens=0恢复精确输出量,应优先使用上游 usage/账单记录;根据响应文本重新分词只能作为估算。 - HIGH — 修复并发扣减突破余额下界:用户和普通 token 的扣减在同一条更新语句中校验剩余额度,只有实际更新一行才视为成功;并发请求不能再同时通过旧余额检查后把额度打成负数。
- HIGH — 修复 Redis/DB 更新顺序、旧快照回填与结算部分失败:额度变更先提交数据库,再以共享单调 generation 原子推进并失效缓存;旧 DB 读取只能在 generation 未变化时写回。BillingSession 的 token 调整失败时会尝试反向补偿:返回成功但仅部分应用时记录已确认残差,并在再次调整 token 前补齐;补偿调用报错时视为结果不明,不采用返回额度推断结果,也不会自动再次调用同一笔非幂等补偿。
- 持续失败边界:单次结算最多尝试 3 次。若 token 对账仍失败,错误会继续返回并写入结算错误日志;补偿结果不明时后续只允许 token 对账重试,不能视为资金已自动恢复完成。运维侧仍需依据 user/token/request 标识和上游账单人工对账。
- HIGH — 修复 token 撤销后旧缓存继续鉴权:单个和批量删除会在数据库提交后同步登记缓存删除任务;Redis 长故障不再于 350ms 后放弃,而是在缓存 TTL 窗口内按缓存键去重、指数退避并持续重试,到期仍失败会写入终态日志并清理队列。任务代次会阻止执行中的旧成功结果覆盖后到的新删除请求。
- HIGH — 修复预扣失败遗留 token 扣减:旧版钱包预扣不再先扣 token、再依赖失败后补偿;用户额度与 token 额度在同一数据库事务中执行条件扣减,任一步骤失败都会整体回滚。
- HIGH — 修复数据看板快照重试重复累计:新增持久化快照去重记录,快照登记与
quota_data累计更新在同一事务中完成;数据库已提交但客户端收到错误时,携带同一快照 ID 的重试不会再次增加 count、quota 或 token_used。 - HIGH — 修复邀请奖励覆盖并发字段:邀请次数、可转额度和历史额度改为原子增量,不再用旧用户快照覆盖 quota、status、role 等并发修改。
- HIGH — 修复配置别名与指针配置更新脱节:
group_ratio_setting.group_ratio不再在旧入口更新后提前返回,注册配置导出和运行时倍率读取会保持一致;指针型配置优先复用已有UnmarshalJSON对象,避免替换掉被其他包持有的运行时实例。 - HIGH — 修复旧
quota_data聚合键迁移后重复建行与迁移竞态:迁移会在保持正式唯一索引在线时清理 stale key、合并同维度历史行、回填aggregate_key并删除重复记录;跨实例迁移和看板刷盘通过数据库 operation lock 串行化,短租约由 heartbeat 全程续租,失去 owner 会中止后续写入,避免全局 scratch 表互相覆盖,或用旧扫描汇总覆盖迁移期间的新 quota 写入。 - HIGH — 修复关机 quota flush 超时后 snapshot 滞留后台 goroutine:
QUOTA_DATA_CACHE_SAVE_TIMEOUT_SECONDS现在会形成真实的取消 deadline,而不是只让 main goroutine 停止等待;锁获取被取消或截止时间到达时,已脱离全局缓存的 snapshot 会先重入队再返回。单条数据库写入失败会继续处理同批其他数据、只重入队失败项,并把首个持久化错误返回给关机调用方。 - HIGH — 修复分布式 quota operation lock 使用主机时间造成的租约误抢占:锁插入、过期判断、owner 抢占和 heartbeat 续租全部改用数据库时钟原子计算,时钟较快的应用节点不能再仅凭本机时间提前接管仍由其他节点持有的迁移或看板刷盘锁。
- HIGH — 修复用户缓存失效/删除失败造成的状态漂移:用户设置更新失败清缓存时会登记失效重试;软删除/硬删除用户提交成功后,Redis 删除失败会转为日志和删除重试,不再把数据库已完成的删除误报为接口失败。
- HIGH — 修复 OAuth 身份检查与写入之间的并发窗口:GitHub、Discord、OIDC、WeChat、Telegram 和 LinuxDO 标识会在清理旧数据后建立唯一约束;重复旧值优先保留未软删除、ID 更小的用户,其余重复绑定会被清空。
- 安全边界修复:补齐 Footer 存储型 XSS、OAuth 协议相对地址跳转、价格预估任意 JavaScript 执行、Turnstile URL 泄露和新窗口反向标签页控制等路径。
- 错误与数据可靠性修复:
FillUserBy*返回真实数据库错误,并通过ErrUserDeleted明确区分 OAuth 软删除账户;内置和通用 OAuth 流程都返回“用户已注销”域错误。OAuth 身份唯一性查询失败会记录 provider 与内部错误,但客户端只收到本地化通用信息。配置反序列化失败改为向上返回,group_ratio_setting.group_ratio会与旧GroupRatio入口更新同一运行时倍率映射,兑换码前缀搜索正确转义_/%,数据看板刷盘失败会保留待重试数据。
Compatibility Notes
- access token 生成接口已由
GET /api/user/token改为POST /api/user/token,依赖旧接口的脚本、SDK 和自动化客户端需要同步调整。 - 默认
TrustedProxies不再信任私网网段;使用 Nginx、Cloudflare Tunnel、内网负载均衡或容器代理时,请显式配置TRUSTED_PROXIES。如果后端未信任代理的实际来源地址,多名公网用户可能被识别为同一个代理 IP,进而共享登录、OAuth、支付、令牌明文读取等关键接口的限流桶并统一返回 429。请仅信任精确代理地址或最小 CIDR,并确认代理转发X-Real-IP/X-Forwarded-For,不要直接信任整个私网地址段。 GLOBAL_API_RATE_LIMIT的未配置默认值调整为 720 次、窗口仍为 180 秒;显式环境变量继续优先。该配置不改变CRITICAL_RATE_LIMIT的默认 20 分钟 20 次,也不改变默认关闭、按用户/分组独立配置的模型请求限流。- 任务
Param Override现在会在计费前生效,header override 会在 adaptor 默认 header 之后应用;请复核已有任务渠道的改写规则和价格配置。 - 通用 rate card 可能使过去未精确计费的任务按最终请求参数结算,建议升级前核对常用视频、图像和音频模型的费率表。
- MySQL/PostgreSQL 老库会迁移部分用户额度字段到
bigint;升级前请备份数据库,并先在测试环境验证启动迁移。 - MySQL/PostgreSQL 老库还会把 token 的
remain_quota/used_quota迁移为bigint。大规模tokens表执行 DDL 可能持有元数据锁或触发表重写,建议安排低峰窗口,必要时提前使用在线 DDL。 BATCH_UPDATE_ENABLED=true不再延迟聚合用户/token 可用额度变更;这些账务写入会直接落库以保证条件扣减和错误传播,批量模式仍可用于非余额类统计。高吞吐部署应观察数据库写入负载。- 启用 Redis 的部署需要允许
GET、SET、WATCH、MULTI/EXEC、EVAL/EVALSHA、INCR、DEL、HSET和过期时间相关命令;额度缓存 generation 由共享 Redis 的cache-version:sequence单调序列协调,不能用仅存在于单个进程的本地计数替代。专属版本键只在对应用户/token 删除时清理,不应手工设置普通 TTL。token 撤销和用户缓存失效/删除重试队列位于应用进程内,进程存活时会在各自缓存 TTL 窗口内持续重试;若故障期间同时重启全部实例,未完成任务不会跨进程持久化,旧 hash 仍以缓存 TTL 为最终上界。 - 数据库迁移会新增
quota_data_snapshots去重表,用于保证看板聚合快照重试幂等;SQLite、MySQL 5.7.8+ 和 PostgreSQL 9.6+ 均通过 GORM 自动迁移创建,数据库账号需要具备建表和索引权限。 - 数据库启动迁移还会整理
quota_data.aggregate_key:老库中的 NULL/空键会按统计维度合并、清理重复行并回填 survivor。迁移会额外创建quota_data_operation_locks和短生命周期 scratch 表/索引,需数据库账号具备建表、建索引、更新和删除权限;多实例启动时其他实例或看板刷盘会等待该 operation lock。锁使用短租约和 heartbeat,持有实例异常退出后不会长期阻塞,长迁移也会持续续租;大表建议低峰升级并保留升级前备份。 QUOTA_DATA_CACHE_SAVE_TIMEOUT_SECONDS现在同时限制本进程 flush 串行等待和数据库 operation lock 获取;超时会返回context deadline exceeded并重新入队未确认完成的 snapshot。运维日志中出现 quota cache save failure 或待重试数量大于 0 时,应视为本次关机保存未完全落库,不能仅依据进程已退出判断保存成功。- SQLite 继续作为受支持的本地体验和测试数据库,但不建议用于正式/生产环境。正式环境,尤其是多实例、高并发、大量日志/用量数据或频繁迁移场景,应迁移到 MySQL ≥ 5.7.8 或 PostgreSQL ≥ 9.6,并配置数据库备份、恢复演练和升级窗口。
users表会为 GitHub、Discord、OIDC、WeChat、Telegram 和 LinuxDO 身份字段建立非空唯一约束;升级时空字符串会归一为 NULL,重复值会保留排序最靠前的一个账户(优先未软删除用户)并清空其他重复绑定。MySQL 通过生成列实现可空唯一语义,需 MySQL 5.7.8+ 与 DDL 权限。- GPT-5.6 的
input_tokens_details.cache_write_tokens会按缓存创建 token 计费:ratio 模式使用CacheCreationRatio,表达式模式使用cc;请根据实际上游价格检查对应配置。 - 如果上游同时返回
cached_creation_tokens和cache_write_tokens,系统取两者中的较大值作为缓存创建总量,不会相加,外部对账工具应采用相同口径。 tiered_expr系数表示每 100 万 token 的实际美元价格,不包含旧倍率表的隐式换算;未启用该模式的模型继续使用原有ModelRatio/ModelPrice。tiered_expr的header()仅开放anthropic-beta/openai-beta,param()仅开放文档列出的计价元数据、数组计数和 role/type 路径;其他路径、@this、查询、修饰符、通配符与未知 header 均返回空字符串或nil。旧规则需要按新白名单调整。- Responses 兼容路径会保留更完整的 usage 明细;读取用量的外部系统应兼容
prompt_tokens_details、input_tokens_details、cache_write_tokens和billing_usage。 /v1/messages或其他 Anthropic Messages 兼容入口可能把非claude-*模型也交给 Claude 流式响应处理器;升级验证和对账应按实际响应适配器检查,不能只按模型名称筛选。- 新版前端通过
X-Turnstile-Token发送验证 token;后端仍接受旧 query 参数作为过渡兼容,但自定义前端、SDK 和网关应尽快迁移到请求头。 - 数据库中的注册配置如果包含无法解析的布尔、数值或 JSON 子配置,加载过程现在会返回错误而不是跳过坏值继续运行。升级前请清理损坏或手工编辑错误的 option 值。
- 二次开发、社区鸣谢和临时商用授权以各语言最新版 README 公告为准;临时授权不替代或免除上游项目及 AGPLv3 的开源许可义务,长期商用授权需另行联系项目方。
Upgrade Checklist
- 升级前备份数据库和关键配置,尤其是用户额度、渠道配置、分组倍率、模型价格、任务 rate card、
Param Override、TrustedProxies和 access token 自动化脚本。 - 在重建或重启容器前核对实际生效的
TRUSTED_PROXIES、GLOBAL_API_RATE_LIMIT*和CRITICAL_RATE_LIMIT*环境变量。反向代理部署应从不同公网网络分别执行状态页与登录探针,确认后端识别到各自真实客户端 IP,普通控制台请求与关键操作不会因共享代理 IP 限流桶而同时返回 429。 - 对大规模
users/tokens表预估 bigint 迁移时间,并在升级窗口观察数据库锁等待、启动日志和额度字段默认值。 - 老库升级前用只读查询排查重复 OAuth 标识和
quota_data同维度多行;在测试环境启动一次迁移,确认清理日志、回填结果和唯一索引创建完成。 - 先在测试环境验证常用 OpenAI Responses、Chat Completions、Claude/Anthropic Messages、Gemini、视频任务和
auto:*自动链路,确认路由、流式响应、usage 明细和结算日志符合预期。 - 对 Claude/Anthropic 流式历史日志进行风险筛查:若修复前存在
completion_tokens=0但响应有实际输出的记录,应结合上游 usage 或账单记录进行人工对账。 - 复核 GPT-5.6 与其他缓存写入模型的
CacheCreationRatio/cc配置;外部报表请采用“缓存创建 token 取最大值而非相加”的同一口径。 - 检查现有
tiered_expr是否读取敏感 header 或请求内容;将这类条件迁移到明确、非敏感的计价元数据,并在图形预估器和真实请求上分别验证结果。 - 检查 Redis ACL、代理层和集群模式是否允许版本栅栏所需的事务与 Lua 命令;升级后执行一次有限 token 请求并确认数据库额度、Redis 缓存重建值和日志扣费一致。建议在测试环境模拟超过 350ms 的 Redis 故障,撤销 token 后恢复 Redis,确认对应 hash 与专属版本键最终被清理且旧 token 无法继续鉴权。
- 确认启动迁移成功创建
quota_data_snapshots;升级后连续触发两次看板刷盘并抽查 count、quota、token_used 未因重试重复累计。 - 确认启动迁移可创建、续租并释放
quota_data_operation_locks,quota_data.aggregate_key唯一索引在旧数据合并期间保持存在;大表或多实例部署应观察启动日志、heartbeat 和锁等待时间,避免在迁移窗口内误判看板刷盘延迟为数据丢失。 - 在测试环境占用
quota_data_operation_locks后触发关机 flush,确认QUOTA_DATA_CACHE_SAVE_TIMEOUT_SECONDS到期时调用会返回、snapshot 仍保留相同 ID 等待重试,释放锁后再次刷盘只累计一次;同时模拟单条持久化失败,确认关机日志收到非空错误而失败项仍在缓存中。 - 如果当前正式环境仍使用 SQLite,升级前应先完成数据备份并规划迁移到 MySQL 或 PostgreSQL;至少应避免多实例共享 SQLite 文件,并评估现有
quota_data、日志和任务表规模、迁移耗时、写锁等待及恢复流程。 - 升级后抽查
group_ratio_setting.group_ratio的导出值和运行时倍率是否一致;模拟用户设置更新和用户删除期间 Redis 短故障,确认恢复后缓存会被失效或删除,接口不把已提交的数据库删除误报为失败。 - 为
billing settlement failed after 3 attempts、error adjusting token quota after funding settled和资金补偿失败日志配置告警;出现后按 request/user/token 维度对照上游 usage,不要仅依赖本地预扣值判断最终费用。 - 对软删除且曾绑定 GitHub、Discord、OIDC、WeChat、Telegram、LinuxDO 或自定义 OAuth 的账户执行登录探针,确认统一返回“用户已注销”;再模拟一次 OAuth 唯一性查询故障,确认服务端保留内部错误日志而客户端响应不包含数据库地址、表名或驱动详情。
- 自定义登录/注册/邮箱验证/签到前端应改用
X-Turnstile-Token,并确认反向代理允许该请求头通过。 - 复核任务类渠道的最终请求体计费结果,重点检查视频时长、分辨率、音频、图片数量、媒体输入和 header override 是否与实际调用一致。
- 更新依赖旧
GET /api/user/token的脚本或 SDK,改用POST /api/user/token,并准备 Passkey、2FA 或限定作用域密码验证流程。 - 升级后在管理端执行渠道连接测试,确认响应时间会回写到渠道列表;同时抽查模型定价图形化编辑器的新增、删除和保存流程,确保草稿与最终配置一致。
Verification
- Claude 完整流式序列回归通过:上游/顶层
CompletionTokens = 53,最终BillingUsage.ClaudeUsage.OutputTokens = 53。 - 上游值保留回归通过:当上游已提供非零
OutputTokens时,不会被本地回填值覆盖。 - Claude 非流式、OpenAI Chat、OpenAI Responses、Chat/Responses 转换、Gemini 原生 usage、Gemini 估算 usage 和 Gemini prompt-only 快照替换探针均通过。
- 跨适配器验证通过:
go test ./relay/channel/claude ./relay/channel/aws ./relay/channel/vertex ./relay/channel/advancedcustom ./service -count=1。 - 全仓测试验证通过:
go test ./... -count=1;本轮涉及的 model、service、billingexpr、config、middleware、controller 定向测试与go vet ./...通过,go run ./tools/jsonwrapcheck和git diff --check通过。 - 管理端前端补充验证通过:
bun run typecheck、bun test src/features/channels/lib/channel-actions.test.ts、针对渠道测试与模型定价编辑器变更文件的bunx eslint、bunx prettier --check、bun run i18n:sync与git diff --check。 - 本轮前端维护复核通过:
bun run typecheck、bunx eslint --no-warn-ignored src/features/system-settings/models/model-ratio-visual-editor.tsx、bunx prettier --check src/features/system-settings/models/model-ratio-visual-editor.tsx src/i18n/locales/ru.json与bun run i18n:sync。 - 本轮额度/安全复核通过:并发用户/token 扣减、无限 token、DB 失败不触碰缓存、邀请奖励原子更新、用户/token 同事务预扣、BillingSession 完整/失败/部分补偿及结果不明补偿、数据看板失败重入队与快照幂等、兑换码转义、配置错误传播、表达式敏感字段隔离和有界缓存等回归测试全部通过。
- 二次一致性复核通过:单次 BillingSession 瞬时故障恢复、用户/token 旧异步快照跨失效回填、有限 token
int64信任判断、计费表达式全请求/查询绕过、OAuth 软删除域错误和 SSE 未完成关闭均有定向回归覆盖。 - Redis 竞态测试使用内存 Redis、Lua 单调代次和真实
WATCH/事务交错,主动阻塞旧用户/token DB 快照及用户 group 窄字段回填;同时验证实体删除后 hash/版本键释放、删除前快照被拒绝且重建 generation 大于旧值。 - 本轮核心回归可复现执行:
go test ./common -run "TestVersionedHashDeletionRejectsStaleRefillsAndReleasesEntityKeys" -count=1、go test ./service -run "TestBillingSession|TestPreConsume" -count=1、go test ./model -run "TestSaveQuotaData|TestUserQuotaInvalidation|TestUserGroupInvalidation|TestTokenQuotaInvalidation|TestTokenDeleteRetries|TestTokenCacheRetry|TestIsOidcIdAlreadyTaken|TestAtomicTokenAndUserPreConsume|TestUpdateOption" -count=1、go test ./controller -run "TestOAuthBindMasksUniquenessLookupDatabaseError|TestFindOrCreateOAuthUser" -count=1。 - token 撤销重试覆盖 Redis 连续失败超过旧三次短重试窗口后恢复,以及旧任务执行期间叠加同 token 新删除请求的确定性交错;
go test ./... -count=1、go vet ./...、jsonwrapcheck和git diff --check均通过。race 模式因验证环境CGO_ENABLED=0未执行。 - GitHub Backend checks 中的
TestUpdateOptionFiltersAutoRouteGroupRatioNamesBeforePersistence和TestUpdateOptionMapFiltersAutoRouteGroupRatioNames已修复;分层键group_ratio_setting.group_ratio现在会更新实际运行时RWMap。完整go test ./model -count=1与go test ./... -count=1均通过。 - 本轮配置/缓存/迁移回归覆盖
TestUpdateConfigFromMap_PointerUnmarshalerUpdatesInPlace、TestLoadFromDBReturnsInvalidSubConfigError、TestTokenCacheDeleteRetryGetsBoundedDeadline、TestQuotaDataMigrationBackfillsAndMergesLegacyRows、TestUpdateUserSettingRetriesCacheInvalidation、TestUserDeletesRetryCacheDeletionAfterDatabaseCommit和TestMigrateUserOAuthIdentityConstraintsBackfillsAndEnforcesUniqueness。 - 本轮后端全量复核通过:
go test ./model -count=1、go test ./setting/config ./types -count=1、go test ./... -count=1、go vet ./...与git diff --check。 - 本轮前端安全复核通过:11 个 OAuth redirect、Turnstile header、受限表达式求值和脱敏错误摘要测试,以及 3 个 HTML sanitizer 测试通过;
bun run typecheck、bun run build:check与变更文件 Prettier 检查通过。 - 限流配置与路由边界复核通过:
go test ./common ./middleware ./router;控制台/api/*、关键操作和模型中继分别使用全局 API、Critical 与 Model Request 三套独立限流配置。 - 本轮
quota_data迁移补强通过:保留正式唯一索引、stale key 修复、row B 计数保真、bigintscratch schema、迁移 operation lock 等待、quota 写入等待锁、锁竞争测试先观察到真实抢锁尝试再断言阻塞、短租约 heartbeat 续租、失去 owner 中止和 release 失败重试均有回归覆盖;同时确认旧 token/user 逐字段缓存 setter 已无残留符号。 - 最新后端复核通过:
go test ./model -count=1、go test ./... -count=1、go vet ./...、go run ./tools/jsonwrapcheck与git diff --check。 - 最新 quota flush / operation lock 回归覆盖
TestSaveQuotaDataCacheRequeuesSnapshotWhenCallerStopsWaiting、TestSaveQuotaDataCacheReturnsIndividualPersistenceFailure和TestQuotaDataOperationLockUsesDatabaseClockForLeaseSQL;单条失败错误传播、超时重入队、后续幂等落库,以及 SQLite/MySQL/PostgreSQL 数据库时钟 SQL 均已验证。聚焦回归连续 10 次、go test ./model -count=1、go test ./... -count=1、go vet ./...、go run ./tools/jsonwrapcheck与git diff --check通过。 - 发布状态:计费阻断已解除。 Claude/Anthropic 流式输出 token 映射已修复并由持久化回归测试覆盖。
Full Changelog: https://github.com/MAX-API-Next/MAX-API/compare/v1.0.3…v1.0.4
更多推荐




所有评论(0)