Skip to content

fix(subscription): 移除额度快照时间失效 - #454

Merged
tbphp merged 6 commits into
v2from
codex/remove-observation-freshness
Aug 21, 2026
Merged

fix(subscription): 移除额度快照时间失效#454
tbphp merged 6 commits into
v2from
codex/remove-observation-freshness

Conversation

@tbphp

@tbphp tbphp commented Aug 21, 2026

Copy link
Copy Markdown
Owner

关联 Issue / Related Issue

N/A

变更内容 / Change Content

  • Bug 修复 / Bug fix
  • 新功能 / New feature
  • 其他改动 / Other changes
  • 删除额度观测的 fresh_until_ms 运行时、管理 API 和前端字段,并通过 0003 迁移从 SQLite、MySQL、PostgreSQL 物理删除数据库列。
  • 额度快照保持最后一次成功同步结果,不再随时间或窗口结束自动失效;窗口结束后仅将卡片时间提示改为“待刷新”,不改变进度、剩余额度或调度状态。
  • 窗口统计严格使用快照记录的 [start, end),整小时复用聚合数据,两侧边界读取请求日志;缺少有效窗口时间时不展示统计。
  • 将诊断字段改为“上次额度同步”,并只在已记录可用重置卡时展示数量、到期信息和操作入口。
  • OAuth Token 自动刷新、手动 Token 刷新、429 冷却及请求调度逻辑保持不变。

兼容性与迁移影响:管理 API 不再返回 fresh_until_ms;应用启动时 0003_remove_observation_fresh_until 会删除已有数据库列并保留观测数据。

验证:

  • make check
  • 真实 MySQL 8.4 增量迁移与生命周期验证
  • 真实 PostgreSQL 18 增量迁移与生命周期验证

自查清单 / Checklist

  • 我已运行 make check,或在说明中写明无法运行的原因和未验证范围。 / I ran make check, or documented why it could not run and what remains unverified.
  • 本 PR 范围聚焦,未包含无关改动。 / This PR is focused and contains no unrelated changes.
  • 我已更新必要的公开文档或发布说明。 / I updated any required public documentation or release notes.
  • 我已确认提交、日志和测试数据不包含敏感信息。 / I confirmed that commits, logs, and fixtures contain no sensitive data.
  • 如适用,我已说明兼容性或数据迁移影响。 / Where applicable, I documented compatibility or data-migration impact.

Summary by CodeRabbit

  • 新功能

    • 订阅账户配额依据配额周期及重置时间展示,并提供手动刷新提示。
    • 新增重置额度详情、有效期状态及操作提示。
    • 首页和运行状况中新增即将到期重置额度提醒。
  • 问题修复

    • 配额观测不再因时间经过自动失效,状态展示更加稳定。
    • 优化配额使用统计的时间边界计算,确保窗口内请求准确统计。
    • 运行状况检查现在识别所有已记录的低额度凭据。
    • 无有效期的可用重置额度也会正常保留和展示。

@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: QUIET

Plan: Pro Plus

Run ID: fcf7cd0a-584b-432c-976e-8bcdf8e1f410

📥 Commits

Reviewing files that changed from the base of the PR and between 588d579 and 3d184de.

📒 Files selected for processing (2)
  • internal/control/health_quota_test.go
  • internal/control/health_reset_credits.go

Included review availability: Your plan provides up to 8 included reviews per hour; 5 remain after this review.


📝 Walkthrough

Walkthrough

