Files
new-api-key-usage/docs/design/qpu_history表字段设计.md
T
skycurtain 45b312b357 docs: 设计文档体系落定(七篇定稿)
- docs/design:四张表字段设计 · 交互设计(方向层 + 细节层)· API 契约 · 同步引擎设计
- docs/upstream:sk-key 接口实证(430 行)· 接口范围(9 个接口)
- README(全景入口)· AGENTS.md(AI 协作者指引)
- 废弃旧稿已删除(不随仓库留存)
2026-09-14 23:54:52 +08:00

5.3 KiB
Raw Blame History

qpu_history 表字段设计

数据模型第四张表:换算参数时间线(表名 qpu_history,QPU = QuotaPerUnit 缩写)——quota_per_unit(quota → 额度美元)的历史取值,折算链第一层的系数来源。历史值在 sk-key 视角无从观测,本表由同步引擎自动采样、只记变化点;纯只读(唯一写入者是同步引擎)。本文记录字段清单、语义与决策理由。

项目 内容
状态 定稿(2026-09-13,多轮讨论收敛:只读化、按购买时刻取尺)
关联 docs/design/purchases表字段设计.md(折算链第二条:额度美元 → 实付人民币)· docs/design/API契约.md §2.4(只读查看端点)· docs/upstream/NewAPI-接口范围.md(采集来源 /api/status)
范围 列结构 + 语义 + 写入规则;采样调度(同步引擎)不在此文
字段数 3 = 1 主键 + 2 业务字段

1. 表定位

  • 一行 = 一次「换算单位取值变化」事件(值 + 生效时间)——正常情况全表仅 1 行(当前站点为出厂默认值,从未变过)
  • 它是折算链第一条(quota → 额度美元)的时间线:任何时刻的换算取值 = 「该时刻之前最近一条」
  • 为什么要自己攒:/api/status 只能看到当前值,历史值无从观测(上游不留历史、管理审计不记值)——没有本表,历史日志只能用今天的尺子量,账会串
  • 与日志零耦合:折算全部发生在展示 / 聚合层——本表任何变动都不触发 usage_logs 写入

2. 字段清单

列 类型 值来源 说明
id bigserial PK 自增
qpu numeric /api/status.quota_per_unit 当时的 quota_per_unit 值
effective_from timestamptz 首次采样或检测到变化的时间 生效时间;采样误差 ≤ 同步周期

3. 决策记录(含理由)

3.1 为什么自动采样(而非人工登记)

它是「可登记的事实」的反面——历史值无从观测(只能看到当前值);自动采样(每轮同步)是唯一能沿时间轴捕获它的方式。采样误差 ≤ 同步周期(边界影响可忽略)。

3.2 只记变化点,不记每次采样

部署时插基线;此后每轮同步顺带读 /api/status,值变化才追加一行——行数 = 调价次数 + 1(正常为 1)。

3.3 取值语义与跨期统计

  • 取尺基准 = 购买时刻(paid_at):一条日志的折算 = 先按 subscription_id 归属到购买记录(见 purchases表字段设计.md),再取该购买的购买时刻在本表中的当值——同一笔订阅的全部日志共用一把尺子。完整链:日志.quota ÷ 购买时刻的 quota_per_unit × 购买汇率 = 实付人民币
  • 为什么不按日志自身的时刻:订阅期内若发生重定标,同一笔订阅的「已用美元」会在调价点跳变,而额度与实付没变——分子分母尺子不一致,账就不自洽;按购买时刻取尺等价于「按 quota 占比分摊实付」,恒定成立
  • 跨期统计:把查询时间范围按购买期间边界切成若干段,各段用该笔购买的系数聚合——quota_per_unit 只在每笔购买处取一次值,调价点不再制造分段
  • 边界:购买时刻早于本表最早记录时(如补录历史购买),回退用「最早已知值」(近似规则)
  • 充值(wallet)路径:同样取「充值执行时刻」的尺子(池子近似算法后议)

3.4 quota_per_unit 的可变性说明(本表存在的理由)

它是「全站计价单位的定义」——改它 ≈ 重定义货币单位(全站一致重定标);管理员极少动(当前站点为出厂默认值)。本设计以「按时间线折算」从根上免疫它的任何变更。

3.5 为什么不做人工修正(只读设计,2026-09-13 定)

  • 原设计预留「修正生效时间 / 删除」等人工介入能力;源码评估后判定场景不成立——quota_per_unit 在上游无编辑入口(前台默认隐藏且只读)、管理审计不记值、历史上从未变化(见 docs/upstream/NewAPI-接口范围.md)
  • 本表由此定型为纯只读时间线:唯一写入者是同步引擎(值变化才追加);管理通道仅提供只读查看
  • 未来若真出现需要人工介入的场景(如运营方主动告知一次精确切换时刻),再评估启用

3.6 命名:表名 qpu_history、值列 qpu(2026-09-13 改)

  • 表名:原名 quota_per_unit_history 过长、逐处引用啰嗦 → 改为 qpu_history——QPU 是 QuotaPerUnit 的通用缩写,短且醒目
  • 值列:原名 value 过泛("什么的值"不自明)→ 改为 qpu,与表名一体、一眼即知
  • 通用约定:表名 / 列名用 QPU 缩写,引用上游字段 quota_per_unit 时保持全称

4. 写入时机(唯一写入者:同步引擎)

时机 动作
部署(基线) INSERT 基线一行(当时 /api/status 取值)
每轮同步 读 /api/status:值变化才追加一行
  • 除追加外无 UPDATE / DELETE——数据不可变

5. 待定事项(关联后续环节)

事项 归属
采样调度(读取频率、失败重试) 同步引擎设计