v0.65.0: per-airport job pools with real-time refresh — open jobs spawn per pool airport (grounded/flying/queued locations) in a fixed POOL_BANDS composition, expire on the wall clock after JOB_LIFETIME_MS even while the world is frozen, and refill taken slots after a per-band cooldown; /api/state + SSE filter open jobs to pool origins and expose expiresRealMs for the right-pane countdown
CI / build + unit + e2e (pull_request) Failing after 17m26s

This commit is contained in:
2026-09-23 13:09:49 +00:00
parent 9c2c64fe89
commit 12d900b22a
24 changed files with 556 additions and 344 deletions
+6 -4
View File
@@ -90,8 +90,10 @@ export async function loadPackage(inst: GameDb, packageId: string, planeId: stri
throw new GameActionError(409, `no payload room: the ${type.name} carries ${Math.round(usedKg)}/${type.maxPayloadKg} kg`);
}
// v0.65.0: taking the job starts its slot's refill cooldown — the pool spawner holds this
// (origin, band) empty for the delay after now so the board visibly refreshes.
await inst.db.update(schema.packages)
.set({ status: 'loaded', planeId })
.set({ status: 'loaded', planeId, slotFreeAtRealMs: Date.now() })
.where(eq(schema.packages.id, packageId));
await persist(inst);
}
@@ -264,8 +266,8 @@ export async function abandonPackage(inst: GameDb, packageId: string): Promise<{
// --- Ignore (POST /api/packages/:id/ignore) — ISS-047 part B ---
// Dismiss an OPEN job so it leaves the market permanently; no penalty, nothing else
// changes. The top-up logic (spawnOpenPackages counts 'open') refills the market with
// a new random package on the next tick. 404 unknown id; 409 unless open.
// changes. The pool spawner refills this (origin, band) slot after its refill delay —
// ignoring starts that cooldown via slotFreeAtRealMs (v0.65.0). 404 unknown id; 409 unless open.
export async function ignorePackage(inst: GameDb, packageId: string): Promise<void> {
const pkgRows = await inst.db.select().from(schema.packages).where(eq(schema.packages.id, packageId));
const pkg = pkgRows[0];
@@ -274,7 +276,7 @@ export async function ignorePackage(inst: GameDb, packageId: string): Promise<vo
throw new GameActionError(409, `package is ${pkg.status}, only open packages can be ignored`);
}
await inst.db.update(schema.packages).set({ status: 'ignored' }).where(eq(schema.packages.id, packageId));
await inst.db.update(schema.packages).set({ status: 'ignored', slotFreeAtRealMs: Date.now() }).where(eq(schema.packages.id, packageId));
await persist(inst);
}