HOTFIX výkon: delta-profile cache 44 s/site se přepočítávala každých 15 min
fn_fill_forecast_accuracy (tick :02/:17/:32/:47, 4 lokality) na konci volá fn_refresh_site_pv_delta_profile_cache → fn_pv_forecast_delta_profile = agregace 120 dní nad 4.1M řádky forecast_accuracy = ~44 s/site na prod → ~3 minuty plné DB zátěže KAŽDOU čtvrthodinu → timeouty /sites a /health/detailed (30 s), celodenní 'pomalý server'. Fix: (1) cache refresh throttle 6 h přes delta_profile_cached_at (+p_force; profil má 14d poločas — 4×/den bohatě stačí); (2) 15min tick lookback 48→3 h (insert část); (3) denní 48h catch-up job 05:50. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -108,7 +108,7 @@ async def lifespan(app: FastAPI):
|
|||||||
for site in await _active_site_rows(conn):
|
for site in await _active_site_rows(conn):
|
||||||
try:
|
try:
|
||||||
n = await conn.fetchval(
|
n = await conn.fetchval(
|
||||||
"SELECT ems.fn_fill_forecast_accuracy($1, 48)",
|
"SELECT ems.fn_fill_forecast_accuracy($1, 3)",
|
||||||
site["id"],
|
site["id"],
|
||||||
)
|
)
|
||||||
if n:
|
if n:
|
||||||
@@ -257,6 +257,19 @@ async def lifespan(app: FastAPI):
|
|||||||
"scheduled_tuv_usage_stats site=%s failed", site["id"]
|
"scheduled_tuv_usage_stats site=%s failed", site["id"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def scheduled_forecast_accuracy_catchup() -> None:
|
||||||
|
"""Denní 48h catch-up (pozdní telemetrie) — 15min tick jede jen 3 h okno."""
|
||||||
|
async with app.state.pg_pool.acquire() as conn:
|
||||||
|
for site in await _active_site_rows(conn):
|
||||||
|
try:
|
||||||
|
await conn.fetchval(
|
||||||
|
"SELECT ems.fn_fill_forecast_accuracy($1, 48)", site["id"]
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
logger.exception(
|
||||||
|
"forecast_accuracy catchup site=%s failed", site["id"]
|
||||||
|
)
|
||||||
|
|
||||||
async def scheduled_ev_usage_stats() -> None:
|
async def scheduled_ev_usage_stats() -> None:
|
||||||
async with app.state.pg_pool.acquire() as conn:
|
async with app.state.pg_pool.acquire() as conn:
|
||||||
try:
|
try:
|
||||||
@@ -431,6 +444,14 @@ async def lifespan(app: FastAPI):
|
|||||||
id="tuv_usage_stats",
|
id="tuv_usage_stats",
|
||||||
replace_existing=True,
|
replace_existing=True,
|
||||||
)
|
)
|
||||||
|
scheduler.add_job(
|
||||||
|
scheduled_forecast_accuracy_catchup,
|
||||||
|
"cron",
|
||||||
|
hour=5,
|
||||||
|
minute=50,
|
||||||
|
id="forecast_accuracy_catchup",
|
||||||
|
replace_existing=True,
|
||||||
|
)
|
||||||
scheduler.add_job(
|
scheduler.add_job(
|
||||||
scheduled_ev_usage_stats,
|
scheduled_ev_usage_stats,
|
||||||
"cron",
|
"cron",
|
||||||
|
|||||||
@@ -1,13 +1,29 @@
|
|||||||
-- Cache delta profilu PV (těžká agregace forecast_accuracy) — refresh po fn_fill_forecast_accuracy.
|
-- Cache delta profilu PV (těžká agregace forecast_accuracy) — refresh po fn_fill_forecast_accuracy.
|
||||||
-- Prefix R__018: musí běžet před R__022 (volá fn_refresh_site_pv_delta_profile_cache).
|
-- Prefix R__018: musí běžet před R__022 (volá fn_refresh_site_pv_delta_profile_cache).
|
||||||
|
|
||||||
create or replace function ems.fn_refresh_site_pv_delta_profile_cache(p_site_id int)
|
drop function if exists ems.fn_refresh_site_pv_delta_profile_cache(int);
|
||||||
|
|
||||||
|
create or replace function ems.fn_refresh_site_pv_delta_profile_cache(
|
||||||
|
p_site_id int,
|
||||||
|
p_force boolean default false
|
||||||
|
)
|
||||||
returns void
|
returns void
|
||||||
language plpgsql
|
language plpgsql
|
||||||
as $fn$
|
as $fn$
|
||||||
declare
|
declare
|
||||||
v_profile jsonb;
|
v_profile jsonb;
|
||||||
begin
|
begin
|
||||||
|
-- VÝKON: agregace 120 dní nad forecast_accuracy trvá ~44 s/site na prod —
|
||||||
|
-- po 15 min ji přepočítávat dusilo celou DB (timeouty API). Profil má 14d
|
||||||
|
-- poločas, denní granularitu — čerstvost 6 h bohatě stačí.
|
||||||
|
if not p_force and exists (
|
||||||
|
select 1 from ems.site_pv_forecast_calibration c
|
||||||
|
where c.site_id = p_site_id
|
||||||
|
and c.delta_profile_cached_at > now() - interval '6 hours'
|
||||||
|
) then
|
||||||
|
return;
|
||||||
|
end if;
|
||||||
|
|
||||||
v_profile := ems.fn_pv_forecast_delta_profile(
|
v_profile := ems.fn_pv_forecast_delta_profile(
|
||||||
p_site_id,
|
p_site_id,
|
||||||
now() - interval '120 days',
|
now() - interval '120 days',
|
||||||
|
|||||||
Reference in New Issue
Block a user