flagon-io/g1t

public

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t/services/repos/src/shared.rs

54 lines1,919 bytesCodeBlame

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.

Mission control shows where you are needed and what agents landed without you; git answers in about 200ms1//! What isolates share with each other: a key-value store whose every value
2//! is sealed (AES-256-GCM) under the service's own key, `REPOS_KEY`, with
3//! the value's own key as associated data, so a value copied onto another
4//! key does not open.
5//!
6//! Optional: without the `GIT_CACHE` binding or the key, nothing is shared
7//! and each isolate keeps only what it made itself. Self-hosted, any
8//! Workers KV-compatible store will do.
9
10use g1t_secrets::Sealer;
11use worker::Env;
12use worker::kv::KvStore;
13
14/// The shortest life Workers KV gives a value.
15pub const MIN_TTL_SECONDS: u64 = 60;
16
17pub struct Shared {
18 kv: KvStore,
19 sealer: Sealer,
20}
21
22impl Shared {
23 pub fn from_env(env: &Env) -> Option<Shared> {
24 let kv = env.kv("GIT_CACHE").ok()?;
25 let sealer = Sealer::new(&env.secret("REPOS_KEY").ok()?.to_string())?;
26 Some(Shared { kv, sealer })
27 }
28
29 /// The value under `key`, if there is one that opens. A failure to
30 /// read is a miss.
31 pub async fn get(&self, key: &str) -> Option<Vec<u8>> {
32 let sealed = self.kv.get(key).bytes().await.ok()??;
33 self.sealer.open_bytes(&sealed, key)
34 }
35
36 /// Keeps `value` under `key` for `ttl_seconds` (at least a minute). A
37 /// failure only costs a later miss.
38 pub async fn put(&self, key: &str, value: &[u8], ttl_seconds: u64) {
39 let sealed = self.sealer.seal_bytes(value, key);
40 let put = match self.kv.put_bytes(key, &sealed) {
41 Ok(put) => put.expiration_ttl(ttl_seconds.max(MIN_TTL_SECONDS)),
42 Err(_) => return,
43 };
44 if let Err(error) = put.execute().await {
45 worker::console_error!("shared cache: {key} not kept: {error}");
46 }
47 }
48
49 pub async fn delete(&self, key: &str) {
50 if let Err(error) = self.kv.delete(key).await {
51 worker::console_error!("shared cache: {key} not removed: {error}");
52 }
53 }
54}