Skip to content

Remote-Config Freshness

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 null gesetzt → 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.

QuestData.has_remote_config_fetched() -> bool # ein erfolgreicher Fetch in dieser Session?
QuestData.config_last_fetched_at() -> int # unix sec, 0 wenn nie
QuestData.config_freshness_seconds() -> int # secs seit letztem Fetch, -1 wenn nie
QuestData.is_config_stale() -> bool # true wenn nie ODER > Threshold
MethodeBoot-StateNach erfolgreichem FetchNach failed Fetch
has_remote_config_fetched()falsetrueunverändert
config_last_fetched_at()0unix-sec von jetztunverändert
config_freshness_seconds()-10, dann monoton wachsendunverändert
is_config_stale()truefalse bis Thresholdunverä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 nichtlast_fetched_at bleibt was es war. Ein 5xx oder Timeout reset-tet dir nicht den letzten erfolgreichen Pull.

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):

offline_banner.gd
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.

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))

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
# }
  • 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”.