Patch release rolling up live-migration findings and dogfood polish.
Fixes
Engine pool leak (7d8b9c3): every Celery task module was creating a fresh create_engine(...) per call; high-fire-rate tasks (import_media_file) exhausted Postgres max_connections. Centralized into backend/app/tasks/_sync_engine.py — one engine per worker process, reused across invocations.
pg_dump URL (ec44c65): strip SQLAlchemy +psycopg/+asyncpg driver suffix before handing the URL to libpq tools (backup/restore).
scan_directory idempotency (8f25b27): skip paths that already have a non-failed ImportTask so re-triggers don't 3× duplicate work.
Modal redirect bug (505dca1): <ImageViewer> now mounts globally in App.vue; tile clicks in Showcase/Artist views open as overlay instead of navigating to /gallery.
Ruff I001 spacing (061dc9e): collapse double blank line after imports in import_file.py.
UX
Thumbnail size 1.5× (6f68bf5): gallery + masonry grids ≈ 240/180px tiles; Settings view goes fluid; new subscription_count stat card.
SubscriptionsView redesign (d6eba8e): <v-data-table> of artists with expandable nested source rows (GS-style), replacing the per-artist section blocks.
Commits
505dca1 fix(ui): mount ImageViewer globally so tile clicks open as overlay, not route-redirect to /gallery
061dc9e fix(tasks): collapse double blank line between imports and IMAGES_ROOT in import_file.py (ruff I001)
7d8b9c3 fix(tasks): share one sync engine per worker process to stop connection-pool leak
8f25b27 fix(import): scan_directory skips paths with existing non-failed ImportTask
d6eba8e feat(ui): redesign /subscriptions as v-data-table with expandable source rows (GS-style)
6f68bf5 feat(ui): bump thumbnail sizes 1.5x, make Settings fluid, add subscription_count stat
ec44c65 fc5: strip SQLAlchemy +psycopg/+asyncpg driver suffix when passing URL to pg_dump/psql
Patch release rolling up live-migration findings and dogfood polish.
## Fixes
- **Engine pool leak** (`7d8b9c3`): every Celery task module was creating a fresh `create_engine(...)` per call; high-fire-rate tasks (`import_media_file`) exhausted Postgres `max_connections`. Centralized into `backend/app/tasks/_sync_engine.py` — one engine per worker process, reused across invocations.
- **pg_dump URL** (`ec44c65`): strip SQLAlchemy `+psycopg`/`+asyncpg` driver suffix before handing the URL to libpq tools (backup/restore).
- **scan_directory idempotency** (`8f25b27`): skip paths that already have a non-failed `ImportTask` so re-triggers don't 3× duplicate work.
- **Modal redirect bug** (`505dca1`): `<ImageViewer>` now mounts globally in `App.vue`; tile clicks in Showcase/Artist views open as overlay instead of navigating to `/gallery`.
- **Ruff I001 spacing** (`061dc9e`): collapse double blank line after imports in `import_file.py`.
## UX
- **Thumbnail size 1.5×** (`6f68bf5`): gallery + masonry grids ≈ 240/180px tiles; Settings view goes fluid; new `subscription_count` stat card.
- **SubscriptionsView redesign** (`d6eba8e`): `<v-data-table>` of artists with expandable nested source rows (GS-style), replacing the per-artist section blocks.
## Commits
```
505dca1 fix(ui): mount ImageViewer globally so tile clicks open as overlay, not route-redirect to /gallery
061dc9e fix(tasks): collapse double blank line between imports and IMAGES_ROOT in import_file.py (ruff I001)
7d8b9c3 fix(tasks): share one sync engine per worker process to stop connection-pool leak
8f25b27 fix(import): scan_directory skips paths with existing non-failed ImportTask
d6eba8e feat(ui): redesign /subscriptions as v-data-table with expandable source rows (GS-style)
6f68bf5 feat(ui): bump thumbnail sizes 1.5x, make Settings fluid, add subscription_count stat
ec44c65 fc5: strip SQLAlchemy +psycopg/+asyncpg driver suffix when passing URL to pg_dump/psql
```
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Patch release rolling up live-migration findings and dogfood polish.
Fixes
7d8b9c3): every Celery task module was creating a freshcreate_engine(...)per call; high-fire-rate tasks (import_media_file) exhausted Postgresmax_connections. Centralized intobackend/app/tasks/_sync_engine.py— one engine per worker process, reused across invocations.ec44c65): strip SQLAlchemy+psycopg/+asyncpgdriver suffix before handing the URL to libpq tools (backup/restore).8f25b27): skip paths that already have a non-failedImportTaskso re-triggers don't 3× duplicate work.505dca1):<ImageViewer>now mounts globally inApp.vue; tile clicks in Showcase/Artist views open as overlay instead of navigating to/gallery.061dc9e): collapse double blank line after imports inimport_file.py.UX
6f68bf5): gallery + masonry grids ≈ 240/180px tiles; Settings view goes fluid; newsubscription_countstat card.d6eba8e):<v-data-table>of artists with expandable nested source rows (GS-style), replacing the per-artist section blocks.Commits