diff --git a/dashboard/dashboard.py b/dashboard/dashboard.py
index 63b3757..93bafe8 100644
--- a/dashboard/dashboard.py
+++ b/dashboard/dashboard.py
@@ -16,7 +16,7 @@ def fetch_state():
def broadcast_loop():
while True:
- time.sleep(3)
+ time.sleep(5)
data = fetch_state(); payload = json.dumps(data)
with sse_lock:
dead = [q for q in sse_subscribers if not q.put(payload)]
@@ -256,7 +256,13 @@ var aHTML=agents.map(function(a){return'
-
';}
}
-function poll(){fetch('/api/state').then(function(r){return r.json()}).then(function(data){render(data);$('connection-status').textContent='live';}).catch(function(){$('connection-status').textContent='reconnecting';});}
+var sseConnected = false;
+function poll(){if(sseConnected)return;fetch('/api/state').then(function(r){return r.json()}).then(function(data){render(data);$('connection-status').textContent='live';}).catch(function(){$('connection-status').textContent='reconnecting';});}
+// SSE connection tracking
+var es = new EventSource('/api/stream');
+es.onopen = function(){sseConnected = true; $('connection-status').textContent = 'live (SSE)';};
+es.onmessage = function(e){try{render(JSON.parse(e.data));}catch(ex){}};
+es.onerror = function(){sseConnected = false; $('connection-status').textContent = 'polling';};
function loadScatter(){
var m=$('scatter-model').value;
fetch('/api/scatter?window=24&model='+m).then(function(r){return r.json()}).then(renderScatter).catch(function(){});
@@ -293,7 +299,7 @@ el.innerHTML=''+gri
var models=[];pts.forEach(function(p){if(models.indexOf(p.model)===-1)models.push(p.model);});
lg.innerHTML=models.map(function(m){return' '+mlab[m]+' ';}).join('');
}
-poll();setInterval(poll,3000);loadTS();loadPerf();setInterval(loadPerf,15000);loadScatter();setInterval(loadScatter,30000);
+poll();setInterval(poll,10000);loadTS();loadPerf();setInterval(loadPerf,15000);loadScatter();setInterval(loadScatter,30000);