Skip to content

fix: @thumbor-auth prefers storage conn over psycopg pool (related to #8) - #10

Merged
jensens merged 1 commit into
mainfrom
fix/thumbor-auth-use-storage-connection
Apr 20, 2026
Merged

jensens merged 1 commit into
mainfrom
fix/thumbor-auth-use-storage-connection

Conversation

@jensens

@jensens jensens commented Apr 20, 2026

Copy link
Copy Markdown
Member

Summary

  • Follow-up to fix: drop per-image SQL from _needs_auth_url (closes #8) #9 targeting the other per-image SQL site in this repo: ThumborAuthService in restapi.py.
  • Prefers get_storage_connection(self.context) — the ZODB storage's PG connection already held for the request — over pool.getconn(), eliminating pool contention for the @thumbor-auth code path.
  • SQL query and response semantics are unchanged — this is strictly a connection-acquisition change.

Why minimal (not a full rewrite)

Unlike _needs_auth_url (closed by #9), this service answers a multi-principal question:

Does the user's principal set (['Anonymous', 'user:alice', 'Manager', …]) overlap with this object's allowed_roles?

rolesForPermissionOn alone is not sufficient here — allowed_roles also carries user:<id> tokens from local-role grants, which rolesForPermissionOn doesn't return. A full Zope-native rewrite (load the object, ask checkPermission("View", obj) against the current security manager) is a larger change, trades one PG round-trip for one ZODB load, and changes semantics (live vs. cached). Worth considering separately, but out of scope for the pool-saturation fix.

This PR is the smallest change that stops @thumbor-auth from contending on the psycopg pool. It:

Behaviour matrix (unchanged from before)

Scenario Status Body
Principals overlap allowed_roles 200 {}
No overlap 401 {"error": "Unauthorized"}
zoid missing / non-hex 400 {"error": ...}
zoid not in object_state 404 {"error": "Not found"}
PG error 503 {"error": "Service unavailable"}

Test plan

  • New test: test_prefers_storage_connection_over_pool — verifies get_storage_connection is called, get_pool / get_request_connection are not.
  • New test: test_falls_back_to_pool_when_no_storage_connection — verifies pool path still works when no storage conn is available.
  • Updated _patch_dependencies helper and test_db_error_returns_503 to patch the new import.
  • Full suite: 150/150 passing.

🤖 Generated with Claude Code

The REST service's per-image SQL auth check called pool.getconn(),
which contends with other request-scoped catalog queries for the
same per-pod psycopg pool. Under cold-cache production load this
was a contributor to the PoolTimeout incident (#8).

Prefer the ZODB storage connection (already held for the request)
so the auth check doesn't touch the pool at all. Falls back to the
pool when no ZODB storage is in scope (tests, scripts, non-Zope
contexts).

The SQL itself is unchanged — semantics preserved.

Related to #8.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jensens
jensens merged commit d2471e1 into main Apr 20, 2026
4 checks passed
@jensens
jensens deleted the fix/thumbor-auth-use-storage-connection branch April 20, 2026 00:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant