Remote-Config Freshness
Wann ist meine Config live?
Section titled “Wann ist meine Config live?”get_config(key, default) liefert dir den Default in drei Situationen — und du kannst sie an der Rückgabe nicht unterscheiden:
- Backend wurde noch nie erreicht in dieser Session → Default
- Backend ist down, nichts auf Disk gecached → Default
- Backend hat den Key aktiv auf "" oder
nullgesetzt → Default
Solange das Spiel läuft sieht beides gleich aus. Customer denkt Config ist live, ist aber alt-cached oder nie gefetcht.
Seit SDK v1.20.0 (DIG-73) liefert die Freshness-API vier neue Top-Level-Methoden auf QuestData, mit denen du den State introspecten kannst.
Die vier Methoden
Section titled “Die vier Methoden”QuestData.has_remote_config_fetched() -> bool # ein erfolgreicher Fetch in dieser Session?QuestData.config_last_fetched_at() -> int # unix sec, 0 wenn nieQuestData.config_freshness_seconds() -> int # secs seit letztem Fetch, -1 wenn nieQuestData.is_config_stale() -> bool # true wenn nie ODER > Threshold| Methode | Boot-State | Nach erfolgreichem Fetch | Nach failed Fetch |
|---|---|---|---|
has_remote_config_fetched() | false | true | unverändert |
config_last_fetched_at() | 0 | unix-sec von jetzt | unverändert |
config_freshness_seconds() | -1 | 0, dann monoton wachsend | unverändert |
is_config_stale() | true | false bis Threshold | unverändert |
Wichtig: Disk-Cache-Hits flippen has_remote_config_fetched nicht. Boot startet bei false bis der Live-Backend wirklich erreicht wurde. Customer wollte wissen ob Live, nicht ob Cache überlebte.
Failed Fetches verändern den State nicht — last_fetched_at bleibt was es war. Ein 5xx oder Timeout reset-tet dir nicht den letzten erfolgreichen Pull.
Threshold konfigurieren
Section titled “Threshold konfigurieren”is_config_stale() flippt auf true wenn der letzte Fetch älter ist als das Threshold. Default: 300 Sekunden (5 min).
Project Settings → Advanced → quest_data/config_stale_threshold_seconds (TYPE_INT). Beispiel: für ein PvP-Spiel das Balancing aggressiv pulled — 60. Für ein Single-Player-Idle-Game wo Werte selten ändern — 3600.
Pattern 1 — “Values from Cache” UI-Banner
Section titled “Pattern 1 — “Values from Cache” UI-Banner”Spieler soll sehen ob die Werte gerade live sind oder aus dem Cache kommen (z.B. Backend down, Spieler offline):
extends Label
func _process(_delta: float) -> void: visible = QuestData.is_config_stale() if visible: text = "Werte aus Cache (zuletzt aktualisiert vor %d sec)" % QuestData.config_freshness_seconds()Kein eigener Timer, kein eigener Threshold-State, kein eigenes “wann war der letzte Fetch”-Tracking. Die SDK macht’s.
Pattern 2 — Auto-Refetch wenn stale
Section titled “Pattern 2 — Auto-Refetch wenn stale”Vor einem critical-path Config-Read aktualisieren falls zu alt:
func enter_shop() -> void: if QuestData.is_config_stale(): QuestData.fetch_remote_config() # Customer-Code wartet hier nicht — fetch ist async und non-blocking. # Beim nächsten frame (oder via Signal) sind die Werte da. open_shop_ui()is_config_stale() ist eine reine Read-Operation, kostet keine Network-Calls. Du kannst’s ohne Sorgen jeden Frame oder vor jedem Call aufrufen.
Pattern 3 — Pre-Check vor critical Reads
Section titled “Pattern 3 — Pre-Check vor critical Reads”Wenn ein Wert zwingend frisch sein muss (z.B. Live-Event-Toggle), Pre-Check ob überhaupt schon mal gefetcht:
func is_holiday_event_active() -> bool: if not QuestData.has_remote_config_fetched(): # Wir haben den Backend nie erreicht — defaultet auf false. return false return bool(QuestData.get_config("holiday_event_active", false))Pattern 4 — Bug-Reports
Section titled “Pattern 4 — Bug-Reports”dump_state() enthält die Freshness-Section, kann direkt in Bug-Reports kopiert werden:
print(JSON.stringify(QuestData.dump_state().remote_config, " "))# {# "has_been_fetched": true,# "last_fetched_at": 1714845600,# "freshness_seconds": 42,# "is_stale": false,# "stale_threshold_seconds": 300,# "config_keys_count": 12# }Was nicht in Scope ist
Section titled “Was nicht in Scope ist”- Auto-Refetch bei stale — bewusst Customer-Choice. SDK pollt nicht im Hintergrund. Wenn du polling willst, bau dir einen Timer der
fetch_remote_config()ruft. - Per-Key Freshness-Tracking — der Status ist global. Wenn du wissen willst “wann war Key X zuletzt gefetcht”, ist die Antwort dieselbe wie für jeden anderen Key (alle kommen im gleichen Response).
- Persistence über Sessions — Boot startet immer bei
has_remote_config_fetched=false. Disk-Cache (user://quest_config.save) lebt weiter, aber das Freshness-Flag nicht. Sonst würdest du nach 4 Wochen offline immer noch glauben “ist live”.