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>
6.8 KiB
RoundRobinPool
Stability: 2 - Stable
A pool of Client instances connected to the same upstream target that
selects clients in a round-robin fashion.
Unlike Pool, which always reuses the first available client,
RoundRobinPool cycles through its clients so that requests are distributed
evenly across every open connection. This is useful when the upstream target is
fronted by a load balancer that distributes TCP connections across multiple
backend servers (for example, a Kubernetes Service): each connection is pinned
to a backend by the load balancer, and RoundRobinPool spreads requests across
those connections so every backend receives a comparable share of traffic.
Requests are not guaranteed to be dispatched in the order they were invoked.
import { RoundRobinPool } from 'undici'
const pool = new RoundRobinPool('http://localhost:3000', { connections: 10 })
RoundRobinPool distributes HTTP requests evenly across TCP connections, not
across backend servers directly. Even backend distribution therefore depends on
the load balancer assigning different connections to different backends (for
example, round-robin, random, or least-connections without client affinity). If
the load balancer pins all connections from one source to the same backend (for
example, source-IP affinity or sticky sessions), consider BalancedPool
with the individual backend addresses instead.
Class: RoundRobinPool
- Extends: {Dispatcher}
new RoundRobinPool(url[, options])
url{URL|string} The upstream target. It should only include the protocol, hostname, and port.options{RoundRobinPoolOptions} (optional)
Parameter: RoundRobinPoolOptions
Extends: {ClientOptions}
factory{Function} A function used to create the underlying {Client} instances. Default:(origin, opts) => new Client(origin, opts).origin{URL}opts{Object}- Returns: {Dispatcher}
connections{number|null} (optional) The maximum number of {Client} instances to create. When set tonull, theRoundRobinPoolinstance creates an unlimited number of {Client} instances. Default:null.clientTtl{number|null} (optional) The amount of time, in milliseconds, before a {Client} instance is removed from theRoundRobinPooland closed. When set tonull, {Client} instances are not removed or closed based on age. Default:null.
RoundRobinPool inherits all Client options. A Client instance is
created lazily on the first dispatch and additional instances are created on
demand, up to connections, when every existing client is busy.
roundRobinPool.closed
- Type: {boolean}
true after roundRobinPool.close() has been called.
roundRobinPool.destroyed
- Type: {boolean}
true after roundRobinPool.destroy() has been called, or after
roundRobinPool.close() has been called and the pool shutdown has completed.
roundRobinPool.stats
- Type: {PoolStats}
Aggregate connection statistics for the pool. See PoolStats.
roundRobinPool.close([callback])
Closes the pool and gracefully waits for enqueued requests to complete before
resolving. Implements [dispatcher.close([callback])][].
roundRobinPool.destroy([error[, callback]])
Destroys the pool abruptly. All pending and running requests are aborted with
the given error. Implements [dispatcher.destroy([error[, callback]])][].
roundRobinPool.connect(options[, callback])
Starts two-way communications with the requested resource using
HTTP CONNECT. See [dispatcher.connect(options[, callback])][].
roundRobinPool.dispatch(options, handler)
Dispatches a request through the next client selected in round-robin order.
Implements [dispatcher.dispatch(options, handler)][].
roundRobinPool.pipeline(options, handler)
For easy use with [stream.pipeline][]. See
[dispatcher.pipeline(options, handler)][].
roundRobinPool.request(options[, callback])
Performs an HTTP request. See [dispatcher.request(options[, callback])][].
roundRobinPool.stream(options, factory[, callback])
A faster version of [roundRobinPool.request()][]. See
[dispatcher.stream(options, factory[, callback])][].
roundRobinPool.upgrade(options[, callback])
Upgrades a connection to a different protocol. See
[dispatcher.upgrade(options[, callback])][].
Event: 'connect'
See [Dispatcher Event: 'connect'][].
Event: 'disconnect'
See [Dispatcher Event: 'disconnect'][].
Event: 'drain'
See [Dispatcher Event: 'drain'][].
Example
import { RoundRobinPool } from 'undici'
const pool = new RoundRobinPool('http://localhost:3000', {
connections: 10
})
// Requests are distributed evenly across all 10 connections.
for (let i = 0; i < 100; i++) {
const { body } = await pool.request({
path: '/api/data',
method: 'GET'
})
console.log(await body.json())
}
await pool.close()
[dispatcher.close([callback])]: Dispatcher.md#dispatcherclosecallback-promise
[dispatcher.connect(options[, callback])]: Dispatcher.md#dispatcherconnectoptions-callback
[dispatcher.destroy([error[, callback]])]: Dispatcher.md#dispatcherdestroyerror-callback-promise
[dispatcher.dispatch(options, handler)]: Dispatcher.md#dispatcherdispatchoptions-handler
[dispatcher.pipeline(options, handler)]: Dispatcher.md#dispatcherpipelineoptions-handler
[dispatcher.request(options[, callback])]: Dispatcher.md#dispatcherrequestoptions-callback
[dispatcher.stream(options, factory[, callback])]: Dispatcher.md#dispatcherstreamoptions-factory-callback
[dispatcher.upgrade(options[, callback])]: Dispatcher.md#dispatcherupgradeoptions-callback
[roundRobinPool.request()]: #roundrobinpoolrequestoptions-callback
[stream.pipeline]: https://nodejs.org/api/stream.html#streampipelinesource-transforms-destination-callback
[Dispatcher Event: 'connect']: Dispatcher.md#event-connect
[Dispatcher Event: 'disconnect']: Dispatcher.md#event-disconnect
[Dispatcher Event: 'drain']: Dispatcher.md#event-drain