fix(parcel-sync): fix session expiry during long pagination (Cluj 0 features bug)

Three bugs caused sync to return 0 features after 37 minutes:

1. reloginAttempted was instance-level flag — once set to true after first
   401, all subsequent 401s threw immediately without retry. Moved to
   per-request scope so each request can independently relogin on 401.

2. Session lastUsed never updated during pagination — after ~10 min of
   paginating, the session store considered it expired and cleanup could
   evict it. Added touchSession() call before every request.

3. Single eTerra client shared across all cities/steps for hours — now
   creates a fresh client per city/step (session cache still avoids
   unnecessary logins when session is valid).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
AI Assistant
2026-03-28 10:05:06 +02:00
parent 9bab9db4df
commit 58442da355
2 changed files with 16 additions and 23 deletions
@@ -299,17 +299,6 @@ export async function runWeekendDeepSync(): Promise<void> {
`[weekend-sync] Sesiune #${state.totalSessions} pornita. ${state.cities.length} orase in coada.`,
);
// Create eTerra client (shared across steps)
let client: EterraClient;
try {
client = await EterraClient.create(username, password);
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
console.error(`[weekend-sync] Nu se poate conecta la eTerra: ${msg}`);
await saveState(state);
return;
}
// Sort cities: priority first, then shuffle within same priority
const sorted = [...state.cities].sort((a, b) => {
if (a.priority !== b.priority) return a.priority - b.priority;
@@ -348,9 +337,10 @@ export async function runWeekendDeepSync(): Promise<void> {
await sleep(pause);
}
// Execute step
// Execute step — fresh client per step (sessions expire after ~10 min)
console.log(`[weekend-sync] ${city.name}: ${stepName}...`);
try {
const client = await EterraClient.create(username, password);
const result = await executeStep(city, stepName, client);
city.steps[stepName] = result.success ? "done" : "error";
if (!result.success) city.errorMessage = result.message;