Queue concurrent uploads instead of rejecting with 503
Server: replace hard 503 rejection with a bounded queue (50 slots, 2min timeout) so requests wait for a processing slot instead of failing. Client: upload files sequentially instead of via Promise.all, and retry with exponential backoff on 503/504 responses.
This commit is contained in:
parent
4cbc3163de
commit
b52d6b1a6f
2 changed files with 66 additions and 21 deletions
|
|
@ -730,29 +730,41 @@ export const useGame = (defaultGameConfig?: GameConfig) => {
|
|||
};
|
||||
}, []);
|
||||
|
||||
const uploadDocument = async (file: File, useOcr: boolean = false): Promise<ProcessedDocument> => {
|
||||
const uploadDocument = async (file: File, useOcr: boolean = false, maxRetries = 5): Promise<ProcessedDocument> => {
|
||||
if (!auth.user?.access_token) {
|
||||
throw new Error('Authentication required to upload documents');
|
||||
}
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('document', file);
|
||||
formData.append('useOcr', String(useOcr));
|
||||
|
||||
const response = await fetch(`${BACKEND_URL}/api/upload`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${auth.user.access_token}`,
|
||||
},
|
||||
body: formData
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const error = await response.json();
|
||||
throw new Error(error.error || 'Failed to upload document');
|
||||
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
||||
const formData = new FormData();
|
||||
formData.append('document', file);
|
||||
formData.append('useOcr', String(useOcr));
|
||||
|
||||
const response = await fetch(`${BACKEND_URL}/api/upload`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${auth.user.access_token}`,
|
||||
},
|
||||
body: formData
|
||||
});
|
||||
|
||||
if (response.status === 503 || response.status === 504) {
|
||||
if (attempt < maxRetries) {
|
||||
const delay = Math.min(1000 * 2 ** attempt, 15000);
|
||||
await new Promise(r => setTimeout(r, delay));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
const error = await response.json();
|
||||
throw new Error(error.error || 'Failed to upload document');
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
|
||||
return response.json();
|
||||
throw new Error('Failed to upload document after multiple retries');
|
||||
};
|
||||
|
||||
const startQuizGen = async (options: {
|
||||
|
|
@ -773,9 +785,10 @@ export const useGame = (defaultGameConfig?: GameConfig) => {
|
|||
|
||||
let documents: ProcessedDocument[] | undefined;
|
||||
if (options.files && options.files.length > 0) {
|
||||
documents = await Promise.all(
|
||||
options.files.map(file => uploadDocument(file, options.useOcr))
|
||||
);
|
||||
documents = [];
|
||||
for (const file of options.files) {
|
||||
documents.push(await uploadDocument(file, options.useOcr));
|
||||
}
|
||||
}
|
||||
|
||||
const generateOptions: GenerateQuizOptions = {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue