Skip to content

Architektur

Julian Schoemaker edited this page Aug 27, 2018 · 6 revisions

Architektur

Aufgaben

Dienstnutzer

  • Ein Command Line Interface
  • User Login wird "zwischengespeichert"
  • Bündelt REST Befehle zusammen (falls nötig)

bsp. Um einem Event beizutreten muss nur noch ein Befehl ausgeführt werden anstelle von GET events/ + POST events/(id)/users

  • Versteckt POST Befehle hinter leicht nachvollziehbaren switch-case Abfragen
  • Empfangen von Notifications über Faye
  • Handeln von Subscriptions auf bestimmte Faye - Channels

bsp. Ein User, der Teil eines bestimmten Events ist, bekommt eine Nachricht sobald die Shoppingliste dieses Events fertiggestellt ist

Dienstgeber

  • Klar definierte REST Schnittstelle
  • Nimmt REST Befehle entgegen
  • Speichert Daten in / liest Daten aus Firestore
  • Handelt das Matching der "Wishes" zu "Shoppinglists"
  • Dient als Faye - Server und published nachrichten bei dem Erstellen einer Shoppingliste

Interner Aufbau

Sowohl der Dienstnutzer als auch der Dienstgeber wurde in Node.js implementiert.

Dienstnutzer

Command Line Interface

Wir haben uns dafür entschieden den Dienstnutzer als ein Command Line Interface zu implementieren. Rückblickend hätten wir dies nicht in Node.js tun sollen. Node.js ist darauf ausgelegt mehrere Ereignisse gleichzeitig zu verarbeiten und dies in einem sehr asynchronen Stil. Ein Command Line Interface ist rein sequenziell und somit nur sehr begrenzt kompatibel mit Node.js. Wir haben für die Entwicklung der Ein- und Ausgabe auf der Commandline das Modul “Readline-sync” verwendet. Nach viel ausprobieren und einer Vielzahl von nicht-nachvollziehbaren Verhalten haben wir festgestellt, dass readline-sync während der Ein- und Ausgabe alle Pending-Promises blockiert. Es sorgt somit dafür das Promises für lange Zeit nicht “resolved” werden. Um diese Blockade zu umgehen, mussten wir im Dienstnutzer bei jedem Erstellen eines Promises auf das Result warten. Dies macht den Code teilweise sehr verschachtelt und zudem arbeiten wir so genau gegen die Kernidee von Node.js.

Cluster und Faye

Als wir dann zu der Implementierung von Faye kamen gab es ein weiteres Problem: “Wie können wir asynchrone Nachrichten in ein rein sequenzielles Commandline Interface implementieren?” Die Lösung hierfür ist ein wenig unkonventionell aber funktioniert einwandfrei. “Cluster” ist ein Node Module was für Process Optimierung auf Serverseite gedacht ist. Es ermöglicht Multi-Threading und implementiert ein Funktion “fork()” die der gleichnamigen Funktion in der Programmiersprache C sehr ähnlich ist.

console.log("start of script");

if(cluster.isMaster){
   cluster.fork();
   //This is the Master Thread
}else{
   //This is the Child/Worker Thread
}

Nach dem Aufruf von fork() laufen zwei Instanzen des Scriptes, die mit der Variable “isMaster” unterschieden werden können. Eine Limitierung des Cluster Modules ist, dass nach dem Forken des Master Threads der Worker-Thread von der ersten Zeile des Skriptes beginnt und nicht direkt nach dem Aufruf von fork(). Somit wird z.B. in dem Code oben sowohl von dem Master als auch von dem Worker-Thread das console.log("start of script"); aufgerufen.

In unsere Implementierung verwenden wir Cluster, um das sequenzielle Commandline Interface gleichzeitig mit dem Erhalten von Faye-Benachrichtigungen realisieren zu können. Jedes mal wenn der Dienstnutzer eine neue Subscription aktiviert, wird über Cluster ein Prozess erstellt, der das Erhalten dieser Nachrichten handelt. In unserem Code geschieht dies an zwei Stellen: Nach dem Login subscribt der Dienstnutzer einmal allen Events denen der User angehört. Wenn ein User zur Laufzeit neuen Events beitritt wird diesen ebenfalls subscribt.

Forks

Da wir diese beiden Logik-Stränge in unterschiedlich Prozess aufteilen, können wir problemlos, wenn wir ein Faye Benachrichtigung erhalten, in die Standardausgabe schreiben, während der User im Dialog Baum des Commandline Interfaces arbeitet.

Dienstgeber

Der Dienstgeber ist in seinem internen Aufbau sehr viel simpler. HTTP Befehle werden über ein REST Schnittstelle mithilfe der Modules “Express” entgegengenommen. Die Befehle werden dann verarbeitet und es wird gegebenenfalls auf unseren externen Web Service Firebase zugegriffen. Im weiteren published der Dienstgeber mit Hilfe von Faye Benachrichtigungen, die die Shoppinglist eines gegebenen Events enthalten.