diff --git a/src/modules/parcel-sync/services/eterra-client.ts b/src/modules/parcel-sync/services/eterra-client.ts index 96387f4..a0d1f73 100644 --- a/src/modules/parcel-sync/services/eterra-client.ts +++ b/src/modules/parcel-sync/services/eterra-client.ts @@ -60,8 +60,8 @@ const BASE_URL = "https://eterra.ancpi.ro/eterra"; const LOGIN_URL = `${BASE_URL}/api/authentication`; const DEFAULT_TIMEOUT_MS = 40_000; -const DEFAULT_PAGE_SIZE = 2000; -const PAGE_SIZE_FALLBACKS = [1000, 500, 200]; +const DEFAULT_PAGE_SIZE = 1000; +const PAGE_SIZE_FALLBACKS = [500, 200]; const MAX_RETRIES = 2; const SESSION_TTL_MS = 9 * 60 * 1000; const MAX_URL_LENGTH = 1500; @@ -343,6 +343,7 @@ export class EterraClient { // If we request 2000 but get exactly 1000, we hit the server cap. // Track this so we continue paginating instead of stopping. let serverMaxRecordCount: number | null = null; + let retried = false; // one retry per page for transient ArcGIS errors while (true) { const params = new URLSearchParams(); @@ -360,15 +361,27 @@ export class EterraClient { data = await this.queryLayer(layer, params, Boolean(options?.geometry)); } catch (err) { const cause = err instanceof Error ? err.message : String(err); + const isQueryError = cause.includes("Error performing query"); + + // ArcGIS "Error performing query" — retry same page size first + // (often a transient server-side timeout), then try smaller. + if (isQueryError && !retried) { + retried = true; + await sleep(2000); + continue; + } + retried = false; + // Try next smaller page size const nextSize = PAGE_SIZE_FALLBACKS.find((s) => s < pageSize); if (nextSize) { pageSize = nextSize; - await sleep(500); // small delay before retry with smaller page + await sleep(1000); continue; } throw new Error(`Failed to fetch layer ${layer.name}: ${cause}`); } + retried = false; // reset on success const features = data.features ?? []; if (features.length === 0) {