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"""
|
"""Performance tuning settings"""
|
||||||
max_concurrent_thumbnails: int = 10
|
max_concurrent_thumbnails: int = 10
|
||||||
cache_ttl: int = 3600
|
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
|
db_pool_recycle: int = 3600
|
||||||
|
|
||||||
class EmbedderSettings(BaseModel):
|
class EmbedderSettings(BaseModel):
|
||||||
|
|||||||
@@ -73,7 +73,9 @@ else:
|
|||||||
settings.database_url,
|
settings.database_url,
|
||||||
echo=False,
|
echo=False,
|
||||||
pool_size=settings.performance.db_pool_size,
|
pool_size=settings.performance.db_pool_size,
|
||||||
|
max_overflow=settings.performance.db_pool_max_overflow,
|
||||||
pool_recycle=settings.performance.db_pool_recycle,
|
pool_recycle=settings.performance.db_pool_recycle,
|
||||||
|
pool_pre_ping=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create async session factory
|
# Create async session factory
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ export function ColorsView() {
|
|||||||
representative: uncolored[0],
|
representative: uncolored[0],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
result.sort((a, b) => b.count - a.count)
|
||||||
return result
|
return result
|
||||||
}, [allPhotos])
|
}, [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 { Users, Pencil, Check, X, Loader2, ArrowLeft } from 'lucide-react'
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query'
|
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
|
* 2. Detail view showing a person's photos in the full Timeline — Esc to go back
|
||||||
*/
|
*/
|
||||||
export function PeopleView() {
|
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 queryClient = useQueryClient()
|
||||||
const setTagIds = useFilterStore((s) => s.setTagIds)
|
const setTagIds = useFilterStore((s) => s.setTagIds)
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export function RatedView() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Highest rating first
|
// Sort by count, biggest first
|
||||||
const result: RatingGroup[] = []
|
const result: RatingGroup[] = []
|
||||||
for (let r = 5; r >= 1; r--) {
|
for (let r = 5; r >= 1; r--) {
|
||||||
const photos = buckets.get(r) ?? []
|
const photos = buckets.get(r) ?? []
|
||||||
@@ -49,6 +49,7 @@ export function RatedView() {
|
|||||||
representative: photos[0],
|
representative: photos[0],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
result.sort((a, b) => b.count - a.count)
|
||||||
return result
|
return result
|
||||||
}, [allPhotos])
|
}, [allPhotos])
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,10 @@ export function TagsView() {
|
|||||||
|
|
||||||
// Exclude face_cluster tags (those live in PeopleView)
|
// Exclude face_cluster tags (those live in PeopleView)
|
||||||
const tags = useMemo(
|
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]
|
[allTags]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user