Release Fenris 0.3.6
Release / release (push) Failing after 6s

This commit is contained in:
xavierk
2026-09-16 08:05:28 +05:30
parent f06424f3b8
commit 44c57b70dd
29 changed files with 788 additions and 810 deletions
+54 -39
View File
@@ -188,7 +188,7 @@ def _determine_explanation(
) -> str:
"""Determine the explanation line for the status state."""
if store_fault:
return "observation store unreadable — see journal"
return "observation store unreadable — see collector logs"
if newer_schema:
return "observation store written by a newer Fenris — upgrade Fenris"
@@ -200,7 +200,7 @@ def _determine_explanation(
if last_collect_reason:
parts.append("(%s)" % last_collect_reason)
if freshness_age_s is not None and freshness != "empty":
parts.append("· last good sample %s ago" % freshness_age_human(freshness_age_s))
parts.append("· last good sample %s" % freshness_age_human(freshness_age_s))
return " ".join(parts) if parts else "last run failed"
if state == StatusState.INTERRUPTED:
@@ -211,7 +211,7 @@ def _determine_explanation(
if state == StatusState.STALE:
if freshness_age_s is not None:
return "last sample %s ago" % freshness_age_human(freshness_age_s)
return "last sample %s" % freshness_age_human(freshness_age_s)
return "data is stale"
if state == StatusState.WAITING:
@@ -223,7 +223,7 @@ def _determine_explanation(
if state == StatusState.MONITORING:
if freshness_age_s is not None:
return "last sample %s ago" % freshness_age_human(freshness_age_s)
return "last sample %s" % freshness_age_human(freshness_age_s)
return "monitoring active"
if state == StatusState.UNKNOWN:
@@ -257,7 +257,7 @@ def _determine_collecting_overlay(
def compose_status(
conn: sqlite3.Connection,
conn: Optional[sqlite3.Connection],
service: Optional[Dict[str, Any]],
clock_now: datetime,
store_fault: Optional[str] = None,
@@ -269,14 +269,17 @@ def compose_status(
This is the single entry point consumed by both TUI and CLI.
"""
service_available = service is not None and len(service) > 0
service_available = bool(service) and any(
service.get(key) is not None
for key in ("boot_enabled", "timer_active")
)
# --- Separate facts from service ---
boot_enabled = service.get("boot_enabled") if service_available else None
timer_active = service.get("timer_active") if service_available else None
last_collect_ok = service.get("last_collect_ok") if service_available else None
last_collect_age_s = service.get("last_collect_age_s") if service_available else None
last_collect_reason = service.get("last_collect_reason") if service_available else None
boot_enabled = service.get("boot_enabled") if service else None
timer_active = service.get("timer_active") if service else None
last_collect_ok = service.get("last_collect_ok") if service else None
last_collect_age_s = service.get("last_collect_age_s") if service else None
last_collect_reason = service.get("last_collect_reason") if service else None
# --- Freshness from store ---
freshness = "unknown"
@@ -285,7 +288,10 @@ def compose_status(
day_count = 0
deliberately_paused = False
if store_fault is None and newer_schema is None:
if conn is None and store_fault is None and newer_schema is None:
freshness = "empty"
if conn is not None and store_fault is None and newer_schema is None:
try:
cursor = conn.execute("SELECT ts FROM samples ORDER BY id DESC LIMIT 1")
row = cursor.fetchone()
@@ -301,28 +307,35 @@ def compose_status(
freshness_age_s = int((clock_now - ts).total_seconds())
except (ValueError, TypeError):
pass
except sqlite3.Error:
freshness = "unknown"
except sqlite3.Error as exc:
store_fault = str(exc)
try:
cursor = conn.execute("SELECT COUNT(*) FROM samples")
sample_count = cursor.fetchone()[0]
cursor = conn.execute("SELECT COUNT(*) FROM day_aggregates")
day_count = cursor.fetchone()[0]
except sqlite3.Error:
pass
except sqlite3.Error as exc:
store_fault = str(exc)
try:
svc_for_pause = service if service_available else {}
deliberately_paused = is_deliberately_paused(conn, svc_for_pause)
except sqlite3.Error:
deliberately_paused = False
except sqlite3.Error as exc:
store_fault = str(exc)
if store_fault or newer_schema:
freshness = "unknown"
freshness_age_s = None
sample_count = day_count = 0
deliberately_paused = False
# --- External stop detection ---
# External stop = timer inactive + boot disabled + NOT deliberately paused
# + period still open (the timer was stopped but Fenris didn't close the period)
external_stop_reason = None
if not deliberately_paused and timer_active is False and boot_enabled is False:
if (conn is not None and not store_fault and not newer_schema
and not deliberately_paused and timer_active is False and boot_enabled is False):
# Check if there's an open monitoring period (external stop left it open)
try:
open_period = conn.execute(
@@ -428,10 +441,9 @@ def render_status_cli(comp: StatusComposition) -> str:
# Separate facts
facts = []
if comp.freshness != "unknown":
facts.append("freshness: %s" % comp.freshness)
if comp.freshness_age_s is not None:
facts[-1] += " (%s)" % freshness_age_human(comp.freshness_age_s) if facts else "freshness: %s" % freshness_age_human(comp.freshness_age_s)
facts.append("freshness: %s" % comp.freshness)
if comp.freshness_age_s is not None and facts:
facts[-1] += " (%s)" % freshness_age_human(comp.freshness_age_s)
if comp.last_collect_ok is True:
facts.append("last collect: ok")
elif comp.last_collect_ok is False:
@@ -441,10 +453,12 @@ def render_status_cli(comp: StatusComposition) -> str:
facts.append(collect_str)
else:
facts.append("last collect: unknown")
if comp.boot_enabled is not None:
facts.append("boot: %s" % ("enabled" if comp.boot_enabled else "disabled"))
if comp.timer_active is not None:
facts.append("timer: %s" % ("active" if comp.timer_active else "inactive"))
facts.append("boot: %s" % (
"unknown" if comp.boot_enabled is None else "enabled" if comp.boot_enabled else "disabled"
))
facts.append("timer: %s" % (
"unknown" if comp.timer_active is None else "active" if comp.timer_active else "inactive"
))
if facts:
lines.append(" · ".join(facts))
@@ -486,29 +500,30 @@ def render_status_tui(comp: StatusComposition) -> str:
# Explanation
if comp.explanation:
lines.append(comp.explanation)
lines.append(comp.explanation[:1].upper() + comp.explanation[1:])
lines.append("")
# Separate facts
facts = []
if comp.freshness != "unknown":
facts.append("freshness: %s" % comp.freshness)
facts.append("Freshness: %s" % comp.freshness)
if comp.freshness_age_s is not None and facts:
facts[-1] += " (%s)" % freshness_age_human(comp.freshness_age_s)
if comp.last_collect_ok is True:
facts.append("last collect: ok")
facts.append("Last collect: ok")
elif comp.last_collect_ok is False:
collect_str = "last collect: FAILED"
collect_str = "Last collect: failed"
if comp.last_collect_reason:
collect_str += " (%s)" % comp.last_collect_reason
facts.append(collect_str)
else:
facts.append("last collect: unknown")
if comp.boot_enabled is not None:
facts.append("boot: %s" % ("enabled" if comp.boot_enabled else "disabled"))
if comp.timer_active is not None:
facts.append("timer: %s" % ("active" if comp.timer_active else "inactive"))
facts.append("Last collect: unknown")
facts.append("Boot: %s" % (
"unknown" if comp.boot_enabled is None else "enabled" if comp.boot_enabled else "disabled"
))
facts.append("Timer: %s" % (
"unknown" if comp.timer_active is None else "active" if comp.timer_active else "inactive"
))
if facts:
lines.append(" · ".join(facts))
@@ -516,11 +531,11 @@ def render_status_tui(comp: StatusComposition) -> str:
# Continuity
if comp.continuity:
lines.append("")
lines.append("[bold]CONTINUITY[/bold] %s" % comp.continuity)
lines.append("[bold]Continuity[/bold] %s" % comp.continuity)
# Deliberate pause
if comp.paused_lines:
for pl in comp.paused_lines:
lines.append(pl)
lines.append(pl[:1].upper() + pl[1:])
return "\n".join(lines)