Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

feat(account): add daily/weekly periodic quota limits for API Key accounts#841

Open
touwaeriol wants to merge 5 commits intoWei-Shaw:mainfrom
touwaeriol:feature/account-periodic-quota
Open

feat(account): add daily/weekly periodic quota limits for API Key accounts#841
touwaeriol wants to merge 5 commits intoWei-Shaw:mainfrom
touwaeriol:feature/account-periodic-quota

Conversation

@touwaeriol
Copy link
Contributor

背景 / Background

当前 API Key 账号仅支持设置总额度限制(quota_limit),缺乏周期性(日/周)配额维度。用户需要更灵活的配额控制——例如设置每日限额防止短时间内消耗过多,或设置周限额进行周期性预算管理。

Currently API Key accounts only support a total quota limit (quota_limit), lacking periodic (daily/weekly) quota dimensions. Users need more flexible quota controls — e.g., daily limits to prevent excessive consumption in short periods, or weekly limits for periodic budget management.


目的 / Purpose

为 API Key 账号新增日限额和周限额两个独立维度,与现有总限额共存。三个维度可独立配置,任一维度超限即暂停账号调度。日/周限额采用滚动周期+懒重置机制(周期过期后在下次计费时自动重置为 0),无需后台定时任务。

Add daily and weekly quota limit dimensions to API Key accounts, coexisting with the existing total quota limit. All three dimensions are independently configurable; exceeding any one pauses account scheduling. Daily/weekly limits use rolling periods with lazy reset (automatically reset to zero on next billing after period expiry), requiring no background cron jobs.


改动内容 / Changes

后端 / Backend

  • 新增 Account 方法GetQuotaDailyLimit/UsedGetQuotaWeeklyLimit/UsedHasAnyQuotaLimitgetExtraFloat64getExtraTimeisPeriodExpired
  • 重写 IsQuotaExceeded:检查总/日/周三个维度,任一超限返回 true
  • 重写 IncrementQuotaUsed SQL:原子更新三维度用量,日/周额度在周期过期时自动重置(inline UPDATE 避免 CTE 快照在 READ COMMITTED 下丢失更新)
  • 重写 ResetQuotaUsed SQL:重置所有维度用量并删除周期时间戳
  • postUsageBilling:条件从 GetQuotaLimit() > 0 改为 HasAnyQuotaLimit()
  • admin_service.go:编辑账号时保留 quota_daily_used/startquota_weekly_used/start 避免意外重置

  • New Account methods: GetQuotaDailyLimit/Used, GetQuotaWeeklyLimit/Used, HasAnyQuotaLimit, getExtraFloat64, getExtraTime, isPeriodExpired
  • Rewrite IsQuotaExceeded: checks total/daily/weekly — any dimension exceeding returns true
  • Rewrite IncrementQuotaUsed SQL: atomically updates 3 dimensions; daily/weekly auto-reset on period expiry (inline UPDATE to avoid CTE snapshot lost-update under READ COMMITTED)
  • Rewrite ResetQuotaUsed SQL: resets all dimensions and removes period timestamps
  • postUsageBilling: condition changed from GetQuotaLimit() > 0 to HasAnyQuotaLimit()
  • admin_service.go: preserve quota_daily_used/start, quota_weekly_used/start on account edit

前端 / Frontend

  • QuotaLimitCard.vue:从单一 v-model 改为三个独立 props(totalLimit/dailyLimit/weeklyLimit),支持同时配置多个维度
  • 新增 QuotaBadge.vue:通用配额徽章组件,显示 $used/$limit 及颜色状态(绿/黄/红)
  • AccountCapacityCell.vue:使用 QuotaBadge 显示 D(日)/W(周)/$(总)三维度徽章
  • EditAccountModal.vue / CreateAccountModal.vue:新增日/周配额输入字段
  • AccountActionMenu.vuehasQuotaLimit 检查扩展为三维度
  • i18n:新增日/周/总配额的标签和提示文案(中英文)

  • QuotaLimitCard.vue: refactored from single v-model to 3 independent props (totalLimit/dailyLimit/weeklyLimit), supporting simultaneous multi-dimension configuration
  • New QuotaBadge.vue: reusable quota badge component showing $used/$limit with color-coded status (green/yellow/red)
  • AccountCapacityCell.vue: uses QuotaBadge to display D(daily)/W(weekly)/$(total) dimension badges
  • EditAccountModal.vue / CreateAccountModal.vue: added daily/weekly quota input fields
  • AccountActionMenu.vue: hasQuotaLimit check extended to three dimensions
  • i18n: added labels and hints for daily/weekly/total quota (zh + en)

技术细节 / Technical Details

懒重置机制 / Lazy Reset Mechanism

日/周配额不使用后台定时任务重置,而是在 IncrementQuotaUsed SQL 中内联处理:

  • 检查 quota_daily_start + 24h 是否 <= NOW()
  • 如果已过期:重置 quota_daily_used = $amount,更新 quota_daily_start 为当前 UTC 时间
  • 如果未过期:累加 quota_daily_used += $amount
  • 周配额同理(168h 周期)
  • 使用 inline UPDATE(非 CTE)避免 PostgreSQL READ COMMITTED 隔离级别下的并发丢失更新

Daily/weekly quotas use inline lazy reset in IncrementQuotaUsed SQL instead of background cron:

  • Check if quota_daily_start + 24h <= NOW()
  • If expired: reset quota_daily_used = $amount, update quota_daily_start to current UTC
  • If not expired: accumulate quota_daily_used += $amount
  • Weekly quota uses same logic with 168h period
  • Uses inline UPDATE (not CTE) to avoid lost-update under PostgreSQL READ COMMITTED isolation

touwaeriol and others added 5 commits March 7, 2026 19:06
…ounts

Extend the existing total quota limit with daily and weekly periodic
dimensions. Each dimension is independently configurable and uses lazy
reset — when the period expires, usage is automatically reset to zero on
the next increment. Any dimension exceeding its limit will pause the
account from scheduling.

Backend:
- Add GetQuotaDailyLimit/Used, GetQuotaWeeklyLimit/Used, HasAnyQuotaLimit
- Rewrite IncrementQuotaUsed with atomic CTE SQL for 3-dimension update
- Rewrite ResetQuotaUsed to clear all dimensions and period timestamps
- Update postUsageBilling to use HasAnyQuotaLimit()
- Preserve daily/weekly used values on account edit

Frontend:
- Refactor QuotaLimitCard from single v-model to 3-dimension props
- Add QuotaBadge component for compact D/W/$ display
- Update AccountCapacityCell with per-dimension badges
- Update Create/Edit modals with daily/weekly quota fields
- Update AccountActionMenu hasQuotaLimit to check all dimensions
- Add i18n strings for daily/weekly/total quota labels

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The recent upstream commit added allow_messages_dispatch to the Group
DTO but did not update the API contract test expectation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Show a semi-transparent blue rectangle overlay while dragging to
select rows, matching the project's primary color theme with dark
mode support. The box spans the full table width from drag start
to current mouse position.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant