Add batch upload endpoint to avoid sequential upload+OCR bottleneck

Client sends all files in a single request to /api/upload/batch,
server receives them all upfront via multer then processes OCR
sequentially. Eliminates network round-trips between each file.
This commit is contained in:
Joey Yakimowich-Payne 2026-02-19 14:00:20 -07:00
commit bce534486c
2 changed files with 76 additions and 9 deletions

View file

@ -730,17 +730,19 @@ export const useGame = (defaultGameConfig?: GameConfig) => {
};
}, []);
const uploadDocument = async (file: File, useOcr: boolean = false, maxRetries = 5): Promise<ProcessedDocument> => {
const uploadDocuments = async (files: File[], useOcr: boolean = false, maxRetries = 5): Promise<ProcessedDocument[]> => {
if (!auth.user?.access_token) {
throw new Error('Authentication required to upload documents');
}
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const formData = new FormData();
formData.append('document', file);
for (const file of files) {
formData.append('documents', file);
}
formData.append('useOcr', String(useOcr));
const response = await fetch(`${BACKEND_URL}/api/upload`, {
const response = await fetch(`${BACKEND_URL}/api/upload/batch`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${auth.user.access_token}`,
@ -758,13 +760,13 @@ export const useGame = (defaultGameConfig?: GameConfig) => {
if (!response.ok) {
const error = await response.json();
throw new Error(error.error || 'Failed to upload document');
throw new Error(error.error || 'Failed to upload documents');
}
return response.json();
}
throw new Error('Failed to upload document after multiple retries');
throw new Error('Failed to upload documents after multiple retries');
};
const startQuizGen = async (options: {
@ -785,10 +787,7 @@ export const useGame = (defaultGameConfig?: GameConfig) => {
let documents: ProcessedDocument[] | undefined;
if (options.files && options.files.length > 0) {
documents = [];
for (const file of options.files) {
documents.push(await uploadDocument(file, options.useOcr));
}
documents = await uploadDocuments(options.files, options.useOcr);
}
const generateOptions: GenerateQuizOptions = {