fix: HEIC vips fallback, DB pool exhaustion, auth session persistence

HEIC thumbnails:
- Switch fallback from ffmpeg to vips for HEIC files that pillow-heif
  rejects. ffmpeg decoded gain map tiles instead of the primary image,
  producing inverted/negative thumbnails. vips uses libheif's item
  references correctly and extracts the full-resolution primary image.

Database pool exhaustion:
- Add idle_in_transaction_session_timeout=60s so Postgres auto-kills
  leaked connections from disconnected thumbnail requests.
- Add pool_timeout=10 so new requests fail fast instead of hanging.
- Bump pool from 5+5 to 10+10 for thumbnail concurrency headroom.
- get_db rolls back on exception before closing.

Auth session persistence:
- Narrow 401 interceptor exclusion to only /auth/refresh and /auth/login
  (was excluding all /auth/* including /auth/me, preventing token refresh
  on boot).
- fetchMe only clears tokens on 401/403, not network errors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
root
2026-04-13 15:25:55 +02:00
parent 2adaaf18a1
commit ecd8bbe61d
4 changed files with 39 additions and 18 deletions

View File

@@ -76,6 +76,10 @@ else:
max_overflow=settings.performance.db_pool_max_overflow,
pool_recycle=settings.performance.db_pool_recycle,
pool_pre_ping=True,
pool_timeout=10, # fail fast if pool exhausted (default 30)
# Kill connections idle in a transaction for >60s. Prevents leaked
# sessions from thumbnail requests that disconnect mid-flight.
connect_args={"server_settings": {"idle_in_transaction_session_timeout": "60000"}},
)
# Create async session factory
@@ -89,10 +93,17 @@ AsyncSessionLocal = async_sessionmaker(
Base = declarative_base()
async def get_db() -> AsyncSession:
"""Dependency to get database session"""
"""Dependency to get database session.
Rolls back any uncommitted transaction before closing so a client
disconnect doesn't leave idle-in-transaction connections in the pool.
"""
async with AsyncSessionLocal() as session:
try:
yield session
except Exception:
await session.rollback()
raise
finally:
await session.close()