发布

  • fix(cache): stringify ids at the SQL bind layer and stop sliding-TTL … (#4182)

    frostbyte_neo 发布于 2026-07-22 11:51:20 +00:00

    …deadlocks

    Two production failures on the Postgres cache backend, both in
    SqlCacheAdapter:

    1. A caller holding user.id as uuid.UUID made the asyncpg dialect bind
      the parameter as $1::UUID, so Postgres parsed text = uuid and raised
      42883 ("operator does not exist") instead of coercing; sqlite rejects
      such binds outright. Key columns
      (user_id/session_id/qa_id/entry_id/log_key/key) now use a StringKey
      TypeDecorator that coerces stringable ids to str in the bind processor,
      covering every read, write, and IN-list in one place. Client-side only:
      the emitted DDL is still plain TEXT (verified identical), so existing
      tables keep working with no migration.

    2. Session writes end with the sliding-TTL UPDATE over all of the
      session's rows while already holding row locks taken earlier in the
      transaction, so concurrent same-session writers acquired row locks in
      opposite orders and deadlocked (40P01) faster than the 3-attempt retry
      could absorb. Write transactions now take a transaction-scoped
      pg_advisory_xact_lock keyed by (table, user, session) up front, so
      same-session writers queue instead. No-op on SQLite.

    Verified on Postgres 17: uuid.UUID ids round-trip identically to their
    string form, a table created by the previous code (old DDL + legacy
    rows) is read and extended seamlessly, and an 8-worker concurrent-update
    hammer that previously produced 579 server-side deadlocks (189 surfaced
    as CacheConnectionError) now produces 0.

    Description

    Acceptance Criteria

    Type of Change

    • Bug fix (non-breaking change that fixes an issue)
    • New feature (non-breaking change that adds functionality)
    • Code refactoring
    • Other (please specify):

    Screenshots

    Pre-submission Checklist

    • I have tested my changes thoroughly before submitting this PR
      (See CONTRIBUTING.md)
    • This PR contains minimal changes necessary to address the
      issue/feature
    • My code follows the project's coding standards and style
      guidelines
    • I have added tests that prove my fix is effective or that my
      feature works
    • I have added necessary documentation (if applicable)
    • All new and existing tests pass
    • I have searched existing PRs to ensure this change hasn't been
      submitted already
    • I have linked any relevant issues in the description
    • My commits have clear and descriptive messages

    DCO Affirmation

    I affirm that all code in every commit of this pull request conforms to
    the terms of the Topoteretes Developer Certificate of Origin.

    下载附件