Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| The docs folder is gone, and what it held lives where people read it: how a self-hosted g1t runs and how to deploy g1t to Cloudflare are pages on docs.g1t.sh under Run g1t yourself, and speed, rate limits and operating g1t.sh are sections of CONTRIBUTING.md; code that cited a file in docs/ now points to the page or section that covers it, or says what it means itself, and applied migrations and the runner images are left as they were. | 1 | //! g1t-wide pauses (billing's `platform_pause`; "Spend guardrails" in |
| 2 | //! docs.g1t.sh/guides/deploy-to-cloudflare/), | |
| Merge platform pause and the hourly usage watcher: staff can pause compute, schedules, indexing or renders for everyone, the watcher emails on a breach and is never blind quietly, and the models proxy holds each run to its cap (billing 0051, integrations 0006) | 3 | //! read cheaply: one call to billing per isolate every 30 seconds at most, |
| 4 | //! never a database read per request. | |
| 5 | //! | |
| 6 | //! When billing cannot say, nothing is paused: a pause is a brake staff | |
| 7 | //! (or billing's usage watcher) pull on purpose, and a billing outage must | |
| 8 | //! not stop schedules and indexing everywhere. The failure is kept for the | |
| 9 | //! same 30 seconds, so an outage is not asked about on every request. | |
| 10 | ||
| 11 | use std::cell::RefCell; | |
| 12 | ||
| 13 | use g1t_contracts::billing::{PauseLevel, PlatformPause}; | |
| 14 | use worker::Fetcher; | |
| 15 | ||
| 16 | /// How long an answer is kept in the isolate. | |
| 17 | pub const KEEP_MS: u64 = 30_000; | |
| 18 | ||
| 19 | thread_local! { | |
| 20 | static KEPT: RefCell<Option<(PlatformPause, u64)>> = const { RefCell::new(None) }; | |
| 21 | } | |
| 22 | ||
| 23 | /// A kept answer, while it is fresh. | |
| 24 | fn fresh(kept: Option<(PlatformPause, u64)>, now: u64) -> Option<PlatformPause> { | |
| 25 | kept.filter(|(_, until)| *until > now).map(|(pause, _)| pause) | |
| 26 | } | |
| 27 | ||
| 28 | /// Whether `level` is paused, through the billing service's binding. | |
| 29 | pub async fn paused(billing: &Fetcher, level: PauseLevel) -> bool { | |
| 30 | current(billing).await.is(level) | |
| 31 | } | |
| 32 | ||
| 33 | /// Every level, kept for `KEEP_MS`. Nothing paused when billing cannot say. | |
| 34 | pub async fn current(billing: &Fetcher) -> PlatformPause { | |
| 35 | let now = crate::now_ms(); | |
| 36 | if let Some(pause) = KEPT.with(|kept| fresh(*kept.borrow(), now)) { | |
| 37 | return pause; | |
| 38 | } | |
| 39 | let pause = match crate::call::<_, PlatformPause>(billing, "platform_pause", &serde_json::json!({})).await { | |
| 40 | Ok(pause) => pause, | |
| 41 | Err(error) => { | |
| 42 | worker::console_error!("platform pause unreadable, so nothing is paused: {error}"); | |
| 43 | PlatformPause::default() | |
| 44 | } | |
| 45 | }; | |
| 46 | KEPT.with(|kept| *kept.borrow_mut() = Some((pause, now + KEEP_MS))); | |
| 47 | pause | |
| 48 | } | |
| 49 | ||
| 50 | #[cfg(test)] | |
| 51 | mod tests { | |
| 52 | use super::*; | |
| 53 | ||
| 54 | #[test] | |
| 55 | fn an_answer_is_kept_thirty_seconds() { | |
| 56 | let paused = PlatformPause { schedules: true, ..PlatformPause::default() }; | |
| 57 | assert_eq!(fresh(Some((paused, 1_000 + KEEP_MS)), 1_000), Some(paused)); | |
| 58 | assert_eq!(fresh(Some((paused, 1_000 + KEEP_MS)), 1_000 + KEEP_MS), None); | |
| 59 | assert_eq!(fresh(None, 0), None); | |
| 60 | } | |
| 61 | ||
| 62 | #[test] | |
| 63 | fn an_unread_pause_pauses_nothing() { | |
| 64 | let none = PlatformPause::default(); | |
| 65 | assert!(PauseLevel::ALL.into_iter().all(|level| !none.is(level))); | |
| 66 | assert!(!none.any()); | |
| 67 | } | |
| 68 | } |
This file's history is long; its oldest lines are credited to the oldest commit read.