v0.69.0: remove job ignore feature
CI / build + unit + e2e (pull_request) Successful in 14m31s

This commit is contained in:
2026-09-23 22:01:39 +00:00
parent 7d117f6809
commit d2defe4cd3
20 changed files with 48 additions and 171 deletions
-31
View File
@@ -28,7 +28,6 @@ import {
cancelQueuedLeg,
flyPlane,
GameActionError,
ignorePackage,
loadPackage,
queueLeg,
repairPlane,
@@ -530,36 +529,6 @@ describe('abandonPackage', () => {
});
});
describe('ignorePackage', () => {
it('flips an open package to ignored — no penalty, nothing else changes', async () => {
const inst = await freshDb('ig-open.db');
await insertOpenPackage(inst, 'p-ig');
const cashBefore = (await inst.db.select().from(schema.account))[0].cash;
await ignorePackage(inst, 'p-ig');
const row = (await inst.db.select().from(schema.packages).where(eq(schema.packages.id, 'p-ig')))[0];
expect(row.status).toBe('ignored');
expect(row.planeId).toBeNull(); // was never bound
expect((await inst.db.select().from(schema.account))[0].cash).toBe(cashBefore); // no penalty
});
it.each(['loaded', 'delivered', 'expired', 'abandoned', 'ignored'] as const)(
'rejects a %s package with 409 (must be open)',
async (status) => {
const inst = await freshDb(`ig-${status}.db`);
await insertOpenPackage(inst, 'p-x', { status });
await expectActionError(ignorePackage(inst, 'p-x'), 409, new RegExp(status));
},
);
it('rejects an unknown id with 404', async () => {
const inst = await freshDb('ig-unknown.db');
await expectActionError(ignorePackage(inst, 'nope'), 404);
});
});
describe('buyPlane', () => {
it('deducts the full price and delivers a full-tank plane at the home base', async () => {
const inst = await freshDb('buy-ok.db');
-17
View File
@@ -263,23 +263,6 @@ export async function abandonPackage(inst: GameDb, packageId: string): Promise<{
return { penalty };
}
// --- 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 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];
if (!pkg) throw new GameActionError(404, `package ${packageId} not found`);
if (pkg.status !== 'open') {
throw new GameActionError(409, `package is ${pkg.status}, only open packages can be ignored`);
}
await inst.db.update(schema.packages).set({ status: 'ignored', slotFreeAtRealMs: Date.now() }).where(eq(schema.packages.id, packageId));
await persist(inst);
}
// --- Market (POST /api/market/buy-plane {model}) ---
// Buy a catalog model at its reputation-scaled price (v0.38.0, ISS-072 — discount grows with
+1 -1
View File
@@ -122,7 +122,7 @@ function envMs(name: string, fallback: number): number {
}
export const JOB_LIFETIME_MS = envMs('FLIGHT_JOB_LIFETIME_MS', 3_600_000); // 1 h wall clock
// Refill cooldown after a job is TAKEN (loaded or ignored): the slot stays empty this long so the
// Refill cooldown after a job is TAKEN (loaded): the slot stays empty this long so the
// board visibly refreshes instead of instantly refilling. Expired/delivered/abandoned never block —
// an untaken job's slot respawns immediately. Small jobs (<4 t) refill faster; they're common.
export const REFILL_DELAY_MS = envMs('FLIGHT_JOB_REFILL_MS', 15 * 60_000); // 15 min wall clock
-1
View File
@@ -40,7 +40,6 @@ describe('sseFrame', () => {
pkg('loaded', 'p-loaded'),
pkg('abandoned', 'p-abandoned'),
pkg('expired', 'p-expired'),
pkg('ignored', 'p-ignored'),
];
const frame = sseFrame(snapshot(all));
expect(frame.packages.map((p) => p.id)).toEqual(['p-open', 'p-loaded', 'p-expired']);
+2 -3
View File
@@ -81,8 +81,7 @@ export interface PackageState {
// Great-circle leg distance in km (v0.48.0, ISS-095) — computed from airport coords, not stored.
distanceKm: number;
deadlineSimTime: number;
// 'ignored' (v0.29.0, ISS-047 part B) = a dismissed open job — terminal, leaves the market.
status: 'open' | 'loaded' | 'delivered' | 'expired' | 'abandoned' | 'ignored';
status: 'open' | 'loaded' | 'delivered' | 'expired' | 'abandoned';
planeId: string | null;
createdSimTime: number;
// Wall-clock expiry of an OPEN job (v0.65.0) — createdRealMs + JOB_LIFETIME_MS, shown as a live
@@ -106,7 +105,7 @@ export interface StateSnapshot {
// ISS-133 (v0.59.0): the SSE projection of a snapshot — only the package statuses any component
// renders: open (market list), loaded + expired (on-board cargo, which keeps its payload slot).
// Terminal history (delivered/abandoned/ignored) is unbounded in the DB and never read by the
// Terminal history (delivered/abandoned) is unbounded in the DB and never read by the
// client, so it stays out of every pushed frame; /api/state and action responses keep the full set.
export const SSE_PACKAGE_STATUSES = ['open', 'loaded', 'expired'] as const;