fix(wds): auto-initialize queue with default cities on first access

The /wds page was showing 0 cities because the KeyValueStore was empty
until the scheduler ran for the first time. Now the GET endpoint
initializes the queue with the 9 default cities on first access.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
AI Assistant
2026-03-26 22:46:50 +02:00
parent 54d9a36686
commit a6d7e1d87f
+50 -28
View File
@@ -26,22 +26,58 @@ type WeekendSyncState = {
completedCycles: number;
};
const FRESH_STEPS: Record<StepName, StepStatus> = {
sync_terenuri: "pending",
sync_cladiri: "pending",
import_nogeom: "pending",
enrich: "pending",
};
const DEFAULT_CITIES: Omit<CityState, "steps">[] = [
{ siruta: "54975", name: "Cluj-Napoca", county: "Cluj", priority: 1 },
{ siruta: "32394", name: "Bistri\u021Ba", county: "Bistri\u021Ba-N\u0103s\u0103ud", priority: 1 },
{ siruta: "114319", name: "T\u00E2rgu Mure\u0219", county: "Mure\u0219", priority: 2 },
{ siruta: "139704", name: "Zal\u0103u", county: "S\u0103laj", priority: 2 },
{ siruta: "26564", name: "Oradea", county: "Bihor", priority: 2 },
{ siruta: "9262", name: "Arad", county: "Arad", priority: 2 },
{ siruta: "155243", name: "Timi\u0219oara", county: "Timi\u0219", priority: 2 },
{ siruta: "143450", name: "Sibiu", county: "Sibiu", priority: 2 },
{ siruta: "40198", name: "Bra\u0219ov", county: "Bra\u0219ov", priority: 2 },
];
/** Initialize state with default cities if not present in DB */
async function getOrCreateState(): Promise<WeekendSyncState> {
const row = await prisma.keyValueStore.findUnique({
where: { namespace_key: { namespace: KV_NAMESPACE, key: KV_KEY } },
});
if (row?.value && typeof row.value === "object") {
return row.value as unknown as WeekendSyncState;
}
// First access — initialize with defaults
const state: WeekendSyncState = {
cities: DEFAULT_CITIES.map((c) => ({ ...c, steps: { ...FRESH_STEPS } })),
totalSessions: 0,
completedCycles: 0,
};
await prisma.keyValueStore.upsert({
where: { namespace_key: { namespace: KV_NAMESPACE, key: KV_KEY } },
update: { value: state as unknown as Prisma.InputJsonValue },
create: {
namespace: KV_NAMESPACE,
key: KV_KEY,
value: state as unknown as Prisma.InputJsonValue,
},
});
return state;
}
/**
* GET /api/eterra/weekend-sync
* Returns the current queue state.
*/
export async function GET() {
// Auth handled by middleware (route is not excluded)
const row = await prisma.keyValueStore.findUnique({
where: { namespace_key: { namespace: KV_NAMESPACE, key: KV_KEY } },
});
if (!row?.value) {
return NextResponse.json({ state: null });
}
// Enrich with DB feature counts per city
const state = row.value as unknown as WeekendSyncState;
const state = await getOrCreateState();
const sirutas = state.cities.map((c) => c.siruta);
const counts = await prisma.gisFeature.groupBy({
@@ -99,21 +135,7 @@ export async function POST(request: Request) {
priority?: number;
};
// Load current state
const row = await prisma.keyValueStore.findUnique({
where: { namespace_key: { namespace: KV_NAMESPACE, key: KV_KEY } },
});
const state: WeekendSyncState = row?.value
? (row.value as unknown as WeekendSyncState)
: { cities: [], totalSessions: 0, completedCycles: 0 };
const freshSteps: Record<StepName, StepStatus> = {
sync_terenuri: "pending",
sync_cladiri: "pending",
import_nogeom: "pending",
enrich: "pending",
};
const state = await getOrCreateState();
switch (body.action) {
case "add": {
@@ -134,7 +156,7 @@ export async function POST(request: Request) {
name: body.name,
county: body.county ?? "",
priority: body.priority ?? 3,
steps: { ...freshSteps },
steps: { ...FRESH_STEPS },
});
break;
}
@@ -145,14 +167,14 @@ export async function POST(request: Request) {
case "reset": {
const city = state.cities.find((c) => c.siruta === body.siruta);
if (city) {
city.steps = { ...freshSteps };
city.steps = { ...FRESH_STEPS };
city.errorMessage = undefined;
}
break;
}
case "reset_all": {
for (const city of state.cities) {
city.steps = { ...freshSteps };
city.steps = { ...FRESH_STEPS };
city.errorMessage = undefined;
}
state.completedCycles = 0;