fix(service): add database fallback to PlanLifecycleService.list_plans()

list_plans() only read from the in-memory self._plans dict, but the
DI container creates PlanLifecycleService via providers.Factory (a new
instance per call), so every CLI invocation started with an empty dict.
Plans created by "plan use" were persisted to the database via
UnitOfWork.transaction() but "plan lifecycle-list" could never find
them because it never queried the database.

Added a database query path to list_plans() that calls
LifecyclePlanRepository.list_all() when persistence is enabled,
mirroring the existing database fallback in get_plan().  Also added
the list_all() method to LifecyclePlanRepository.

Refs: #746
This commit is contained in:
Luis Mendes
2026-03-13 23:03:57 +00:00
parent ab911dbdc4
commit 22580752d2
@@ -788,9 +788,8 @@ class PlanLifecycleService:
) -> list[Plan]:
"""List plans with optional filtering.
Returns plans from the in-memory cache. When persistence is
enabled the cache is populated during ``use_action`` and
``get_plan`` calls.
Queries the database when persistence is enabled, falling back
to the in-memory cache otherwise.
Args:
namespace: Filter by namespace
@@ -800,7 +799,22 @@ class PlanLifecycleService:
Returns:
List of matching Plans
"""
plans = list(self._plans.values())
# Query the database when persistence is enabled so that plans
# created by previous CLI invocations are visible.
if self._persisted and self.unit_of_work is not None:
try:
with self.unit_of_work.transaction() as ctx:
plans = ctx.lifecycle_plans.list_all()
# Refresh the in-memory cache with persisted plans.
for p in plans:
pid = str(p.identity.plan_id)
if pid not in self._plans:
self._plans[pid] = p
except Exception:
logger.debug("DB list_all failed, falling back to in-memory cache")
plans = list(self._plans.values())
else:
plans = list(self._plans.values())
if namespace:
plans = [p for p in plans if p.namespaced_name.namespace == namespace]