KI-AGENT: Überspringe fehlende S3-Dateien beim Mandantenexport

This commit is contained in:
2026-05-19 19:47:38 +02:00
parent 697abc99fa
commit 6cc7dc87ad

View File

@@ -25,7 +25,9 @@ export type TenantFullExport = {
name: string | null name: string | null
mimeType: string | null mimeType: string | null
size: number | null size: number | null
contentBase64: string contentBase64: string | null
missing?: boolean
error?: string
}[] }[]
} }
@@ -121,18 +123,37 @@ const decryptEntityBankAccountsForExport = (rows: Record<string, any>[] = []) =>
}) })
} }
const isMissingObjectError = (err: any) =>
err?.Code === "NoSuchKey" ||
err?.name === "NoSuchKey" ||
err?.$metadata?.httpStatusCode === 404
const loadObjectAsBase64 = async (path: string) => { const loadObjectAsBase64 = async (path: string) => {
const { Body } = await s3.send(new GetObjectCommand({ try {
Bucket: secrets.S3_BUCKET, const { Body } = await s3.send(new GetObjectCommand({
Key: path, Bucket: secrets.S3_BUCKET,
})) Key: path,
}))
const chunks: Buffer[] = [] const chunks: Buffer[] = []
for await (const chunk of Body as any) { for await (const chunk of Body as any) {
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk))
}
return {
contentBase64: Buffer.concat(chunks).toString("base64"),
missing: false,
error: null,
}
} catch (err: any) {
if (!isMissingObjectError(err)) throw err
return {
contentBase64: null,
missing: true,
error: err?.Code || err?.name || "NoSuchKey",
}
} }
return Buffer.concat(chunks).toString("base64")
} }
export const buildTenantFullExport = async (server: FastifyInstance, tenantId: number): Promise<TenantFullExport> => { export const buildTenantFullExport = async (server: FastifyInstance, tenantId: number): Promise<TenantFullExport> => {
@@ -198,13 +219,25 @@ export const buildTenantFullExport = async (server: FastifyInstance, tenantId: n
for (const file of fileRows) { for (const file of fileRows) {
if (!file.path) continue if (!file.path) continue
const object = await loadObjectAsBase64(file.path)
if (object.missing) {
server.log.warn({
fileId: file.id,
path: file.path,
bucket: secrets.S3_BUCKET,
error: object.error,
}, "Tenant full export skipped missing S3 object")
}
files.push({ files.push({
id: file.id, id: file.id,
path: file.path, path: file.path,
name: file.name || null, name: file.name || null,
mimeType: file.mimeType || null, mimeType: file.mimeType || null,
size: file.size || null, size: file.size || null,
contentBase64: await loadObjectAsBase64(file.path), contentBase64: object.contentBase64,
missing: object.missing || undefined,
error: object.error || undefined,
}) })
} }