本次变更移除配额观测的 FreshUntilMSQuotaFreshUntil 及相关 TTL 判断。观测状态改为依据当前结果和历史快照确定。配额用量查询使用记录的 ResetAtMS。新增数据库迁移以删除 fresh_until_ms 列,并支持 SQLite 重建和恢复校验。前端改用额度窗口状态显示待刷新提示、最后同步时间和用量信息。

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.90% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 62 functions across 35 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 标题准确概括了移除额度快照时间失效逻辑这一主要变更,简洁且与变更内容相关。
Description check ✅ Passed 描述包含变更内容、迁移影响、验证范围和自查清单,整体符合模板要求。
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch codex/remove-observation-freshness

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@tbphp
tbphp marked this pull request as ready for review August 21, 2026 12:18
Copilot AI lite review requested due to automatic review settings August 21, 2026 12:18
@tbphp tbphp self-assigned this Aug 21, 2026
@tbphp tbphp added the bug Something isn't working label Aug 21, 2026
@tbphp tbphp added this to the v2.0.0 milestone Aug 21, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 365babd274

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/control/credential_observations.go
Comment thread web/src/features/groups/credentials/SubscriptionAccountCard.vue Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR removes the time-based “freshness” expiry for subscription quota snapshots (fresh_until_ms), so the system keeps the last successfully synced quota state until a new sync happens, and physically drops the retired column via a new DB migration.

Changes:

  • Remove fresh_until_ms from backend models/API, frontend DTO projection, and UI labels; add migration 0003_remove_observation_fresh_until (SQLite rebuild + MySQL/Postgres drop column).
  • Update subscription account UI to show a “pending refresh” hint after a quota window ends, and rename diagnostics to “last quota sync”.
  • Tighten quota window usage aggregation to use the snapshot’s recorded [start, end) boundaries, reusing hourly stats for full hours and request logs for both boundary fragments.

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
web/src/i18n/locales/zh-CN/group.ts Add pending-refresh hint text; rename quota sync diagnostic label.
web/src/i18n/locales/ja-JP/group.ts Add pending-refresh hint text; rename quota sync diagnostic label.
web/src/i18n/locales/en-US/group.ts Add pending-refresh hint text; rename quota sync diagnostic label.
web/src/features/groups/credentials/SubscriptionAccountCard.vue Remove time-based staleness gating; show pending refresh tooltip; adjust reset-credit display logic.
web/src/app/resources/credentials.ts Stop projecting fresh_until_ms into the web resource DTO.
web/src/api/control/types.ts Remove fresh_until_ms from CredentialObservationDto.
internal/storage/models/subscription.go Drop FreshUntilMS field from CredentialObservation model.
internal/storage/migrations/0003_remove_observation_fresh_until.go New migration to drop the retired fresh_until_ms column (+ validators).
internal/storage/migrations/0003_remove_observation_fresh_until_test.go Test that migration drops the column and preserves rows/idempotency.
internal/storage/migration.go Add ValidateCurrent hook; register migration 0003; validate applied chain with current validator when present.
internal/storage/migration_test.go Update expected migration registry IDs to include 0003.
internal/storage/migration_recovery_test.go Add MySQL resume coverage for 0003; broaden external incremental migration test to include all migrations.
internal/storage/db_test.go Update expected schema migration ledger to include 0003.
internal/storage/database_integration_test.go Assert fresh_until_ms is absent after lifecycle migrations; expect 0001–0003 ledger.
internal/state/runtime_view.go Replace FreshQuotaRemaining with ObservedQuotaRemaining; drop QuotaFreshUntil from runtime view.
internal/state/registry.go Remove quotaFreshUntil tracking; simplify SetCredentialQuotaObservation signature/validation.
internal/state/registry_test.go Update tests for new quota-observation semantics (no time expiry).
internal/scheduler/inspect_test.go Update test naming/fixtures for removed QuotaFreshUntil.
internal/requestlog/credential_window_usage.go Fix hourly window end alignment; merge request-log usage for both start/end boundaries.
internal/requestlog/credential_window_usage_test.go Add coverage ensuring both boundary fragments use exact request logs.
internal/control/health.go Use observed quota remaining without time-based expiry gating.
internal/control/health_quota_test.go Update expectations to include all recorded low-quota credentials.
internal/control/credentials.go Update observation presentation call site for removed freshness parameter.
internal/control/credential_reset_credits.go Clear quota observation without fresh_until state.
internal/control/credential_observations.go Remove TTL-based freshness logic; stop emitting/using fresh_until_ms; use recorded window [start,end) for usage enrichment.
internal/control/credential_observations_test.go Update/add tests for “no time expiry” semantics and recorded window boundaries.
internal/control/credential_mutations.go Update observation presentation call site for removed freshness parameter.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread web/src/features/groups/credentials/SubscriptionAccountCard.vue

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.

