Prevent tenant merge dry-run memory spikes
All checks were successful
Build and Push Docker Images / build-backend (push) Successful in 39s
Build and Push Docker Images / build-frontend (push) Successful in 24s
Build and Push Docker Images / build-website (push) Successful in 23s
Build and Push Docker Images / build-central-services-api (push) Successful in 24s
Build and Push Docker Images / build-central-services-admin (push) Successful in 24s
Build and Push Docker Images / build-docs (push) Successful in 24s

This commit is contained in:
2026-08-06 14:39:58 +02:00
parent 291f278d99
commit ec4e3f39d6
3 changed files with 62 additions and 9 deletions

View File

@@ -53,9 +53,13 @@ const comparableRow = (row: Record<string, any>) => Object.fromEntries(
.sort(([left], [right]) => left.localeCompare(right))
)
const rowDifferences = (source: Record<string, any>, target: Record<string, any>) => {
const rowDifferences = (table: string, source: Record<string, any>, target: Record<string, any>) => {
const sourceComparable = comparableRow(source)
const targetComparable = comparableRow(target)
if (table === "citys") {
delete sourceComparable.geometry
delete targetComparable.geometry
}
const columns = Array.from(new Set([
...Object.keys(sourceComparable),
...Object.keys(targetComparable),
@@ -111,7 +115,7 @@ export const buildTenantMergePlan = (
const naturalTarget = sourceNaturalKey ? targetByNaturalKey.get(sourceNaturalKey) : undefined
const primaryTarget = targetByPrimaryKey.get(sourceKey)
const targetRow = naturalTarget || primaryTarget || null
const differences = targetRow ? rowDifferences(sourceRow, targetRow) : []
const differences = targetRow ? rowDifferences(table, sourceRow, targetRow) : []
let kind: TenantMergeKind
if (!targetRow) {

View File

@@ -161,16 +161,43 @@ const sensitiveColumns = new Set([
"tokenHash",
])
const redactRow = (row: Record<string, any> | null) => row && Object.fromEntries(
Object.entries(row).map(([column, value]) => [column, sensitiveColumns.has(column) && value ? "***" : value])
)
const compactValue = (value: any) => {
if (value === null || typeof value !== "object") return value
const serialized = JSON.stringify(value)
return `[Struktur mit ${serialized.length} Zeichen]`
}
const compactReviewRow = (row: Record<string, any> | null, differences: string[]) => {
if (!row) return null
const displayColumns = new Set([
"id",
"tenant",
"tenant_id",
"name",
"label",
"title",
"number",
"email",
"zip",
"short",
"accountChart",
...differences,
])
return Object.fromEntries(Object.entries(row)
.filter(([column]) => displayColumns.has(column))
.map(([column, value]) => [
column,
sensitiveColumns.has(column) && value ? "***" : compactValue(value),
]))
}
export const sanitizeTenantMergePlan = (plan: TenantMergePlan): TenantMergePlan => ({
...plan,
items: plan.items.map((item) => ({
items: plan.items.filter((item) => item.kind !== "existing").map((item) => ({
...item,
sourceRow: redactRow(item.sourceRow) || {},
targetRow: redactRow(item.targetRow),
sourceRow: compactReviewRow(item.sourceRow, item.differences) || {},
targetRow: compactReviewRow(item.targetRow, item.differences),
})),
})