feat(go-services): Phase 2 ingest — shared Ingestor + shadow consumer
Implements the plugin event handlers (the /ws/position write logic) as a shared Ingestor, validated against real traffic by replaying Python's /ws/live firehose into an isolated dereth_go DB (no production write, no plugin stolen). - ingest.go: faithful ports of telemetry (kill-delta -> char_stats, server received_at stamp), rare (rare_stats/rare_stats_sessions/rare_events), portal (coord upsert), character_stats (stats_data JSONB subset + upsert), spawn, and the memory-only handlers (vitals/quest/equipment_cantrip/nearby/dungeon). In -memory live state + read-side overlay accessors. - shadow.go: coder/websocket consumer of /ws/live -> Ingestor.dispatch (telemetry matched by shape since its broadcast has no type field). - main.go/store.go: ingest mode (READ_ONLY=false + SHADOW_INGEST_WS) wires the ingestor; read handlers (/character-stats, /equipment-cantrip, /quest-status) now consult the live overlay first, like Python. - compose: shadow instance ingests ws://dereth-tracker:8765/ws/live. Validated live: dereth_go has 73 distinct telemetry chars; shadow /live online set == production (73=73); character_stats 5/5 exact byte-match (0 mismatch); char_stats kill-deltas + portals accumulating. compare/compare_ingest.py. Deferred to next pass: combat_stats (delta/merge), share_*, the /ws/position + /ws/live servers (for cutover). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
6a839e69bc
commit
a5d69ba88d
7 changed files with 621 additions and 3 deletions
|
|
@ -14,14 +14,27 @@ import (
|
|||
|
||||
// GET /quest-status (main.py:1940)
|
||||
func (s *Server) handleQuestStatus(w http.ResponseWriter, r *http.Request) {
|
||||
questData := map[string]any{}
|
||||
playerCount := 0
|
||||
if s.ingestor != nil {
|
||||
qd, n := s.ingestor.questData()
|
||||
playerCount = n
|
||||
for c, qs := range qd {
|
||||
m := map[string]any{}
|
||||
for k, v := range qs {
|
||||
m[k] = v
|
||||
}
|
||||
questData[c] = m
|
||||
}
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string]any{
|
||||
"quest_data": map[string]any{},
|
||||
"quest_data": questData,
|
||||
"tracked_quests": []string{
|
||||
"Stipend Collection Timer",
|
||||
"Blank Augmentation Gem Pickup Timer",
|
||||
"Insatiable Eater Jaw",
|
||||
},
|
||||
"player_count": 0,
|
||||
"player_count": playerCount,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -36,6 +49,12 @@ func (s *Server) handleVitalSharingPeers(w http.ResponseWriter, r *http.Request)
|
|||
// GET /equipment-cantrip-state/{name} (main.py:4167)
|
||||
func (s *Server) handleEquipmentCantrip(w http.ResponseWriter, r *http.Request) {
|
||||
name := r.PathValue("name")
|
||||
if s.ingestor != nil {
|
||||
if v, ok := s.ingestor.getEquipmentCantrip(name); ok {
|
||||
writeJSON(w, http.StatusOK, v)
|
||||
return
|
||||
}
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string]any{
|
||||
"type": "equipment_cantrip_state",
|
||||
"character_name": name,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue