Files
new-api-key-usage/packages/core/src/usage.ts
T
skycurtain 6980d09750 feat(core,db): 业务核心与数据访问层
core:DTO/错误信封/时间口径/微分折算/dedupe_key/加密与 PBKDF2/契约 zod/logtape/上游客户端。
db:八表 Drizzle schema + 仓储 + drizzle 配置。
2026-10-06 01:30:51 +08:00

65 lines
1.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 用量聚合辅助(公共约定 §5:后端换算、微分取整、聚合先求和再一次取整)
*/
import {
microSumToUsdStr,
qpuAt,
quotaToMicroUsd,
quotaToUsdStr,
} from "./money.ts";
/** 上游事实:QuotaPerUnit 默认 500000(qpu_history 未采样时的回退) */
export const DEFAULT_QPU = 500_000;
export type QpuPoint = { qpu: number; effective_from: Date | number };
export function resolveQpuTimeline(
rows: readonly QpuPoint[],
): QpuPoint[] {
if (rows.length > 0) return [...rows];
return [{ qpu: DEFAULT_QPU, effective_from: 0 }];
}
export interface UsageSum {
count: number;
quota: number;
quota_usd: string;
}
export function emptyUsage(): UsageSum {
return { count: 0, quota: 0, quota_usd: "0.00" };
}
/** 逐行微分累加(历史正确性:按日志时刻取 QPU) */
export function sumUsage(
rows: ReadonlyArray<{ quota: number; created_at: Date | number }>,
timeline: readonly QpuPoint[],
): UsageSum {
let quota = 0;
let micro = 0;
for (const r of rows) {
quota += r.quota;
const qpu = qpuAt(r.created_at, timeline);
micro += quotaToMicroUsd(r.quota, qpu);
}
return { count: rows.length, quota, quota_usd: microSumToUsdStr(micro) };
}
export function usageAt(
quota: number,
created_at: Date | number,
timeline: readonly QpuPoint[],
): UsageSum {
const qpu = qpuAt(created_at, timeline);
return { count: 1, quota, quota_usd: quotaToUsdStr(quota, qpu) };
}
export function addUsage(a: UsageSum, b: UsageSum): UsageSum {
// 合并已成形的两段时,quota_usd 需重算——调用方应尽量走 sumUsage
return {
count: a.count + b.count,
quota: a.quota + b.quota,
quota_usd: a.quota_usd,
};
}