Skip to content

Per-account quota poller + /quota schema {accounts, aggregate, legacy} #6

Closed

Description

@longphamdev

Quota poller + /quota multi-account

What to build

Per-account quota poller (tối ưu phụ — failover ở ticket 3 vẫn là cơ chế chính):

  • Poll quota mỗi acc (tái dùng code snapshot trong routes-quota.ts) mỗi ~5 phút với jitter (acc không poll cùng lúc), timeout riêng, lastPolledAt per acc.
  • Poll fail ≠ exhausted: lỗi poll chỉ log + đánh stale, không đổi health.
  • Tách bạch expiry: tokenExpiresAt (JWT) vs quotaExpiresAt (entitlement) — không gộp.
  • Poller feed remainingUnits vào pool (cho option most-remaining-quota).

/quota schema cố định — không đổi shape theo số acc:

{
  accounts: [{ id: ..., label: ..., status: healthy, remainingUnits: 100, lastPolledAt: 0 }],
  aggregate: { accountCount: 2, healthyCount: 1 },
  legacy: { balances: [], claimablePlans: [], ... }
}
  • legacy = top-level fields cũ của primary account (ổn định, KHÔNG phụ thuộc round-robin). Primary không có → legacy null có chủ đích.
  • Chỉ tính tổng ở aggregate khi cùng unitType + phạm vi; đánh dấu stale khi lastPolledAt cũ.
  • auth list thêm cột status/quota từ pool/poller (phần bị tách khỏi ticket CLI).

Acceptance criteria

  • Poller poll đúng N acc với jitter, không burst đồng thời
  • Poll fail → log + stale, acc KHÔNG bị đánh exhausted
  • tokenExpiresAt và quotaExpiresAt tách bạch trong response
  • /quota với 1 acc và 2 acc trả cùng shape (consumer cũ không vỡ)
  • legacy ổn định theo primary kể cả khi round-robin đang dùng acc khác
  • aggregate chỉ cộng khi cùng unitType; stale được đánh dấu
  • auth list hiện status + quota per acc

Activity

  1. longphamdev commented on Nov 9, 2026

    @longphamdev
    OwnerAuthor

    #6 hoàn thành. Commits: abd519a (poller + /quota schema), 6e6b7b6 (thiết kế nền), b72e980 (auth list).

    Acceptance theo review:

    1. ✅ Poller per-account: single-flight (test maxConcurrent=1), jitter ±20%, timeout riêng (abort + failure count), không chiếm reservation slot (đọc credential trực tiếp từ store), tự bắt đầu/dừng khi thêm/xóa acc (follower, test chứng minh)
    2. ✅ Poll fail ≠ exhausted: giữ nguyên trạng thái, chỉ consecutiveFailures++; poll thành công heal expired/exhausted (poller là probe chính)
    3. ✅ Sick acc poll thưa hơn: probe cadence = 2× interval
    4. ✅ /quota luôn trả {accounts[], aggregate, legacy} — cùng shape 1 hay 2 acc; legacy theo primary giữ nguyên field cũ; poll fail → legacyStale: true; aggregate ghi rõ accountsReporting/accountsTotal + unit check; tokenExpiresAt ≠ quotaExpiresAt; không credential trong response (test assert)
    5. ✅ auth list: status + quota, userId che bớt, không in key
    6. ✅ Poller tests với injectable clock — không sleep thật

    Lưu ý: e2e với 2 acc thật chưa chạy được (acc thứ hai quota rỗng) — sẽ chạy khi có quota. Header x-zcode-account + phân phối đã có unit tests.

    Frontier: #2 (CLI accounts) — worktree t2 đã sync tới HEAD.

  2. longphamdev commented on Nov 9, 2026

    @longphamdev
    OwnerAuthor

    Hoàn thành đầy đủ 6 acceptance criteria. Suite 1222/0 local, 1223/0 container.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions