feat: atomically journal and deliver authorized native operation outcomes
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a0e747-8f27-7242-8df8-8bc44f88c929
This commit is contained in:
parent
3c5cbfbafe
commit
f0eff0ac92
13 changed files with 583 additions and 28 deletions
|
|
@ -68,6 +68,9 @@ def create_app(
|
|||
browser = BrowserSessions(settings=browser_settings, controller=access_controller) if browser_settings else None
|
||||
resolved_store = port_store or _create_store(resolved_settings)
|
||||
owns_store = port_store is None
|
||||
outcome_delivery = (access_controller is not None
|
||||
and callable(getattr(access_controller.audit, "append_outcome", None))
|
||||
and callable(getattr(resolved_store, "deliver_outcomes", None)))
|
||||
resolved_repo_projection_client = repo_projection_client
|
||||
owns_repo_projection_client = False
|
||||
if (
|
||||
|
|
@ -111,9 +114,14 @@ def create_app(
|
|||
await workload_projection.refresh()
|
||||
except WorkloadProjectionRejected:
|
||||
pass
|
||||
outcome_task = asyncio.create_task(_deliver_outcomes(resolved_store, access_controller.audit)) if outcome_delivery else None
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
if outcome_task is not None:
|
||||
outcome_task.cancel()
|
||||
with suppress(asyncio.CancelledError):
|
||||
await outcome_task
|
||||
if browser is not None:
|
||||
browser.clear()
|
||||
if refresh_task is not None:
|
||||
|
|
@ -166,6 +174,8 @@ def create_app(
|
|||
}
|
||||
if resolved_settings.enforce_access:
|
||||
dependency_checks["access_profile"] = "ok" if access_controller else "unavailable"
|
||||
if callable(getattr(resolved_store, "deliver_outcomes", None)):
|
||||
dependency_checks["outcome_delivery"] = (await resolved_store.outcome_readiness()) if outcome_delivery else "unavailable"
|
||||
ready = resolved_settings.is_ready(resolved_store.backend_name) and all(
|
||||
value in {"ok", "not_applicable"} for value in dependency_checks.values()
|
||||
)
|
||||
|
|
@ -191,6 +201,16 @@ def create_app(
|
|||
return app
|
||||
|
||||
|
||||
async def _deliver_outcomes(store, sink) -> None:
|
||||
while True:
|
||||
try:
|
||||
await store.deliver_outcomes(sink)
|
||||
except Exception:
|
||||
# DB outages leave rows durable; readiness exposes missing/stale data.
|
||||
pass
|
||||
await asyncio.sleep(1)
|
||||
|
||||
|
||||
async def _refresh_repository_projection(
|
||||
service: RepositoryNavigationService,
|
||||
interval_seconds: float,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue