M8-R06: refresh Tibber prices after startup and configuration

This commit is contained in:
2026-08-24 06:45:31 +02:00
parent 0924e8df52
commit 09abe05f66
8 changed files with 275 additions and 14 deletions
+7 -10
View File
@@ -1,6 +1,7 @@
import logging
import os
from contextlib import asynccontextmanager
from datetime import UTC, datetime
from pathlib import Path
from typing import Callable
@@ -38,7 +39,7 @@ from app.services.dsmr_ingest import apply_dsmr_subscription
from app.services.public_ip import check_public_ipv4_and_notify
from app.services.modbus_poll import poll_all_enabled_devices, BASE_POLL_TICK_SECONDS
from app.services.ha_discovery import publish_discovery, publish_states
from app.services.tibber_prices import refresh_prices
from app.services.tibber_prices import run_tibber_refresh_best_effort
from app.services.energy_cost import compute_closed_periods
from app.services.meter_cost import compute_closed_periods as compute_closed_meter_cost_periods
from app.services.warmtelink_worker import warmtelink_worker_manager
@@ -91,15 +92,7 @@ def _run_scheduled_tibber_refresh() -> None:
so that a single failed fetch does not crash the scheduler or affect the
other background jobs.
"""
session_local = get_session_local()
session: Session = session_local()
try:
runtime_settings = build_runtime_settings(session, get_settings())
refresh_prices(session, runtime_settings)
except Exception:
logger.exception("_run_scheduled_tibber_refresh: unexpected error")
finally:
session.close()
run_tibber_refresh_best_effort()
def _run_scheduled_energy_cost() -> None:
@@ -264,6 +257,10 @@ async def lifespan(_: FastAPI):
replace_existing=True,
max_instances=1,
coalesce=True,
# APScheduler otherwise waits one full interval before its first run.
# This preserves the hourly cadence while requesting a non-blocking
# startup fetch as soon as the scheduler starts.
next_run_time=datetime.now(UTC),
)
# Energy cost billing: compute uncalculated closed 15-minute periods every minute.
# The job is a no-op when no active contract or DSMR data is present, so it is