Skip to content

SetMeta UPSERTs lack a transaction boundary; metadata vs dependent state can diverge on crash #1753

Description

@Widthdom

Summary

SetMeta / SetMetaInt (DbWriter.cs:1888-1894) issue an UPSERT against the meta key/value table without wrapping it in a transaction or sharing the caller's transaction. When the writer process crashes between the metadata UPDATE and the next dependent write (e.g. clearing a readiness bit, then writing rows under that schema), the on-disk DB is left with metadata that says "schema vN" but rows that match vN-1, or vice versa. Because there is no commit boundary, recovery has to make a best-guess decision about which side is "real".

Where

  • src/CodeIndex/Database/DbWriter.cs:1888-1894 (SetMeta)
  • Callers across IndexCommandRunner and DbContext migration paths

Suggested approach

(1) Audit every SetMeta / SetMetaInt call site and require either an enclosing BeginTransaction (existing pattern via _transactionDepth) or a single statement that the caller can recover from. (2) Add a SetMetaWithGuard(key, value, Action commit) helper that opens a transaction, performs the UPSERT, runs commit() (the dependent write), then commits, so the metadata stamp and the dependent state become atomic. (3) Add an integrity test that kill -9 between metadata write and dependent write leaves the DB in a recoverable, well-defined state (either both old or both new). (4) Document the contract in DEVELOPER_GUIDE under "Metadata invariants".

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions