make pipeline responsive at scale: cap review query, debounce sse reload, indexable done count
Build and Push Docker Image / build (push) Successful in 37s

The pipeline endpoint returned every pending plan (no LIMIT) while the audio
list capped at 500 — that alone was the main lag. SSE compounded it: every
job_update (which fires per-line of running ffmpeg output) re-ran the entire
endpoint and re-rendered every card.

- review query: LIMIT 500 + a separate COUNT for reviewTotal; column header
  shows 'X of Y' and a footer 'Showing first X of Y. Approve some to see
  the rest' when truncated
- doneCount: split the OR-form into two indexable counts (is_noop + done&!noop),
  added together — uses idx_review_plans_is_noop and idx_review_plans_status
  instead of full scan
- pipeline page: 1s debounce on SSE-triggered reload so a burst of
  job_update events collapses into one refetch
This commit is contained in:
2026-04-13 10:00:08 +02:00
parent 9ee0dd445f
commit ec28e43484
3 changed files with 46 additions and 19 deletions
+9 -2
View File
@@ -4,11 +4,13 @@ import { SeriesCard } from "./SeriesCard";
interface ReviewColumnProps {
items: any[];
total: number;
jellyfinUrl: string;
onMutate: () => void;
}
export function ReviewColumn({ items, jellyfinUrl, onMutate }: ReviewColumnProps) {
export function ReviewColumn({ items, total, jellyfinUrl, onMutate }: ReviewColumnProps) {
const truncated = total > items.length;
// Group by series (movies are standalone)
const movies = items.filter((i: any) => i.type === "Movie");
const seriesMap = new Map<string, { name: string; key: string; jellyfinId: string | null; episodes: any[] }>();
@@ -45,7 +47,7 @@ export function ReviewColumn({ items, jellyfinUrl, onMutate }: ReviewColumnProps
return (
<div className="flex flex-col w-96 min-w-96 min-h-0 bg-gray-50 rounded-lg">
<div className="px-3 py-2 border-b font-medium text-sm">
Review <span className="text-gray-400">({items.length})</span>
Review <span className="text-gray-400">({truncated ? `${items.length} of ${total}` : total})</span>
</div>
<div className="flex-1 overflow-y-auto p-2 space-y-2">
{allItems.map((entry) => {
@@ -78,6 +80,11 @@ export function ReviewColumn({ items, jellyfinUrl, onMutate }: ReviewColumnProps
}
})}
{allItems.length === 0 && <p className="text-sm text-gray-400 text-center py-8">No items to review</p>}
{truncated && (
<p className="text-xs text-gray-400 text-center py-3 border-t mt-2">
Showing first {items.length} of {total}. Approve some to see the rest.
</p>
)}
</div>
</div>
);