fix(parcel-sync): batch deleteMany to avoid PostgreSQL 32767 bind variable limit

Cluj-Napoca sync failed with 62,307 removed features exceeding the limit.
Batch deletions in chunks of 30,000 in both sync-service and no-geom-sync.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
AI Assistant
2026-03-28 10:17:57 +02:00
parent 91fb23bc53
commit dfb5ceb926
2 changed files with 17 additions and 11 deletions
@@ -537,9 +537,12 @@ export async function syncNoGeometryParcels(
} }
if (staleIds.length > 0) { if (staleIds.length > 0) {
const BATCH = 30_000;
for (let i = 0; i < staleIds.length; i += BATCH) {
await prisma.gisFeature.deleteMany({ await prisma.gisFeature.deleteMany({
where: { id: { in: staleIds } }, where: { id: { in: staleIds.slice(i, i + BATCH) } },
}); });
}
console.log( console.log(
`[no-geom-sync] Cleanup: removed ${staleIds.length} stale/invalid no-geom records`, `[no-geom-sync] Cleanup: removed ${staleIds.length} stale/invalid no-geom records`,
); );
@@ -318,17 +318,20 @@ export async function syncLayer(
// PostGIS not available yet — not critical, skip silently // PostGIS not available yet — not critical, skip silently
} }
// Mark removed features // Mark removed features (batch to avoid PostgreSQL 32767 bind variable limit)
if (removedObjIds.length > 0) { if (removedObjIds.length > 0) {
push({ phase: "Marcare șterse" }); push({ phase: "Marcare șterse" });
const BATCH = 30_000;
for (let i = 0; i < removedObjIds.length; i += BATCH) {
await prisma.gisFeature.deleteMany({ await prisma.gisFeature.deleteMany({
where: { where: {
layerId, layerId,
siruta, siruta,
objectId: { in: removedObjIds }, objectId: { in: removedObjIds.slice(i, i + BATCH) },
}, },
}); });
} }
}
// Update sync run // Update sync run
const localCount = await prisma.gisFeature.count({ const localCount = await prisma.gisFeature.count({