fix: validate atomic configuration updates and expire stale monitoring snapshots

This commit is contained in:
way
2026-10-18 18:15:22 +08:00
parent c82d9ab3c2
commit 9b83937d60
10 changed files with 244 additions and 85 deletions
+9 -4
View File
@@ -4,6 +4,7 @@ from contextlib import closing
import http.client
import json
import socket
import time
import threading
import uuid
from pathlib import Path
@@ -65,14 +66,15 @@ class Publisher:
"""One replaceable snapshot, not an unbounded queue of animation commands."""
def __init__(self,plugins,source,log):
self.plugins=plugins;self.source=source;self.log=log
self.session=str(uuid.uuid4());self.revision=0;self.snapshot=None
self.session=str(uuid.uuid4());self.revision=0;self.snapshot=None;self.published_at=None
self.lock=threading.Lock();self.stop_event=threading.Event();self.status={}
self.threads=[threading.Thread(target=self.run,args=(key,path),name='plugin-'+key,daemon=True)
for key,path in plugins.items()]
for thread in self.threads:thread.start()
def publish(self,state):
with self.lock:self.snapshot=copy.deepcopy(state)
with self.lock:
self.snapshot=copy.deepcopy(state);self.published_at=time.monotonic()
def current_status(self):
with self.lock:return copy.deepcopy(self.status)
@@ -80,8 +82,11 @@ class Publisher:
def run(self,key,path):
previous_error=None;revision=0;descriptor=None
while not self.stop_event.is_set():
with self.lock:state=self.snapshot
if state is not None:
with self.lock:
state=self.snapshot
fresh=self.published_at is not None and time.monotonic()-self.published_at<3
# Never renew a hardware lease from a stalled monitoring loop.
if state is not None and fresh:
revision+=1
payload={'api_version':1,'source':self.source,'session':self.session,'revision':revision,
'ttl_seconds':10,'system':state['system'],'network':state['network'],'alerts':state['display']['alerts']}