Repository navigation
feat: serve GET and HEAD from an autocommit, read-only engine - #84
Merged
Merged
Conversation
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.
Closes #83.
GET and HEAD now always go to a read engine. It is built from
DB_REPLICA_DSNwhen that is set and fromDB_DSNotherwise, and it is created with:isolation_level="AUTOCOMMIT", so SQLAlchemy sends no BEGIN/ROLLBACK and the pre-ping is a bare;. A one-query GET drops from six round trips to two.server_settings={"default_transaction_read_only": "on"}, so Postgres rejects writes on these connections. The setting goes in the startup packet and costs nothing per request.Pre-ping stays on for both engines. The issue has the measurements: locally 4,022 to 5,281 req/s with one client, and about 3x under added network latency.
Code changes:
create_read_sa_enginereplacescreate_replica_sa_engineand never returnsNone, sochoose_sa_engineandclose_sa_enginelose theirNonehandling.database_read_enginereplacesdatabase_replica_engineinapp/ioc.py.create_sa_enginetakesread_only: bool, rather than accepting arbitrary engine kwargs.Behaviour changes, also written up in AGENTS.md:
fetch_with_cards(deck, then cards throughselectinload) can see a card committed between the two queries.2 × db_pool_sizeconnections.Tests:
DB_DSN, that two statements on it get differenttransaction_timestamp()values (autocommit), and that an INSERT fails with a read-only error. Both behaviour tests fail if the engine options are removed.test_tracing.pyalready sends a realGET /api/decks/through the DI graph without overrides, so it covers the read engine end to end.