Anstehen Mendix Kann eine gute Sache sein
Schlangestehen wird häufig als Zeitverschwendung angesehen, egal ob Sie in der Schlange für den Bus/die Straßenbahn/den Zug nach Hause stehen, in der Schlange stehen, um Ihr Mittagessen zu bekommen, oder ob Sie in der Warteschleife warten, bis jemand im Kundenservice Ihren Anruf aus der Telefonwarteschlange entgegennimmt.Geben Sie hier Ihren bevorzugten Einzelhändler/Lieferanten ein>.
Kurz und Mendix app sind die meisten Aktionen einfädig, so dass beispielsweise die von Ihnen definierte Aktion am Anfang beginnt und am Ende endet und dazwischen die von Ihnen angegebenen Vorgänge in der angegebenen Reihenfolge abläuft. Dies hält die Dinge schön und einfach, da Sie sich nicht zu viele Gedanken darüber machen müssen, ob die von Ihnen definierten Vorgänge wie erwartet ausgeführt werden oder nicht, und wenn Sie Abhängigkeiten innerhalb Ihrer Aktion haben, können Sie diese klar erkennen.

Andererseits können Warteschlangen für Ihre App von Vorteil sein, da sie dazu verwendet werden können, die Ausführung eines Prozesses auf mehrere Threads und Knoten zu verteilen. Wenn Sie eine bestimmte Arbeit zu erledigen haben, können Warteschlangen Ihnen helfen, indem sie es Ihnen ermöglichen, verschiedene Teile der Arbeit gleichzeitig auszuführen, und der Prozess insgesamt weniger Zeit in Anspruch nimmt. Wie können Sie das also erreichen?
Dies ist der dritte in einer Reihe von Blogbeiträgen über Effizienz in Mendix Apps. Im ersten Teil der Serie (Gesundheit und Effizienz in Mendix) habe ich einige einfache Möglichkeiten hervorgehoben, mit denen Sie die Effizienz Ihres Low-Codes verbessern können, und im zweiten (In Mendix wie lang ist ein String?) habe ich gezeigt, wie der Einsatz von Java-Aktionen die Leistung in engen Kurven verbessern kann. Dieses Mal möchte ich veranschaulichen, wie Mendix Aufgabenwarteschlangen kann verwendet werden, um Ihre App effizienter zu machen.
Aufgabenwarteschlangen
Mendix Aufgabenwarteschlangen wurden in eingeführt Mendix 9 als moderner Ersatz für das Marktplatzmodul Process Queue, und ihre Funktionen sind gut dokumentiert. In diesem Beitrag werde ich einen bestimmten, einfachen Anwendungsfall betrachten und zeigen, wie ein Aufgabenwarteschlange kann sein wird verwendet, um die für die Durchführung des erforderlichen Prozesses erforderliche Zeit deutlich zu verkürzen.
Es gibt eine ausführliche Dokumentation über die Seite „Aufgabenwarteschlangen“ das deckt ab, was Sie tun können mit Aufgabenwarteschlangen, und wie es geht, einschließlich der neueren Funktionen wie der automatischen Wiederholung fehlgeschlagener Aufgaben und der Planung von Aufgaben, damit sie zu einem bestimmten Zeitpunkt ausgeführt werden. Ein wichtiger Punkt, den Sie beachten sollten, ist, dass Sie darauf achten müssen, keine Abhängigkeiten zwischen den „Unteraufgaben“ in Ihrem Prozess zu haben, es sei denn, Sie verwalten dies selbst – der hier gezeigte Beispielanwendungsfall hat einfache Abhängigkeiten und ich habe eine Möglichkeit entwickelt, dies zu kontrollieren.
Eine große Löschung

Meine App wird verwendet, um Daten aus definierten externen Datenquellen abzurufen wenn der Benutzer sie anfordert. Diese Daten werden einer einfachen Analyse unterzogen, sodass der Benutzer Entscheidungen darüber treffen kann, wie die Daten verwendet werden sollen. Wenn der Benutzer zufrieden ist und die anstehende Aufgabe erledigt hat, die Daten müssen gelöscht werden.
Eine Test-App wurde zusammengestellt, um zu veranschaulichen, wie ein Aufgabenwarteschlange kann den Löschvorgang beschleunigen: GitHub – Adrian-Preston/QueueingCanBeAGoodThing

In der anfänglichen Einrichtung wurde das Domänenmodell für die automatische Löschung konfiguriert, sodass beim Löschen des Quellobjekts automatisch alle zugehörigen Objekte im Baum gelöscht werden (hervorgehoben durch die rot umrandeten Zuordnungsfelder im Domänenmodell). Dies ist eine sichere Option, da dadurch verhindert wird, dass „verwaiste“ Objekte zurückbleiben. Außerdem bedeutet dies, dass der Entwickler einfach die Quelle löschen kann und alles andere folgt. Da es sich jedoch um einen Single-Thread-Vorgang handelt, kann dies einige Zeit dauern, wenn sich im Baum viele Daten befinden.

