feat: use dateless Six Flags API endpoint for live today data
All checks were successful
Build and Deploy / Build & Push (push) Successful in 17s
All checks were successful
Build and Deploy / Build & Push (push) Successful in 17s
The API without a date param returns today's operating data directly,
invalidating the previous assumption that today's date was always missing.
- Add fetchToday(apiId, revalidate?) to sixflags.ts — calls the dateless
endpoint with optional ISR cache
- Extract parseApiDay() helper shared by scrapeMonth and fetchToday
- Update upsertDay WHERE clause: >= date('now') so today can be updated
(was > date('now'), which froze today after first write)
- scrape.ts: add a today-scrape pass after the monthly loop so each run
always writes fresh today data to the DB
- app/page.tsx: fetch live today data for all parks (5-min ISR) and merge
into the data map before computing open/closing/weatherDelay status
- app/park/[id]/page.tsx: prefer live today data from API for todayData
so weather delays and hour changes surface within 5 minutes
- scrapeRidesForDay: update comment only — role unchanged (QT fallback)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
29
app/page.tsx
29
app/page.tsx
@@ -1,10 +1,12 @@
|
||||
import { HomePageClient } from "@/components/HomePageClient";
|
||||
import { PARKS } from "@/lib/parks";
|
||||
import { openDb, getDateRange } from "@/lib/db";
|
||||
import { openDb, getDateRange, getApiId } from "@/lib/db";
|
||||
import { getTodayLocal, isWithinOperatingWindow, getOperatingStatus } from "@/lib/env";
|
||||
import { fetchLiveRides } from "@/lib/scrapers/queuetimes";
|
||||
import { fetchToday } from "@/lib/scrapers/sixflags";
|
||||
import { QUEUE_TIMES_IDS } from "@/lib/queue-times-map";
|
||||
import { readParkMeta, getCoasterSet } from "@/lib/park-meta";
|
||||
import type { DayData } from "@/lib/db";
|
||||
|
||||
interface PageProps {
|
||||
searchParams: Promise<{ week?: string }>;
|
||||
@@ -49,6 +51,31 @@ export default async function HomePage({ searchParams }: PageProps) {
|
||||
|
||||
const db = openDb();
|
||||
const data = getDateRange(db, weekStart, endDate);
|
||||
|
||||
// Merge live today data from the Six Flags API (dateless endpoint, 5-min ISR cache).
|
||||
// This ensures weather delays, early closures, and hour changes surface within 5 minutes
|
||||
// without waiting for the next scheduled scrape. Only fetched when viewing the current week.
|
||||
if (weekDates.includes(today)) {
|
||||
const todayResults = await Promise.all(
|
||||
PARKS.map(async (p) => {
|
||||
const apiId = getApiId(db, p.id);
|
||||
if (!apiId) return null;
|
||||
const live = await fetchToday(apiId, 300); // 5-min ISR cache
|
||||
return live ? { parkId: p.id, live } : null;
|
||||
})
|
||||
);
|
||||
for (const result of todayResults) {
|
||||
if (!result) continue;
|
||||
const { parkId, live } = result;
|
||||
if (!data[parkId]) data[parkId] = {};
|
||||
data[parkId][today] = {
|
||||
isOpen: live.isOpen,
|
||||
hoursLabel: live.hoursLabel ?? null,
|
||||
specialType: live.specialType ?? null,
|
||||
} satisfies DayData;
|
||||
}
|
||||
}
|
||||
|
||||
db.close();
|
||||
|
||||
const scrapedCount = Object.values(data).reduce(
|
||||
|
||||
@@ -5,6 +5,7 @@ import { PARK_MAP } from "@/lib/parks";
|
||||
import { openDb, getParkMonthData, getApiId } from "@/lib/db";
|
||||
import { scrapeRidesForDay } from "@/lib/scrapers/sixflags";
|
||||
import { fetchLiveRides } from "@/lib/scrapers/queuetimes";
|
||||
import { fetchToday } from "@/lib/scrapers/sixflags";
|
||||
import { QUEUE_TIMES_IDS } from "@/lib/queue-times-map";
|
||||
import { readParkMeta, getCoasterSet } from "@/lib/park-meta";
|
||||
import { ParkMonthCalendar } from "@/components/ParkMonthCalendar";
|
||||
@@ -44,7 +45,13 @@ export default async function ParkPage({ params, searchParams }: PageProps) {
|
||||
const apiId = getApiId(db, id);
|
||||
db.close();
|
||||
|
||||
const todayData = monthData[today];
|
||||
// Prefer live today data from the Six Flags API (5-min ISR cache) so that
|
||||
// weather delays and hour changes surface immediately rather than showing
|
||||
// stale DB values. Fall back to DB if the API call fails.
|
||||
const liveToday = apiId !== null ? await fetchToday(apiId, 300).catch(() => null) : null;
|
||||
const todayData = liveToday
|
||||
? { isOpen: liveToday.isOpen, hoursLabel: liveToday.hoursLabel ?? null, specialType: liveToday.specialType ?? null }
|
||||
: monthData[today];
|
||||
const parkOpenToday = todayData?.isOpen && todayData?.hoursLabel;
|
||||
|
||||
// ── Ride data: try live Queue-Times first, fall back to schedule ──────────
|
||||
@@ -80,10 +87,8 @@ export default async function ParkPage({ params, searchParams }: PageProps) {
|
||||
liveRides.rides.length > 0 &&
|
||||
liveRides.rides.every((r) => !r.isOpen);
|
||||
|
||||
// Only hit the schedule API as a fallback when live data is unavailable
|
||||
// Only hit the schedule API as a fallback when Queue-Times live data is unavailable.
|
||||
if (!liveRides && apiId !== null) {
|
||||
// Note: the API drops today's date from its response (only returns future dates),
|
||||
// so scrapeRidesForDay may fall back to the nearest upcoming date.
|
||||
ridesResult = await scrapeRidesForDay(apiId, today);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user