Check whether ``estimated_cost`` fits under every configured window. ``additional_committed`` covers in-flight reservations (estimated costs of concurrent requests that passed ``check`` but have not yet been settled). It is added to every windowed denominator but NOT to the
(self, estimated_cost: float, additional_committed: float = 0.0)
| 153 | return self._limits |
| 154 | |
| 155 | def check(self, estimated_cost: float, additional_committed: float = 0.0) -> CheckResult: |
| 156 | """Check whether ``estimated_cost`` fits under every configured window. |
| 157 | |
| 158 | ``additional_committed`` covers in-flight reservations (estimated costs of |
| 159 | concurrent requests that passed ``check`` but have not yet been settled). |
| 160 | It is added to every windowed denominator but NOT to the per-request |
| 161 | comparison, which stays strictly about a single call. |
| 162 | """ |
| 163 | now = self._now() |
| 164 | |
| 165 | if self._limits.per_request is not None and estimated_cost > self._limits.per_request: |
| 166 | return CheckResult( |
| 167 | allowed=False, |
| 168 | blocked_by="per_request", |
| 169 | remaining=self._limits.per_request, |
| 170 | reason=f"Per-request limit: ${estimated_cost:.4f} > ${self._limits.per_request:.2f} max", |
| 171 | ) |
| 172 | |
| 173 | if self._limits.hourly is not None: |
| 174 | hourly_spent = self._window_total(now - HOUR_S, now) + additional_committed |
| 175 | remaining = self._limits.hourly - hourly_spent |
| 176 | if estimated_cost > remaining: |
| 177 | oldest = next((r for r in self._history if r.timestamp >= now - HOUR_S), None) |
| 178 | reset_in = int(oldest.timestamp + HOUR_S - now) if oldest else 0 |
| 179 | return CheckResult( |
| 180 | allowed=False, blocked_by="hourly", remaining=remaining, |
| 181 | reason=f"Hourly limit: ${hourly_spent + estimated_cost:.2f} > ${self._limits.hourly:.2f}", |
| 182 | reset_in_s=max(0, reset_in), |
| 183 | ) |
| 184 | |
| 185 | if self._limits.daily is not None: |
| 186 | daily_spent = self._window_total(now - DAY_S, now) + additional_committed |
| 187 | remaining = self._limits.daily - daily_spent |
| 188 | if estimated_cost > remaining: |
| 189 | oldest = next((r for r in self._history if r.timestamp >= now - DAY_S), None) |
| 190 | reset_in = int(oldest.timestamp + DAY_S - now) if oldest else 0 |
| 191 | return CheckResult( |
| 192 | allowed=False, blocked_by="daily", remaining=remaining, |
| 193 | reason=f"Daily limit: ${daily_spent + estimated_cost:.2f} > ${self._limits.daily:.2f}", |
| 194 | reset_in_s=max(0, reset_in), |
| 195 | ) |
| 196 | |
| 197 | if self._limits.session is not None: |
| 198 | remaining = self._limits.session - self._session_spent - additional_committed |
| 199 | if estimated_cost > remaining: |
| 200 | return CheckResult( |
| 201 | allowed=False, blocked_by="session", remaining=remaining, |
| 202 | reason=f"Session limit: ${self._session_spent + additional_committed + estimated_cost:.2f} > ${self._limits.session:.2f}", |
| 203 | ) |
| 204 | |
| 205 | return CheckResult(allowed=True) |
| 206 | |
| 207 | def record(self, amount: float, model: str | None = None, action: str | None = None) -> None: |
| 208 | if amount < 0: |