Skip to content

fix: serialize concurrent profile deletions with RLock#60

Open
Sidbad12 wants to merge 1 commit into
vasu-devs:mainfrom
Sidbad12:fix-concurrent-profile-deletions
Open

fix: serialize concurrent profile deletions with RLock#60
Sidbad12 wants to merge 1 commit into
vasu-devs:mainfrom
Sidbad12:fix-concurrent-profile-deletions

Conversation

@Sidbad12

Copy link
Copy Markdown

Summary

What changed:
Added a reentrant thread lock (_profile_write_lock / threading.RLock) in backend/data/graph/profile.py that wraps the 5 functions performing read-modify-write operations on the SQLite profile state. Also added a new concurrency regression test in tests/test_concurrent_profile_delete.py.

Why:
When a user rapidly deletes multiple profile items (e.g., skills or experience), concurrent FastAPI thread pool workers race on the SQLite snapshot read-modify-write cycle. The last writer overwrites earlier writers, causing the deleted items to lose their tombstones, resurface in the UI, and remain permanently in the Kùzu graph and vector databases. Serializing these writes resolves the race condition natively on the backend.

Type of Change

  • Scraper/source adapter
  • Ranking/scoring
  • Vector/profile intelligence
  • Customizer/document generation
  • Frontend/UI
  • Backend/API/storage
  • Docs/OSS hygiene
  • CI/release
  • Experimental automation

Testing

Commands run:

  • npm run typecheck
  • npm test
  • npm run build
  • backend/.venv/Scripts/python.exe -m pytest backend/tests (247 passing)
  • cd src-tauri && cargo check
  • Other: .venv\Scripts\pytest tests\test_concurrent_profile_delete.py -v (concurrency test passes)

Privacy And Safety

  • No API keys, cookies, bearer tokens, resumes, local databases, or generated private documents are included.
  • User-facing behavior is clear about what is core vs experimental.
  • Ranking/filtering changes include explanations or tests where relevant.

Licensing

  • I have read CLA.md and understand this contribution may be distributed under AGPL-3.0-only and separate commercial licenses.

Notes For Reviewers

  • Why RLock instead of Lock? delete_skill internally calls _remember_profile_deletion and save_profile_snapshot. Using a standard Lock would cause the thread to deadlock itself. RLock elegantly handles this re-entry.
  • Why no frontend changes? The frontend already has per-key deduplication (deletingItems Set), so it won't fire duplicate deletes for the same item. The race condition only happens when different items are deleted rapidly, which is a purely backend concern.

@Sidbad12 Sidbad12 requested a review from vasu-devs as a code owner May 18, 2026 08:01
@vercel

vercel Bot commented May 18, 2026

Copy link
Copy Markdown

@Sidbad12 is attempting to deploy a commit to the Vasu-Devs' projects Team on Vercel.

A member of the Team first needs to authorize it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant