fix: address PR review round 2 — expiry checks, race guards, poll tests

- Log warning if /app mount not found when sharing poll task group
- Add docstring explaining unconditional task group creation
- Check session expires_at in provision_status to catch stale sessions
- Guard _poll_and_store status writes against cleanup-while-polling race
- Use "error" status (not "expired") when app_password is missing
- Remove hardcoded "Astrolabe Background Sync" user_agent string
- Fix async mock pattern (new_callable=AsyncMock) in test
- Add autouse fixture to clear _provision_sessions between tests
- Add _poll_and_store unit tests: completed, expired, error, cleanup
- Document all status values in provision_status docstring

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Chris Coutinho
2026-03-30 09:29:14 +02:00
co-authored by Claude Opus 4.6
parent 777a09c806
commit 2508f36ebf
3 changed files with 235 additions and 18 deletions
+13 -1
View File
@@ -1413,16 +1413,28 @@ def get_app(transport: str = "streamable-http", enabled_apps: list[str] | None =
@asynccontextmanager
async def _maybe_login_flow_cleanup(app: Starlette):
"""Start Login Flow cleanup task and provision poll task group."""
"""Start Login Flow cleanup task and provision poll task group.
The task group is always created (even when Login Flow cleanup is
disabled) because provision routes use it to spawn background poll
tasks via ``browser_app.state.poll_task_group``.
"""
async with anyio.create_task_group() as tg:
if settings.enable_login_flow:
tg.start_soon(_login_flow_cleanup_loop)
# Share task group with provision routes for background polling
found_app_mount = False
for route in app.routes:
if isinstance(route, Mount) and route.path == "/app":
browser_app = cast(Starlette, route.app)
browser_app.state.poll_task_group = tg
found_app_mount = True
break
if not found_app_mount:
logger.warning(
"Could not find /app mount to share poll task group; "
"web provisioning will return 500"
)
yield
tg.cancel_scope.cancel()