fix db import
This commit is contained in:
parent
275b5125c1
commit
ab5ead3416
1 changed files with 71 additions and 10 deletions
|
|
@ -961,38 +961,99 @@ const MigrationTab: React.FC = () => {
|
||||||
const fileMb = (file.size / (1024 * 1024)).toFixed(1);
|
const fileMb = (file.size / (1024 * 1024)).toFixed(1);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Phase 1: Upload file to disk
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('file', file);
|
formData.append('file', file);
|
||||||
const res = await api.post('/api/admin/database-health/migration/upload-import', formData, {
|
const uploadRes = await api.post('/api/admin/database-health/migration/upload-import', formData, {
|
||||||
headers: { 'Content-Type': 'multipart/form-data' },
|
headers: { 'Content-Type': 'multipart/form-data' },
|
||||||
timeout: 0,
|
timeout: 0,
|
||||||
onUploadProgress: (e) => {
|
onUploadProgress: (e) => {
|
||||||
if (e.total) {
|
if (e.total) {
|
||||||
const pct = Math.round((e.loaded / e.total) * 100);
|
const pct = Math.round((e.loaded / e.total) * 100);
|
||||||
const loadedMb = (e.loaded / (1024 * 1024)).toFixed(1);
|
const loadedMb = (e.loaded / (1024 * 1024)).toFixed(1);
|
||||||
setUploadProgress(pct < 100
|
setUploadProgress(
|
||||||
|
pct < 100
|
||||||
? t('Upload: {loaded} / {total} MB ({pct}%)', { loaded: loadedMb, total: fileMb, pct })
|
? t('Upload: {loaded} / {total} MB ({pct}%)', { loaded: loadedMb, total: fileMb, pct })
|
||||||
: t('Validierung laeuft ({total} MB)...', { total: fileMb }),
|
: t('Verarbeitung wird gestartet...'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const token = uploadRes.data.token;
|
||||||
|
if (!token) throw new Error('No token returned from upload');
|
||||||
|
|
||||||
|
// Phase 2: Stream validation + split with progress
|
||||||
|
const baseURL = api.defaults.baseURL || '';
|
||||||
|
const streamUrl = `${baseURL}/api/admin/database-health/migration/process-import-stream?token=${encodeURIComponent(token)}`;
|
||||||
|
const streamRes = await fetch(streamUrl, { credentials: 'include' });
|
||||||
|
|
||||||
|
if (!streamRes.ok) {
|
||||||
|
const errText = await streamRes.text();
|
||||||
|
throw new Error(`Server ${streamRes.status}: ${errText}`);
|
||||||
|
}
|
||||||
|
if (!streamRes.body) throw new Error('ReadableStream not supported');
|
||||||
|
|
||||||
|
const reader = streamRes.body.getReader();
|
||||||
|
const decoder = new TextDecoder();
|
||||||
|
let buf = '';
|
||||||
|
let finalResult: any = null;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
const { done, value } = await reader.read();
|
||||||
|
if (done) break;
|
||||||
|
buf += decoder.decode(value, { stream: true });
|
||||||
|
|
||||||
|
const lines = buf.split('\n');
|
||||||
|
buf = lines.pop() || '';
|
||||||
|
|
||||||
|
for (const line of lines) {
|
||||||
|
if (!line.trim()) continue;
|
||||||
|
try {
|
||||||
|
const evt = JSON.parse(line);
|
||||||
|
if (evt.phase === 'validate') {
|
||||||
|
setUploadProgress(
|
||||||
|
t('Pass 1 Validierung: {db}.{table} ({rows} Datensaetze)', {
|
||||||
|
db: evt.db, table: evt.table, rows: evt.rows,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
} else if (evt.phase === 'split') {
|
||||||
|
setUploadProgress(
|
||||||
|
t('Pass 2 Split: {db}.{table} ({rows} Datensaetze)', {
|
||||||
|
db: evt.db, table: evt.table, rows: evt.rows,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
} else if (evt.phase === 'done') {
|
||||||
|
finalResult = evt.result;
|
||||||
|
} else if (evt.phase === 'error') {
|
||||||
|
throw new Error(evt.detail || 'Processing failed');
|
||||||
|
}
|
||||||
|
} catch (parseErr) {
|
||||||
|
if ((parseErr as Error).message?.startsWith('Processing'))
|
||||||
|
throw parseErr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setUploadProgress('');
|
setUploadProgress('');
|
||||||
importTokenRef.current = res.data.token || '';
|
|
||||||
|
if (!finalResult) throw new Error('No result received from processing stream');
|
||||||
|
|
||||||
|
importTokenRef.current = finalResult.token || token;
|
||||||
setValidation({
|
setValidation({
|
||||||
valid: res.data.valid,
|
valid: finalResult.valid,
|
||||||
summary: (res.data.databases || []).map((d: any) => ({
|
summary: (finalResult.databases || []).map((d: any) => ({
|
||||||
database: d.database,
|
database: d.database,
|
||||||
tableCount: d.tableCount,
|
tableCount: d.tableCount,
|
||||||
recordCount: d.recordCount,
|
recordCount: d.recordCount,
|
||||||
registered: true,
|
registered: true,
|
||||||
})),
|
})),
|
||||||
warnings: res.data.warnings || [],
|
warnings: finalResult.warnings || [],
|
||||||
systemObjectsFound: res.data.systemObjectsFound || [],
|
systemObjectsFound: finalResult.systemObjectsFound || [],
|
||||||
});
|
});
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
setUploadProgress('');
|
setUploadProgress('');
|
||||||
const detail = err?.response?.data?.detail;
|
const detail = err?.response?.data?.detail || err?.message;
|
||||||
setValidation({
|
setValidation({
|
||||||
valid: false, summary: [], systemObjectsFound: [],
|
valid: false, summary: [], systemObjectsFound: [],
|
||||||
warnings: [typeof detail === 'string' ? detail : t('Upload oder Validierung fehlgeschlagen')],
|
warnings: [typeof detail === 'string' ? detail : t('Upload oder Validierung fehlgeschlagen')],
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue