6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 1 | use std::{io, os::unix::net::UnixStream, path::PathBuf}; |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 2 | |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 3 | use pound::Parse; |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 4 | |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 5 | use crate::{ |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 6 | artifacts, client, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 7 | config::Config, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 8 | daemon, history, hook, paths, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 9 | proto::{self, Event, Reader, Request}, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 10 | run, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 11 | units::{Amount, Bytes, Dur}, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 12 | }; |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 13 | |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 14 | /// one build at a time, please |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 15 | #[derive(Parse)] |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 16 | #[pound(name = "rabt", version = env!("CARGO_PKG_VERSION"))] |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 17 | pub enum Rabt { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 18 | /// wait your turn, then run the thing |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 19 | Run { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 20 | /// preset from config, s m l xl out of the box |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 21 | #[pound(short, long)] |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 22 | size: Option<String>, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 23 | #[pound(long)] |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 24 | ram: Option<Bytes>, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 25 | #[pound(long)] |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 26 | disk: Option<Bytes>, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 27 | /// count or percentage of the machine |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 28 | #[pound(long)] |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 29 | cores: Option<Amount<u32>>, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 30 | /// how long you reckon it'll take |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 31 | #[pound(short, long)] |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 32 | time: Option<Dur>, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 33 | /// kill it past this, exit 124 |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 34 | #[pound(long)] |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 35 | deadline: Option<Dur>, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 36 | /// stop queueing past this, exit 75 |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 37 | #[pound(long)] |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 38 | max_wait: Option<Dur>, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 39 | #[pound(long, hidden, env = "CLAUDE_CODE_SESSION_ID")] |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 40 | session: Option<String>, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 41 | #[pound(trailing)] |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 42 | cmd: Vec<String>, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 43 | }, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 44 | /// who's running, who's waiting |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 45 | Status { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 46 | #[pound(long)] |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 47 | json: bool, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 48 | }, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 49 | /// a size guess from past runs |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 50 | Suggest { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 51 | #[pound(trailing)] |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 52 | cmd: Vec<String>, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 53 | }, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 54 | /// stop a lease's build |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 55 | Kill { lease: u64 }, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 56 | /// buy an overdue build more time |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 57 | Extend { lease: u64, by: Dur }, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 58 | /// exit when a lease goes overdue or finishes |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 59 | Watch { lease: u64 }, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 60 | /// build output and how much of it there is |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 61 | Artifacts { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 62 | #[pound(subcommand)] |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 63 | action: Artifacts, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 64 | }, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 65 | /// claude code hook entrypoint, json on stdin |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 66 | Hook { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 67 | /// pre-tool-use post-tool-use prompt-submit stop subagent-stop |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 68 | event: String, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 69 | }, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 70 | #[pound(hidden)] |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 71 | Daemon, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 72 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 73 | |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 74 | #[derive(Parse)] |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 75 | pub enum Artifacts { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 76 | /// sizes against the caps, exits 1 when over |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 77 | Check { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 78 | /// re-measure instead of trusting the cache |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 79 | #[pound(long)] |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 80 | fresh: bool, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 81 | }, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 82 | /// everything tracked, biggest first |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 83 | List, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 84 | /// delete idle artifacts |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 85 | Gc { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 86 | /// keep going, oldest first, until under the caps |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 87 | #[pound(long)] |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 88 | cap: bool, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 89 | #[pound(short = 'n', long)] |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 90 | dry_run: bool, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 91 | }, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 92 | /// never gc this |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 93 | Pin { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 94 | path: PathBuf, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 95 | }, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 96 | Unpin { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 97 | path: PathBuf, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 98 | }, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 99 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 100 | |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 101 | fn artifacts(cfg: &Config, action: Artifacts) -> i32 { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 102 | let cwd = std::env::current_dir().unwrap_or_else(|_| "/".into()); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 103 | let root = paths::project_root(&cwd); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 104 | match action { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 105 | Artifacts::Check { fresh } => { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 106 | let r = artifacts::check(cfg, Some(&root), fresh); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 107 | if let Some((root, size)) = &r.project { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 108 | println!( |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 109 | "{}: {size} of {}", |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 110 | root.display(), |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 111 | cfg.artifacts.project_cap |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 112 | ); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 113 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 114 | println!("everything: {} of {}", r.global, cfg.artifacts.global_cap); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 115 | if r.over() { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 116 | println!("over. `rabt artifacts gc --cap`"); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 117 | 1 |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 118 | } else { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 119 | 0 |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 120 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 121 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 122 | Artifacts::List => { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 123 | let r = artifacts::check(cfg, Some(&root), false); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 124 | let mut rows: Vec<_> = r.entries.iter().collect(); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 125 | rows.sort_by_key(|(_, e)| std::cmp::Reverse(e.size)); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 126 | for (path, e) in rows { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 127 | println!( |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 128 | "{:>10} {}{}", |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 129 | e.size.to_string(), |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 130 | path.display(), |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 131 | if e.pinned { " (pinned)" } else { "" } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 132 | ); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 133 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 134 | 0 |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 135 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 136 | Artifacts::Gc { cap, dry_run } => { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 137 | let g = artifacts::gc(cfg, cap, dry_run); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 138 | for p in &g.removed { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 139 | println!( |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 140 | "{}{}", |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 141 | if dry_run { "would remove " } else { "removed " }, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 142 | p.display() |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 143 | ); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 144 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 145 | for f in &g.failed { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 146 | eprintln!("rabt: {f}"); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 147 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 148 | println!( |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 149 | "{} {}", |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 150 | if dry_run { "would free" } else { "freed" }, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 151 | g.freed |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 152 | ); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 153 | i32::from(!g.failed.is_empty()) |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 154 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 155 | Artifacts::Pin { path } | Artifacts::Unpin { path } if !path.exists() => { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 156 | eprintln!("rabt: {} doesn't exist", path.display()); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 157 | 1 |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 158 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 159 | Artifacts::Pin { path } => report(artifacts::pin(&path, true)), |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 160 | Artifacts::Unpin { path } => report(artifacts::pin(&path, false)), |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 161 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 162 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 163 | |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 164 | fn report(r: Result<(), String>) -> i32 { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 165 | r.map_or_else( |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 166 | |e| { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 167 | eprintln!("rabt: {e}"); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 168 | 1 |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 169 | }, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 170 | |()| 0, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 171 | ) |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 172 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 173 | |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 174 | fn ask(req: &Request) -> io::Result<Option<Event>> { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 175 | let Some(mut s) = client::connect() else { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 176 | return Ok(None); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 177 | }; |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 178 | proto::send(&mut s, req)?; |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 179 | Reader::new(&s)?.recv() |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 180 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 181 | |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 182 | fn reply(ev: io::Result<Option<Event>>) -> i32 { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 183 | match ev { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 184 | Ok(Some(Event::Ok)) => 0, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 185 | Ok(Some(Event::Err { msg })) => { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 186 | eprintln!("rabt: {msg}"); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 187 | 1 |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 188 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 189 | Ok(None) => { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 190 | eprintln!("rabt: nothing running"); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 191 | 1 |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 192 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 193 | Ok(Some(_)) => 1, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 194 | Err(e) => { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 195 | eprintln!("rabt: {e}"); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 196 | 1 |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 197 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 198 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 199 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 200 | |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 201 | fn status(json: bool) -> i32 { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 202 | let Ok(Some(Event::Status(st))) = ask(&Request::Status) else { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 203 | if json { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 204 | println!("null"); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 205 | } else { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 206 | println!("idle"); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 207 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 208 | return 0; |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 209 | }; |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 210 | if json { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 211 | println!("{}", serde_json::to_string(&st).unwrap_or_default()); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 212 | return 0; |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 213 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 214 | println!( |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 215 | "ram {} free of {}, cores {} free of {}", |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 216 | st.ram_free, st.ram_budget, st.cores_free, st.cores |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 217 | ); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 218 | for l in &st.leases { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 219 | let state = if l.running { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 220 | format!( |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 221 | "running {}{}", |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 222 | Dur::secs(l.elapsed), |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 223 | if l.overdue { " OVERDUE" } else { "" } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 224 | ) |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 225 | } else { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 226 | format!( |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 227 | "#{} {}", |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 228 | l.position, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 229 | l.waiting.map(|r| r.to_string()).unwrap_or_default() |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 230 | ) |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 231 | }; |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 232 | println!( |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 233 | "{:>4} {}{} {} ram {} cores {} rss {} {}", |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 234 | l.id, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 235 | if l.heavy { "H " } else { "" }, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 236 | state, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 237 | Dur(l.need.time), |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 238 | l.need.ram, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 239 | l.need.cores, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 240 | l.rss, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 241 | l.cmd.join(" ") |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 242 | ); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 243 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 244 | 0 |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 245 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 246 | |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 247 | fn suggest(cfg: &Config, cmd: &[String]) -> i32 { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 248 | let cwd = std::env::current_dir().unwrap_or_else(|_| "/".into()); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 249 | let key = history::key(&paths::project_root(&cwd), cmd); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 250 | let Some(rec) = history::lookup(&key) else { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 251 | println!("never seen it, pick a --size"); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 252 | return 1; |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 253 | }; |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 254 | let base = match run::base(cfg) { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 255 | Ok(b) => b, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 256 | Err(e) => { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 257 | eprintln!("rabt: {e}"); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 258 | return 2; |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 259 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 260 | }; |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 261 | let n = history::suggest(&rec, base, cmd); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 262 | println!( |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 263 | "--ram {} --cores {} --time {} --disk {}", |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 264 | n.ram, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 265 | n.cores, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 266 | Dur(n.time), |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 267 | n.disk |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 268 | ); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 269 | 0 |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 270 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 271 | |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 272 | fn watch(lease: u64) -> i32 { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 273 | let Some(mut s): Option<UnixStream> = client::connect() else { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 274 | return 0; |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 275 | }; |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 276 | if proto::send(&mut s, &Request::Watch { lease }).is_err() { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 277 | return 0; |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 278 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 279 | if matches!( |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 280 | Reader::new(&s).and_then(|mut r| r.recv::<Event>()), |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 281 | Ok(Some(Event::Fired { overdue: true })) |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 282 | ) { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 283 | println!("lease {lease} is overdue, `rabt kill {lease}` or `rabt extend {lease} <dur>`"); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 284 | 3 |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 285 | } else { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 286 | println!("lease {lease} is done"); |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 287 | 0 |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 288 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 289 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 290 | |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 291 | pub fn dispatch(cfg: &Config, cmd: Rabt) -> i32 { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 292 | match cmd { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 293 | Rabt::Run { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 294 | size, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 295 | ram, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 296 | disk, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 297 | cores, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 298 | time, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 299 | deadline, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 300 | max_wait, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 301 | session, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 302 | cmd, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 303 | } => run::run( |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 304 | cfg, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 305 | &run::Args { |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 306 | size, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 307 | ram, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 308 | disk, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 309 | cores, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 310 | time, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 311 | deadline, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 312 | max_wait, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 313 | session, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 314 | cmd, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 315 | }, |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 316 | ), |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 317 | Rabt::Status { json } => status(json), |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 318 | Rabt::Suggest { cmd } => suggest(cfg, &cmd), |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 319 | Rabt::Kill { lease } => reply(ask(&Request::Kill { lease })), |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 320 | Rabt::Extend { lease, by } => reply(ask(&Request::Extend { lease, by })), |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 321 | Rabt::Watch { lease } => watch(lease), |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 322 | Rabt::Artifacts { action } => artifacts(cfg, action), |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 323 | Rabt::Hook { event } => hook::main(cfg, &event), |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 324 | Rabt::Daemon => daemon::main(Config::load().unwrap_or_default()), |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 325 | } |
6f5b84fad3ef | atagen | 2026-09-27 03:59 UTC | 326 | } |