Echtzeit & Presence
Eviworx hält geöffnete Flächen aktuell, ohne dass jemand neu laden muss: eine Liste zeigt ein neues Ticket, ein Detail übernimmt die Statusänderung eines Kollegen, und am Vorgang stehen die Namen derjenigen, die ihn gerade offen haben. Diese Seite beschreibt, was davon sichtbar ist, welche Idee dahintersteht und wie es technisch funktioniert.
Was Anwender sehen
| Fläche | Verhalten |
|---|---|
| Detailseite eines Vorgangs | Oben stehen die Betrachter: Avatar und Name jeder Person, die denselben Vorgang offen hat. Tippt jemand in ein Feld, wird daraus ein Bearbeitungs-Hinweis — zwei Leute, die gleichzeitig antworten wollen, merken es VORHER. |
| Listen und Arbeitsvorräte | Eine neue, geänderte oder gelöschte Zeile lädt die Liste nach — ebenso die Zähler an Tabs und Pillen. Was der Betrachter nicht sehen darf, löst keine Aktualisierung aus. |
| Benachrichtigungen | Die Glocke zählt ohne Neuladen in beide Richtungen: eine neue Benachrichtigung erhöht den Zähler, und wer in einem Fenster liest oder löscht, sieht den Stand auch in allen anderen sinken. Eine Entscheidung in der Genehmigungs-Inbox aktualisiert Inbox- und Aufgaben-Zähler ebenso in allen offenen Fenstern. |
| Fremde Änderung am offenen Vorgang | Der Inhalt zieht nach, und eine kurze Meldung nennt die Änderung. Wer sie selbst ausgelöst hat, sieht keine Meldung — auch dann nicht, wenn das System im selben Moment eine Folge daraus zieht (etwa eine SLA-Pause). |
| Sub-Ticket eines offenen Elterntickets | Wird ein Sub-Ticket fertig oder wieder geöffnet, zieht ein offenes Elternticket nach: seine Sub-Ticket-Liste, die Zähler und die SLA-Anzeige. Holt ein wieder geöffnetes Sub-Ticket das Elternticket aus „fertig" zurück, wandert dessen Status mit. Einzelheiten zur Beziehung: Tickets-API. |
| Eingeschränkte Verknüpfungen | Eine Verknüpfung, die nur als Platzhalter erscheint, aktualisiert sich bewusst nicht live: der Platzhalter verrät nichts über den Inhalt, und der Live-Kanal soll es auch nicht. |
| NOC-Wallboard | Das Wallboard lebt vollständig aus diesem Kanal — es ist für den Dauerbetrieb auf einem Bildschirm gedacht. |
Die Idee
Drei Entscheidungen prägen das Verhalten — sie erklären auch, warum manches bewusst NICHT passiert:
- Benachrichtigen statt fragen. Eine Fläche, die alle 30 Sekunden nachfragt, erzeugt Last auch dann, wenn sich nichts ändert — und hinkt trotzdem bis zu 30 Sekunden nach. Der Server sagt stattdessen Bescheid, wenn etwas passiert ist.
- Der Kanal trägt keine Daten. Eine Nachricht sagt „an diesem Objekt hat sich etwas geändert" und welche Felder betroffen sind — den Inhalt lädt die Oberfläche über die normale, rechtegeprüfte API nach. Damit verrät ein Echtzeit-Kanal strukturell höchstens so viel wie ein REST-Aufruf.
- Die eigene Tat ist keine Nachricht. Jede Meldung trägt den Verursacher. Wer die Änderung selbst ausgelöst hat, bekommt den Inhalt aktualisiert, aber keinen Hinweis darauf — er weiß es ja. Andere Betrachter sehen den Hinweis unverändert.
Wie es funktioniert
Die Verbindung läuft über eine WebSocket-Sitzung (Socket.IO), die Traefik unter /socket.io/ an das Backend durchreicht. Sie wird mit derselben Sitzung authentifiziert wie die REST-Aufrufe — es gibt keinen zweiten Anmeldeweg. Darauf liegen zwei Arten von Kanälen:
| Kanal | Gilt für | Inhalt der Nachricht |
|---|---|---|
| Objekt-Kanal | ein einzelner Vorgang — betreten wird er, wenn jemand die Detailseite öffnet | entityType, entityId, event (erstellt, geändert, zugewiesen, gelöscht, wiederhergestellt), der Verursacher und die geänderten Feldnamen |
| Listen-Kanal | eine ganze Objektart — betreten wird er von Listen, Zählern und Dashboards | bewusst OHNE Objekt-ID und ohne Nutzdaten: nur „in dieser Art hat sich etwas geändert". Ein Nutzer mit eingeschränkter Sicht erfährt damit nichts über fremde Zeilen, und die Liste lädt einfach neu. |
Rechte: jeder Kanal trägt die Sicht seiner Objektart
Für jede der 18 Objektarten ist hinterlegt, welche Rechte den Listen-Kanal öffnen und welche Zeilen-Sicht den Objekt-Kanal öffnet. Diese Zeilen-Sicht ist dieselbe, die Liste, Detailseite und globale Suche verwenden — einschließlich Asset-Typ-Sperren, Postfach- und Gruppenzuschnitt, Vertretungsregeln und der Freigaben eines Wissensartikels.
- Führen mehrere Übersichten mit verschiedenen Rechten auf dieselbe Objektart, öffnet jedes dieser Rechte den Listen-Kanal — der Kanal folgt der Vereinigung dieser Übersichten, nicht einer einzelnen davon. Nutzer-Zeilen erreichen so auch eine Datenschutz-Rolle, die den Lösch-Rückstand einsehen darf, ohne die vollständige Benutzerliste zu sehen.
- Ohne Sicht auf ein Objekt bekommt der Client beim Betreten eine Ablehnung statt einer Betrachter-Liste.
- Ein Sammel-Abonnement (eine Liste abonniert viele Zeilen auf einmal) filtert unsichtbare Objekte still heraus.
- Eine unbekannte Objektart wird abgelehnt, und ein Abonnement umfasst höchstens 500 Objekte — dieselbe Obergrenze wie eine Listen-Seite.
- Name und Avatar eines Betrachters kommen immer aus der Datenbank, nie aus der Nachricht des Clients.
- Der Kontostatus schlägt den Sitzungszustand: Wird ein Konto gesperrt oder archiviert, trennt der Server dessen offene Verbindungen sofort, und ein Verbindungsaufbau wird mit „Konto deaktiviert" abgewiesen — derselbe Status beantwortet einen API-Aufruf mit 403 ACCOUNT_DEACTIVATED. Ein offener Tab erhält damit keine Live-Daten mehr, auch nicht bis zum Sitzungsende.
- Dasselbe gilt für die Rolle: Wird eine Rolle deaktiviert, verlieren alle Konten mit dieser Rolle ihren Zugang — offene Verbindungen werden getrennt, obwohl die Konten selbst aktiv bleiben. Andernfalls liefe der Live-Kanal weiter, während jeder API-Aufruf bereits abgewiesen wird.
Betrachter-Zustand
Wer eine Detailseite offen hat, ist „betrachtend"; tippt er in ein Feld, wird er „bearbeitend"; bleibt er untätig, wird er „untätig". Der Zustand liegt in Redis mit einer Lebensdauer von fünf Minuten und wird durch ein regelmäßiges Lebenszeichen der Oberfläche erneuert. Ein abgestürzter Browser oder ein geschlossenes Notebook verschwindet deshalb von selbst aus der Liste; ein Aufräum-Job ist nicht nötig.
Bündelung kurz aufeinanderfolgender Änderungen
Eine Mutation löst oft mehrere Folgen aus — ein Statuswechsel pausiert eine SLA-Frist, eine Verknüpfung verändert beide Seiten. Nachrichten zum selben Objekt innerhalb von 50 Millisekunden werden deshalb zu EINER zusammengefasst, mit der Vereinigung der geänderten Felder. Der Verursacher bleibt dabei erhalten, auch wenn das System im selben Moment Folgeänderungen auslöst (etwa die SLA-Pause). So bekommt niemand eine Meldung über seine eigene Änderung.
Welche Objektarten wie viel Echtzeit haben
Beide Kanäle stehen für achtzehn Objektarten bereit, aber nicht jede Fläche nutzt beide. Die Betrachter-Anzeige setzt eine Detailseite voraus, die den Objekt-Kanal betritt — Listen und Zähler brauchen nur den Listen-Kanal.
| Umfang | Objektarten |
|---|---|
| Betrachter-Anzeige und Live-Detail | TICKET · INCIDENT · PROBLEM · CHANGE · ASSET · CONTRACT · LICENSE · KB |
| Live-Aktualisierung von Listen und Zählern | zusätzlich CHANGE_TEMPLATE · ASSET_TYPE · ELIBRARY · ABSENCE · COST_CENTER · USER · AGENT_GROUP · INVENTORY_SESSION · WORKFLOW · SAVED_VIEW |
In der zweiten Gruppe ziehen Übersichten und Zähler nach, es gibt dort aber keine Betrachter-Avatare — die eLibrary etwa hat keine Detailfläche, die sie zeigen könnte. Ihr Kanal umfasst Dokumente, Sammlungen und Kategorien unter einer Objektart. Gespeicherte Ansichten laufen über dieselben beiden Kanäle: Auswahlliste, Seitenleiste und Trefferzähler ziehen darüber nach, ohne regelmäßig nachzufragen.
Betrieb
- Gateway: Traefik reicht /socket.io/ an das Backend durch (WebSocket-Upgrade). Ein Reverse Proxy davor muss das Upgrade ebenfalls zulassen, sonst fällt die Verbindung auf Long-Polling zurück oder bleibt aus.
- Redis: trägt den Betrachter-Zustand. Ist Redis weg, verschwinden die Avatare — die Anwendung bleibt benutzbar, nur ohne Live-Komfort.
- Kein Ersatz für die API: Der Kanal ist ein Hinweis-Kanal für die Oberfläche, keine Integrations-Schnittstelle. Für eigene Anbindungen sind die REST-Endpunkte der Weg; sie liefern dieselben Daten mit denselben Rechten.
- Mehrere Backend-Instanzen: Sitzungen sind an die Instanz gebunden, die sie angenommen hat. Wer das Backend horizontal skaliert, braucht Sticky Sessions am Gateway.
Verwandte Seiten
- Notifications — die Kanäle einer Benachrichtigung; der In-App-Weg nutzt dieselbe Verbindung
- Security — die Rechteprüfung der Echtzeit-Kanäle im Sicherheits-Zusammenhang
- Permissions & RBAC — die Rechte und Sichtbarkeitsregeln, auf denen die Kanal-Prüfung beruht
- Container-Architektur — Gateway-Routen und Redis im Zusammenspiel