Wie strukturiere ich die Daten, die vom Server an den Benutzer gesendet werden?
Verwenden Sie das Nachrichtenmuster . Nun, Sie verwenden bereits ein Nachrichtenprotokoll, aber ich meine, strukturieren Sie die Änderungen als Nachrichten ... speziell als Ereignisse. Wenn sich die Serverseite ändert, führt dies zu Geschäftsereignissen. In Ihrem Szenario interessieren sich Ihre Kundenansichten für diese Ereignisse. Die Ereignisse sollten alle Daten enthalten, die für diese Änderung relevant sind (nicht unbedingt alle Ansichtsdaten). Die Client-Seite sollte dann die von ihr verwalteten Teile der Ansicht mit den Ereignisdaten aktualisieren.
Wenn Sie beispielsweise einen Börsenticker aktualisieren und AAPL ändern, möchten Sie nicht alle Aktienkurse oder sogar alle Daten zu AAPL (Name, Beschreibung usw.) nach unten drücken. Sie würden nur AAPL, das Delta und den neuen Preis drücken. Auf dem Client würden Sie dann nur diesen Aktienkurs in der Ansicht aktualisieren.
Soll ich nur Ereignisse wie "Diese Ressource wurde aktualisiert und Sie sollten sie über einen AJAX-Aufruf neu laden" senden oder die aktualisierten Daten übertragen und frühere Daten ersetzen, die über erste AJAX-Aufrufe geladen wurden?
Ich würde auch nicht sagen. Wenn Sie das Ereignis senden, senden Sie relevante Daten (nicht die Daten des gesamten Objekts). Geben Sie ihm einen Namen für die Art des Ereignisses. (Die Benennung und die für dieses Ereignis relevanten Daten liegen außerhalb des Bereichs der mechanischen Funktionsweise des Systems. Dies hat mehr mit der Modellierung der Geschäftslogik zu tun.) Ihre Ansichtsaktualisierer müssen wissen, wie sie die einzelnen Ereignisse in das jeweilige Ereignis übersetzen eine genaue Ansichtsänderung (dh nur aktualisieren, was sich geändert hat).
Wie definiere ich ein kohärentes und skalierbares Gerüst für gesendete Daten? Handelt es sich um eine Modellaktualisierungsmeldung oder um eine Meldung, dass ein Fehler mit blahblahblah aufgetreten ist?
Ich würde sagen, dies ist eine große, offene Frage, die in mehrere andere Fragen unterteilt und separat gestellt werden sollte.
Im Allgemeinen sollte Ihr Back-End-System Ereignisse für wichtige Ereignisse in Ihrem Unternehmen erstellen und auslösen. Diese können von externen Feeds oder von Aktivitäten im Back-End selbst stammen.
Wie kann man nicht von überall im Backend Daten über alles senden?
Verwenden Sie das Publish / Subscribe-Muster . Wenn Ihr SPA eine neue Seite lädt, die Echtzeitaktualisierungen erhalten möchte, sollte die Seite nur die Ereignisse abonnieren, die sie verwenden kann, und die Aktualisierungslogik für die Ansicht aufrufen, sobald diese Ereignisse eintreten. Möglicherweise muss die Pub / Sub-Logik aktiviert sein der Server, um die Netzwerklast zu reduzieren. Es gibt Bibliotheken für Websocket Pub / Sub, aber ich bin mir nicht sicher, was diese im Rails-Ökosystem sind.
Wie kann die Duplizierung der Geschäftslogik sowohl auf der Server- als auch auf der Clientseite reduziert werden?
Es hört sich so an, als müssten Sie die Ansichtsdaten sowohl auf dem Client als auch auf dem Server aktualisieren. Vermutlich benötigen Sie die serverseitigen Ansichtsdaten, damit Sie einen Schnappschuss haben, um den Echtzeit-Client zu starten. Da es sich um zwei Sprachen / Plattformen handelt (Ruby und Javascript), muss die Ansichtsaktualisierungslogik in beiden Sprachen geschrieben werden. Abgesehen von der Transpilation (die ihre eigenen Probleme hat) sehe ich keinen Ausweg.
Technischer Punkt: Datenmanipulation (Ansichtsaktualisierung) ist keine Geschäftslogik. Wenn Sie Use-Case-Validierung meinen, dann scheint dies unvermeidbar, da die Validierungen des Clients für eine gute Benutzererfahrung erforderlich sind, aber letztendlich vom Server nicht als vertrauenswürdig eingestuft werden können.
So sehe ich so etwas gut strukturiert.
Kundenansichten:
- Fordert einen Ansichtsschnappschuss und die Nummer des zuletzt gesehenen Ereignisses der Ansicht an
- Dadurch wird die Ansicht vorab ausgefüllt, sodass der Client nicht von Grund auf neu erstellen muss.
- Könnte der Einfachheit halber über HTTP GET erfolgen
- Stellt eine Websocket-Verbindung her und abonniert bestimmte Ereignisse, beginnend mit der letzten Ereignisnummer der Ansicht.
- Empfängt Ereignisse über das Websocket und aktualisiert seine Ansicht basierend auf Ereignistyp / -daten.
Client-Befehle:
- Datenänderung anfordern (HTTP PUT / POST / DELETE)
- Antwort ist nur Erfolg oder Misserfolg + Fehler
- (Die durch die Änderung erzeugten Ereignisse werden über den Websocket übertragen und lösen eine Ansichtsaktualisierung aus.)
Die Serverseite könnte tatsächlich in mehrere Komponenten mit begrenzten Verantwortlichkeiten aufgeteilt werden. Eine, die nur die eingehenden Anforderungen verarbeitet und Ereignisse erstellt. Ein anderer kann Client-Abonnements verwalten, auf Ereignisse warten (etwa in Bearbeitung) und entsprechende Ereignisse an Abonnenten weiterleiten. Sie könnten ein Drittel haben, das Ereignisse abhört und serverseitige Ansichten aktualisiert - möglicherweise geschieht dies sogar, bevor Abonnenten die Ereignisse empfangen.
Was ich beschrieben habe, ist eine Form von CQRS + Messaging und eine typische Strategie zur Lösung der Probleme, mit denen Sie konfrontiert sind.
Ich habe Event Sourcing nicht in diese Beschreibung aufgenommen, da ich nicht sicher bin, ob Sie es übernehmen möchten oder ob Sie es unbedingt brauchen. Aber es ist ein ähnliches Muster.