Einige Operationen sind rechenintensiv und können Minuten oder Stunden dauern (Bulk-Export, Reindizierung von Suchparametern, vollständige Ressourcenrevalidierung). Ihre asynchrone Ausführung verhindert, dass der Client blockiert wird, und ermöglicht es dem Server, die Last zu steuern. In einem asynchronen Ablauf startet der Client den Job, der Server führt ihn im Hintergrund aus, und der Client fragt entweder den Status ab (Polling) oder erhält einen Callback, wenn der Job abgeschlossen ist.
FHIR bietet bereits asynchrone Unterstützung durch Bulk Data Access und das R5 Asynchronous Interaction Request-Muster. Sie teilen denselben Lebenszyklus:
-
Kick-off-Anfrage -> 202 Accepted mit Content-Location.
-
Statusanfrage (während der Ausführung) -> 202 Accepted mit Retry-After und optional X-Progress.
-
Optionaler Abbruch -> DELETE an die Status-URL gibt 202 Accepted zurück.
-
Terminalstatus -> entweder 200 OK (Nutzlast inline) oder 303 See Other (Weiterleitung zur Nutzlast).
Inline-Modi (Bundle, Bulk-Manifest) geben bei Abschluss stets 200 OK zurück; Erfolg oder Fehler werden durch die Nutzlast angezeigt (z. B. ein Ergebnis-Bundle gegenüber einem OperationOutcome oder Fehler-Links innerhalb eines Manifests). Der Redirect-Modus gibt die ursprünglichen synchronen Statuscodes bei der weitergeleiteten Anfrage zurück (z. B. 200/201 bei Erfolg, 4XX/5XX bei Fehler).
Die Muster unterscheiden sich hauptsächlich durch den Rahmen für die endgültige Nutzlast:
- Bulk Data Access gibt ein benutzerdefiniertes JSON-Manifest zurück.
- Asynchronous Interaction Request gibt ein FHIR Bundle zurück.
- Der Redirect-Modus gibt zurück, was die synchrone Interaktion zurückgegeben hätte (Parameters, Bundle, Binary usw.).
Dies stößt an Grenzen, wenn die Nutzlast nicht als Bundle ausgedrückt werden kann (z. B. bei Streaming-Ausgaben oder binären Inhalten).
Die R6-Arbeiten zielen darauf ab, Asynchronität über alle Interaktionen hinweg zu standardisieren. Jede Interaktion erlaubt nun 202 Accepted, und Joshs Entwurfsspezifikation schlägt ein zusätzliches Redirect-Muster vor: Die terminale Statusantwort ist 303 See Other mit einem Location-Header, der auf das Ergebnis zeigt; dieser Endpunkt gibt die eigentliche Nutzlast und ihren Status zurück.
Idealerweise lassen sich diese Muster zu einem einzigen parametrisierten Muster vereinheitlichen. Verwenden Sie Prefer: respond-async sowie ein benutzerdefiniertes Prefer-Token, um den Modus anzufordern. Aus Gründen der Abwärtskompatibilität ist der Standard bundle; wenn _outputFormat vorhanden ist, wird die Anfrage als Bulk behandelt und ein Manifest zurückgegeben (Server DÜRFEN einen widersprüchlichen async-mode mit 400 Bad Request ablehnen).
GET /fhir/[$operation] HTTP/1.1
Prefer: respond-async, async-mode=[redirect|bundle] # async-mode is a proposed extension token
Server SOLLTEN bestätigte Präferenzen über Preference-Applied zurückspiegeln.
Clients sollten davon ausgehen, dass unbekannte Prefer-Tokens ignoriert werden, und darauf vorbereitet sein, auf den Standard-Bundle-Modus zurückzufallen.
Wenn die Operation abgeschlossen ist:
-
async-mode=bundle: Der Server SOLLTE mit 200 OK und einem Bundle-Body antworten; Fehler verwenden eine OperationOutcome-Nutzlast. -
Parameter
_outputFormatvorhanden: Der Server SOLLTE mit 200 OK und einem Bulk-Manifest-Body antworten; Fehler werden über Manifest-Fehler-Links und/oder einen OperationOutcome-Eintrag angezeigt. -
async-mode=redirect: Der Server SOLLTE mit 303 See Other und einer Location-URL antworten, die auf das Ergebnis der Operation zeigt; die weitergeleitete Anfrage gibt dieselben Statuscodes wie die synchrone Interaktion zurück.
Clients können Abschluss und Modus anhand des Statuscodes (200 oder 303) ableiten; Erfolg oder Fehler hängen von der endgültigen Nutzlast oder dem Status der weitergeleiteten Antwort ab.
Erweiterungen
Im Folgenden finden Sie eine Liste zusätzlicher Erweiterungen, die zur Verbesserung der Unterstützung für asynchrone Operationen hinzugefügt werden können:
Long-Polling-Erweiterung
Server können Long Polling für Statusanfragen verwenden, um die Latenz zu minimieren. Der Server hält die Verbindung offen, bis die Operation abgeschlossen ist oder ein Timeout eintritt. Bei einem Timeout wiederholt der Client die Anfrage, und der Server steuert die Häufigkeit eingehender Statusanfragen. Long Polling reduziert unnötigen Polling-Verkehr und ermöglicht gleichzeitig eine schnelle Benachrichtigung, wenn sich der Zustand ändert (Abschluss oder Abbruch).
Callback-Erweiterung
Zweck: Dem Server ermöglichen, den Client zu benachrichtigen, wenn ein Job abgeschlossen ist, damit der Client das Polling pausieren oder beenden kann.
Motivation: Callbacks halten die Antwortlatenz niedrig, ohne aggressives Polling zu erfordern. Clients können auf langsame, kostengünstige Abfragen (oder keine) zurückschalten und erhalten dennoch nahezu in Echtzeit eine Benachrichtigung, wenn der Job abgeschlossen ist.
Ablauf:
-
Der Client fügt
callback-urlmitPrefer: respond-async(und optionalemasync-mode) ein. -
Wenn der Job abgeschlossen oder abgebrochen wird, sendet der Server ein POST an diese URL.
-
Wenn der Callback fehlschlägt oder nicht eintrifft, verlässt sich der Client auf Polling.
Beispiel-Kick-off mit Callback:
POST /fhir/$operation HTTP/1.1
Prefer: respond-async, async-mode=redirect, callback-url=https://example.com/callback
Accept: application/fhir+json
Content-Type: application/fhir+json
{ ...normal operation body... }
Nutzlast: Eine FHIR Parameters-Ressource, die Folgendes enthält:
-
status(completed | failed | cancelled) -
resultUrl(URL, die der Client für die endgültige Nutzlast abrufen kann) -
Optionaler OperationOutcome-Parameter, wenn der Job fehlgeschlagen ist
Zustellung: Best-Effort, keine Wiederholungsversuche; Callbacks sind ein Signal, nicht der primäre Zustellungskanal (Polling ist es). Callbacks SOLLTEN idempotent sein, damit Duplikate harmlos sind.
Sicherheit: Server SOLLTEN Callbacks authentifizieren (z. B. OAuth2 Bearer Token, mTLS oder HMAC).
Client-Verarbeitung: Mit 2XX bei Erfolg antworten; Nicht-2XX bedeutet lediglich, dass der Client weiter pollt.
Beispiel-Callback-Anfrage:
POST https://example.com/callback HTTP/1.1
Content-Type: application/fhir+json
Authorization: Bearer eyJhbGciOi...
{
"resourceType": "Parameters",
"parameter": [
{ "name": "status", "valueCode": "completed" },
{ "name": "resultUrl", "valueUrl": "https://fhir.example.com/whatever/path/1ab7162f-result" }
]
}
Beispiele für visuelle Abläufe
Im Folgenden finden Sie einige Beispiele für visuelle Abläufe der verschiedenen Modi.
Bulk-Manifest-Modus

Bundle-Modus

Redirect-Modus

Abbruchablauf

Callback-Modus

Haben Sie Fragen? Wenden Sie sich an unseren CTO
Wenn Sie weitere Fragen zu diesem Muster haben, wenden Sie sich direkt an unseren CTO, Nikolai Ryzhikov. Wir sprechen stets gern über FHIR und reale Implementierungen.
Siehe auch: Topic-based Subscriptions: Top 5 Use Cases und Building Healthcare Microservices.





