Parent umbrella issue: #308
Source audit: Weekly tech debt audit: dispatch - 2026-06-03
Source audit date: 2026-06-03
Original recommendation
P1 — Share sync locking/concurrency controls: extend the scheduled sync lock or a repo-scoped lock to manual issue sync and automation sync, including useful 409 responses.
Matched top finding
Scheduled sync has a DB-backed single-row lock, but normal issue sync and automation sync do not appear to share that lock. Browser refreshes, cron overlap, or repeated clicks can trigger concurrent GitHub scans and per-run/per-job writes.
Evidence:
src/app/api/sync/scheduled/route.ts:13-59 has acquireLock() / releaseLock().
src/app/api/sync/route.ts:8-65 performs issue sync without that lock.
src/app/api/automation/sync/route.ts:329-356 loops through tracked repos; syncRepo() does multiple GitHub calls and upserts per workflow/run/job/release/PR/package.
Parent umbrella issue: #308
Source audit: Weekly tech debt audit: dispatch - 2026-06-03
Source audit date: 2026-06-03
Original recommendation
P1 — Share sync locking/concurrency controls: extend the scheduled sync lock or a repo-scoped lock to manual issue sync and automation sync, including useful 409 responses.
Matched top finding
Scheduled sync has a DB-backed single-row lock, but normal issue sync and automation sync do not appear to share that lock. Browser refreshes, cron overlap, or repeated clicks can trigger concurrent GitHub scans and per-run/per-job writes.
Evidence:
src/app/api/sync/scheduled/route.ts:13-59hasacquireLock()/releaseLock().src/app/api/sync/route.ts:8-65performs issue sync without that lock.src/app/api/automation/sync/route.ts:329-356loops through tracked repos;syncRepo()does multiple GitHub calls and upserts per workflow/run/job/release/PR/package.