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

@@ -401,6 +401,12 @@ export default async function adminRoutes(server: FastifyInstance) {
contentType: string,
filename: string
) => {
const heartbeat = setInterval(() => {
void server.db
.update(tenantExportJobs)
.set({ updatedAt: new Date() })
.where(eq(tenantExportJobs.id, jobId));
}, 15_000);
try {
const exportData = await parseMergeSource(source, contentType, filename);
const report = sanitizeTenantMergePlan(await createTenantMergeDryRun(exportData, targetTenantId));
@@ -434,6 +440,8 @@ export default async function adminRoutes(server: FastifyInstance) {
updatedAt: new Date(),
})
.where(eq(tenantExportJobs.id, jobId));
} finally {
clearInterval(heartbeat);
}
};
@@ -1466,11 +1474,25 @@ export default async function adminRoutes(server: FastifyInstance) {
if (!job) return reply.code(404).send({ error: "Export not found" });
let returnedStatus = job.status;
const staleMergeReview = job.operation === "merge"
&& ["running", "recovering"].includes(job.status)
&& (!job.updatedAt || Date.now() - new Date(job.updatedAt).getTime() > 60_000);
if (staleMergeReview && job.storagePath) {
const source = await readS3Buffer(job.storagePath);
await server.db
.update(tenantExportJobs)
.set({ status: "recovering", updatedAt: new Date(), error: null })
.where(eq(tenantExportJobs.id, job.id));
void startTenantMergeReviewJob(job.id, job.tenantId, source, job.contentType, job.filename);
returnedStatus = "recovering";
}
return {
exportId: job.id,
tenantId: job.tenantId,
operation: job.operation,
status: job.status,
status: returnedStatus,
filename: job.filename,
fileSize: job.fileSize,
filesDone: job.filesDone,