This is an old revision of the document!
Pollen ist das regelmäßige Anfragen nach Daten, so lange, bis das gewünschte Ergebnis da ist oder man sich entscheidet, das Pollen abzubrechen. Pollen ist im Zusammenhang mit Eventual Consistency sehr nützlich. Wenn ich einen Befehl abschicke, weiß ich auch nach einem ACK1) nicht, ob das Ergebnis in den Sichten, die ich mir angucken kann, bereits vorhanden ist.
Wenn mir somit der Empfang oder die Durchführung eines Befehls bestätigt wird, habe ich im Grunde lediglich die Möglichkeit danach zu pollen, ob das Ergebnis auch schon in den Sichten angekommen ist, bevor ich mir die Sichten angucke. Die Frage ist natürlich, wonach ich polle.
Wenn ich einen neuen Datensatz mit einer neuen Aggregate ID angelegt habe, und mir der Befehl2) bestätigt wurde, kann ich nach der Aggregate ID pollen, d.h. bevor ich mir eine Mitarbeiterliste angucke, kann ich solange fragen, ob der neue Mitarbeiter schon in die Liste mit eingearbeitet wurde, bis ich eine positive Antwort erhalte, bevor ich mir dann die Liste ziehe.
Der neue Mitarbeiter, bzw. die ID des neuen Mitarbeiters, ist in diesem Fall ein natürliches Polling-Kennzeichen. Es ist zwar theoretisch möglich, dass ich nach der ID frage, der Mitarbeiter noch nicht in der Liste ist. Jetzt sieht jemand anderes den Mitarbeiter, löscht ihn wieder, und die Neuanlage und das Löschen werden beide von der Liste berücksichtigt, bevor ich das nächste mal nach der ID frage. Die ID ist immer noch nicht da, aber nicht weil sie nicht angekommen ist, sondern weil sie bereits wieder gelöscht wurde. Da kann ich lange Pollen.
Diesen Fall halte ich aber nicht für dramatisch. Das Polling bricht immer nach einer definierten Zeit ab, z.B. 20 Sekunden. Wenn ich dann mitbekomme, das jemand anderes den Mitarbeiter gelöscht hat, akzeptiere ich auch das Verhalten vom System.
Was aber, wenn ich was am Mitarbeiter ändere? Dann kann ich nicht nach einer eindeutigen ID pollen. Ich brauche also was anderes:
Die Lösung wird ähnlich sein wie die für die Idempotenz ID. Ich als Absender des Befehls3) setze im Befehl eine Polling ID. Diese Polling ID wird in alle Ereignisse4) geschrieben, die ein direktes Ergebnis dieses Befehls sind. Event Handlers und Sagas, die Ereignisse abfangen und als Reaktion auf diese neue Befehle absenden, übernehmen die Polling ID in die Befehle. Die Event Handler und Sagas haben keine eigene Verwendung für die Polling ID5).
Die Polling ID ist recht wichtig. Wenn ich z.B. einen Report ausdrucken möchte, der alles, was ich erfasst und angegeben habe, beinhalten soll, dann möchte ich das erst machen nachdem alle Angaben auch im Report enthalten sind. Das Pollen kann aber erst gestartet werden, nachdem der Befehl bestätigt wurde. Bei unerwarteten Fehlern beim Bestätigen sollte der Befehl erneut geschickt werden, so lange, bis mir entweder mitgeteilt wurde, dass er fehlgeschlagen ist, oder dass er durchgeführt wurde. Dafür wird die Befehlsidempotenz verwendet. Erst danach kann das Pollen starten.
Da ich erst polle, nachdem ich weiß, dass der Befehl bestätigt wurde, weiß ich, dass ich schließlich6) ein Ergebnis mit der Polling ID erhalten werde. Ich könnte also unendlich lang pollen. Wenn es zu lange dauert, sollte der Admin informiert werden, dass Ereignisse irgendwo in einer Pipeline hängen geblieben sind. Die Frage ist, woraus sich die Polling ID zusammen setzt.
Die PollingID ist die idempotente und somit auch global eindeutige Befehls-ID. Wenn ein Befehl ohne PollingID ausgeführt wird, wird im Domain Event automatisch die BefehlsID als PollingID gesetzt. Wenn ein Event Handler nun ein Ereignis denormalisiert, kann er die PollingID in die Liste der behandelten IDs aufnehmen, damit er, wenn danach gefragt wird, antworten kann, dass die PollingID in der denormalisierten Menge enthalten ist.
Es kann aber sein, dass ein Befehl einen Prozess auslöst, und dass Event Handler und Sagas weitere Befehle absenden, um diesen Prozess zu beenden. Diese Event Handler und Sagas können nun die PollingID zusammen mit der Befehls-ID speichern, und wenn sie gepollt werden, geben sie die Befehls-ID7) raus.
Alternativ könnten die Event-Handler/Sagas die Polling-ID im Befehl direkt setzen, und zwar mit der Polling-ID des auslösenden Ereignisses. Auch nicht uninteressant. Damit Polling-IDs global eindeutig bleiben, sollte das aber nur bestimmten System Agenten8)erlaubt werden, damit sie keine wilkürlichen Polling-IDs setzen.