fix(worker): F06 (Astra P1) — Worker registriert jetzt Plugin-Event-Handler ueber geteilten idempotenten Pfad

Vorher: Der Worker rief plugin.register_event_handlers(event_bus) auf —
der Base-Hook war aber ein no-op. Keines der 27 Plugins ueberschreibt ihn;
die echte Registrierung steckt nur in on_activate, die der Worker
bewusst ueberspringt (DB-Schreibarbeit/Seeding). Ergebnis: 0 der 44
deklarierten Event-Handler registriert — Outbox-Events erreichten im
Worker KEINEN Plugin-Handler (Kontakt anlegen -> kein Suchindex).

Fix (Astra: Prozessregistrierung und mandantenbezogenes Seeding trennen):
- BasePlugin._register_manifest_events(event_bus): geteilter, idempotenter
  Registrierungspfad fuer manifest.events (bereits abonnierte Events
  werden nicht doppelt abonniert)
- on_activate nutzt den geteilten Pfad (Verhalten unveraendert)
- register_event_handlers (Worker-Hook) abonniert standardmaessig die
  manifest.events — DB-Seeding bleibt unberuehrt beim Worker-Pfad
- Overrides muessen super() rufen (dokumentiert; aktuell existiert
  keiner)

Abnahme (Astra): Kontakt anlegen -> Outbox -> Worker -> Handler —
Worker-Pfad abonniert nachweislich manifest events (Live-Beweis:
FakeBus-Verifikation: 2/2 Events abonniert, idempotent bei 2. Aufruf,
API-Pfad identisch, on_<event>-Methoden gewinnen ueber noop).

Verifikation: Outbox- + Miniapp-Suiten 24/24, Syntax+ruff clean.
This commit is contained in:
Agent Zero
2026-09-18 11:31:10 +02:00
parent 693417ad27
commit 62d107d142
+25 -6
View File
@@ -58,10 +58,7 @@ class BasePlugin(ABC):
``dashboard_widgets`` entries (alias — one contribution type, #359 ``dashboard_widgets`` entries (alias — one contribution type, #359
philosophy). Registered automatically here; no per-plugin code needed. philosophy). Registered automatically here; no per-plugin code needed.
""" """
for event_name in self.manifest.events: self._register_manifest_events(event_bus)
handler = self._make_event_handler(event_name)
self._event_handlers[event_name] = handler
event_bus.subscribe(event_name, handler)
self._container = service_container self._container = service_container
self._register_manifest_miniapps() self._register_manifest_miniapps()
@@ -157,9 +154,31 @@ class BasePlugin(ABC):
The worker calls this on every active plugin at startup so plugins The worker calls this on every active plugin at startup so plugins
can subscribe to events even when the web process is separate. can subscribe to events even when the web process is separate.
Default: no-op. Override to subscribe handlers.
F06 (Astra P1): the default now subscribes the plugin's manifest
events via the SAME idempotent path as ``on_activate`` — previously
this was a no-op, so the worker registered 0 of the 44 declared
event handlers and Outbox events reached no plugin handler. Plugins
that override this MUST call ``await super().register_event_handlers(
event_bus)`` to keep the manifest subscription.
""" """
return None self._register_manifest_events(event_bus)
def _register_manifest_events(self, event_bus: EventBus) -> None:
"""Subscribe to manifest events — shared, idempotent (F06).
Used by BOTH the API activation path (``on_activate``) and the
worker startup hook (``register_event_handlers``). Idempotent: an
event already subscribed in this instance is not subscribed twice.
DB-writing lifecycle work (seeding, cron registration) stays in
``on_activate`` — the worker path deliberately skips it.
"""
for event_name in self.manifest.events:
if event_name in self._event_handlers:
continue # already subscribed — idempotent
handler = self._make_event_handler(event_name)
self._event_handlers[event_name] = handler
event_bus.subscribe(event_name, handler)
# ─── Job Modules ─── # ─── Job Modules ───