Da dies ein relativ einfaches Domänenmodell ist, ist es ziemlich einfach zu erkennen, dass wir Objekte für bestimmte Entitäten gleichzeitig problemlos löschen können. Daher sind ItemValue, ItemAttachment, ItemLink, AnalysedValue und AnalysedAttachment (Set eins) für eine bestimmte Quelle können gleichzeitig sicher gelöscht werden. Ebenso können Item und AnalysedItem (Set zwei) können gleichzeitig gelöscht werden, jedoch erst, nachdem die Datensätze in Set eins wurden alle gelöscht. Schließlich müssen Quelle, Dokumenttyp und Dokument in der richtigen Reihenfolge gelöscht werden, nachdem Set eins , Set zwei wurden gelöscht. Dies sind die Abhängigkeiten, die ich zuvor erwähnt habe.
Wie kann das also erreicht werden?
Auf der Benutzeroberfläche der App gibt es eine Seite, auf der die aktuell geladenen Quellen aufgelistet sind. Von dort aus identifiziert der Benutzer die zu löschende Quelle und klickt in dieser Zeile auf die Schaltfläche „Smart Delete Source“.

Dadurch wird ein Nanoflow mit der Bezeichnung „ACT_SmartDeletion“ aufgerufen, der zwei Hauptaufgaben hat: erstens den Löschvorgang im Hintergrund zu starten und zweitens zu warten, bis der Quelldatensatz aus der Datenbank verschwindet und damit anzeigt, dass die Aufgabe abgeschlossen ist.


Der Nanoflow ruft einen Microflow namens „SUB_StartSmartDeletion“ auf, der einen Sub-Microflow für jeden Entitätstyp in Set eins Diese werden jedoch jeweils aufgerufen, indem sie in eine Task-Warteschlange gestellt werden. Dies bedeutet, dass sie nicht direkt ausgeführt, sondern nur in die Warteschlange gestellt werden, sodass sie im Hintergrund ausgeführt werden.. Wir erstellen außerdem ein spezielles DeletionControl-Objekt für jeden der zu empfangenden Sub-Microflows – mehr dazu weiter unten. Wenn dieser Microflow beendet ist, kehrt er zum Nanoflow zurück.

Der Nanoflow beginnt dann eine Schleife, um zu prüfen, ob der Quelldatensatz noch in der Datenbank vorhanden ist. Während er dort ist, hält der Nanoflow kurz inne und prüft dann erneut. Wenn der Quelldatensatz nicht mehr in der Datenbank vorhanden ist, informiert der Nanoflow den Benutzer darüber und schließt ab.
Jeder der fünf Sub-Mikroflows ist gleich (bis auf einen mit etwas zusätzlichem Code). Der Sub-Mikroflow löscht alle Datensätze für die Quelle eines bestimmten Entitätstyps und löscht dann abschließend das oben angegebene DeletionControl-Objekt.


Der zusätzliche Code in 'SUB_DeleteItemValue' wartet, bis alle Set eins is abgeschlossen (durch Überprüfung, ob alle DeletionControl-Objekte gelöscht wurden) und startet dann Sub-Microflows im selben Aufgabenwarteschlange um die Löschung der Entitäten durchzuführen in Set zwei, also wann Set eins abgeschlossen Set zwei Der Löschvorgang wird automatisch über den gleichen Mechanismus gestartet.

Ähnlich verhält es sich mit 'SUB_DeleteItem', wenn es alle Elemente gelöscht hat und wartet auf Set zwei abgeschlossen werden und löscht schließlich den Quelldatensatz, womit der Vorgang abgeschlossen wird. Da es nur wenige DocumentType- und Document-Datensätze gibt, löschen wir sie einfach mit dem Domänenmodellverhalten „beim Löschen“.

