Fix async scan state recovery (#168)#169
Merged
Vishnu2707 merged 1 commit intoJul 8, 2026
Merged
Conversation
Vishnu2707
approved these changes
Jul 8, 2026
Vishnu2707
left a comment
Member
There was a problem hiding this comment.
Exactly what was flagged when merging #129. postgres backed retry is the right call to take from what i understand, no need for Redis at this scale. approving this!
10 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Hardens async scan execution so scan state survives Render restarts and stale
runningscans recover through the PostgreSQL-backed queue. Addresses #168 by making interrupted worker runs retryable before they are marked failed.Before merging
No repo-admin action is required for this PR.
This change adds a schema migration through the existing startup-safe
run_migrations()path. Deployments should run the normal startup flow so theattempt_countcolumn is added before workers claim scans.What changed
Persistent scan retry state (#168)
attempt_countto thescanstable for fresh databases and existing deployments.attempt_count = 0.attempt_countand clear staleerror_messagevalues when a pending scan moves torunning.error_messageso old retry messages do not remain attached to successful scan records.Render restart recovery
recover_stale_scans()now returns stalerunningscans topendingwhile retry attempts remain.failedafter reaching the max attempt count, preventing infinite retry loops for persistent Azure credential or permission failures.claimed_at, allowing the worker to claim them again with the existingFOR UPDATE SKIP LOCKEDflow.Tests
POST /api/scans/triggerpersists a pending row throughDatabaseManager.GET /api/scans/<scan_id>reads durable database status instead of consulting memory.Docs
docs/async-scan-architecture.mdto explain how queued and running scans behave across Render web or worker restarts.Notes for reviewers
GET /api/scans/<scan_id>and sees the samepending,running,completed, orfailedstatuses.Local verification
ruff check .ruff format --check .bandit -r api/ scanner/ ai/ -llpip-audit -r requirements.txt --ignore-vuln PYSEC-2025-217 --ignore-vuln CVE-2026-1839 --ignore-vuln CVE-2026-4372npm run lintandnpm run buildpass with existing warnings onlyLocal caveat
gitleaks detect --source . --no-gitfails locally because an ignored.envfile exists in the working tree with real local secrets. The file is not tracked and is not part of this PR. GitHub CI runs on a clean checkout, so this local-only file should not affect the PR secret-scan gate.Files to review
api/models/finding.pytests/test_async_scan_persistence.pydocs/async-scan-architecture.md