Plan Checker (neues Studenten-Werkzeug, Seitenleiste + Admin → Plan-Checker- Merkmale): lädt einen Bauplan als PDF hoch und lässt ChatGPT oder Claude ihn gegen eine gepflegte Merkmalsliste prüfen. PDF-Rendering (pdf.js + @napi-rs/canvas) berücksichtigt jetzt Ebenen (Optional Content Groups) und WASM-Decoder korrekt, sendet eine Übersicht plus mehrere hochaufgelöste Kachel-Ausschnitte statt eines einzelnen, zu groben Bilds, und beide Anbieter bekommen dasselbe Bildmaterial. Jedes Prüfergebnis kann auf eines der gesendeten Bilder als Beleg verweisen (bildIndex) — als Screenshot im Ergebnis anklickbar, öffnet vergrößert in einem Modal statt eines von Chrome blockierten target=_blank-Links auf eine data:-URL. KI-Modellname ist jetzt pro Konto überschreibbar (Einstellungen → Mein Konto) für Drittanbieter mit abweichendem Modell-Katalog. Wochenbericht: dichte Kartenansicht bekommt einen Fokus-Modus — nur der Kommentar liegt offen, Leistungsphasen und Beteiligte stecken in aufklappbaren Abschnitten statt dauerhaft nebeneinander zu stehen. Projektbereich: Terminplan-Auslastung rechnet jetzt exakt wie der Auslastungs-Tab/die Wandtafel (statt einer unabhängigen, tageweisen Schätzung); die LPH-Fortschrittsliste im Dashboard zeigt nur noch die beauftragten Leistungsphasen. Wandtafel: Dashboard-Kopf mit Kennzahlen-Reihe und Panel-Reihe neu strukturiert, in den Blautönen des Firmenlogos; dieselbe Palette wurde anschließend auf den gesamten App-weiten Dark Mode übernommen. Dateibereinigung: nicht mehr benötigte Test-Uploads/Backups entfernt. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
7.2 KiB
RetryHandler
Stability: 2 - Stable
A Dispatcher handler that automatically retries a request when it fails
with a recoverable network error or an eligible HTTP status code. It wraps an
inner handler and re-dispatches the request, applying an exponential backoff and
honouring the Retry-After response header. When a response is partially
consumed before the failure, the handler resumes the download with a Range
request guarded by the original ETag.
The handler is most often used indirectly through RetryAgent, but it can
also be supplied directly to dispatcher.dispatch() for fine-grained
control over the retry behaviour.
import { RetryHandler } from 'undici'
Class: RetryHandler
- Extends: {DispatchHandler}
Implements the DispatchHandler interface. An instance is consumed by a
single dispatch call and forwards the dispatch lifecycle to the inner handler,
re-issuing the request through the supplied dispatch function whenever a retry
is warranted.
Note: The
RetryHandlerdoes not retry over stateful bodies (for example streams orAsyncIterable), because once consumed they cannot be replayed. In these situations the body is identified as stateful and the request is rejected with theUND_ERR_REQ_RETRYerror instead of being retried.
new RetryHandler(options, retryHandlers)
options{DispatchOptions} The dispatch options for the request, extended with an optionalretryOptionsfield. Type isDispatchOptions & { retryOptions?: RetryOptions }.retryOptions{RetryOptions} (optional) Configuration controlling when and how the request is retried. SeeRetryOptions.
retryHandlers{RetryHandlers} The handlers used to drive the retry loop. SeeRetryHandlers.- Returns: {RetryHandler}
RetryOptions
throwOnError{boolean} Whentrue, an error is thrown on the last retry attempt and propagated to the inner handler; whenfalse, the failing response is passed through instead, which is useful when the error body is needed or a custom error handler is in place. Default:true.retry{Function} Callback invoked on every retry iteration to decide whether another attempt should be made. It receives the error, the retry context, and a callback. Call the callback with anErrorto stop retrying, or withnullto schedule another attempt. Default: the built-in retry strategy described below.err{Error} The error that triggered the retry.context{RetryContext} The current retry context. SeeRetryContext.callback{Function} Signals the outcome of this iteration.result{Error|null} (optional) AnErrorto abort retrying, ornullto retry.
maxRetries{number} Maximum number of retries allowed. Default:5.maxTimeout{number} Maximum number of milliseconds to wait between retries. Default:30000(30 seconds).minTimeout{number} Initial number of milliseconds to wait before the first retry. Default:500(half a second).timeoutFactor{number} Multiplier applied to the timeout between successive retries to produce an exponential backoff. Default:2.retryAfter{boolean} Whentrue, the delay before the next retry is inferred from theRetry-Afterresponse header when present. Default:true.methods{string[]} HTTP methods that are eligible for retrying. Default:['GET', 'HEAD', 'OPTIONS', 'PUT', 'DELETE', 'TRACE'].statusCodes{number[]} HTTP status codes that trigger a retry. Default:[500, 502, 503, 504, 429].errorCodes{string[]} Network error codes that trigger a retry. Default:['ECONNRESET', 'ECONNREFUSED', 'ENOTFOUND', 'ENETDOWN', 'ENETUNREACH', 'EHOSTDOWN', 'EHOSTUNREACH', 'EPIPE', 'UND_ERR_SOCKET'].
The default retry strategy computes the delay before the next attempt as
minTimeout * timeoutFactor ** (counter - 1), capped at maxTimeout. When a
Retry-After header is present it takes precedence (interpreted as seconds, or as
an HTTP date), still capped at maxTimeout. The default strategy stops retrying
once counter exceeds maxRetries, when the error code is not in errorCodes,
when the method is not in methods, or when the response status code is not in
statusCodes.
RetryContext
state{RetryState} The current retry state. SeeRetryState.opts{DispatchOptions} The dispatch options passed to the handler, including the resolvedretryOptions. Type isDispatchOptions & { retryOptions?: RetryOptions }.
The context object passed as the second argument to the retry callback.
RetryState
counter{number} The current retry attempt, starting at1for the first retry.
Represents the retry state for a given request.
Parameter: RetryHandlers
dispatch{Function} The dispatch function called to (re-)issue the request on every attempt. Type is(options, handler) => boolean.handler{DispatchHandler} The inner handler invoked once the request succeeds or the retries are exhausted.
Examples
import { Client, RetryHandler } from 'undici'
const client = new Client(`http://localhost:${server.address().port}`)
const chunks = []
const handler = new RetryHandler(
{
...dispatchOptions,
retryOptions: {
// Custom retry decision function.
retry (err, { state, opts }, callback) {
if (err.code === 'UND_ERR_DESTROYED') {
callback(err)
return
}
if (err.statusCode === 206) {
callback(err)
return
}
setTimeout(() => callback(null), 1000)
}
}
},
{
dispatch (...args) {
return client.dispatch(...args)
},
handler: {
onRequestStart () {},
onResponseStart (controller, status, headers) {
// Do something with the response headers.
},
onResponseData (controller, chunk) {
chunks.push(chunk)
},
onResponseEnd () {},
onResponseError (controller, err) {
// Handle the error.
}
}
}
)
client.dispatch(dispatchOptions, handler)
A minimal handler that relies entirely on the default retry options:
import { Client, RetryHandler } from 'undici'
const client = new Client(`http://localhost:${server.address().port}`)
const handler = new RetryHandler(dispatchOptions, {
dispatch: client.dispatch.bind(client),
handler: {
onRequestStart () {},
onResponseStart (controller, status, headers) {},
onResponseData (controller, chunk) {},
onResponseEnd () {},
onResponseError (controller, err) {}
}
})
client.dispatch(dispatchOptions, handler)