Wie schneiden sie im Vergleich ab?
Die Test-App verfügt außerdem über eine Schaltfläche „Quelle einfach löschen“ an der Quelle. Diese löscht die Quelle direkt und lässt das Domänenmodell stehen, um sicherzustellen, dass auch die abhängigen Objekte gelöscht werden. Wir können also entweder die einfache oder die intelligente Löschung für einen Satz Testdaten ausführen. Außerdem kann die App einen neuen Satz Testdaten erstellen, einen Satz Testdaten exportieren und einen Satz Testdaten erneut importieren. Auf diese Weise Die App ermöglicht die Erstellung neuer Sets und kann diese exportieren/importieren, sodass die Optionen „Einfaches Löschen“ und „Intelligentes Löschen“ wiederholt mit denselben Daten verwendet werden können..
Ich habe einen Testdatensatz, der in der App im Ressourcenverzeichnis enthalten ist und „Source-36e63c07–9a8a-4c94–8f87–0fbf9b7dd39f“ heißt. Dies ist der Satz, der auf meinem Computer zum Vergleichen der Löschungen verwendet wird. Sie können diesen verwenden oder Ihren eigenen erstellen.
Ich habe die Test-App in Mendix 9.18.0, konfiguriert für den Zugriff auf eine lokale Postgres 10-Datenbank. Bevor ich die einzelnen Löscharten testete, startete ich die App von Grund auf neu. Dann importierte ich den Testdatensatz und führte die Löschung fünfmal aus. Dabei ignorierte ich die besten und schlechtesten Ergebnisse der fünf und berechnete den Durchschnitt der verbleibenden drei Zeiten.
Was war also das Ergebnis? Die Option „Einfaches Löschen“ dauerte durchschnittlich 163.9 Sekunden. Die Option Smart Delete dauerte durchschnittlich 29.4 Sekunden — weniger als ein Fünftel der verstrichenen Zeit, die das einfache Löschen in Anspruch nimmt. Wenn der Benutzer nun auf den Abschluss des Löschvorgangs wartet, klingt dies nach einer lohnenden Einsparung.
Es gibt andere Möglichkeiten, die Benutzerfreundlichkeit dieses Vorgangs zu verbessern. Sie können beispielsweise die Quelle als gelöscht markieren, indem Sie dem Quelldatensatz ein Boolesches Flag hinzufügen und dann einen separaten, periodisch geplanten Ereignisprozess ausführen, der die so markierten Quelldatensätze und ihre abhängigen Elemente löscht. Es gibt nie nur eine Lösung für Ihr Problem.
Darüber hinaus sollte berücksichtigt werden, dass die intensive Arbeit mehrerer Threads für einen Benutzer dazu führen kann, dass die App für andere Benutzer langsamer wird. Daher sollten die Anforderungen des genauen Anwendungsfalls und die Auswirkung der Lösung vollständig verstanden und abgewogen werden.
Vergessen Sie nicht, dass wenn Sie eine Produktionsumgebung haben, die horizontal skaliert ist, dann die Aufgaben in einer Aufgabenwarteschlange wird auf die verfügbaren Knoten im Cluster verteilt, was Ihnen zusätzliche Zeiteinsparungen bringen kann (das hier vorgestellte Szenario konzentriert sich jedoch auf die Datenbank, die immer eine gemeinsam genutzte Ressource ist).
Noch etwas
Derzeit sparen wir dem Benutzer viel Zeit und wir hoffen, dass sich dies positiv auf seine Benutzererfahrung bei der Nutzung der App auswirkt. Aber eine Sache haben wir übersehen.
Im Domänenmodell sind für die Verknüpfungen zwischen Item, ItemValue, ItemAttachment, ItemLink, AnaysedItem, AnalysedValue und AnalysedAttachment noch die Optionen zum automatischen Löschen konfiguriert. Wenn Sie nun die Option Smart Delete verwenden, wird beim automatischen Löschen dieser Objekte im Domänenmodell eigentlich nichts gelöscht, da die Zieldaten bereits gelöscht wurden. Allerdings Mendix Die Runtime muss weiterhin prüfen, ob Datensätze zum Löschen vorhanden sind, und das kostet Zeit.
Schließlich können wir die Optionen zum automatischen Löschen aus dem Domänenmodell entfernen und die intelligente Löschung erneut ausführen, um zu sehen, welche Auswirkungen dies hat.

Nach dieser Änderung ergab das fünfmalige Ausführen des Smart Delete wie zuvor eine durchschnittliche verstrichene Zeit von 10.0 Sekunden im Vergleich zu 29.4 Sekunden. Wir haben also die „normale“ verstrichene Zeit von 163 Sekunden bis 10 Sekunden. Das klingt für mich nach einem Gewinn, aber seien Sie sich bewusst, dass das Löschen einer Quelle die Abhängigkeiten nicht mehr kaskadiert. Wenn es also andere Stellen in der App gibt, an denen Löschungen auf diese Daten angewendet werden müssen, müssen Sie auch dafür eine Lösung entwickeln.
Zusammenfassend
Die Verwendung von Aufgabenwarteschlangen kann die verstrichene Zeitleistung erheblich verbessern, wenn sie in einem geeigneten Anwendungsfall umsichtig angewendet wird. In diesem Fall zeigen die Testergebnisse eine erhebliche Einsparung für den Benutzer.

Ihr Kilometerstand kann variieren
Ich muss das wahrscheinlich nicht sagen, aber die Vorteile dieser Technik (für jede Art von Prozess, nicht nur für große Löschungen) variieren stark, je nach Komplexität der durchgeführten Operation und des Domänenmodells, wie viele freie Ressourcen Sie in Ihrer Umgebung haben und wie kompliziert Ihr Modell sein soll. Ich verweise noch einmal auf meine Kommentare in meinen vorherigen Blogs darüber, wie Sie Ihren Code lesbar und wartbar halten.
Wenn außerdem zwei oder mehr Benutzer gleichzeitig Quelldatensätze löschen, werden die Warteschlangenressourcen gemeinsam genutzt und die Einsparung für jeden einzelnen Benutzer kann geringer sein.
Ich habe eine solche Technik in einer realen Produktionsumgebung verwendet (die vor derMendix 9, also wurde das ProcessQueue Marketplace-Modul verwendet) und es wurden Leistungssteigerungen erzielt, die mich überraschten und den Product Owner erfreuten. Erstellen Sie also unbedingt einen Zweig und probieren Sie es aus.
Viel Spaß beim Anstehen!