Seit wir das Deployment-Feature in Structr 2.1 eingeführt haben, ist unsere Produktivität stetig gestiegen.
Die Möglichkeit, schnell eine komplett emtpy Structr-Instanz aufzusetzen und eine bestehende Anwendung ohne die Benutzerdaten zu deployen, hat sich als sehr bequemer und schneller Weg erwiesen, neue Features zu testen/entwickeln. Ganz zu schweigen von den anderen Vorteilen wie Versionskontrolle, Erleichterung der Arbeit mit mehreren Entwicklern und so weiter…
Mit der zunehmenden Größe der Structr-Anwendungen und den wachsenden Nutzerdaten kam es jedoch zu einem drastischen Anstieg der Bereitstellungszeiten, wenn es darum ging,
neue Versionen einer Structr-Anwendung in die Live-Umgebung zu übertragen. Eine Anwendung benötigte satte 60 Minuten (!) für den Import – zugegebenermaßen auf einem etwas schwachen Server, aber immer noch eine völlig inakzeptable Ausfallzeit für eine Anwendung.
Also beschloss ich zu untersuchen, ob die Bereitstellungszeiten verbessert werden könnten – mit erstaunlichen Ergebnissen.
Die Untersuchung
Durch die Verwendung von jstack, um Stack Traces einer Structr-Instanz während eines Deployment-Imports zu erfassen, wurde mir schnell klar, dass die langsamen Geschwindigkeiten durch
eine Kombination von Structrs Kernfunktionen verursacht wurden: Kardinalitätserzwingung und Sicherheit.
Durchsetzung der Kardinalität
Im Schema-Editor können die Kardinalitätsregeln für Beziehungen definiert werden.
Im Wesentlichen gibt es vier Möglichkeiten: OneToOne, OneToMany, ManyToOne und ManyToMany. Jedes Mal, wenn eine Beziehung erstellt wird, prüft Structr, ob die Kardinalitätsregeln verletzt werden.
Sicherheit
Jedes Mal, wenn ein Knoten erstellt wird, werden zwei Beziehungen erstellt. Eine Beziehung, die den Eigentümer identifiziert, und eine, die die Erstellerrechte für den Knoten gewährt. Beide Beziehungen verweisen auf den Benutzer, der den Knoten erstellt hat.
Die Kardinalität ist OneToMany für die Eigentümerschaft (ein Knoten kann genau einen Eigentümer haben und ein Benutzer kann viele Knoten besitzen) und ManyToMany für Sicherheitszuschüsse (ein Benutzer kann mehrere Sicherheitszuschüsse haben und ein Knoten kann ebenfalls mehrere Sicherheitszuschüsse haben).
Das Problem
Wie man wahrscheinlich sehen kann, führt die Erstellung vieler Knoten (wie bei der Erstellung von Seiten) zu einer Vielzahl von Beziehungen zu dem Benutzerkonto, das man verwendet – wahrscheinlich der Benutzer „admin“.
Da Sicherheitsberechtigungen für die unterschiedliche Darstellung von Seiten für verschiedene Benutzer unerlässlich sind, müssen diese Beziehungen in den Deployment-Export aufgenommen werden, wenn man
die Anwendung auf eine andere Instanz übertragen möchte. Und genau hier liegt das Problem – beim Importieren eines Deployment-Exports müssen wir prüfen, ob die Beziehungen die Kardinalitätsregeln verletzen.
Wenn ein Knoten sehr viele Beziehungen dieses Typs hat, dauert die Prüfung eine Weile (und wird immer langsamer, je mehr Beziehungen angehängt werden).
Für OneToOne, OneToMany und ManyToOne gab es eine intelligente Strategie: Prüfen Sie immer von der Seite der Beziehung aus, die den „One“-Teil darstellt, da es nur eine
Beziehung geben kann. Für ManyToMany funktioniert diese Optimierung nicht, da beide Enden viele Beziehungen haben können. Diese Richtung war zufällig von der Quelle zum Ziel.
In unserem speziellen Fall war dies ein Problem, weil dies während der Bereitstellung die Richtung Benutzer->Knoten war und der Benutzer der Knoten mit der ständig wachsenden Anzahl von Beziehungen war.
Die Lösung
Die Lösung war so einfach wie die Umkehrung der Prüfrichtung von „Quelle zu Ziel“ zu „Ziel zu Quelle“. Dies funktioniert, weil die Prüfung zum Zeitpunkt der Erstellung erfolgt und zu diesem Zeitpunkt
der Benutzer bereits viele Beziehungen haben kann und der zuvor erstellte Knoten+Beziehung nur eine Handvoll Beziehungen haben kann.
Mit diesem Ansatz konnte die Bereitstellungszeit (für diese spezielle Anwendung) von etwa 60 Minuten auf etwa 3 Minuten reduziert werden.
Die Bereitstellung dieser Anwendung in einer leeren Datenbank dauerte vorher etwa 300 Sekunden und dauert jetzt etwa 100 Sekunden. Eine allgemeine Faustregel lautet: Je mehr Daten in der Datenbank vorhanden sind, die für einen Benutzer/eine Gruppe im Bereitstellungsexport gewährt werden, desto mehr Zeit wird mit dem neuen Ansatz eingespart.
Eine weitere Sache
Wir haben die Dinge weiter verbessert! In neueren Versionen haben wir ein Flag zum Typ User hinzugefügt, das für Admin-Benutzer gesetzt werden kann. Wenn dieses Flag gesetzt ist, legt Structr keine Beziehungen für Eigentum und Sicherheit (für diesen Benutzer) an, was die Geschwindigkeit erhöht und auch die Exporte bereinigt. Öffnen Sie einfach den Dialog „Eigenschaften bearbeiten“ für den Benutzer im Bereich „Sicherheit“ und suchen Sie nach „Sicherheitsbeziehungen überspringen“.