# Caching & Monitoring

Muster für ML-Prognosen im Produktivbetrieb – Caching, Batching und Kontingentverwaltung.



Fehlerbehandlung und 422-Codes: [Fehlerbehandlung](/docs/v31/ml-integration-errors). HTTP-Fehler der Plattform und Wiederholungsversuche: [Fehlerbehandlung](/docs/errors).

### Datenaktualität [#data-freshness]

Beide ML-Endpoints liefern für einen gegebenen Satz von Eingaben deterministische Schätzungen. Die Ergebnisse bleiben über Zeiträume von Tagen bis Wochen stabil — das Modell wird regelmäßig neu trainiert, nicht in Echtzeit.

| Endpoint               | Empfohlene TTL | Cache-Schlüssel                         | Hinweise                                                                                     |
| ---------------------- | -------------- | --------------------------------------- | -------------------------------------------------------------------------------------------- |
| `GET /ml/flight-time`  | 24 Stunden     | `flighttime:{from}:{to}:{aircraft}`     | Routenstatistiken ändern sich selten; 24 h sind für die meisten Anwendungsfälle unbedenklich |
| `GET /carbon/estimate` | 1–24 Stunden   | `carbon:{dep}:{arr}:{passengers}:{rfi}` | Kürzere TTL, wenn sich die Passagierzahl oder das RFI-Flag in Ihrer UI häufig ändert         |

Routenstatistiken werden aus historischen Betriebsdaten abgeleitet. Eine TTL von 24 Stunden für die Flugzeit ist angemessen, weil sich die Blockzeit-Normwerte für ein bestimmtes Städtepaar und einen bestimmten Flugzeugtyp nur ändern, wenn Fluggesellschaften ihre Flugpläne saisonal anpassen.

**ML-Hinweis:*&#x2A; Stellen Sie Schätzungen als historische Durchschnittswerte dar, nicht als Echtzeitprognosen. Bei der Flugzeit werden Wind und aktuelle Streckenführung nicht modelliert. Bei CO₂ folgen die Schätzungen der Methodik von &#x2A;*[ICAO Doc 9988](https://www.icao.int/environmental-protection/CarbonOffset/Pages/default.aspx)**; bei `include_rfi=true` enthält der Wert den [Radiative Forcing Index](https://en.wikipedia.org/wiki/Radiative_forcing) (\~2× Basis-CO₂) und muss in Texten für Passagiere offengelegt werden.

```python
import os
import time
import requests

HEADERS = {
    "X-RapidAPI-Key": os.getenv("RAPIDAPI_KEY", "YOUR_RAPIDAPI_KEY"),
    "X-RapidAPI-Host": "skylink-api.p.rapidapi.com",
}
BASE = "https://skylink-api.p.rapidapi.com"

_cache: dict[str, tuple[dict, float]] = {}


def _cached_get(url: str, params: dict, ttl_seconds: int) -> dict | None:
    """In-process TTL cache. Replace with Redis for multi-instance deployments."""
    key = url + str(sorted(params.items()))
    cached = _cache.get(key)
    if cached and time.time() < cached[1]:
        return cached[0]

    r = requests.get(url, headers=HEADERS, params=params, timeout=(10, 15))
    if r.status_code == 404:
        return None
    r.raise_for_status()
    data = r.json()
    _cache[key] = (data, time.time() + ttl_seconds)
    return data


def get_flight_time(
    origin: str, destination: str, aircraft: str | None = None
) -> dict | None:
    """Cached ML flight time estimate. TTL 24 hours."""
    params: dict[str, str] = {"from": origin, "to": destination}
    if aircraft:
        params["aircraft"] = aircraft
    return _cached_get(f"{BASE}/ml/flight-time", params, ttl_seconds=86400)


def get_carbon(
    departure_icao: str,
    arrival_icao: str,
    passengers: int = 1,
    include_rfi: bool = False,
) -> dict | None:
    """Cached carbon estimate. TTL 1 hour (adjust to 24 h for stable routes)."""
    params: dict[str, str | int] = {
        "departure_icao": departure_icao,
        "arrival_icao": arrival_icao,
        "passengers": passengers,
        "include_rfi": str(include_rfi).lower(),
    }
    return _cached_get(f"{BASE}/carbon/estimate", params, ttl_seconds=3600)


if __name__ == "__main__":
    data = get_flight_time("KJFK", "KLAX", aircraft="B738")
    if data:
        print(
            f"Estimated: {data['estimated_hours_display']}  "
            f"(range {data['min_minutes']}–{data['max_minutes']} min)"
        )
        print("Statistical average — wind not modelled.")

    data2 = get_flight_time("KJFK", "KLAX", aircraft="B738")
    print("Cache hit:", data2 is not None)
```

### Rate Limits [#rate-limits]

Jede Antwort enthält Rate-Limit-Header. Überwachen Sie `X-RateLimit-Requests-Remaining` für beide Endpoints zusammen — jeder Aufruf von `/ml/flight-time` und `/carbon/estimate` wird auf Ihr monatliches Kontingent angerechnet.

| Header                           | Wert                                          |
| -------------------------------- | --------------------------------------------- |
| `X-RateLimit-Requests-Limit`     | Das monatliche Anfragekontingent Ihres Tarifs |
| `X-RateLimit-Requests-Remaining` | In diesem Monat verbleibende Anfragen         |
| `X-RateLimit-Requests-Reset`     | Sekunden bis zum Zurücksetzen des Kontingents |

Eine TTL von 24 Stunden für die Flugzeit reduziert die Aufrufe des ML-Endpoints auf einen pro Route und Tag — wichtig, wenn das Kontingent von allen API-Endpoints gemeinsam genutzt wird.

### Monitoring [#monitoring]

Protokollieren Sie bei jeder ML-Anfrage:

* `endpoint` (`flight-time` oder `carbon`)
* `status_code`
* `elapsed_ms`
* `quota_remaining` (aus `X-RateLimit-Requests-Remaining`)
* `cache_hit` (boolean — stammt die Antwort aus dem Cache?)

**Alarm auslösen bei:**

* `status = 429` — Abfragehäufigkeit verringern oder TTLs verlängern
* wiederholt `elapsed_ms > 5000` — erwägen Sie ein kürzeres Timeout mit einem sauberen Fallback
* `quota_remaining < 200` — das monatliche Limit ist bald erreicht; TTLs verlängern oder Aufrufe für unterschiedliche Routen reduzieren

***

Siehe auch: [Flugzeit](/docs/v31/flight-time) · [CO₂-Emissionen](/docs/v31/carbon) · [Fehlerbehandlung](/docs/v31/ml-integration-errors) · [Fehlerbehandlung](/docs/errors)
