diff --git a/src/routes/internal.js b/src/routes/internal.js index e2ca9f5..d64111f 100644 --- a/src/routes/internal.js +++ b/src/routes/internal.js @@ -487,6 +487,33 @@ router.get('/gamectx/accrual', async (req, res) => { * by waiting for the cron slot. Idempotent — running it twice is a no-op beyond * refreshing values and updated_at. */ +/** + * POST /api/internal/lineup-context/refresh — INDUCE the lineup + baserunner + * context ingest. + * + * Exists for the same reason the statcast one does: a job is proven by running + * it and reading the result, never by waiting for the slot it rides in. It also + * makes the ingest verifiable WITHOUT a full snapshot, which now takes ~3 + * minutes and 524s at the edge — so a zero row count can be diagnosed as a + * wiring bug rather than an honest absence in seconds. + */ +router.post('/lineup-context/refresh', async (req, res) => { + try { + const svc = require('../services/lineupContextService'); + const sb = require('../utils/supabase').getSupabaseServiceClient(); + if (!sb) return res.status(500).json({ ok: false, error: 'no supabase service client' }); + const out = await svc.refreshContext({ + supabase: sb, + sport: 'mlb', + date: req.query.date || undefined, + }); + return res.status(out.ok ? 200 : 500).json(out); + } catch (err) { + console.error('[internal/lineup-context]', err.message); + return res.status(500).json({ ok: false, error: err.message }); + } +}); + router.post('/statcast/refresh', async (req, res) => { try { const agg = require('../services/statcastAggregateService');