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

This commit is contained in:
Jaret Burkett
2026-03-30 10:46:25 -06:00
parent a484e55d66
commit b43ea6c2d3
2 changed files with 24 additions and 13 deletions

View File

@@ -5,8 +5,18 @@ import path from 'path';
import { getDatasetsRoot } from '@/server/settings';
export async function POST(request: NextRequest) {
const body = await request.json();
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 { imgPath } = body;
console.log('Received POST request for caption:', imgPath);
try {

View File

@@ -28,18 +28,19 @@ const DatasetImageCard: React.FC<DatasetImageCardProps> = ({
const [isCaptionLoaded, setIsCaptionLoaded] = useState<boolean>(false);
const [caption, setCaption] = useState<string>('');
const [savedCaption, setSavedCaption] = useState<string>('');
const isGettingCaption = useRef<boolean>(false);
const abortControllerRef = useRef<AbortController | null>(null);
const fetchCaption = async () => {
if (isGettingCaption.current || isCaptionLoaded) return;
isGettingCaption.current = true;
if (isCaptionLoaded) return;
abortControllerRef.current?.abort();
const controller = new AbortController();
abortControllerRef.current = controller;
apiClient
.post(`/api/caption/get`, { imgPath: imageUrl })
.post(`/api/caption/get`, { imgPath: imageUrl }, { signal: controller.signal })
.then(res => res.data)
.then(data => {
console.log('Caption fetched:', data);
if (data) {
// fix issue where caption could be non string
data = `${data}`;
}
setCaption(data || '');
@@ -47,10 +48,13 @@ const DatasetImageCard: React.FC<DatasetImageCardProps> = ({
setIsCaptionLoaded(true);
})
.catch(error => {
if (controller.signal.aborted) return;
console.error('Error fetching caption:', error);
})
.finally(() => {
isGettingCaption.current = false;
if (abortControllerRef.current === controller) {
abortControllerRef.current = null;
}
});
};
@@ -88,6 +92,8 @@ const DatasetImageCard: React.FC<DatasetImageCardProps> = ({
}
} else {
setInViewport(false);
// Cancel any in-flight caption fetch when scrolling away
abortControllerRef.current?.abort();
}
},
{ threshold: 0.1 },
@@ -199,11 +205,6 @@ const DatasetImageCard: React.FC<DatasetImageCardProps> = ({
</button>
</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
className={classNames('w-full p-2 bg-gray-800 text-white text-sm rounded-b-lg h-[75px]', {