Wer an Funktionen mit Queue-Abhängigkeit arbeitet, etwa an eigenen Queues, am Data Import oder an Publish and Synchronize, kennt das Problem: Jenkins verarbeitet im lokalen Setup munter weiter, während man selbst noch mitten in der Entwicklung ist. Nachrichten sind konsumiert, bevor der eigene Code fertig ist, Testdaten verschwinden aus der Queue, und ein Fehler lässt sich kaum zweimal in derselben Form reproduzieren. Das Spryker Docker SDK bringt dafür passende Console-Commands mit, mit denen sich dieser Teil der lokalen Entwicklung deutlich ruhiger gestalten lässt.
Warum Scheduler anhalten vorteilhaft ist
Im Spryker Docker SDK läuft lokal derselbe Scheduler wie später im Betrieb: Jenkins übernimmt Cronjobs und damit auch alles, was über Queues läuft, Data Import, Publish and Synchronize, eigene Queue-Consumer. Das ist im Normalbetrieb genau richtig. Beim gezielten Entwickeln an genau diesen Stellen wird daraus aber ein Störfaktor. Eine Nachricht, die man gerade erst in die Queue gelegt hat, um den eigenen Consumer zu testen, kann schon verarbeitet und aus der Queue entfernt sein, bevor man den Debugger überhaupt gestartet hat. Wiederholtes Testen bedeutet dann: Nachricht neu erzeugen, hoffen, schnell genug zu sein, wieder von vorn.
Jenkins kontrolliert anhalten
Der erste Schritt ist, Jenkins für die Dauer der Entwicklung anzuhalten, statt gegen seine Hintergrundverarbeitung anzuarbeiten. Das Docker SDK bringt dafür den Console-Command scheduler:suspend:
Wichtig dabei: scheduler:suspend wartet, bis aktuell laufende Jobs beendet sind, statt sie hart abzubrechen. Ein Job, der schon vor dem Suspend gestartet war, kann also trotzdem noch fertig durchlaufen. Deshalb lohnt es sich, danach einmal die lokale Jenkins-URL im Browser aufzurufen und nachzusehen, ob noch etwas läuft, und diese Jobs dort direkt zu beenden. Erst wenn Jenkins wirklich still steht, ist der Boden für reproduzierbares Debuggen bereitet.
Wer nur bestimmte Rollen, Scheduler oder Jobs anhalten will statt der gesamten Jenkins-Instanz, kann scheduler:suspend mit --roles, --schedulers oder --jobs gezielt einschränken, statt jedes Mal alles lahmzulegen. --schedulers filtert dabei nicht nur benannte Jenkins-Instanzen, sondern echte Scheduler-Adapter: Spryker erlaubt es, mehrere Scheduler-Engines parallel im selben Projekt zu registrieren, jede als eigenes Adapter-Plugin. Wer mehr als eine Engine betreibt, etwa weil einzelne Jobs auf einer anderen Infrastruktur laufen als der Rest, kann über --schedulers gezielt nur eine davon ansprechen.
Gezielt debuggen mit --no-ack
Für das eigentliche Debuggen eines Queue-Consumers bringt das Docker SDK queue:task:start <queue-name> --no-ack mit (kurz -k). Die Option sorgt dafür, dass eine konsumierte Nachricht nicht aus der Queue entfernt wird. Man kann dieselbe Nachricht also mehrfach verarbeiten, ohne sie nach jedem Durchlauf neu anlegen zu müssen. Das beschleunigt das Debuggen deutlich, hat aber eine klare Grenze: Es funktioniert nur bei Änderungen, die wiederholbar sind. Sobald der Consumer bei jedem Durchlauf einen Zustand verändert, der beim nächsten Mal nicht mehr passt, etwa einen Datensatz, der schon aktualisiert wurde, führt --no-ack zu falschen Ergebnissen statt zu saubereren Debug-Zyklen.
Wenn es nur ums Nachsehen geht, was gerade in einer Queue liegt, ohne überhaupt in die Verarbeitung einzugreifen, ist queue:dump oft die einfachere Wahl. Und wer nicht dauerhaft einen Worker im Hintergrund laufen lassen will, sondern gezielt einmal alles abarbeiten möchte, was aktuell in der Queue steht, bekommt das über queue:worker:start mit --stop-when-empty.
Wer Queue-Inhalte lieber visuell statt über die Console prüft: Das Docker SDK exponiert neben localhost:5672 (AMQP) auch die RabbitMQ-Management-Oberfläche unter api.queue.spryker.local (Eintrag in der lokalen /etc/hosts, kein eigener Port nötig, da über das SDK-eigene Nginx-Gateway geproxied). Die Zugangsdaten dafür sind projektspezifisch aus der Docker-SDK-Konfiguration generiert, es gibt kein generisches guest/guest wie bei einer Standard-RabbitMQ-Installation.
Weitere Queue-Commands im Alltag
Neben Scheduler und Task-Debugging kennt Spryker noch ein paar weitere Queue-Commands, die im Projektalltag gelegentlich hilfreich sind, vor allem wenn Queues und Exchanges einmal in einem Zustand landen, aus dem man sie nicht mehr sauber herausbekommt.
purge-all und delete-all wirken auf alle Queues gleichzeitig, es gibt keinen eigenen Command für eine einzelne Queue. Beide sind entsprechend mit Bedacht einzusetzen, lokal meist unproblematisch, auf einer geteilten Umgebung dagegen nicht ohne Absprache.
Ein praktischer Ablauf
Für die tägliche Arbeit an Queue-abhängigen Funktionen hat sich eine einfache Reihenfolge bewährt: Jenkins zu Beginn der Session mit scheduler:suspend anhalten, kurz im Browser prüfen, ob noch ein Job nachläuft, und diesen gegebenenfalls dort beenden. Danach mit queue:task:start --no-ack oder queue:dump so oft wie nötig gegen dieselbe Nachricht debuggen. Zum Abschluss scheduler:resume, damit Jenkins wieder normal weiterläuft, sobald die eigentliche Entwicklungsarbeit erledigt ist.