Konzepte
Wie Brio-IO aufgebaut ist: Channels und Connectoren, die Pipeline, kanonisches HL7v2-XML, Git als Konfigurationsquelle — und Branches mit Shadowing und Vergleich, inklusive ihrer heutigen Grenze.
Stand: Beispiele geprüft gegen brio-server fa237ec7ad
Dieses Kapitel erklärt die Bausteine, auf die alle anderen Kapitel verweisen. Es beschreibt den Stand, der heute läuft — nicht den Plan.
Channel und Connector
Ein Channel ist eine Verarbeitungsstrecke. Er hat einen Source-Connector, eine Kette von Verarbeitungsschritten und eine oder mehrere Destinations:
Source-Connector
↓
Filter (pro Nachricht: verarbeiten oder verwerfen)
↓
Transformer (Nachricht umschreiben)
↓
Destination-Connector(s)
Connectoren sind eigenständige Objekte, keine Unterfelder eines Channels.
Sie werden getrennt angelegt und im Channel referenziert — derselbe
http-listener kann so von mehreren Channels genutzt werden, und ein Connector
lässt sich unabhängig vom Channel testen und ändern.
Jeder Connector hat ein Protokoll (mllp-listener, file-reader,
http-sender, …) und einen Satz typisierter Properties. Welche Protokolle
es gibt und welche Properties sie kennen, steht in der
Connector-Referenz.
Die Nachricht durchläuft Stufen — und alle bleiben sichtbar
Brio-IO speichert eine Nachricht nicht nur in ihrem Endzustand, sondern in
Stufen: RAW (wie sie ankam), TRANSFORMED (nach Filter und Transformer),
SENT (was rausging). Dazu kommen Zustände, die sonst gerne unsichtbar bleiben:
FILTERED— eine Nachricht, die ein Filter verworfen hat. Sie erscheint als eigene Zeile, statt spurlos zu verschwinden.ERROR— die Verarbeitung ist gescheitert; der Grund steht in den Hinweisen zur Nachricht.SHADOW_SENT— die Nachricht lief in einem Shadow-Branch (siehe unten).
Jede Nachricht trägt außerdem eine Herkunft (origin), die sagt, aus
welchem Zweig sie stammt. Das ist der Grund, warum Shadow-Verkehr die Kennzahlen
des Live-Channels nicht verfälscht.
Kanonisches XML: eine Nachricht, eine Form
Sobald eine HL7v2-Nachricht hereinkommt, überführt Brio-IO sie in eine kanonische XML-Repräsentation. Skripte arbeiten auf dieser Form, nicht auf dem rohen ER7-String mit seinen Pipes und Zirkumflexen.
Zwei Eigenschaften dieser Form sind wichtig, weil beide historische Fehler korrigieren:
Underscores statt Punkte. In der klassischen Mirth-Welt heißt das Feld
PID.5 — und der Punkt ist in jeder Programmiersprache der Zugriffsoperator.
Deshalb muss man dort mit String-Brackets arbeiten. Brio-IO trennt die Ebenen
mit Underscore (PID_5), also sind Element-Namen normale Bezeichner.
Komponenten positional durchnummeriert. Eine Komponente heißt nach ihrer Position, nicht nach ihrem HL7-Datentyp:
<PID>
<PID_3>
<PID_3_1>12345</PID_3_1>
<PID_3_4>MRN</PID_3_4>
</PID_3>
<PID_5>
<PID_5_1>Schmidt</PID_5_1>
<PID_5_2>Hans</PID_5_2>
</PID_5>
</PID>
PID_5_1 ist der Nachname — Feld PID-5, Komponente 1. Genau die Nummerierung,
die HL7 beschreibt und die ein Mirth-Praktiker im Kopf hat.
Für Bestandsskripte wichtig: Eine Zwischenfassung von Brio-IO benannte Komponenten nach ihrem Datentyp (
PID_5→XPN_1→FN_1). Diese Pfade funktionieren heute nicht mehr — sie liefern still einen leeren String. Beim Deployment eines Channels warnt Brio-IO namentlich, wenn ein Skript noch solche Datentyp-Pfade enthält. Der Grund für die laute Warnung statt eines stillen Alias: zwei gleichzeitig gültige Schreibweisen waren genau das Problem, das dieser Umbau beendet hat.
Escape-Sequenzen (\S\, \T\, …) bleiben in der XML verbatim stehen. Wer
sie im Skript auflösen oder erzeugen will, nutzt escapeHl7/unescapeHl7 —
siehe Transformer-Handbuch.
Drei Skript-Engines, ein Satz Built-ins
Filter und Transformer sind Skripte. Brio-IO betreibt drei Engines parallel; die Engine wählst du pro Skript, nicht pro Channel:
| Engine | Kennung | Sprache | Rolle |
|---|---|---|---|
| Groovy | groovy | Apache Groovy | Standard für neue Skripte |
| GraalJS | js-modern | modernes JavaScript | für alle, die lieber JS schreiben |
| Rhino | js-legacy | JavaScript mit E4X | nur für importierte Mirth-Skripte |
Die Built-ins sind in allen Engines dieselben: msg, xml, channelMap,
sourceMap, responseMap, globalMap, globalChannelMap, tmp, logger,
xslt. Skripte werden beim Deployment kompiliert, nicht bei jeder
Nachricht.
Details und Beispiele: Transformer-Handbuch.
Git ist die Konfigurationsquelle
Die Konfiguration eines Brio-IO-Servers — Channels, Connectoren, Skripte, Code-Templates — liegt nicht in einer Datenbanktabelle, sondern in einem Git-Repository, das der Server selbst führt (eingebettetes JGit, ein optionales Remote ist möglich).
Das ist keine Kosmetik, sondern der Grund für mehrere Eigenschaften, die man sonst nachbauen müsste:
- Jede Änderung hat einen Commit. Wer, wann, was — ohne separates Audit-Feature.
- Zurückrollen heißt zurückrollen, nicht „Backup einspielen”.
- Branches sind echte Git-Branches — und damit die Grundlage des nächsten Abschnitts.
Wo das Repository liegt, steuert brio.config.git.local-path; siehe
Betrieb.
Branches: Shadowing und Vergleich
Eine Konfigurationsänderung ist in der Integration selten harmlos: Ein geänderter Transformer trifft echten Traffic, und ob er das Richtige tut, merkt man klassisch erst hinterher. Brio-IO adressiert das mit Branches.
Shadowing. Ein Branch kann den echten Traffic des laufenden Channels
beobachten und die Pipeline auf einer Live-Kopie ausführen — ohne ein
echtes Ziel anzurufen. Die Ergebnisse landen als SHADOW_SENT im
Message-Browser, sauber über origin vom Live-Verkehr getrennt.
Vergleich. Der Vergleich stellt Nachricht für Nachricht gegenüber, was
main und der Branch produziert haben, und fällt ein Urteil:
| Urteil | Bedeutung |
|---|---|
IDENTICAL | Branch erzeugt dasselbe Ergebnis wie main |
DIFFERENT | die Ergebnisse weichen ab — Seite an Seite ansehbar |
NO_PAYLOAD_STORED | der Channel speichert keine Payloads (Storage-Policy MINIMAL), ein inhaltlicher Vergleich ist deshalb nicht möglich |
Das letzte Urteil ist Absicht: Ein Channel, der aus Datenschutzgründen keine Payloads speichert, bekommt kein erfundenes „identisch”, sondern die ehrliche Auskunft, dass hier nichts zu vergleichen ist.
Beim Merge eines Branches schreibt Brio-IO eine Zusammenfassung nach
audit/branch-summaries/ in die Konfiguration auf main — inklusive einer
begrenzten Zahl konkreter Abweichungs-Beispiele (Standard: 20). Wird ein Branch
gelöscht, räumt Brio-IO seine Laufzeit-Routen und seine Datenzeilen ab.
Die heutige Grenze: kein Branch-Deploy
Einen branch-bezogenen Channel deployen kannst du heute nicht. Der Server lehnt das ab:
HTTP 409 Conflict
Branch deployment is not available while branches share the runtime context.
Validate branches via Shadowing; branch deploy becomes available with isolated
contexts.
In der Web-UI ist der Deploy-Schalter im Branch-Kontext deaktiviert und erklärt sich per Tooltip. Das ist kein Fehler. Der Grund ist konkret: Alle Branches teilen heute denselben Laufzeit-Kontext. Ein branch-bezogener Deploy würde deshalb die gemeinsame Route überschreiben — also den Live-Channel verändern, obwohl man glaubt, nur einen Branch zu testen. Lieber eine ehrliche Sperre als eine Funktion, die etwas anderes tut, als ihr Name verspricht.
Der Validierungsweg ist damit: Branch anlegen → Shadowing beobachten → vergleichen → mergen. Der isolierte Kontext je Branch, der den Branch-Deploy freischalten würde, ist in Arbeit.
Was Brio-IO heute nicht tut
Aus demselben Grund, aus dem der Branch-Deploy gesperrt ist, steht hier eine kurze, ehrliche Liste:
- Kein Channel-zu-Channel-Dispatch im Skript. Ein
router.routeMessage()wie in Mirth gibt es nicht; der Weg ist eine Destination am Channel. Der Mirth-Importer warnt genau darauf hin. - Kein LIVE-Modus für Branches (paralleler Echtbetrieb zweier Zweige).
- Kein öffentlicher Download. Brio-IO ist im Early Access; Zugänge werden persönlich eingerichtet.
Diese Seite gibt es bisher auf Deutsch und Englisch. Die spanische Fassung folgt.