Repository navigation
Conversation
Test-First: an_elapsed_block_no_longer_holds_its_task Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Regression-For: 2f487d1 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1db182e9ff
ℹ️ 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".
| let now = now_unix_secs(); | ||
| // A block that names its own end must not outlive it: a blocked profile | ||
| // starts no worker, so no output would ever clear it. | ||
| quota.release_expired(now); |
There was a problem hiding this comment.
Move quota expiry ahead of capacity returns
In the inspected dispatch_project path, this cleanup runs only after the max_workers == 0 and running >= limit returns. If every project is paused or full—or there are no projects—an elapsed global quota row is therefore never cleared by the dispatcher, leaving get_quota_state, provider views, and the persisted row reporting a profile as blocked past blocked_until. Run the global expiry cleanup once at the start of dispatch_once, before per-project capacity checks.
Useful? React with 👍 / 👎.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
fix(queue): lift elapsed quota blocks (replaces #130)
|
Ersetzt durch #183 (gemergt 03.10.). Branch bleibt erhalten. |
Ein Anbieter-Block mit bekanntem Ablaufzeitpunkt blieb in der Warteschlange für immer bestehen, weil ihn nur Ausgabe eines laufenden Workers desselben Profils löschte – und ein blockiertes Profil startet keinen Worker. Jetzt hebt der Dispatcher abgelaufene Blöcke vor jedem Durchgang auf. Dazu liefert dieser PR eine Bestandsaufnahme des Bereichs Warteschlange/Quota (unten) als Grundlage für neue Pakete.
Report
QuotaTracker::release_expired(now)(quota.rs) setzt Zeilen mitstate=blockedundblocked_until <= nowaufok(persistiert über den Sink);dispatch_project(queue.rs) ruft es vor der Kandidatenschleife. Offene Blöcke (blocked_until = None) bleiben unberührt.Test-First) –an_elapsed_block_no_longer_holds_its_taskan der Merge-Base rot (cargo test --bin projecta an_elapsed_block→ FAILED, „the elapsed block is lifted and the task starts"). Fix 1db182e (Regression-For: 2f487d1).bash scripts/ci/gates.sh lane prepushmit dem Fix im Baum → Exit 0 (1657 Tests grün, 7 übersprungen, clippy/fmt/lint grün).#[cfg(windows)]-Tests und Windows-Arme von clippy (Windows-Bahn läuft in der Merge-Queue); der echte Anbieter-Fluss (Statuszeile → Block → Ablauf) ist nicht gegen einen laufenden Agenten gemessen.Bestandsaufnahme
Nur Lesen von
queue.rs,quota.rs,preflight.rs,budget.rs(Teile),status.rs-Quota-Pfad;routing.rs/workers.rsnicht angefasst (PR #115). Nicht alle Befunde wurden gegen einen Lauf bewiesen.status.rs:1474: Anbieter-Blöcke aus der Ausgabe-Heuristik werden immer mitblocked_until=Nonegespeichert und nur durch Aktivität eines Workers dieses Profils gelöscht (status.rs:1476); ein blockiertes Profil mit leerer Warteschlange startet keinen Worker, der Block überlebt zudem den Neustart (main.rs:3281hydrate). Dieser PR löst nur den Fall mit Zeitstempel. Vorschlag: Paket „Quota-Probe": Zeitlimit (z. B. Block ohne Zeit läuft nach N Minuten ab bzw. wird einmal pro Sweep probeweise freigegeben) plus Anzeige in der UI/pa quota clear.queue.rs:~517(Dispatcher-Thread,loop { block_on(dispatch_once) }): Panik in einem Launcher beendet den Thread dauerhaft; die Warteschlange steht bis zum App-Neustart, ohne Log. Vorschlag:catch_unwind/Panik-Log pro Sweep.queue.rs:~330(launcher.launch(..).await): kein Zeitlimit; hängt ein Spawn, bleibt der Eintragdispatchingund der ganze Dispatcher blockiert (alle Projekte). Geklärte Claims gibt es nur beim Start (Reattach inmain.rs), nicht zur Laufzeit. Vorschlag:tokio::time::timeout+ Release des Claims.queue.rs:dispatch_once: höchstens ein Eintrag pro Projekt pro 30-s-Sweep (POLL_INTERVAL); zehn bereite Tasks brauchen bis zu 5 Minuten. Vorschlag: nach erfolgreichem Dispatch sofort weiter, bis Kapazität/Liste leer, oder Wake-Signal beienqueue/Worker-Ende.queue.rs:dispatch_project(Limit): negativesmax_workers(usize::try_fromschlägt fehl) fällt auf den Standard 4 statt zu pausieren;set_project_max_workers(main.rs:914, Naht) prüft den Wert nicht. Vorschlag: Validierung an der Naht oder<0= 0 behandeln.queue.rs:gather_facts:agents.json, das einmal nicht lesbar/leer ist, macht Profile „unbekannt" undmark_queue_failedscheitert alle bereiten Tasks dauerhaft (permanenter Blocker). Vorschlag: prüfen, wasload_profilesbei Parse-Fehler liefert; bei Fehler Sweep überspringen statt Tasks zu verwerfen (nicht bewiesen).queue.rs:~232Preflight-Cache-Fingerprint enthältblocked_until, aber nicht die Uhrzeit; TTL 30 s = Sweep-Takt, d. h. praktisch kein Cache-Nutzen (Verbesserung/Vereinfachung, kein Fehler).mark_queue_dispatched-Slot-Race ist getestet, der Rest nicht).🤖 Generated with Claude Code