llmrouter: Slot an das Verbindungssignal binden (cancel feuert nicht)
Gegenprobe am Produktivrouter nach dem ersten Fix: Ein abgebrochener Stream gab den Slot WEITERHIN nicht frei -- cancel() im TransformStream wird von Bun beim Verbindungsabbruch nicht aufgerufen. Immerhin griff die zweite Haerte: statt zwei Stunden Stille gab es nach 30 s ein 503 mit Grund. Jetzt haengt der Slot an req.signal, das beim Abbruch zuverlaessig feuert, plus einem Sicherheitsnetz von 660 s (laenger als der Upstream-Timeout darf kein Slot gehalten werden). Die Freigabe ist gegen Doppelaufruf gesichert, ein spaeteres flush() schadet also nicht. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -348,6 +348,16 @@ Bun.serve({
|
|||||||
let freigeben: () => void;
|
let freigeben: () => void;
|
||||||
try {
|
try {
|
||||||
freigeben = await belegen(ziel.upstreamName, ziel.upstream);
|
freigeben = await belegen(ziel.upstreamName, ziel.upstream);
|
||||||
|
// Der Slot haengt am LEBEN DER VERBINDUNG, nicht am Ende des Streams.
|
||||||
|
// Gegenprobe am 2026-09-07: cancel() im TransformStream feuert in Bun
|
||||||
|
// NICHT, wenn der Client abbricht -- der Slot blieb belegt, und erst die
|
||||||
|
// 30-s-Frist machte daraus ein 503 statt Stille (42i/intern#1283).
|
||||||
|
// req.signal feuert dagegen zuverlaessig; die Freigabe ist gegen
|
||||||
|
// Doppelaufruf gesichert, ein spaeteres flush() schadet also nicht.
|
||||||
|
// Dazu ein Sicherheitsnetz: laenger als der Upstream-Timeout darf kein
|
||||||
|
// Slot gehalten werden, egal was passiert.
|
||||||
|
req.signal.addEventListener("abort", () => freigeben(), { once: true });
|
||||||
|
setTimeout(() => freigeben(), 660_000);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof SlotFrist) {
|
if (e instanceof SlotFrist) {
|
||||||
eintrag.status = 503; eintrag.fehler = e.message; abschliessen();
|
eintrag.status = 503; eintrag.fehler = e.message; abschliessen();
|
||||||
|
|||||||
Reference in New Issue
Block a user