fix(eterra-client): reduce default pageSize to 1000 + retry on ArcGIS errors

- DEFAULT_PAGE_SIZE: 2000 -> 1000 (matches eTerra maxRecordCount, avoids
  requesting more than the server supports on first try)
- PAGE_SIZE_FALLBACKS: [500, 200] (removed 1000 since it's now the default)
- Add retry-once logic for 'Error performing query operation':
  Wait 2s and retry same page before falling to smaller sizes.
  These errors are often transient server-side timeouts.
- Longer delay (1s vs 0.5s) between page size fallback attempts

Fixes Feleacu (7951 features) background sync failure.
This commit is contained in:
AI Assistant
2026-03-08 03:06:44 +02:00
parent 041bfd4138
commit d7d78c0cc1
@@ -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) {