🟡 Other comments (2)
internal/control/credential_observations.go-618-618 (1)

618-618: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

拒绝非正数的 ResetAtMS

Line 618 只排除 nil。它会接受 0 和负数的 ResetAtMSenrichCredentialObservationUsage 在 Line 736-738 已将这些值定义为不可用窗口。time.UnixMilli(0) 不是零值 time.Time,因此无效边界仍会写入注册表和健康检查响应。

在选择账户额度窗口前,要求 ResetAtMS > 0。同时增加零值和负值的测试。

建议修改
-		if window.Scope != "account" || window.ResetAtMS == nil {
+		if window.Scope != "account" || window.ResetAtMS == nil || *window.ResetAtMS <= 0 {
internal/storage/migrations/0003_remove_observation_fresh_until.go-37-37 (1)

37-37: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

修复 staticcheckQF1008 错误。

db.Dialector.Name() 改为 db.Name(),避免 make check 失败。

Source: Linters/SAST tools


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: QUIET

Plan: Pro Plus

Run ID: a287a2ba-780c-499b-9af5-09340ebac900

📥 Commits

Reviewing files that changed from the base of the PR and between 986a211 and 365babd.

📒 Files selected for processing (27)
  • internal/control/credential_mutations.go
  • internal/control/credential_observations.go
  • internal/control/credential_observations_test.go
  • internal/control/credential_reset_credits.go
  • internal/control/credentials.go
  • internal/control/health.go
  • internal/control/health_quota_test.go
  • internal/requestlog/credential_window_usage.go
  • internal/requestlog/credential_window_usage_test.go
  • internal/scheduler/inspect_test.go
  • internal/state/registry.go
  • internal/state/registry_test.go
  • internal/state/runtime_view.go
  • internal/storage/database_integration_test.go
  • internal/storage/db_test.go
  • internal/storage/migration.go
  • internal/storage/migration_recovery_test.go
  • internal/storage/migration_test.go
  • internal/storage/migrations/0003_remove_observation_fresh_until.go
  • internal/storage/migrations/0003_remove_observation_fresh_until_test.go
  • internal/storage/models/subscription.go
  • web/src/api/control/types.ts
  • web/src/app/resources/credentials.ts
  • web/src/features/groups/credentials/SubscriptionAccountCard.vue
  • web/src/i18n/locales/en-US/group.ts
  • web/src/i18n/locales/ja-JP/group.ts
  • web/src/i18n/locales/zh-CN/group.ts
💤 Files with no reviewable changes (3)
  • web/src/api/control/types.ts
  • web/src/app/resources/credentials.ts
  • internal/storage/models/subscription.go

Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.

🟡 Other comments (1)
web/src/i18n/locales/en-US/core.ts-247-247 (1)

247-247: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

修正英文到期提示。

the nearest expires 缺少名词。此文本会直接显示在首页。请改为 the nearest one expires

建议修改
-        resetCreditExpiring: '{group} has {count} reset credits expiring soon; the nearest expires',
+        resetCreditExpiring: '{group} has {count} reset credits expiring soon; the nearest one expires',

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: QUIET

Plan: Pro Plus

Run ID: 5f25373c-b16c-4182-8b11-9ba9c7980550

📥 Commits

Reviewing files that changed from the base of the PR and between 365babd and b735b97.

📒 Files selected for processing (21)
  • internal/control/credential_observations_test.go
  • internal/control/credential_reset_credits.go
  • internal/control/health.go
  • internal/control/health_quota_test.go
  • internal/control/health_reset_credits.go
  • internal/subscription/providers/codex/observation.go
  • internal/subscription/providers/codex/observation_test.go
  • internal/subscription/providers/observation/snapshot.go
  • web/src/api/control/types.ts
  • web/src/app/resources/credentials.ts
  • web/src/app/resources/health.ts
  • web/src/features/groups/credentials/GroupCredentialsTab.vue
  • web/src/features/groups/credentials/SubscriptionAccountCard.vue
  • web/src/features/home/HomeAttention.vue
  • web/src/features/home/attention.ts
  • web/src/i18n/locales/en-US/core.ts
  • web/src/i18n/locales/en-US/group.ts
  • web/src/i18n/locales/ja-JP/core.ts
  • web/src/i18n/locales/ja-JP/group.ts
  • web/src/i18n/locales/zh-CN/core.ts
  • web/src/i18n/locales/zh-CN/group.ts

Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b735b97a9f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/storage/migrations/0003_remove_observation_fresh_until.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/storage/migrations/0003_remove_observation_fresh_until.go (1)

21-23: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

补齐 MySQL CHECK 约束删除的版本兼容处理。

DontSupportDropConstrainttrue 时,credentialObservation0003 未声明 chk_credential_observation_fresh_until,GORM 会跳过 DROP CHECK。此外,MySQL 8.0.16–8.0.18 支持 CHECK 约束,但不支持 DROP CONSTRAINT;当前驱动仍会生成通用语句,导致迁移失败。请补充同名 CHECK 定义,显式处理这些版本,并为每个支持的 MySQL 版本增加包含实际 CHECK 约束的集成测试。


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: QUIET

Plan: Pro Plus

Run ID: 1b8e02b4-27c6-4ef3-8ade-dfa4cc7108b4

📥 Commits

Reviewing files that changed from the base of the PR and between b735b97 and 7a40e95.

📒 Files selected for processing (2)
  • internal/storage/migrations/0003_remove_observation_fresh_until.go
  • web/src/i18n/locales/en-US/core.ts

Included review availability: Your plan provides up to 8 included reviews per hour; 6 remain after this review.

@tbphp

tbphp commented Aug 21, 2026

Copy link
Copy Markdown
Owner Author

@codex

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7a40e955b2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/storage/migrations/0003_remove_observation_fresh_until.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/storage/migrations/0003_remove_observation_fresh_until.go (1)

73-119: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

在 SQLite 表重建中使用单个事务。

第 114-118 行将复制、删除和重命名作为独立的自动提交操作执行。
如果 DROP TABLE credential_observations 成功后 ALTER TABLE ... RENAME 失败,正式表会缺失。后续 Up0003 会立即失败,现有观测数据无法由迁移流程恢复。

请用 db.Transaction 包裹全部重建语句,并通过事务句柄执行每个 Exec

建议修复
 func rebuildSQLiteCredentialObservations0003(db *gorm.DB) error {
 	statements := []string{
 		// ...
 	}
-	for _, statement := range statements {
-		if err := db.Exec(statement).Error; err != nil {
-			return fmt.Errorf("rebuild SQLite credential observations: %w", err)
+	return db.Transaction(func(tx *gorm.DB) error {
+		for _, statement := range statements {
+			if err := tx.Exec(statement).Error; err != nil {
+				return fmt.Errorf("rebuild SQLite credential observations: %w", err)
+			}
 		}
-	}
-	return nil
+		return nil
+	})
 }

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: QUIET

Plan: Pro Plus

Run ID: 135da3b3-a8e8-4856-b63b-28967629d269

📥 Commits

Reviewing files that changed from the base of the PR and between 7a40e95 and 588d579.

📒 Files selected for processing (4)
  • internal/storage/migration_recovery_test.go
  • internal/storage/migrations/0003_remove_observation_fresh_until.go
  • internal/storage/migrations/0003_remove_observation_fresh_until_internal_test.go
  • internal/storage/migrations/0003_remove_observation_fresh_until_test.go

Included review availability: Your plan provides up to 8 included reviews per hour; 6 remain after this review.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 588d579db1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/control/health_reset_credits.go

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3d184de435

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread web/src/features/groups/credentials/SubscriptionAccountCard.vue Outdated
@tbphp
tbphp merged commit ed5622f into v2 Aug 21, 2026
7 checks passed
@tbphp
tbphp deleted the codex/remove-observation-freshness branch August 21, 2026 18:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants