Skip to content
68 linesCodeBlameRaw

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
11use std::cell::RefCell;
12
13use g1t_contracts::billing::{PauseLevel, PlatformPause};
14use worker::Fetcher;
15
16/// How long an answer is kept in the isolate.
17pub const KEEP_MS: u64 = 30_000;
18
19thread_local! {
20 static KEPT: RefCell<Option<(PlatformPause, u64)>> = const { RefCell::new(None) };
21}
22
23/// A kept answer, while it is fresh.
24fn 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.
29pub 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.
34pub 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)]
51mod 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.