fix(mcp-kb): Race condition in update_document and non-transactional batch insert #77

Closed
opened 2026-01-03 23:57:03 +00:00 by cardosofelipe · 0 comments

Bug Description

Two concurrency issues found in the database layer:

Issue 1: Race Condition in update_document

In database.py:update_document, there's a read-then-write pattern without proper locking:

async def update_document(self, ...):
    # Reads existing document
    existing = await self.get_document(project_id, document_id)
    # ... time passes ...
    # Updates document - another process could have modified it
    await conn.execute(...)

This can lead to lost updates in concurrent scenarios.

Issue 2: Non-Transactional Batch Insert

In database.py:batch_add_documents, multiple documents are inserted without a transaction wrapper:

async def batch_add_documents(self, ...):
    results = []
    for doc in documents:
        result = await self.add_document(...)  # Individual inserts
        results.append(result)

If one insert fails, previous inserts remain, leaving data in inconsistent state.

Fix Required

  1. update_document: Use SELECT ... FOR UPDATE or optimistic locking with version field
  2. batch_add_documents: Wrap in explicit transaction with rollback on failure
  • Found during PR #72 deep review
  • Issue #57 (Knowledge Base MCP Server)
## Bug Description Two concurrency issues found in the database layer: ### Issue 1: Race Condition in update_document In `database.py:update_document`, there's a read-then-write pattern without proper locking: ```python async def update_document(self, ...): # Reads existing document existing = await self.get_document(project_id, document_id) # ... time passes ... # Updates document - another process could have modified it await conn.execute(...) ``` This can lead to lost updates in concurrent scenarios. ### Issue 2: Non-Transactional Batch Insert In `database.py:batch_add_documents`, multiple documents are inserted without a transaction wrapper: ```python async def batch_add_documents(self, ...): results = [] for doc in documents: result = await self.add_document(...) # Individual inserts results.append(result) ``` If one insert fails, previous inserts remain, leaving data in inconsistent state. ### Fix Required 1. **update_document**: Use `SELECT ... FOR UPDATE` or optimistic locking with version field 2. **batch_add_documents**: Wrap in explicit transaction with rollback on failure ### Related - Found during PR #72 deep review - Issue #57 (Knowledge Base MCP Server)
Sign in to join this conversation.