Allow large activity Excel imports (40k+ rows) with bigger chunks and caches.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-03 17:42:11 +03:30
co-authored by Cursor
parent beae16437b
commit c629729a9a
4 changed files with 96 additions and 22 deletions
+23 -2
View File
@@ -103,9 +103,11 @@ async function postImportChunk(opts: {
}
if (opts.sessionId) form.append('sessionId', opts.sessionId);
if (opts.offset != null) form.append('offset', String(opts.offset));
form.append('limit', '250');
const { data } = await api.post<ImportContactsResult>(props.importPath, form, {
headers: { 'Content-Type': undefined },
timeout: 3 * 60 * 1000,
// خواندن فایل‌های خیلی بزرگ در مرحلهٔ اول ممکن است طول بکشد
timeout: opts.file ? 10 * 60 * 1000 : 3 * 60 * 1000,
});
return data;
}
@@ -118,8 +120,9 @@ async function runChunkedImport(file: File, map?: Record<string, string>) {
let sessionId: string | undefined;
let offset = 0;
let guard = 0;
const maxChunks = 2000;
while (guard < 500) {
while (guard < maxChunks) {
guard += 1;
const part = await postImportChunk({
file: sessionId ? undefined : file,
@@ -135,11 +138,28 @@ async function runChunkedImport(file: File, map?: Record<string, string>) {
progressLabel.value = `ورود چندمرحله‌ای: ${processed.toLocaleString('fa-IR')} از ${total.toLocaleString('fa-IR')} ردیف`;
}
// خطای سراسری (مثلاً سقف ردیف) — ادامه نده
if (
part.errors?.some((e) => e.row === 1 && /بیش از .* ردیف/.test(e.message))
) {
break;
}
if (!part.hasMore || !part.sessionId) break;
sessionId = part.sessionId;
offset = part.nextOffset ?? processed;
}
if (guard >= maxChunks && acc.hasMore) {
acc.errors = [
...acc.errors,
{
row: 1,
message: 'ورود به‌خاطر تعداد مراحل زیاد متوقف شد. از جایی که مانده ادامه دهید یا فایل را تقسیم کنید.',
},
];
}
return acc;
}
@@ -164,6 +184,7 @@ async function onFile(ev: Event) {
form.append('file', file);
const { data } = await api.post<ExcelPreviewResult>(props.previewPath, form, {
headers: { 'Content-Type': undefined },
timeout: 5 * 60 * 1000,
});
if (!data.needsMapping) {
try {