fix(parcel-sync): always run syncLayer for delta detection + no-geom freshness
- Always call syncLayer for TERENURI/CLADIRI (not gated by isFresh) so that quick-count + VALID_FROM delta actually run on daily syncs - syncLayer handles efficiency internally via quick-count match - Add 48h freshness check for no-geom import (skip if recent) - Admin layers: skip if synced within 24h - Log sync summary (new features, updated features) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -187,42 +187,38 @@ async function runBackground(params: {
|
||||
getLayerFreshness(siruta, "CLADIRI_ACTIVE"),
|
||||
]);
|
||||
|
||||
const terenuriNeedsSync =
|
||||
forceSync ||
|
||||
!isFresh(terenuriStatus.lastSynced) ||
|
||||
terenuriStatus.featureCount === 0;
|
||||
const cladiriNeedsSync =
|
||||
forceSync ||
|
||||
!isFresh(cladiriStatus.lastSynced) ||
|
||||
cladiriStatus.featureCount === 0;
|
||||
const terenuriNeedsFullSync =
|
||||
forceSync || terenuriStatus.featureCount === 0;
|
||||
const cladiriNeedsFullSync =
|
||||
forceSync || cladiriStatus.featureCount === 0;
|
||||
|
||||
if (terenuriNeedsSync) {
|
||||
phase = "Sincronizare terenuri";
|
||||
push({});
|
||||
const r = await syncLayer(username, password, siruta, "TERENURI_ACTIVE", {
|
||||
forceFullSync: forceSync,
|
||||
jobId,
|
||||
isSubStep: true,
|
||||
});
|
||||
if (r.status === "error")
|
||||
throw new Error(r.error ?? "Sync terenuri failed");
|
||||
}
|
||||
// Always call syncLayer — it handles quick-count + VALID_FROM delta internally.
|
||||
// Only force full download when no local data or explicit forceSync.
|
||||
phase = "Sincronizare terenuri";
|
||||
push({});
|
||||
const terenuriResult = await syncLayer(username, password, siruta, "TERENURI_ACTIVE", {
|
||||
forceFullSync: terenuriNeedsFullSync,
|
||||
jobId,
|
||||
isSubStep: true,
|
||||
});
|
||||
if (terenuriResult.status === "error")
|
||||
throw new Error(terenuriResult.error ?? "Sync terenuri failed");
|
||||
updateOverall(0.5);
|
||||
|
||||
if (cladiriNeedsSync) {
|
||||
phase = "Sincronizare clădiri";
|
||||
push({});
|
||||
const r = await syncLayer(username, password, siruta, "CLADIRI_ACTIVE", {
|
||||
forceFullSync: forceSync,
|
||||
jobId,
|
||||
isSubStep: true,
|
||||
});
|
||||
if (r.status === "error")
|
||||
throw new Error(r.error ?? "Sync clădiri failed");
|
||||
}
|
||||
phase = "Sincronizare clădiri";
|
||||
push({});
|
||||
const cladiriResult = await syncLayer(username, password, siruta, "CLADIRI_ACTIVE", {
|
||||
forceFullSync: cladiriNeedsFullSync,
|
||||
jobId,
|
||||
isSubStep: true,
|
||||
});
|
||||
if (cladiriResult.status === "error")
|
||||
throw new Error(cladiriResult.error ?? "Sync clădiri failed");
|
||||
|
||||
// Sync admin layers (always, lightweight)
|
||||
// Sync admin layers — skip if synced within 24h
|
||||
for (const adminLayer of ["LIMITE_INTRAV_DYNAMIC", "LIMITE_UAT"]) {
|
||||
const adminStatus = await getLayerFreshness(siruta, adminLayer);
|
||||
if (!forceSync && isFresh(adminStatus.lastSynced, 24)) continue;
|
||||
phase = `Sincronizare ${adminLayer === "LIMITE_UAT" ? "limite UAT" : "limite intravilan"}`;
|
||||
push({});
|
||||
try {
|
||||
@@ -232,37 +228,65 @@ async function runBackground(params: {
|
||||
isSubStep: true,
|
||||
});
|
||||
} catch {
|
||||
// Non-critical — don't fail the whole job
|
||||
note = `Avertisment: ${adminLayer} nu s-a sincronizat`;
|
||||
push({});
|
||||
}
|
||||
}
|
||||
|
||||
if (!terenuriNeedsSync && !cladiriNeedsSync) {
|
||||
note = "Date proaspete — sync skip";
|
||||
}
|
||||
const syncSummary = [
|
||||
terenuriResult.newFeatures > 0 ? `${terenuriResult.newFeatures} terenuri noi` : null,
|
||||
terenuriResult.validFromUpdated ? `${terenuriResult.validFromUpdated} terenuri actualizate` : null,
|
||||
cladiriResult.newFeatures > 0 ? `${cladiriResult.newFeatures} cladiri noi` : null,
|
||||
cladiriResult.validFromUpdated ? `${cladiriResult.validFromUpdated} cladiri actualizate` : null,
|
||||
].filter(Boolean);
|
||||
note = syncSummary.length > 0 ? syncSummary.join(", ") : "Fără schimbări";
|
||||
finishPhase();
|
||||
|
||||
/* ── Phase 2: No-geometry import (optional) ──────── */
|
||||
if (hasNoGeom && weights.noGeom > 0) {
|
||||
setPhase("Import parcele fără geometrie", weights.noGeom);
|
||||
const noGeomClient = await EterraClient.create(username, password, {
|
||||
timeoutMs: 120_000,
|
||||
});
|
||||
const res = await syncNoGeometryParcels(noGeomClient, siruta, {
|
||||
onProgress: (done, tot, ph) => {
|
||||
phase = ph;
|
||||
push({});
|
||||
},
|
||||
});
|
||||
if (res.status === "error") {
|
||||
note = `Avertisment no-geom: ${res.error}`;
|
||||
setPhase("Verificare parcele fără geometrie", weights.noGeom);
|
||||
// Skip no-geom import if recently done (within 48h) and not forced
|
||||
const { PrismaClient } = await import("@prisma/client");
|
||||
const _prisma = new PrismaClient();
|
||||
let skipNoGeom = false;
|
||||
try {
|
||||
const recentNoGeom = await _prisma.gisFeature.findFirst({
|
||||
where: {
|
||||
layerId: "TERENURI_ACTIVE",
|
||||
siruta,
|
||||
geometrySource: "NO_GEOMETRY",
|
||||
updatedAt: { gte: new Date(Date.now() - 48 * 60 * 60 * 1000) },
|
||||
},
|
||||
select: { id: true },
|
||||
});
|
||||
skipNoGeom = !forceSync && recentNoGeom != null;
|
||||
} catch { /* proceed with import */ }
|
||||
await _prisma.$disconnect();
|
||||
|
||||
if (skipNoGeom) {
|
||||
note = "Parcele fără geometrie — actualizate recent, skip";
|
||||
push({});
|
||||
} else {
|
||||
const cleanNote =
|
||||
res.cleaned > 0 ? `, ${res.cleaned} vechi șterse` : "";
|
||||
note = `${res.imported} parcele noi importate${cleanNote}`;
|
||||
phase = "Import parcele fără geometrie";
|
||||
push({});
|
||||
const noGeomClient = await EterraClient.create(username, password, {
|
||||
timeoutMs: 120_000,
|
||||
});
|
||||
const res = await syncNoGeometryParcels(noGeomClient, siruta, {
|
||||
onProgress: (done, tot, ph) => {
|
||||
phase = ph;
|
||||
push({});
|
||||
},
|
||||
});
|
||||
if (res.status === "error") {
|
||||
note = `Avertisment no-geom: ${res.error}`;
|
||||
push({});
|
||||
} else {
|
||||
const cleanNote =
|
||||
res.cleaned > 0 ? `, ${res.cleaned} vechi șterse` : "";
|
||||
note = `${res.imported} parcele noi importate${cleanNote}`;
|
||||
push({});
|
||||
}
|
||||
}
|
||||
finishPhase();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user