Abort caption requests when they are not in view to tax the server less.

This commit is contained in:
Jaret Burkett committed 2026-03-30 10:46:25 -06:00
1 parent a484e55d66
commit b43ea6c2d3
2 files changed
+23 -12

No files matched your search

+11 -1
View File
@@ -5,8 +5,18 @@ import path from 'path';
import { getDatasetsRoot } from '@/server/settings'; import { getDatasetsRoot } from '@/server/settings';
export async function POST(request: NextRequest) { export async function POST(request: NextRequest) {
let body;
try {
body = await request.json();
} catch {
// Client aborted the request before body was fully sent
return new NextResponse(null, { status: 499 });
}
if (request.signal.aborted) {
return new NextResponse(null, { status: 499 });
}
const body = await request.json();
const { imgPath } = body; const { imgPath } = body;
console.log('Received POST request for caption:', imgPath); console.log('Received POST request for caption:', imgPath);
try { try {
+12 -11
View File
@@ -28,18 +28,19 @@ const DatasetImageCard: React.FC<DatasetImageCardProps> = ({
const [isCaptionLoaded, setIsCaptionLoaded] = useState<boolean>(false); const [isCaptionLoaded, setIsCaptionLoaded] = useState<boolean>(false);
const [caption, setCaption] = useState<string>(''); const [caption, setCaption] = useState<string>('');
const [savedCaption, setSavedCaption] = useState<string>(''); const [savedCaption, setSavedCaption] = useState<string>('');
const isGettingCaption = useRef<boolean>(false); const abortControllerRef = useRef<AbortController | null>(null);
const fetchCaption = async () => { const fetchCaption = async () => {
if (isGettingCaption.current || isCaptionLoaded) return; if (isCaptionLoaded) return;
isGettingCaption.current = true; abortControllerRef.current?.abort();
const controller = new AbortController();
abortControllerRef.current = controller;
apiClient apiClient
.post(`/api/caption/get`, { imgPath: imageUrl }) .post(`/api/caption/get`, { imgPath: imageUrl }, { signal: controller.signal })
.then(res => res.data) .then(res => res.data)
.then(data => { .then(data => {
console.log('Caption fetched:', data); console.log('Caption fetched:', data);
if (data) { if (data) {
// fix issue where caption could be non string
data = `${data}`; data = `${data}`;
} }
setCaption(data || ''); setCaption(data || '');
@@ -47,10 +48,13 @@ const DatasetImageCard: React.FC<DatasetImageCardProps> = ({
setIsCaptionLoaded(true); setIsCaptionLoaded(true);
}) })
.catch(error => { .catch(error => {
if (controller.signal.aborted) return;
console.error('Error fetching caption:', error); console.error('Error fetching caption:', error);
}) })
.finally(() => { .finally(() => {
isGettingCaption.current = false; if (abortControllerRef.current === controller) {
abortControllerRef.current = null;
}
}); });
}; };
@@ -88,6 +92,8 @@ const DatasetImageCard: React.FC<DatasetImageCardProps> = ({
} }
} else { } else {
setInViewport(false); setInViewport(false);
// Cancel any in-flight caption fetch when scrolling away
abortControllerRef.current?.abort();
} }
}, },
{ threshold: 0.1 }, { threshold: 0.1 },
@@ -199,11 +205,6 @@ const DatasetImageCard: React.FC<DatasetImageCardProps> = ({
</button> </button>
</div> </div>
</div> </div>
{inViewport && isVisible && !isItAudio && (
<div className="text-xs text-gray-100 bg-gray-950 mt-1 absolute bottom-0 left-0 p-1 opacity-25 hover:opacity-90 transition-opacity duration-300 w-full">
{imageUrl}
</div>
)}
</div> </div>
<div <div
className={classNames('w-full p-2 bg-gray-800 text-white text-sm rounded-b-lg h-[75px]', { className={classNames('w-full p-2 bg-gray-800 text-white text-sm rounded-b-lg h-[75px]', {