@@ -1726,12 +1726,7 @@ fn schedule_analytics_rollup_refresh(state: Arc<AppState>) {
17261726async fn refresh_recent_analytics_rollups (
17271727 state : Arc < AppState > ,
17281728) -> std:: result:: Result < ( ) , AppError > {
1729- let ended_at = Utc :: now ( ) - ChronoDuration :: seconds ( ANALYTICS_ROLLUP_LAG_SECS ) ;
1730- let started_at = ended_at - ChronoDuration :: seconds ( ANALYTICS_ROLLUP_LOOKBACK_SECS ) ;
1731- let window = NormalizedPlaybackAnalyticsWindow {
1732- started_at,
1733- ended_at,
1734- } ;
1729+ let window = analytics_rollup_refresh_window ( Utc :: now ( ) ) ;
17351730 let edge_query = clickhouse_edge_rollup_refresh_query ( window) ;
17361731 let player_query = clickhouse_player_rollup_refresh_query ( window) ;
17371732 clickhouse_post (
@@ -1751,6 +1746,21 @@ async fn refresh_recent_analytics_rollups(
17511746 Ok ( ( ) )
17521747}
17531748
1749+ fn analytics_rollup_refresh_window ( now : DateTime < Utc > ) -> NormalizedPlaybackAnalyticsWindow {
1750+ let ended_at = now - ChronoDuration :: seconds ( ANALYTICS_ROLLUP_LAG_SECS ) ;
1751+ let lookback_started_at = ended_at - ChronoDuration :: seconds ( ANALYTICS_ROLLUP_LOOKBACK_SECS ) ;
1752+ NormalizedPlaybackAnalyticsWindow {
1753+ started_at : floor_datetime_to_hour ( lookback_started_at) ,
1754+ ended_at,
1755+ }
1756+ }
1757+
1758+ fn floor_datetime_to_hour ( value : DateTime < Utc > ) -> DateTime < Utc > {
1759+ let timestamp = value. timestamp ( ) ;
1760+ let hour_start = timestamp - timestamp. rem_euclid ( 60 * 60 ) ;
1761+ DateTime :: < Utc > :: from_timestamp ( hour_start, 0 ) . unwrap_or ( value)
1762+ }
1763+
17541764fn clickhouse_datetime ( value : DateTime < Utc > ) -> String {
17551765 value. format ( "%Y-%m-%d %H:%M:%S%.3f" ) . to_string ( )
17561766}
@@ -1957,6 +1967,27 @@ mod tests {
19571967 ) ) ;
19581968 }
19591969
1970+ #[ test]
1971+ fn rollup_refresh_window_starts_on_full_hour ( ) {
1972+ let now = DateTime :: parse_from_rfc3339 ( "2026-06-24T13:53:47.991Z" )
1973+ . unwrap ( )
1974+ . with_timezone ( & Utc ) ;
1975+ let window = analytics_rollup_refresh_window ( now) ;
1976+
1977+ assert_eq ! (
1978+ window. started_at,
1979+ DateTime :: parse_from_rfc3339( "2026-06-24T11:00:00.000Z" )
1980+ . unwrap( )
1981+ . with_timezone( & Utc )
1982+ ) ;
1983+ assert_eq ! (
1984+ window. ended_at,
1985+ DateTime :: parse_from_rfc3339( "2026-06-24T13:52:47.991Z" )
1986+ . unwrap( )
1987+ . with_timezone( & Utc )
1988+ ) ;
1989+ }
1990+
19601991 #[ test]
19611992 fn clickhouse_rows_use_artifact_billing_metadata_for_delivery ( ) {
19621993 let ingested_at = DateTime :: parse_from_rfc3339 ( "2026-06-13T12:00:01.000Z" )
0 commit comments