Skip to content
67 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.

Staff can pause compute, schedules, indexing or renders across g1t, and billing reads the platform's Cloudflare usage every hour: thresholds, spikes, staff emails and automatic pauses (billing 0050)1//! g1t-wide pauses (billing's `platform_pause`; docs/SPEND-GUARDRAILS.md),
2//! read cheaply: one call to billing per isolate every 30 seconds at most,
3//! never a database read per request.
4//!
5//! When billing cannot say, nothing is paused: a pause is a brake staff
6//! (or billing's usage watcher) pull on purpose, and a billing outage must
7//! not stop schedules and indexing everywhere. The failure is kept for the
8//! same 30 seconds, so an outage is not asked about on every request.
9
10use std::cell::RefCell;
11
12use g1t_contracts::billing::{PauseLevel, PlatformPause};
13use worker::Fetcher;
14
15/// How long an answer is kept in the isolate.
16pub const KEEP_MS: u64 = 30_000;
17
18thread_local! {
19 static KEPT: RefCell<Option<(PlatformPause, u64)>> = const { RefCell::new(None) };
20}
21
22/// A kept answer, while it is fresh.
23fn fresh(kept: Option<(PlatformPause, u64)>, now: u64) -> Option<PlatformPause> {
24 kept.filter(|(_, until)| *until > now).map(|(pause, _)| pause)
25}
26
27/// Whether `level` is paused, through the billing service's binding.
28pub async fn paused(billing: &Fetcher, level: PauseLevel) -> bool {
29 current(billing).await.is(level)
30}
31
32/// Every level, kept for `KEEP_MS`. Nothing paused when billing cannot say.
33pub async fn current(billing: &Fetcher) -> PlatformPause {
34 let now = crate::now_ms();
35 if let Some(pause) = KEPT.with(|kept| fresh(*kept.borrow(), now)) {
36 return pause;
37 }
38 let pause = match crate::call::<_, PlatformPause>(billing, "platform_pause", &serde_json::json!({})).await {
39 Ok(pause) => pause,
40 Err(error) => {
41 worker::console_error!("platform pause unreadable, so nothing is paused: {error}");
42 PlatformPause::default()
43 }
44 };
45 KEPT.with(|kept| *kept.borrow_mut() = Some((pause, now + KEEP_MS)));
46 pause
47}
48
49#[cfg(test)]
50mod tests {
51 use super::*;
52
53 #[test]
54 fn an_answer_is_kept_thirty_seconds() {
55 let paused = PlatformPause { schedules: true, ..PlatformPause::default() };
56 assert_eq!(fresh(Some((paused, 1_000 + KEEP_MS)), 1_000), Some(paused));
57 assert_eq!(fresh(Some((paused, 1_000 + KEEP_MS)), 1_000 + KEEP_MS), None);
58 assert_eq!(fresh(None, 0), None);
59 }
60
61 #[test]
62 fn an_unread_pause_pauses_nothing() {
63 let none = PlatformPause::default();
64 assert!(PauseLevel::ALL.into_iter().all(|level| !none.is(level)));
65 assert!(!none.any());
66 }
67}