diff --git a/docs/adr/0012-pool-pre-ping-off.md b/docs/adr/0012-pool-pre-ping-off.md index a133df9..35f468a 100644 --- a/docs/adr/0012-pool-pre-ping-off.md +++ b/docs/adr/0012-pool-pre-ping-off.md @@ -6,8 +6,9 @@ its first statement, SQLAlchemy marks the error `connection_invalidated`, and rejected because it adds a BEGIN, a ping and a ROLLBACK to every checkout, and a request makes two checkouts. Measured on `GET /api/auth/me/` and the message list, it cost 7 to 35% of throughput on a local network and 40 to 57% with 1 ms -of database latency. The price of the retry is a rule the code must keep: every -query a retried use case runs goes inside its `Transaction` block, because a -query outside it leaves the session in a dead transaction that the retry cannot -roll back. `tests/use_cases/test_connection_loss.py` kills a connection both -while it is idle in the pool and while a session holds it. +of database latency. The retry needs one rule: every query a retried use case +runs goes inside its `Transaction` block. Entering `Transaction` rolls back a +session whose connection was lost, so a query after the block is recovered, but +a query before it still fails the retry. +`tests/use_cases/test_connection_loss.py` kills a connection both while it is +idle in the pool and while a session holds it. diff --git a/pyproject.toml b/pyproject.toml index e2a018c..4e57705 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,7 +14,7 @@ dependencies = [ "pydantic-settings", "granian[uvloop]", "argon2-cffi", - "db-retry>=0.8.0", + "db-retry>=0.8.1", # database "alembic", "alembic-postgresql-enum", diff --git a/uv.lock b/uv.lock index 4ffc39d..9de1bcd 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 3 +revision = 5 requires-python = ">=3.14" [[package]] @@ -299,7 +299,7 @@ requires-dist = [ { name = "alembic-postgresql-enum" }, { name = "argon2-cffi" }, { name = "asyncpg" }, - { name = "db-retry", specifier = ">=0.8.0" }, + { name = "db-retry", specifier = ">=0.8.1" }, { name = "granian", extras = ["uvloop"] }, { name = "lite-bootstrap", extras = ["litestar-all"] }, { name = "litestar", extras = ["jwt"] }, @@ -480,15 +480,15 @@ wheels = [ [[package]] name = "db-retry" -version = "0.8.0" +version = "0.8.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "asyncpg" }, { name = "sqlalchemy", extra = ["asyncio"] }, ] -sdist = { url = "https://files.pythonhosted.org/packages/cb/78/71a71ccabcd09175e4351c655b0d1439a6207f9401ce8df4189fa8bfcc84/db_retry-0.8.0.tar.gz", hash = "sha256:dccdc281422f8d01acc2b4f39e622d4a97e03b23adf3d3bf66b61c680c235b71", size = 8737, upload-time = "2026-10-16T15:55:58.283Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c6/b1/e00347fb2f3dbbff67cbc4fec36f1fc30355dadb62a4f99f539ca8325e0c/db_retry-0.8.1.tar.gz", hash = "sha256:12cfcbaa851f46567723b97875d9990b3747a04b41db93909b43f43f9aa5b1d9", size = 9198, upload-time = "2026-10-17T07:45:22.517Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d0/1c/3becec5f059559f88c2b4e343673509bac363ebb255743d144da7af35f95/db_retry-0.8.0-py3-none-any.whl", hash = "sha256:edaf2aed767082eb84a6d22b8d79001d0f2c86d68853dda46a623c94fe819ad3", size = 9338, upload-time = "2026-10-16T15:55:57.339Z" }, + { url = "https://files.pythonhosted.org/packages/02/7f/65efee5727d4a5d3d29b7300a1f165d872c46a4cceb828819a0f13fc9217/db_retry-0.8.1-py3-none-any.whl", hash = "sha256:95e2346d6ea5ae29964f1059128a623665f4e6046f477fc7e2970cf1969dda91", size = 9782, upload-time = "2026-10-17T07:45:21.458Z" }, ] [[package]]