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:
@@ -60,8 +60,8 @@ const BASE_URL = "https://eterra.ancpi.ro/eterra";
|
|||||||
const LOGIN_URL = `${BASE_URL}/api/authentication`;
|
const LOGIN_URL = `${BASE_URL}/api/authentication`;
|
||||||
|
|
||||||
const DEFAULT_TIMEOUT_MS = 40_000;
|
const DEFAULT_TIMEOUT_MS = 40_000;
|
||||||
const DEFAULT_PAGE_SIZE = 2000;
|
const DEFAULT_PAGE_SIZE = 1000;
|
||||||
const PAGE_SIZE_FALLBACKS = [1000, 500, 200];
|
const PAGE_SIZE_FALLBACKS = [500, 200];
|
||||||
const MAX_RETRIES = 2;
|
const MAX_RETRIES = 2;
|
||||||
const SESSION_TTL_MS = 9 * 60 * 1000;
|
const SESSION_TTL_MS = 9 * 60 * 1000;
|
||||||
const MAX_URL_LENGTH = 1500;
|
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.
|
// If we request 2000 but get exactly 1000, we hit the server cap.
|
||||||
// Track this so we continue paginating instead of stopping.
|
// Track this so we continue paginating instead of stopping.
|
||||||
let serverMaxRecordCount: number | null = null;
|
let serverMaxRecordCount: number | null = null;
|
||||||
|
let retried = false; // one retry per page for transient ArcGIS errors
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
@@ -360,15 +361,27 @@ export class EterraClient {
|
|||||||
data = await this.queryLayer(layer, params, Boolean(options?.geometry));
|
data = await this.queryLayer(layer, params, Boolean(options?.geometry));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const cause = err instanceof Error ? err.message : String(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
|
// Try next smaller page size
|
||||||
const nextSize = PAGE_SIZE_FALLBACKS.find((s) => s < pageSize);
|
const nextSize = PAGE_SIZE_FALLBACKS.find((s) => s < pageSize);
|
||||||
if (nextSize) {
|
if (nextSize) {
|
||||||
pageSize = nextSize;
|
pageSize = nextSize;
|
||||||
await sleep(500); // small delay before retry with smaller page
|
await sleep(1000);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
throw new Error(`Failed to fetch layer ${layer.name}: ${cause}`);
|
throw new Error(`Failed to fetch layer ${layer.name}: ${cause}`);
|
||||||
}
|
}
|
||||||
|
retried = false; // reset on success
|
||||||
|
|
||||||
const features = data.features ?? [];
|
const features = data.features ?? [];
|
||||||
if (features.length === 0) {
|
if (features.length === 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user