Promote dev → uat: PostgreSQL connection pool fix (CAR-1077) #44

Merged
Savannah Savings merged 10 commits from promote/car1077-dev-uat into uat 2026-06-02 15:25:04 +00:00
Member

Summary

Promotes devuat to bring in CAR-1077 (PR #39, "Fix PostgreSQL connection pool issues", commit 7a7aaca0) and the dependent dev commits.

Merge conflict resolution

This branch was produced by branching from origin/uat and merging origin/dev. Conflicts occurred in exactly two test files (production files did NOT conflict):

  • tests/conftest.py
  • tests/test_encrypted_json.py

Both conflicts were resolved in favor of origin/dev per CAR-1152, because dev is the source of truth for this promotion. Dev's version of the SQLite test-fixture code is a strict superset of uat's (adds a hasattr(sd, "expression") guard for non-TextClause server_defaults, strips additional PostgreSQL defaults including now(), and registers a before_insert event listener for timestamp columns). No uat-only logic is lost.

Production files preserved

git diff origin/dev -- src/cartsnitch_api/database.py src/cartsnitch_api/routes/health.py is empty — the CAR-1077 production fix is preserved verbatim.

CI expectation

lint and typecheck are expected to be green. The test job will be red due to a pre-existing SQLite UUID test-fixture issue tracked separately under CAR-1132 / PR #42. This red test job is expected and is NOT a blocker for this promotion.

Supersedes

PR #43 (the direct conflicted dev→uat promotion) will be closed by CTO; this branch-based PR replaces it.

cc @cpfarhood

## Summary Promotes `dev` → `uat` to bring in CAR-1077 (PR #39, "Fix PostgreSQL connection pool issues", commit `7a7aaca0`) and the dependent dev commits. ## Merge conflict resolution This branch was produced by branching from `origin/uat` and merging `origin/dev`. Conflicts occurred in exactly two test files (production files did NOT conflict): - `tests/conftest.py` - `tests/test_encrypted_json.py` Both conflicts were resolved in favor of `origin/dev` per CAR-1152, because dev is the source of truth for this promotion. Dev's version of the SQLite test-fixture code is a strict superset of uat's (adds a `hasattr(sd, "expression")` guard for non-TextClause server_defaults, strips additional PostgreSQL defaults including `now()`, and registers a `before_insert` event listener for timestamp columns). No uat-only logic is lost. ## Production files preserved `git diff origin/dev -- src/cartsnitch_api/database.py src/cartsnitch_api/routes/health.py` is empty — the CAR-1077 production fix is preserved verbatim. ## CI expectation `lint` and `typecheck` are expected to be green. The `test` job will be **red** due to a pre-existing SQLite UUID test-fixture issue tracked separately under CAR-1132 / PR #42. This red `test` job is expected and is NOT a blocker for this promotion. ## Supersedes PR #43 (the direct conflicted dev→uat promotion) will be closed by CTO; this branch-based PR replaces it. cc @cpfarhood
Barcode Betty added 10 commits 2026-06-02 15:18:50 +00:00
Fix: strip PostgreSQL server_default from UUID + gen_random_bytes columns for SQLite tests
CI / lint (pull_request) Failing after 3s
CI / typecheck (pull_request) Failing after 19s
CI / test (pull_request) Failing after 16s
CI / build-and-push (pull_request) Has been skipped
CI / deploy-dev (pull_request) Has been skipped
CI / deploy-uat (pull_request) Has been skipped
6755ca8c27
The sync engine fixture (engine) and async engine fixture (db_engine) now
iterate all Base.metadata tables and null server_default on any column
whose SQL text contains 'gen_random_uuid' or 'gen_random_bytes'. This
covers all UUIDPrimaryKeyMixin columns (Purchase, PurchaseItem, Store,
StoreLocation, Coupon, NormalizedProduct, PriceHistory,
ShrinkflationEvent, UserStoreAccount) as well as the
email_inbound_token gen_random_bytes expression in User.

Without this, SQLite raises 'type UUID is not supported' when the ORM
tries to bind Python UUID objects, and NOT NULL constraint failures when
server_default expressions reference non-existent PostgreSQL functions.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Merge pull request 'Fix: strip PostgreSQL server_defaults from SQLite test fixtures' (#32) from betty/fix-email-inbound-token-tests into dev
CI / lint (push) Failing after 7s
CI / typecheck (push) Failing after 17s
CI / test (push) Failing after 18s
CI / build-and-push (push) Has been skipped
CI / deploy-uat (push) Has been skipped
CI / deploy-dev (push) Failing after 25s
1c42e4b0af
Merge PR #32: Fix SQLite server_default stripping for test fixtures
Remove deploy-dev/deploy-uat CI jobs (CAR-1069) (#37)
CI / lint (push) Failing after 3s
CI / typecheck (push) Failing after 19s
CI / lint (pull_request) Failing after 4s
CI / test (push) Failing after 30s
CI / build-and-push (push) Has been skipped
CI / typecheck (pull_request) Failing after 18s
CI / test (pull_request) Failing after 29s
CI / build-and-push (pull_request) Has been skipped
84c143c4e7
Co-authored-by: Barcode Betty <32+cs_betty@noreply.git.farh.net>
Co-committed-by: Barcode Betty <32+cs_betty@noreply.git.farh.net>
Fix SQLite server_default AttributeError and pool_size errors (#35)
CI / lint (push) Failing after 6s
CI / typecheck (push) Failing after 30s
CI / test (push) Failing after 1m34s
CI / build-and-push (push) Has been skipped
ebf69976d4
Fix SQLite server_default AttributeError and pool_size errors

Co-authored-by: Barcode Betty <32+cs_betty@noreply.git.farh.net>
Co-committed-by: Barcode Betty <32+cs_betty@noreply.git.farh.net>
Fix SQLite timestamp and UUID server_defaults in test fixtures
CI / lint (push) Failing after 5s
CI / typecheck (push) Failing after 32s
CI / test (push) Failing after 1m7s
CI / build-and-push (push) Has been skipped
bd6b137c68
Add _set_timestamp_defaults event listener to populate created_at/updated_at
before insert when using SQLite, since func.now() server_default is stripped.

Extended server_default stripping to include "now()" expressions for
timestamp columns (created_at, updated_at) that were failing with
NOT NULL constraint errors.

Fixes remaining CI test failures after PR #35:
- NOT NULL constraint failed: stores.created_at
- NOT NULL constraint failed: normalized_products.created_at

Co-Authored-By: Paperclip <noreply@paperclip.ing>
fix: /health returns 503 on DB failure, pool_timeout=30, CI typecheck fixes
CI / lint (pull_request) Failing after 4s
CI / typecheck (pull_request) Failing after 25s
CI / test (pull_request) Failing after 1m5s
CI / build-and-push (pull_request) Has been skipped
2b20946ad7
QA review of PR #39 (CAR-1121) identified three blocking issues; this
commit addresses all three plus the typecheck errors flagged as CI RED.

CAR-1077 (PR #39) changes:
- database.py: add pool_timeout=30 so the engine fails fast when the
  connection pool is exhausted (defends against the "server closed
  connection unexpectedly" pod failures).
- routes/health.py: /health now calls SELECT 1 through Depends(get_db)
  and raises HTTPException(503) when the database is unreachable, so
  Kubernetes readiness probes can correctly mark the pod unhealthy and
  stop routing traffic to it.  Logs the failure at exception level for
  observability.
- Drop .mcp.json from this PR (root-level MCP server config, not
  related to the pool fix; tracked separately).

CI typecheck fixes (pre-existing on dev, were failing mypy on PR #39):
- auth/passwords.py: cast bcrypt return values so mypy doesn't widen
  to Any.
- config.py: silence the false-positive call-arg on Settings() — the
  three required fields are populated from the environment by
  pydantic-settings at runtime.
- cache.py: coerce the bytes/str union returned by the redis client
  to the documented str | None return type.
- middleware/rate_limit.py: annotate the three module-level limiters
  with the RateLimitBackend protocol, cast the redis zrange score to
  float before arithmetic, and add max_requests/window_seconds to the
  protocol so the response-header builder can read them.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
style: fix ruff format in conftest.py
CI / lint (pull_request) Successful in 5s
CI / typecheck (pull_request) Successful in 29s
CI / test (pull_request) Failing after 1m0s
CI / build-and-push (pull_request) Has been skipped
76781ed238
Add missing blank line between the _set_timestamp_defaults helper
and the next top-level constant so `ruff format --check .` passes.
Pre-existing on dev's HEAD; surfaced after rebasing PR #39 onto dev
in 2b20946.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Fix PostgreSQL connection pool issues (CAR-1077) (#39)
CI / lint (push) Successful in 5s
CI / typecheck (push) Successful in 28s
CI / lint (pull_request) Successful in 6s
CI / test (push) Failing after 1m0s
CI / build-and-push (push) Has been skipped
CI / typecheck (pull_request) Successful in 29s
CI / test (pull_request) Failing after 1m2s
CI / build-and-push (pull_request) Has been skipped
7a7aaca064
QA approved by Checkout Charlie; CTO Dev review approved by Savannah Savings. Adds pool_timeout=30 and DB-connectivity /health probe. Strict CI improvement (lint+typecheck green); remaining test failure pre-existing on dev, tracked under CAR-1132/PR#42.
Merge origin/dev into uat: CAR-1077 (PostgreSQL connection pool fix)
CI / lint (pull_request) Successful in 4s
CI / typecheck (pull_request) Failing after 26s
CI / test (pull_request) Failing after 1m4s
CI / build-and-push (pull_request) Has been skipped
8f1ae26ce3
Conflicts in tests/conftest.py and tests/test_encrypted_json.py were
resolved in favor of origin/dev per CAR-1152. Dev is the source of
truth for this promotion: dev's version of the SQLite test fixtures
is a strict superset of uat's (adds hasattr guard for non-TextClause
server_default, strips additional PostgreSQL defaults, registers a
before_insert event listener for timestamp columns). No uat-only logic
was lost.

Production files (src/cartsnitch_api/database.py,
src/cartsnitch_api/routes/health.py) are unchanged from origin/dev.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Savannah Savings merged commit 2b9145ad04 into uat 2026-06-02 15:25:04 +00:00
Sign in to join this conversation.