import pandas as pd
from spotforecast2_safe.downloader import resilience as resil
result = resil.download_with_fallback(
api_key="YOUR_API_KEY",
start="202301010000",
end="202301050000",
now=pd.Timestamp.now(tz="UTC"),
max_retries=3,
backoff=5.0,
timeout=60.0,
fallback_enabled=True,
)
print(result.report())
if result.mode is None:
raise SystemExit("unrecoverable: no live data and no valid snapshot")downloader.resilience.download_with_fallback
downloader.resilience.download_with_fallback(
api_key,
*,
start,
end,
now,
max_retries,
backoff,
timeout,
fallback_enabled,
sleep=_time_module.sleep,
)Download zone loads with per-zone snapshot fallback.
Per-zone decision tree:
- Bootstrap:
SnapshotStore.seed_from_filefor each zone kind and the combined kind so the first run after adding this layer still has snapshots for existing interim files. - Per outer attempt (
max_retries), calldownload_zone_loads(..., on_zone_failure="collect")for the zones still failing; waitbackoff * 2**(attempt-1)between attempts. - Success for a zone: write snapshot via
SnapshotStore.writeand record status"live". - All attempts exhausted for a zone: if
fallback_enabledand a valid snapshot exists:store.restoretointerim/zone_<col>.csv, record status"cache"with age; else status"missing". - All four zones in {live, cache}:
mode="four_zone"; done. - Else (>= 1 missing): attempt the live combined download (
download_new_data, country_code=“DE”). Success: snapshot + status"live". Fail + valid snapshot: restore + status"cache"+ age. Fail + no snapshot: status"missing". - Combined in {live, cache}:
mode="combined"; elsemode=None(caller should raiseAbort(5, result.report())). SnapshotStore.prune(now)at the end.
This function never raises for download failures; it only returns the DownloadResult describing what happened.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| api_key | str | ENTSO-E Web API security token. | required |
| start | str | Download start in "YYYYMMDDHHMM" format. |
required |
| end | str | Download end in "YYYYMMDDHHMM" format. |
required |
| now | pd.Timestamp | Current UTC timestamp (used for snapshot naming and TTL checks). | required |
| max_retries | int | Number of outer retry rounds (each round retries all still-failing zones via one collect-mode call; one backoff * 2**(round-1) sleep after each failed round). |
required |
| backoff | float | Base wait in seconds (exponential: backoff * 2**(attempt-1)). |
required |
| timeout | float | None | Per-socket read timeout (seconds), or None to disable. |
required |
| fallback_enabled | bool | When False, snapshots are never READ as a fallback (live data or "missing"), but they are still WRITTEN on success. |
required |
| sleep | Callable[[float], None] | Callable used for inter-attempt waits; injected so tests can pass sleep=lambda s: None for instant execution. |
_time_module.sleep |
Returns
| Name | Type | Description |
|---|---|---|
| DownloadResult | DownloadResult | A record describing every zone’s outcome and the |
| DownloadResult | overall mode ("four_zone", "combined", or None). |