fix(import): timeout and retry existing-table column load
This commit is contained in:
1 parent
7f7f011f40
commit
a2e4d15bbc
10 files changed
+43
-4
No files matched your search
@@ -64,6 +64,25 @@ interface BatchImportTask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const SKIP_VALUE = "__skip__";
|
const SKIP_VALUE = "__skip__";
|
||||||
|
const TARGET_COLUMNS_TIMEOUT_MS = 15000;
|
||||||
|
const TARGET_COLUMNS_TIMEOUT = Symbol("target-columns-timeout");
|
||||||
|
|
||||||
|
function withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {
|
||||||
|
return new Promise<T>((resolve, reject) => {
|
||||||
|
const timer = setTimeout(() => reject(TARGET_COLUMNS_TIMEOUT), ms);
|
||||||
|
promise.then(
|
||||||
|
(value) => {
|
||||||
|
clearTimeout(timer);
|
||||||
|
resolve(value);
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
clearTimeout(timer);
|
||||||
|
reject(error);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const targetColumns = ref<ColumnInfo[]>([]);
|
const targetColumns = ref<ColumnInfo[]>([]);
|
||||||
const loadedTargetTableName = ref("");
|
const loadedTargetTableName = ref("");
|
||||||
const existingTableNames = ref<string[]>([]);
|
const existingTableNames = ref<string[]>([]);
|
||||||
@@ -519,7 +538,7 @@ async function loadTargetColumns() {
|
|||||||
errorMessage.value = "";
|
errorMessage.value = "";
|
||||||
try {
|
try {
|
||||||
await store.ensureConnected(props.prefillConnectionId);
|
await store.ensureConnected(props.prefillConnectionId);
|
||||||
const columns = await api.getColumns(props.prefillConnectionId, props.prefillDatabase, targetSchema.value, tableName);
|
const columns = await withTimeout(api.getColumns(props.prefillConnectionId, props.prefillDatabase, targetSchema.value, tableName), TARGET_COLUMNS_TIMEOUT_MS);
|
||||||
if (requestId !== targetColumnsRequestId) return;
|
if (requestId !== targetColumnsRequestId) return;
|
||||||
targetColumns.value = columns;
|
targetColumns.value = columns;
|
||||||
loadedTargetTableName.value = tableName;
|
loadedTargetTableName.value = tableName;
|
||||||
@@ -529,7 +548,7 @@ async function loadTargetColumns() {
|
|||||||
targetColumns.value = [];
|
targetColumns.value = [];
|
||||||
loadedTargetTableName.value = "";
|
loadedTargetTableName.value = "";
|
||||||
columnMapping.value = {};
|
columnMapping.value = {};
|
||||||
errorMessage.value = String(e?.message || e);
|
errorMessage.value = e === TARGET_COLUMNS_TIMEOUT ? t("tableImport.targetColumnsTimeout") : String(e?.message || e);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if (requestId === targetColumnsRequestId) loadingTarget.value = false;
|
if (requestId === targetColumnsRequestId) loadingTarget.value = false;
|
||||||
@@ -1555,8 +1574,11 @@ watch(rawProgressPercent, (percent) => {
|
|||||||
<Loader2 class="h-3.5 w-3.5 animate-spin" />
|
<Loader2 class="h-3.5 w-3.5 animate-spin" />
|
||||||
{{ t("common.loading") }}
|
{{ t("common.loading") }}
|
||||||
</div>
|
</div>
|
||||||
<div v-if="errorMessage && wizardStep !== 'execution'" class="rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-xs text-destructive">
|
<div v-if="errorMessage && wizardStep !== 'execution'" class="flex items-center gap-2 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-xs text-destructive">
|
||||||
{{ errorMessage }}
|
<span class="flex-1">{{ errorMessage }}</span>
|
||||||
|
<Button v-if="targetMode === 'existing' && !loadingTarget && !existingTargetMetadataReady" variant="outline" size="sm" class="h-6 px-2 text-xs" @click="loadTargetColumns()">
|
||||||
|
{{ t("tableImport.retry") }}
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
+1
@@ -268,6 +268,7 @@ describe("TableImportDialog existing targets", () => {
|
|||||||
await vi.waitFor(() => {
|
await vi.waitFor(() => {
|
||||||
expect(mocks.getColumns).toHaveBeenCalledWith("connection-1", "main", "main", "existing_target");
|
expect(mocks.getColumns).toHaveBeenCalledWith("connection-1", "main", "main", "existing_target");
|
||||||
});
|
});
|
||||||
|
await vi.waitFor(() => expect(buttonContaining("Next")?.disabled).toBe(false));
|
||||||
|
|
||||||
buttonContaining("Next")?.click();
|
buttonContaining("Next")?.click();
|
||||||
await flushAsyncUpdates();
|
await flushAsyncUpdates();
|
||||||
|
|||||||
@@ -5536,6 +5536,8 @@ export default {
|
|||||||
searchExistingTables: "Search tables...",
|
searchExistingTables: "Search tables...",
|
||||||
loadingTables: "Loading tables...",
|
loadingTables: "Loading tables...",
|
||||||
noTables: "No tables available",
|
noTables: "No tables available",
|
||||||
|
targetColumnsTimeout: "Loading target table columns timed out. Check the connection and try again.",
|
||||||
|
retry: "Retry",
|
||||||
stepSource: "Source",
|
stepSource: "Source",
|
||||||
stepOptions: "Options",
|
stepOptions: "Options",
|
||||||
stepMapping: "Mapping",
|
stepMapping: "Mapping",
|
||||||
|
|||||||
@@ -5331,6 +5331,8 @@ export default withEnglishFallback({
|
|||||||
status_done: "Import complete",
|
status_done: "Import complete",
|
||||||
status_error: "Import failed",
|
status_error: "Import failed",
|
||||||
status_cancelled: "Import cancelled",
|
status_cancelled: "Import cancelled",
|
||||||
|
targetColumnsTimeout: "Se agotó el tiempo de espera al cargar los campos de la tabla de destino. Compruebe la conexión e inténtelo de nuevo.",
|
||||||
|
retry: "Reintentar",
|
||||||
},
|
},
|
||||||
dataGenerate: {
|
dataGenerate: {
|
||||||
title: "Generación de datos",
|
title: "Generación de datos",
|
||||||
|
|||||||
@@ -5329,6 +5329,8 @@ export default withEnglishFallback({
|
|||||||
status_done: "Import complete",
|
status_done: "Import complete",
|
||||||
status_error: "Import failed",
|
status_error: "Import failed",
|
||||||
status_cancelled: "Import cancelled",
|
status_cancelled: "Import cancelled",
|
||||||
|
targetColumnsTimeout: "Timeout nel caricamento dei campi della tabella di destinazione. Controlla la connessione e riprova.",
|
||||||
|
retry: "Riprova",
|
||||||
},
|
},
|
||||||
dataGenerate: {
|
dataGenerate: {
|
||||||
title: "Generazione dati",
|
title: "Generazione dati",
|
||||||
|
|||||||
@@ -5367,6 +5367,8 @@ export default withEnglishFallback({
|
|||||||
titleRow: "ヘッダー行(0 はなし)",
|
titleRow: "ヘッダー行(0 はなし)",
|
||||||
dataStartRow: "データ開始行",
|
dataStartRow: "データ開始行",
|
||||||
lastDataRow: "データ終了行(0 は末尾まで)",
|
lastDataRow: "データ終了行(0 は末尾まで)",
|
||||||
|
targetColumnsTimeout: "ターゲットテーブルのフィールド読み込みがタイムアウトしました。接続を確認して再試行してください。",
|
||||||
|
retry: "再試行",
|
||||||
},
|
},
|
||||||
dataGenerate: {
|
dataGenerate: {
|
||||||
title: "データ生成",
|
title: "データ生成",
|
||||||
|
|||||||
@@ -5028,6 +5028,8 @@ export default withEnglishFallback({
|
|||||||
status_done: "가져오기 완료",
|
status_done: "가져오기 완료",
|
||||||
status_error: "가져오기 실패",
|
status_error: "가져오기 실패",
|
||||||
status_cancelled: "가져오기 취소됨",
|
status_cancelled: "가져오기 취소됨",
|
||||||
|
targetColumnsTimeout: "대상 테이블 필드를 로드하는 시간이 초과되었습니다. 연결을 확인한 후 다시 시도하십시오.",
|
||||||
|
retry: "재시도",
|
||||||
},
|
},
|
||||||
dataGenerate: {
|
dataGenerate: {
|
||||||
title: "데이터 생성",
|
title: "데이터 생성",
|
||||||
|
|||||||
@@ -5331,6 +5331,8 @@ export default withEnglishFallback({
|
|||||||
status_done: "Import complete",
|
status_done: "Import complete",
|
||||||
status_error: "Import failed",
|
status_error: "Import failed",
|
||||||
status_cancelled: "Import cancelled",
|
status_cancelled: "Import cancelled",
|
||||||
|
targetColumnsTimeout: "Tempo esgotado ao carregar os campos da tabela de destino. Verifique a conexão e tente novamente.",
|
||||||
|
retry: "Tentar novamente",
|
||||||
},
|
},
|
||||||
dataGenerate: {
|
dataGenerate: {
|
||||||
title: "Geração de dados",
|
title: "Geração de dados",
|
||||||
|
|||||||
@@ -5520,6 +5520,8 @@ export default withEnglishFallback({
|
|||||||
searchExistingTables: "搜索表...",
|
searchExistingTables: "搜索表...",
|
||||||
loadingTables: "正在加载表...",
|
loadingTables: "正在加载表...",
|
||||||
noTables: "暂无可用表",
|
noTables: "暂无可用表",
|
||||||
|
targetColumnsTimeout: "加载目标表字段超时,请检查连接后重试。",
|
||||||
|
retry: "重试",
|
||||||
stepSource: "来源",
|
stepSource: "来源",
|
||||||
stepOptions: "选项",
|
stepOptions: "选项",
|
||||||
stepMapping: "映射",
|
stepMapping: "映射",
|
||||||
|
|||||||
@@ -4654,6 +4654,8 @@ export default withEnglishFallback({
|
|||||||
status_done: "匯入完成",
|
status_done: "匯入完成",
|
||||||
status_error: "匯入失敗",
|
status_error: "匯入失敗",
|
||||||
status_cancelled: "匯入已取消",
|
status_cancelled: "匯入已取消",
|
||||||
|
targetColumnsTimeout: "載入目標資料表欄位逾時,請檢查連線後重試。",
|
||||||
|
retry: "重試",
|
||||||
},
|
},
|
||||||
dataGenerate: {
|
dataGenerate: {
|
||||||
title: "資料生成",
|
title: "資料生成",
|
||||||
|
|||||||
Reference in new issue
Block a user