积分系统
批次、过期与 FEFO 扣减如何协作。
双表设计
credit_grant— 每次发放是一个批次,含amount、remaining和可选expiresAtcredit_transaction— 只增不改的流水账,直接展示给用户
余额恒等于 SUM(credit_grant.remaining),没有会漂移的缓存计数器。
过期机制
不同来源可以有不同有效期:注册赠分可能 30 天过期,购买的积分包永不过期。每日任务(默认走 GitHub Actions 定时)清零过期批次并写入 expiration 流水。
FEFO 扣减
消耗时优先扣最快过期的批次(First-Expired, First-Out),用户的积分绝不白白浪费。并发扣减由乐观锁 + 重试保护。
接入你自己的功能
import { consumeCredits, InsufficientCreditsError } from "@/credits/service";
try {
await consumeCredits({
userId,
amount: 1,
description: "我的 AI 功能",
});
} catch (e) {
if (e instanceof InsufficientCreditsError) {
// 返回 402,引导用户升级
}
}
人工调整
管理员可在用户表里加/扣积分——每笔调整都会带备注写入流水记录。