fix: reduce db pool size to prevent connection exhaustion, sort grouped views by count

Pool was 20+10 overflow per engine; uvicorn --reload leaked pools until
Postgres hit max_connections=100. Reduced to 5+5 with pool_pre_ping.

Grouped views (tags, people, colors, rated) now sort cards largest-first.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
root
2026-04-12 21:32:05 +02:00
parent d933ea3842
commit 03a4c75e3e
6 changed files with 17 additions and 5 deletions

View File

@@ -26,7 +26,8 @@ class PerformanceSettings(BaseModel):
"""Performance tuning settings"""
max_concurrent_thumbnails: int = 10
cache_ttl: int = 3600
db_pool_size: int = 20
db_pool_size: int = 5
db_pool_max_overflow: int = 5
db_pool_recycle: int = 3600
class EmbedderSettings(BaseModel):

View File

@@ -73,7 +73,9 @@ else:
settings.database_url,
echo=False,
pool_size=settings.performance.db_pool_size,
max_overflow=settings.performance.db_pool_max_overflow,
pool_recycle=settings.performance.db_pool_recycle,
pool_pre_ping=True,
)
# Create async session factory

View File

@@ -62,6 +62,7 @@ export function ColorsView() {
representative: uncolored[0],
})
}
result.sort((a, b) => b.count - a.count)
return result
}, [allPhotos])

View File

@@ -1,4 +1,4 @@
import { useState, useCallback } from 'react'
import { useState, useCallback, useMemo } from 'react'
import { Users, Pencil, Check, X, Loader2, ArrowLeft } from 'lucide-react'
import clsx from 'clsx'
import { useMutation, useQueryClient } from '@tanstack/react-query'
@@ -19,7 +19,11 @@ import { toast } from '../ToastContainer'
* 2. Detail view showing a person's photos in the full Timeline — Esc to go back
*/
export function PeopleView() {
const { data: clusters = [], isLoading } = useTagsQuery('face_cluster')
const { data: rawClusters = [], isLoading } = useTagsQuery('face_cluster')
const clusters = useMemo(
() => [...rawClusters].sort((a, b) => b.photo_count - a.photo_count),
[rawClusters]
)
const queryClient = useQueryClient()
const setTagIds = useFilterStore((s) => s.setTagIds)

View File

@@ -37,7 +37,7 @@ export function RatedView() {
}
}
// Highest rating first
// Sort by count, biggest first
const result: RatingGroup[] = []
for (let r = 5; r >= 1; r--) {
const photos = buckets.get(r) ?? []
@@ -49,6 +49,7 @@ export function RatedView() {
representative: photos[0],
})
}
result.sort((a, b) => b.count - a.count)
return result
}, [allPhotos])

View File

@@ -19,7 +19,10 @@ export function TagsView() {
// Exclude face_cluster tags (those live in PeopleView)
const tags = useMemo(
() => allTags.filter((t) => t.kind !== 'face_cluster'),
() =>
allTags
.filter((t) => t.kind !== 'face_cluster')
.sort((a, b) => b.photo_count - a.photo_count),
[allTags]
)