feat: instrument model

This commit is contained in:
OpenSquared
2026-07-03 21:48:55 +02:00
parent 716d8fa56c
commit 3be72e44cc
4 changed files with 178 additions and 6 deletions

View File

@@ -563,3 +563,93 @@ def scrape_upcoming(weeks_ahead: int = 5) -> Dict[str, Any]:
conn.close()
print(f"[FF scrape] total upserted: {total_inserted}", flush=True)
return {"weeks_scraped": weeks_ahead, "total_upserted": total_inserted, "by_week": week_results}
def sync_historical_range(from_date: date, to_date: Optional[date] = None) -> Dict[str, Any]:
"""
Backfill ff_calendar for a historical date range by scraping FF HTML week by week.
Skips weeks that already have events with actual_value populated (avoids redundant requests).
Adds a small delay between requests to be respectful of the server.
Returns progress stats.
"""
import time
from services.database import get_conn
if to_date is None:
to_date = date.today()
# Align from_date to the Monday of its week
monday_start = from_date - timedelta(days=from_date.weekday())
monday_today = to_date - timedelta(days=to_date.weekday())
# Collect all Mondays in range
mondays: list[date] = []
cur = monday_start
while cur <= monday_today:
mondays.append(cur)
cur += timedelta(weeks=1)
if not mondays:
return {"weeks_scraped": 0, "total_upserted": 0, "skipped": 0, "by_week": {}}
conn = get_conn()
# Pre-check which weeks already have actual values to avoid redundant scraping
# A week is "done" if it has ≥5 events with actual_value for supported currencies
weeks_with_actuals: set[str] = set()
for m in mondays:
sunday = m + timedelta(days=6)
cnt = conn.execute(
"""SELECT COUNT(*) FROM ff_calendar
WHERE event_date >= ? AND event_date <= ?
AND actual_value IS NOT NULL""",
(str(m), str(sunday))
).fetchone()[0]
if cnt >= 5:
weeks_with_actuals.add(str(m))
total_inserted = 0
skipped = 0
week_results: Dict[str, Any] = {}
with httpx.Client(headers=_FF_HEADERS, follow_redirects=True, timeout=30) as client:
# Warm up session
try:
client.get(_FF_BASE, timeout=10)
time.sleep(1.0)
except Exception:
pass
for monday in mondays:
monday_str = str(monday)
if monday_str in weeks_with_actuals:
week_results[monday_str] = {"status": "skipped", "count": 0}
skipped += 1
print(f"[FF backfill] {monday_str}: already populated, skipping", flush=True)
continue
batch = _scrape_week(client, monday)
if batch:
_upsert_batch(conn, batch)
conn.commit()
total_inserted += len(batch)
week_results[monday_str] = {"status": "ok", "count": len(batch)}
else:
week_results[monday_str] = {"status": "empty", "count": 0}
print(f"[FF backfill] {monday_str}: {len(batch)} events", flush=True)
time.sleep(1.5) # respectful delay between requests
conn.close()
total_weeks = len(mondays)
print(f"[FF backfill] done: {total_inserted} events upserted, {skipped}/{total_weeks} weeks skipped", flush=True)
return {
"from_date": str(from_date),
"to_date": str(to_date),
"weeks_total": total_weeks,
"weeks_scraped": total_weeks - skipped,
"weeks_skipped": skipped,
"total_upserted": total_inserted,
"by_week": week_results,
}