fix(#355): Plugin-Lifecycle Runtime-Registrierungen repariert — Vorher-Status wird jetzt VOR dem registry-Aufruf gelesen (war konstant falsch → Deactivate-Cleanup toter Code); sync_notification_types hinter DB-Statusupdate verschoben; echter Integrationstest tests/test_plugin_lifecycle_service.py (install→activate×2→deactivate×2→re-activate über PluginService) rot→grün
Check Cross-Plugin Imports / check (push) Has been cancelled
Check Cross-Plugin Imports / check (push) Has been cancelled
fixes #355
This commit is contained in:
@@ -635,15 +635,17 @@ class PluginRegistry:
|
||||
# Activation status is enforced per-request via require_active_plugin().
|
||||
# No dynamic route registration here — prevents duplicate routes.
|
||||
|
||||
# Sync notification types from this plugin
|
||||
await self.sync_notification_types(db)
|
||||
|
||||
# Update DB record
|
||||
# Update DB record FIRST — sync_notification_types() only picks up types
|
||||
# from plugins whose record is already active; running it before the
|
||||
# status update silently skipped the freshly activated plugin's types.
|
||||
record.status = "active"
|
||||
record.active = True
|
||||
await db.flush()
|
||||
self._db_status[name] = record
|
||||
|
||||
# Sync notification types from this plugin (AFTER status update)
|
||||
await self.sync_notification_types(db)
|
||||
|
||||
# Invalidate Redis cache for this plugin across all tenants
|
||||
try:
|
||||
from app.core.redis import get_redis
|
||||
|
||||
@@ -91,8 +91,15 @@ class PluginService:
|
||||
Checks that all declared dependencies are active first.
|
||||
"""
|
||||
try:
|
||||
# Pre-state MUST be captured BEFORE the mutation: the record returned
|
||||
# by registry.activate() always reflects the NEW state, so computing
|
||||
# was_already_active afterwards yielded constant True and silently
|
||||
# skipped all runtime registrations (dead code — proven by
|
||||
# tests/test_plugin_lifecycle_service.py, Welle 1 / Kritikpunkt 1).
|
||||
pre = await self._registry._get_plugin_record(db, name)
|
||||
was_already_active = bool(pre and pre.active and pre.status == "active")
|
||||
|
||||
record = await self._registry.activate(db, name)
|
||||
was_already_active = record.active and record.status == "active"
|
||||
|
||||
# Update permission registry at runtime so newly activated plugins
|
||||
# are immediately usable without app restart (P0-10 fix).
|
||||
@@ -155,8 +162,14 @@ class PluginService:
|
||||
Unregisters event listeners and routes. Idempotent.
|
||||
"""
|
||||
try:
|
||||
# Pre-state MUST be captured BEFORE the mutation (same reasoning as
|
||||
# activate_plugin — the returned record always reflects the NEW
|
||||
# state; computing was_already_inactive afterwards yielded constant
|
||||
# True and skipped permission/entity/gate deregistration entirely).
|
||||
pre = await self._registry._get_plugin_record(db, name)
|
||||
was_already_inactive = bool(pre and not pre.active and pre.status == "inactive")
|
||||
|
||||
record = await self._registry.deactivate(db, name)
|
||||
was_already_inactive = not record.active and record.status == "inactive"
|
||||
|
||||
# Update permission registry at runtime so deactivated plugins
|
||||
# immediately stop being usable (P0-10 fix).
|
||||
|
||||
Reference in New Issue
Block a user