-- 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). drop function if exists ems.fn_refresh_site_pv_delta_profile_cache; create or replace function ems.fn_refresh_site_pv_delta_profile_cache( p_site_id int, p_force boolean default false ) returns void language plpgsql as $fn$ declare v_profile jsonb; 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( p_site_id, now() - interval '120 days', now() ); update ems.site_pv_forecast_calibration c set delta_profile_cache = v_profile, delta_profile_cached_at = now(), updated_at = now() where c.site_id = p_site_id; if not found then insert into ems.site_pv_forecast_calibration ( site_id, delta_learn_min_ts, delta_profile_cache, delta_profile_cached_at ) values ( p_site_id, timestamptz '2026-04-11T22:00:00Z', v_profile, now() ); end if; end; $fn$; comment on function ems.fn_refresh_site_pv_delta_profile_cache is 'Přepočte a uloží delta_profile_cache pro site (volá fn_pv_forecast_delta_profile).'; create or replace function ems.fn_pv_forecast_delta_profile_cached( p_site_id int, p_data_from timestamptz default (now() - interval '120 days'), p_data_to timestamptz default now(), p_half_life_days numeric default 14, p_threshold_w int default 150, p_top_n_days int default 3, p_non_top_day_factor numeric default 0.02, p_day_weight_gamma numeric default 1.0, p_max_age interval default interval '30 minutes' ) returns jsonb language plpgsql stable as $fn$ declare v_cached jsonb; v_cached_at timestamptz; begin select c.delta_profile_cache, c.delta_profile_cached_at into v_cached, v_cached_at from ems.site_pv_forecast_calibration c where c.site_id = p_site_id; -- ČTENÁŘ NIKDY NEPOČÍTÁ (přepočet = 44 s/site na prod!). Vrací cache bez -- ohledu na stáří (přepočet řídí výhradně fn_refresh_… — throttle 6 h -- z fill_forecast_accuracy ticku + denní catch-up). p_max_age ponechán -- v signatuře kvůli kompatibilitě volajících, ignoruje se. if v_cached is not null and p_data_from >= (now() - interval '121 days') and p_data_to <= now() + interval '5 minutes' then return v_cached; end if; -- jen first-run (cache NULL) nebo nestandardní analytické okno: return ems.fn_pv_forecast_delta_profile( p_site_id, p_data_from, p_data_to, p_half_life_days, p_threshold_w, p_top_n_days, p_non_top_day_factor, p_day_weight_gamma ); end; $fn$; comment on function ems.fn_pv_forecast_delta_profile_cached is 'Delta profil VŽDY z cache (stáří řídí refresh job, ne čtenář — přepočet 44 s/site); inline přepočet jen first-run / nestandardní okno.';