ShineBridge v1.8.28 — history.py: load_recent Fix + periodisches Cleanup
- load_recent(): Window-Funktion durch pro-Sensor-Indexabfragen ersetzt (SELECT ... ORDER BY ts DESC LIMIT N per sensor_id) — nutzt Index optimal, kein Full-Table-Scan mehr auf 1M+ Zeilen beim Start - Periodisches Cleanup: täglich via Daemon-Thread statt nur beim Start — DB bleibt dauerhaft auf RETENTION_DAYS beschränkt - RETENTION_DAYS: 7 → 14 (explizites Maximum per Konfiguration) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
name: ShineBridge
|
||||
version: "1.8.27"
|
||||
version: "1.8.28"
|
||||
slug: shinebridge
|
||||
description: Growatt Wechselrichter lokal in Home Assistant — Modbus TCP via ShineLAN-X, MQTT Discovery, Web UI
|
||||
url: https://gitea.bitfire.work/retr0/shinebridge
|
||||
|
||||
+22
-15
@@ -7,7 +7,7 @@ from typing import Dict, List, Optional, Tuple
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
DB_PATH = "/data/history.db"
|
||||
RETENTION_DAYS = 7
|
||||
RETENTION_DAYS = 14
|
||||
|
||||
_lock = threading.Lock()
|
||||
_conn: sqlite3.Connection | None = None
|
||||
@@ -59,9 +59,19 @@ def init_db():
|
||||
""")
|
||||
c.commit()
|
||||
cleanup_old()
|
||||
_start_cleanup_scheduler()
|
||||
log.info("History DB initialisiert: %s", DB_PATH)
|
||||
|
||||
|
||||
def _start_cleanup_scheduler():
|
||||
def _loop():
|
||||
while True:
|
||||
time.sleep(86400)
|
||||
cleanup_old()
|
||||
t = threading.Thread(target=_loop, daemon=True, name="history-cleanup")
|
||||
t.start()
|
||||
|
||||
|
||||
def period_key(period_type: str, billing_day: int = 1, billing_month: int = 1) -> str:
|
||||
import datetime
|
||||
today = datetime.date.today()
|
||||
@@ -117,21 +127,18 @@ def write_batch(inv_id: str, ts: float, values: Dict[str, float]):
|
||||
def load_recent(inv_id: str, limit: int = 300) -> Dict[str, List[Tuple[float, float]]]:
|
||||
"""Letzte `limit` Messpunkte pro Sensor — zum Befüllen der In-Memory-Deque beim Start."""
|
||||
with _lock:
|
||||
rows = _get_conn().execute("""
|
||||
SELECT sensor_id, ts, value
|
||||
FROM (
|
||||
SELECT sensor_id, ts, value,
|
||||
ROW_NUMBER() OVER (PARTITION BY sensor_id ORDER BY ts DESC) AS rn
|
||||
FROM measurements
|
||||
WHERE inv_id = ?
|
||||
)
|
||||
WHERE rn <= ?
|
||||
ORDER BY ts ASC
|
||||
""", (inv_id, limit)).fetchall()
|
||||
|
||||
c = _get_conn()
|
||||
sensors = [r[0] for r in c.execute(
|
||||
"SELECT DISTINCT sensor_id FROM measurements WHERE inv_id = ?", (inv_id,)
|
||||
).fetchall()]
|
||||
result: Dict[str, List[Tuple[float, float]]] = {}
|
||||
for sensor_id, ts, value in rows:
|
||||
result.setdefault(sensor_id, []).append((ts, value))
|
||||
for sid in sensors:
|
||||
rows = c.execute(
|
||||
"SELECT ts, value FROM measurements "
|
||||
"WHERE inv_id = ? AND sensor_id = ? ORDER BY ts DESC LIMIT ?",
|
||||
(inv_id, sid, limit),
|
||||
).fetchall()
|
||||
result[sid] = [(ts, val) for ts, val in reversed(rows)]
|
||||
return result
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user