Files
DOLPHIN/prod/hz_warmup.py
hjnormey 01c19662cb initial: import DOLPHIN baseline 2026-04-21 from dolphinng5_predict working tree
Includes core prod + GREEN/BLUE subsystems:
- prod/ (BLUE harness, configs, scripts, docs)
- nautilus_dolphin/ (GREEN Nautilus-native impl + dvae/ preserved)
- adaptive_exit/ (AEM engine + models/bucket_assignments.pkl)
- Observability/ (EsoF advisor, TUI, dashboards)
- external_factors/ (EsoF producer)
- mc_forewarning_qlabs_fork/ (MC regime/envelope)

Excludes runtime caches, logs, backups, and reproducible artifacts per .gitignore.
2026-04-21 16:58:38 +02:00

178 lines
6.1 KiB
Python
Executable File

"""Hazelcast Warm-Up from ClickHouse.
Reconstructs critical HZ map state from ClickHouse after an HZ restart.
Called on startup by MHS or as a standalone script.
HZ is RAM-only volatile — every restart wipes all state. This module
reads the last-known values from CH (the persistent audit trail) and
pre-populates HZ maps so services don't start from zero.
Maps reconstructed:
DOLPHIN_FEATURES["exf_latest"] — from dolphin.exf_data
DOLPHIN_FEATURES["acb_boost"] — from dolphin.acb_state
DOLPHIN_FEATURES["mc_forewarner_latest"] — from dolphin.posture_events (mc_status)
DOLPHIN_SAFETY["latest"] — from dolphin.posture_events
DOLPHIN_HEARTBEAT["nautilus_flow_heartbeat"] — synthetic (marks warm-up)
DOLPHIN_LIFECYCLE["state"] — lifecycle sentinel
Usage:
from hz_warmup import hz_warmup
hz_warmup(hz_client) # call once after HZ client connects
"""
import json
import logging
import time
import urllib.request
from datetime import datetime, timezone
log = logging.getLogger("hz_warmup")
CH_URL = "http://localhost:8123"
CH_USER = "dolphin"
CH_PASS = "dolphin_ch_2026"
CH_DB = "dolphin"
def _ch_query(sql: str) -> list[dict]:
"""Run a CH query, return list of row dicts. Returns [] on failure."""
url = f"{CH_URL}/?database={CH_DB}&query={urllib.parse.quote(sql + ' FORMAT JSONEachRow')}"
req = urllib.request.Request(url)
req.add_header("X-ClickHouse-User", CH_USER)
req.add_header("X-ClickHouse-Key", CH_PASS)
try:
with urllib.request.urlopen(req, timeout=5) as resp:
body = resp.read().decode()
return [json.loads(line) for line in body.strip().split("\n") if line.strip()]
except Exception as e:
log.warning("CH query failed: %s", e)
return []
def _write_lifecycle(hz_client, state: str):
"""Write lifecycle sentinel to DOLPHIN_LIFECYCLE."""
m = hz_client.get_map("DOLPHIN_LIFECYCLE").blocking()
m.put("state", json.dumps({
"state": state,
"ts": datetime.now(timezone.utc).isoformat(),
"pid": __import__("os").getpid(),
}))
log.info("LIFECYCLE: %s", state)
def read_lifecycle_state(hz_client) -> str:
"""Read current lifecycle state. Returns 'UNKNOWN' if not set."""
try:
m = hz_client.get_map("DOLPHIN_LIFECYCLE").blocking()
raw = m.get("state")
if raw:
return json.loads(raw).get("state", "UNKNOWN")
except Exception:
pass
return "UNKNOWN"
import urllib.parse
def hz_warmup(hz_client) -> dict:
"""Reconstruct HZ state from ClickHouse. Returns summary of what was restored."""
summary = {}
_write_lifecycle(hz_client, "STARTING")
features = hz_client.get_map("DOLPHIN_FEATURES").blocking()
# 1. ExF latest
rows = _ch_query("SELECT * FROM exf_data ORDER BY ts DESC LIMIT 1")
if rows:
r = rows[0]
exf_payload = {
"funding_rate_btc": r.get("funding_rate", 0),
"funding_rate_eth": r.get("funding_rate", 0),
"dvol": r.get("dvol", 0),
"fear_greed": r.get("fear_greed", 0),
"taker_buy_sell_ratio": r.get("taker_ratio", 0),
"_ok_count": 5,
"_acb_ready": True,
"_ts": r.get("ts", ""),
"_source": "ch_warmup",
}
features.put("exf_latest", json.dumps(exf_payload))
summary["exf_latest"] = True
log.info("Restored exf_latest from CH (ts=%s)", r.get("ts"))
# 2. ACB boost
rows = _ch_query("SELECT * FROM acb_state ORDER BY ts DESC LIMIT 1")
if rows:
r = rows[0]
acb_payload = {
"boost": r.get("boost", 1.0),
"beta": r.get("beta", 0.8),
"signals": r.get("signals", 0),
"_ts": r.get("ts", ""),
"_source": "ch_warmup",
}
features.put("acb_boost", json.dumps(acb_payload))
summary["acb_boost"] = True
log.info("Restored acb_boost from CH (boost=%.2f)", r.get("boost", 0))
# 3. Posture (DOLPHIN_SAFETY)
rows = _ch_query("SELECT * FROM posture_events ORDER BY ts DESC LIMIT 1")
if rows:
r = rows[0]
safety_payload = {
"posture": r.get("posture", "APEX"),
"Rm": r.get("rm", 0.97),
"timestamp": r.get("ts", ""),
"breakdown": {},
"_source": "ch_warmup",
}
safety_map = hz_client.get_map("DOLPHIN_SAFETY").blocking()
safety_map.put("latest", json.dumps(safety_payload))
summary["posture"] = r.get("posture")
log.info("Restored posture from CH: %s (Rm=%.3f)", r.get("posture"), r.get("rm", 0))
# 4. Heartbeat (synthetic — marks that warm-up populated state)
hb_map = hz_client.get_map("DOLPHIN_HEARTBEAT").blocking()
hb_payload = {
"ts": time.time(),
"iso": datetime.now(timezone.utc).isoformat(),
"phase": "warmup",
"flow": "hz_warmup",
}
hb_map.put("nautilus_flow_heartbeat", json.dumps(hb_payload))
summary["heartbeat"] = True
# 5. MC-Forewarner (if available)
rows = _ch_query("""
SELECT ts, posture, rm,
JSONExtractString(trigger, 'Cat2') as cat2
FROM posture_events
ORDER BY ts DESC LIMIT 1
""")
# MC status isn't directly in CH — use a safe default
mc_payload = {
"status": "GREEN",
"catastrophic_prob": 0.05,
"envelope_score": 0.95,
"timestamp": datetime.now(timezone.utc).isoformat(),
"_source": "ch_warmup_default",
}
features.put("mc_forewarner_latest", json.dumps(mc_payload))
summary["mc_forewarner"] = True
_write_lifecycle(hz_client, "READY")
log.info("HZ warm-up complete: %s", summary)
return summary
if __name__ == "__main__":
"""Standalone warm-up — run after HZ container starts."""
import hazelcast
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(name)s: %(message)s")
client = hazelcast.HazelcastClient(cluster_name="dolphin", cluster_members=["localhost:5701"])
result = hz_warmup(client)
print(json.dumps(result, indent=2))
client.shutdown()