diff --git a/app/main.py b/app/main.py index f817186..945c58b 100644 --- a/app/main.py +++ b/app/main.py @@ -95,6 +95,7 @@ _state = { "sync_attempts": 0, "sync_failures": 0, "source_used": None, + "data_updated": None, # freshest govUK price_last_updated across dataset } # --------------------------------------------------------------------------- @@ -299,12 +300,24 @@ def _parse_csv_to_stations(text: str) -> list: def _fetch_csv() -> list: """Download the hourly full-UK CSV mirror.""" + import csv + import io + with httpx.Client(timeout=120) as client: resp = client.get(CSV_URL) resp.raise_for_status() stations = _parse_csv_to_stations(resp.text) if not stations: raise RuntimeError("CSV parse returned zero stations") + # Freshest price-change timestamp in the CSV dump (govUK-side update + # time for the mirror's source data). + latest = None + for row in csv.DictReader(io.StringIO(resp.text)): + for key, val in row.items(): + if key.startswith("forecourts.price_change_effective_timestamp."): + if val and (latest is None or val > latest): + latest = val + _state["data_updated"] = latest return stations @@ -383,6 +396,15 @@ def _fetch_api() -> list: stations = _normalise_api_payload(stations_info, fuel_prices) if not stations: raise RuntimeError("API fetch returned zero stations") + # Freshest price timestamp the GOV.UK server itself reports — this is + # the dataset's own update time, independent of when we synced. + latest = None + for rec in fuel_prices: + for entry in rec.get("fuel_prices") or []: + ts = entry.get("price_last_updated") + if ts and (latest is None or ts > latest): + latest = ts + _state["data_updated"] = latest return stations @@ -504,6 +526,7 @@ def health(): "source": _state["source_used"], "stations_cached": _state["stations"] is not None, "stations_count": len(_stations_list()), + "data_updated": _state["data_updated"], "last_sync": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(_state["stations_fetched_at"])) if _state["stations_fetched_at"] else None, "sync_attempts": _state["sync_attempts"], "sync_failures": _state["sync_failures"], @@ -565,7 +588,14 @@ def stations( else: rows.sort(key=lambda r: r["price"] if r["price"] is not None else float("inf")) - return {"fuel": fuel, "count": len(rows[:limit]), "stations": rows[:limit]} + return { + "fuel": fuel, + "count": len(rows[:limit]), + "stations_count": len(rows), + "source": _state["source_used"], + "data_updated": _state["data_updated"], + "stations": rows[:limit], + } if __name__ == "__main__":