Repository navigation
perf: create a direct chat with one INSERT ... ON CONFLICT DO UPDATE - #58
Merged
Merged
Conversation
The pre-check SELECT, the insert and the DuplicateKeyError recovery re-read become one statement. Members are inserted in one INSERT ... RETURNING when the chat is new and selected on a replay, then attached to the chat, so both paths take two statements.
Members go back to the per-member create and fetch_with_members, now inside the transaction with populate_existing. Group chats keep their old path.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
CreateChatUseCasehandled direct chats with afetch_direct_by_keypre-check, then an insert, then a rollback afterDuplicateKeyErrorand a second fetch outside theTransactionblock. A direct chat now uses the same statement shape as message sends (#57):Members are created only when
xmax = 0reports a new chat, andfetch_with_membersnow runs inside the transaction, so nothing reads outside the retried unit. Group chats have no unique key and keepchats_repository.create.Trade-off
Replay is the common path: every "open a DM with Bob" after the first. It goes from 2 statements (pre-check SELECT plus selectin) to 3 (upsert, SELECT, selectin). The first version of this PR kept replay at 2 by inserting or selecting members by hand and attaching them to the viewonly relationship. That was more machinery than one statement is worth, so it was dropped. ADR 0013 records this.
Two details that look odd
fetch_with_membersgainspopulate_existing. The chat returned by the upsert is already in the identity map with itsmembersnoloaded, and without the option the selectin result would not replace that. The old code only escaped this because it fetched after the session had closed.wrap_sqlalchemy_exception(error_messages=DEFAULT_ERROR_MESSAGE_TEMPLATES, ...). The repository'screateused to turn an unknowncreated_by_idintoForeignKeyError(400). A rawsession.executeraises SQLAlchemy'sIntegrityErrorinstead, which becomes a 500.test_direct_chat_upsert_recovers_from_a_connection_lost_while_pooledcaught this.Tests
test_direct_chat_replay_starts_with_the_upsert: onmain, a replay starts with a plain SELECT onchats.test_direct_chat_returns_the_chat_a_concurrent_request_created_for_the_same_pair: a second real connection inserts the chat and both members without committing. The use case blocks on the lock (the test pollspg_stat_activityforwait_event_type = 'Lock'), then gets that chat back withcreated=Falseand exactly the two members. It passed repeated runs locally._RacingChatsRepository,_NeverFoundChatsRepository,_AlwaysDuplicateChatsRepositoryand their three tests, along withfetch_direct_by_key.Docs
ADR 0013 is new, and ADR 0005 is marked
superseded_byit. ADR 0009 and AGENTS.md now describe the real-connection concurrency tests in place of the removed stubs.Verification
Run locally against Postgres 17:
ruff format,ruff check,ty check, the full suite (140 passed, 100% coverage),tests/migrations, andjust adr-check.