fix: only sample wait times within each park's operating window
Build and Deploy / Build & Push (push) Successful in 1m5s
Build and Deploy / Build & Push (push) Successful in 1m5s
Queue-Times keeps reporting yesterday's last wait with isOpen=true overnight, so the per-ride open check wasn't enough — the sampler was recording phantom "open" samples between close and the next morning's first refresh, padding both wait-time averages and uptime% with stale data. Add isWithinOperatingWindow gate (same check the /rides route uses) so the sampler only runs during the park's actual hours plus the 1-hour closing buffer. Includes a one-off wipe script for the accumulated bad data. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* One-off cleanup: wipe ride history accumulated before the operating-window
|
||||
* gate was added to the sampler. Safe to re-run; truncates only the two
|
||||
* sample-related tables, leaves park_days untouched.
|
||||
*/
|
||||
import Database from "better-sqlite3";
|
||||
import path from "path";
|
||||
|
||||
const dbPath = path.join(__dirname, "..", "data", "parks.db");
|
||||
const db = new Database(dbPath);
|
||||
|
||||
const before = {
|
||||
samples: (db.prepare("SELECT COUNT(*) AS c FROM ride_wait_samples").get() as { c: number }).c,
|
||||
rides: (db.prepare("SELECT COUNT(*) AS c FROM rides").get() as { c: number }).c,
|
||||
};
|
||||
console.log("Before:", before);
|
||||
|
||||
db.exec("DELETE FROM ride_wait_samples; DELETE FROM rides;");
|
||||
|
||||
const after = {
|
||||
samples: (db.prepare("SELECT COUNT(*) AS c FROM ride_wait_samples").get() as { c: number }).c,
|
||||
rides: (db.prepare("SELECT COUNT(*) AS c FROM rides").get() as { c: number }).c,
|
||||
};
|
||||
console.log("After: ", after);
|
||||
|
||||
db.close();
|
||||
@@ -23,6 +23,7 @@ import { fetchLiveRides } from "../../../lib/scrapers/queuetimes";
|
||||
import { fetchFastLaneWaits, lookupFastLane } from "../../../lib/scrapers/sixflags-waittimes";
|
||||
import { slugifyRideName } from "../../../lib/ride-slug";
|
||||
import { formatLocalDate, formatLocalTime } from "../../../lib/timezone";
|
||||
import { isWithinOperatingWindow } from "../../../lib/env";
|
||||
import { liveRidesCache, fastLaneCache } from "./live-cache";
|
||||
import { getDayData, upsertRide, insertSample, transact } from "../db/queries";
|
||||
|
||||
@@ -133,10 +134,15 @@ export async function sampleAllOpenParks(): Promise<SampleRunResult> {
|
||||
errors: 0,
|
||||
};
|
||||
|
||||
// Filter to parks open today.
|
||||
// Filter to parks that are open today AND currently within their operating
|
||||
// window. Queue-Times keeps reporting yesterday's last wait with isOpen=true
|
||||
// overnight, so the per-ride open check isn't enough on its own — we'd
|
||||
// otherwise pollute uptime stats with phantom open samples between close
|
||||
// and the next morning's first refresh.
|
||||
const openParks = PARKS.filter((park) => {
|
||||
const day = getDayData(park.id, today);
|
||||
return day?.isOpen ?? false;
|
||||
if (!day?.isOpen || !day.hoursLabel) return false;
|
||||
return isWithinOperatingWindow(day.hoursLabel, park.timezone);
|
||||
});
|
||||
result.parksSkipped = PARKS.length - openParks.length;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user