billing-service/docs/reference/model.md

182 lines
7.5 KiB
Markdown
Raw Permalink Normal View History

# model 包参考
本文档覆盖 `internal/model/types.go`。该包只定义结构体,不包含行为函数,是 `exporter`、`repository`、`service`、`httpapi` 共享的数据契约层。
## 1. 上游快照模型
### `Sample`
签名:`type Sample struct`
| 字段 | 类型 | JSON 字段 | 含义 |
| --- | --- | --- | --- |
| `UUID` | `string` | `uuid` | 账户 UUID服务层会校验其为合法 UUID |
| `Email` | `string` | `email` | 上游样本附带的邮箱,当前服务层不使用此字段做计费决策 |
| `InboundTag` | `string` | `inbound_tag` | 线路标签,写入分钟桶的 `line_code` |
| `UplinkBytesTotal` | `int64` | `uplink_bytes_total` | 截止采样时累计上行字节 |
| `DownlinkBytesTotal` | `int64` | `downlink_bytes_total` | 截止采样时累计下行字节 |
### `Snapshot`
签名:`type Snapshot struct`
| 字段 | 类型 | JSON 字段 | 含义 |
| --- | --- | --- | --- |
| `CollectedAt` | `time.Time` | `collected_at` | 快照采集时间,服务层会按分钟截断 |
| `NodeID` | `string` | `node_id` | 上游节点标识 |
| `Env` | `string` | `env` | 环境标识,例如 `prod` |
| `Samples` | `[]Sample` | `samples` | 本次快照中的样本列表 |
### `SnapshotWindowPage`
签名:`type SnapshotWindowPage struct`
| 字段 | 类型 | JSON 字段 | 含义 |
| --- | --- | --- | --- |
| `NodeID` | `string` | `node_id` | 分页级别的节点标识 |
| `Env` | `string` | `env` | 分页级别的环境标识 |
| `Snapshots` | `[]Snapshot` | `snapshots` | 窗口拉取结果中的快照列表 |
| `HasMore` | `bool` | `has_more` | 是否还有下一页 |
| `NextCursor` | `string` | `next_cursor` | 下一页游标,当前实现要求其为 RFC3339 时间字符串 |
## 2. 持久化实体模型
### `Checkpoint`
签名:`type Checkpoint struct`
| 字段 | 类型 | 含义 |
| --- | --- | --- |
| `NodeID` | `string` | 存储层节点 ID实际由 `env:node_id` 组合而成 |
| `AccountUUID` | `string` | 账户 UUID |
| `LastUplinkTotal` | `int64` | 上次记录的累计上行字节 |
| `LastDownlinkTotal` | `int64` | 上次记录的累计下行字节 |
| `LastSeenAt` | `time.Time` | 上次成功处理该样本的采样时间 |
| `XrayRevision` | `string` | 当前写路径版本标识 |
| `ResetEpoch` | `int64` | 检测到累计值回退后的重置计数 |
### `MinuteBucket`
签名:`type MinuteBucket struct`
| 字段 | 类型 | 含义 |
| --- | --- | --- |
| `BucketStart` | `time.Time` | 分钟桶起始时间,按 UTC 分钟对齐 |
| `NodeID` | `string` | 存储层节点 ID |
| `AccountUUID` | `string` | 账户 UUID |
| `Region` | `string` | 地域代码,当前来自 `cfg.DefaultRegion` |
| `LineCode` | `string` | 线路代码,当前来自 `sample.InboundTag` |
| `UplinkBytes` | `int64` | 当前分钟增量上行字节 |
| `DownlinkBytes` | `int64` | 当前分钟增量下行字节 |
| `TotalBytes` | `int64` | 当前分钟总字节数 |
| `Multiplier` | `float64` | 最终乘数,当前为地域乘数 * 线路乘数 |
| `RatingStatus` | `string` | 当前实现固定写 `rated` |
| `SourceRevision` | `string` | 写路径版本或计费规则版本 |
### `LedgerEntry`
签名:`type LedgerEntry struct`
| 字段 | 类型 | 含义 |
| --- | --- | --- |
| `ID` | `string` | 账本主键,基于分钟桶确定性生成 |
| `AccountUUID` | `string` | 账户 UUID |
| `BucketStart` | `time.Time` | 对应分钟桶起始时间 |
| `BucketEnd` | `time.Time` | 对应分钟桶结束时间,当前实现为 `BucketStart + 1 分钟` |
| `EntryType` | `string` | 当前实现固定为 `traffic_charge` |
| `RatedBytes` | `int64` | 真正参与计费的字节数,已扣除包含流量 |
| `AmountDelta` | `float64` | 本次金额变化,当前为负值表示扣费 |
| `BalanceAfter` | `float64` | 扣费后的余额 |
| `PricingRuleVersion` | `string` | 实际应用的定价规则版本 |
### `QuotaState`
签名:`type QuotaState struct`
| 字段 | 类型 | 含义 |
| --- | --- | --- |
| `AccountUUID` | `string` | 账户 UUID |
| `RemainingIncludedQuota` | `int64` | 剩余包含流量字节数 |
| `CurrentBalance` | `float64` | 当前余额 |
| `Arrears` | `bool` | 是否欠费 |
| `ThrottleState` | `string` | 节流状态,当前实现用 `normal` / `throttled` |
| `SuspendState` | `string` | 挂起状态,当前新建状态默认 `active` |
| `LastRatedBucketAt` | `*time.Time` | 最近一次成功计费的分钟桶时间 |
| `EffectiveAt` | `time.Time` | 当前状态生效时间 |
### `BillingProfile`
签名:`type BillingProfile struct`
| 字段 | 类型 | 含义 |
| --- | --- | --- |
| `AccountUUID` | `string` | 账户 UUID |
| `PackageName` | `string` | 套餐名 |
| `IncludedQuotaBytes` | `int64` | 套餐包含流量 |
| `BasePricePerByte` | `float64` | 基础单价 |
| `RegionMultiplier` | `float64` | 地域乘数 |
| `LineMultiplier` | `float64` | 线路乘数 |
| `PeakMultiplier` | `float64` | 峰时乘数,当前代码未参与计算 |
| `OffPeakMultiplier` | `float64` | 非峰时乘数,当前代码未参与计算 |
| `PricingRuleVersion` | `string` | 计费规则版本号 |
### `SourceSyncState`
签名:`type SourceSyncState struct`
| 字段 | 类型 | 含义 |
| --- | --- | --- |
| `SourceID` | `string` | 来源 ID |
| `LastCompletedUntil` | `*time.Time` | 最近一次成功推进到的窗口终点 |
| `LastAttemptedAt` | `*time.Time` | 最近一次开始尝试采集的时间 |
| `LastSucceededAt` | `*time.Time` | 最近一次成功完成采集的时间 |
| `LastError` | `string` | 最近一次失败信息 |
## 3. HTTP 与运行状态模型
### `SourceStatus`
签名:`type SourceStatus struct`
| 字段 | 类型 | JSON 字段 | 含义 |
| --- | --- | --- | --- |
| `SourceID` | `string` | `source_id` | 来源 ID |
| `LastCompletedUntil` | `*time.Time` | `last_completed_until` | 对外暴露的窗口完成位置 |
| `LastAttemptedAt` | `*time.Time` | `last_attempted_at` | 对外暴露的最近尝试时间 |
| `LastSucceededAt` | `*time.Time` | `last_succeeded_at` | 对外暴露的最近成功时间 |
| `LastError` | `string` | `last_error` | 最近错误 |
### `JobResult`
签名:`type JobResult struct`
| 字段 | 类型 | JSON 字段 | 含义 |
| --- | --- | --- | --- |
| `Job` | `string` | `job` | 作业名,当前为 `collect-and-rate``reconcile` |
| `StartedAt` | `time.Time` | `started_at` | 作业开始时间 |
| `FinishedAt` | `time.Time` | `finished_at` | 作业结束时间 |
| `ProcessedSamples` | `int` | `processed_samples` | 成功进入处理主路径的样本数 |
| `WrittenMinutes` | `int` | `written_minutes` | 新写入的分钟桶数 |
| `ReplayedMinutes` | `int` | `replayed_minutes` | 由于回放或重复写命中的分钟数 |
| `Status` | `string` | `status` | `ok` / `partial` / `error` |
| `Error` | `string` | `error` | 汇总错误信息 |
| `SourceStatuses` | `[]SourceStatus` | `source_statuses` | 各来源状态摘要 |
### `PingInfo`
签名:`type PingInfo struct`
| 字段 | 类型 | JSON 字段 | 含义 |
| --- | --- | --- | --- |
| `Image` | `string` | `image` | 原始镜像引用 |
| `Tag` | `string` | `tag` | 解析出的镜像 tag |
| `Commit` | `string` | `commit` | 解析出的完整 commit |
| `Version` | `string` | `version` | 当前实现等于 commit |
## 4. 使用约束
- 所有 `time.Time` 在服务层和仓储层都按 UTC 处理
- `Snapshot` / `Sample` 是上游输入契约,不应被仓储层直接修改
- `MinuteBucket`、`LedgerEntry`、`QuotaState` 共同构成计费事实链
- `JobResult``SourceStatus` 只代表最近一次执行的内存快照,不是持久化审计日志