Skip to content

perf(quota-plane): parallel provider fetching + per-provider timeout budget for the 15-min tick #1268

Closed

Description

@dezren39

Part of epic #1149; supports #1151 (gatherer). Priority P1. Observed 2026-10-26: a full openchamber quota --json run over 7 configured providers took ~19s wall — fetching appears effectively sequential and unbounded per provider. At ~30 catalogue providers on a 15-minute gatherer tick, that profile risks tick overruns and head-of-line blocking by one slow dashboard API.
Work: parallelize provider fetching in the CLI/module list path with a bounded concurrency (e.g. 6) and a per-provider timeout (default 10s, configurable); a timed-out provider returns a timeout state row, never blocks the batch; the gatherer gets a total tick budget with per-adapter time reported in its heartbeat (feeds #1116/#1175).
Acceptance: full-catalogue run completes within the tick budget on this host with all providers answered or timed-out-with-state; timing per provider visible in --json output.

Acceptance criteria

  • A refresh fetches all providers' quota data in parallel instead of serial awaits.
  • The refresh is bounded by a timeout budget, so total wall time is capped regardless of provider count.
  • A slow or hung provider degrades to its last-known snapshot with the staleness visible, instead of stalling the whole refresh.

Activity

  1. developing-today commented on Oct 27, 2026

    @developing-today
    Contributor
  2. dezren39 commented on Oct 27, 2026

    @dezren39
    MemberAuthor

    The fetch-performance half of this is in review: developing-today-forks/openchamber#529 (not merged).

    What changed in openchamber quota:

    • Providers now fetch in parallel with bounded concurrency (6) instead of one after another; output order is unchanged (argument/listing order).
    • A per-provider timeout applies (default 10s, OPENCHAMBER_QUOTA_TIMEOUT_MS): a provider that outlives it answers a status: 'timeout' row and the batch completes without it.
    • Every --json result carries elapsedMs, so a slow provider is visible in the output, not just in wall-clock time.
    • Measured on the laptop at the PR head: a full 8-provider read completes in under 2 seconds when the providers answer promptly; per-provider elapsed times in the earlier sequential runs ran 4–8s each, which is what used to add up to the ~19s wall.

    Tests: new coverage for the timeout row and for parallel fetching (in-flight count and order preservation) in commands-quota.test.js; the CLI + auth suites (62) and quota dispatcher/routes/utils suites (42) pass, and bun run check:changed is green.

  3. added
    kind/performancePerformance problem or optimization
    source/humanFiled directly by a human
    priority/normalOrdinary priority (the default)
    effort/sSmall: expected under 2 hours of work
    meta/enrichedIntake review done: acceptance criteria, links, and normalized labels added
    on Oct 28, 2026
  4. dezren39 commented on Oct 28, 2026

    @dezren39
    MemberAuthor

    Intake review

    Fleet-monitor intake pass (protocol §5), 2026-10-28. Filed with only meta/follow-up; labels normalised in this pass (kind/performance, source/human — author dezren39 — status/needs-triage, priority/normal, effort/s). The body's Acceptance line (wall time bounded by the slowest provider plus timeout budget; one hung provider degrades to last-known) is restated as criteria.

    Still live: no merged or open PR references this issue (checked 2026-10-28T01:47Z); nothing has implemented it yet.

    Related: part of epic #1149; siblings #1269 (credential lifecycle) and #1270 (reconciliation diff) work the same quota-plane read path.

    Notes / risks: parallel fetching raises the burst profile against provider endpoints — per-provider timeouts and the last-known fallback are what keep that safe; keep both as hard criteria, not options. Effort/s: a scoped change to the gather path.

    Suggested approach: parallelise the gather with an explicit per-provider timeout, keep the serial path's snapshot semantics for degraded providers, and cover the hung-provider case with a stubbed slow provider test.

  5. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed on Nov 1, 2026
  6. 19 remaining items

  7. added
    queue/queuedHas a queued task in the Supabase agent queue
    task/triageQueue packet kind: verify, reproduce, and route this item
    on Nov 3, 2026
  8. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    state: triaged (coverage pass)
    Coverage pass 2026-11-03: reviewed in the fleet-wide per-issue pass (drift / overlap / already-handled / stale / blockers / ordering). Verdict: still live; queued in repo-health-code-pilot as triage at priority 40 (priority/normal). If this is already handled at current main, the triage closes it with evidence; if it needs splitting, the triage files the split.
    Found via: coverage pass 2026-11-03

  9. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 3, 2026
  10. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    event: picked_up
    task: 7674 (repo-health-code-pilot, repo-worker-code — OpenChamber scheduled lane c29174f1)
    state: Claimed via atomic queue claim. Triage of #1268 (parallel provider fetching + per-provider timeout budget), timebox 20m.
    next: Confirm at current main whether the parallel fetch/timeout work exists, then scope or close with evidence.

  11. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    event: closed (already implemented)
    task: 7674 (repo-health-code-pilot, repo-worker-code — OpenChamber scheduled lane c29174f1)
    verdict: Already done — closing with evidence. All three acceptance criteria are implemented and on main; nothing remains for this issue.

    Evidence at current main (cd3b299ae, 2026-11-03):

    1. Parallel fetch. pm-stack/aggregator/scripts/gather-quota.ts collects provider runs through mapWithConcurrency(providerIds, gatherConcurrency, ...) (line ~507), with QUOTA_GATHER_CONCURRENCY default 6. CLI half in openchamber: packages/web/bin/lib/commands-quota.js uses QUOTA_FETCH_CONCURRENCY = 6 + mapWithConcurrency (merged openchamber PR lab-ops-hub: container validator blanket-refuses percent-encoded hosts the Worker validator decodes and accepts — public spellings (%65xample.com, 8%2e8%2e8%2e8) diverge, including as redirect targets #529).
    2. Bounded by timeout, slow provider never stalls the batch. Gatherer: per-provider withTimeout(..., timeoutMs) with QUOTA_GATHER_TIMEOUT_MS default 15s; a timeout/error degrades to the last-known entries marked retained/stale (PR fix(quota-gatherer): bound provider concurrency + retain last-known snapshot on error (#1268) #3996, merge b5fc3f069, in main). CLI: DEFAULT_QUOTA_TIMEOUT_MS = 10_000 (configurable), timed-out provider yields a status: 'timeout' row.
    3. Timing visible. Gatherer heartbeat carries durationMs plus perProvider[id].{state,ms,rows} (QuotaGatherHeartbeat, written into quota-current each tick); CLI JSON rows carry elapsedMs per provider.

    Prior queue history: triage task 2527 found the CLI half done and routed the gatherer half as task 4978; PR #3996 merged 2026-11-01 with quota tests 96/96 and Codex review clean. No open PR references #1268; no branch carries remaining work.

    Closing as implemented. If tick-level wall time later grows with the catalogue, that belongs to the gatherer tick-budget follow-ups (#1116/#1175), not to this issue.

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

Metadata

Metadata

Assignees

Labels

effort/sSmall: expected under 2 hours of workkind/performancePerformance problem or optimizationmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedmeta/follow-upFollow-up spun out of earlier workmode/onlineFully doable remotely: design, config, code, cloudpriority/normalOrdinary priority (the default)source/humanFiled directly by a humantask/triageQueue packet kind: verify, reproduce, and route this item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions