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:
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -62,6 +62,7 @@ export function ColorsView() {
|
||||
representative: uncolored[0],
|
||||
})
|
||||
}
|
||||
result.sort((a, b) => b.count - a.count)
|
||||
return result
|
||||
}, [allPhotos])
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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])
|
||||
|
||||
|
||||
@@ -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]
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user