` which leaked transient * internals and broke under external object caches. * * @param int $now Current unix timestamp. * @param int $window Window length in seconds. */ public static function seconds_until_reset( int $now, int $window ): int { $t = $window - ( $now % $window ); return $t > 0 ? $t : $window; } /** * Weighted estimate of in-flight count for the sliding window. * * @param int $prev_count Count in the previous bucket. * @param int $curr_count Count in the current bucket. * @param int $now Current unix timestamp. * @param int $window Window length in seconds. * * @return float Weighted estimate. Caller compares with the policy limit. */ public static function estimate( int $prev_count, int $curr_count, int $now, int $window ): float { $elapsed = self::elapsed_in_bucket( $now, $window ); $weight = ( $window - $elapsed ) / $window; return ( $prev_count * $weight ) + $curr_count; } }