Skip to content

Commit 86bf0a5

Browse files
committed
do not spawn runners if something is wrong endlessly
Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
1 parent 49094cb commit 86bf0a5

1 file changed

Lines changed: 37 additions & 4 deletions

File tree

  • docker/docker_jit_monitor/src

docker/docker_jit_monitor/src/main.rs

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::{
2+
collections::HashMap,
23
process::{Child, Command},
34
string::FromUtf8Error,
45
sync::atomic::{AtomicU32, AtomicU64, Ordering},
@@ -15,6 +16,9 @@ use crate::github_api::{get_idle_runners, spawn_runner};
1516

1617
mod github_api;
1718

19+
const MAX_SPAWN_RETRIES: u32 = 10;
20+
/// How long the loop will sleep in milliseconds.
21+
const LOOP_SLEEP: u64 = 500;
1822
static RUNNER_ID: AtomicU64 = AtomicU64::new(0);
1923
static EXITING: AtomicU32 = AtomicU32::new(0);
2024

@@ -143,7 +147,7 @@ enum SpawnRunnerError {
143147
#[cfg(target_os = "linux")]
144148
const OS_TAG: &str = "Linux";
145149

146-
#[derive(Clone, Debug, PartialEq)]
150+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
147151
enum ContainerType {
148152
Builder,
149153
Runner,
@@ -187,7 +191,7 @@ impl Iterator for ContainerTypeIterator {
187191
None
188192
}
189193
};
190-
self.current.clone()
194+
self.current
191195
}
192196
}
193197

@@ -207,6 +211,30 @@ struct DockerContainer {
207211
container_type: ContainerType,
208212
}
209213

214+
#[derive(Debug, Default)]
215+
/// Store the number of retries per container type
216+
struct Retries {
217+
t: HashMap<ContainerType, u32>,
218+
}
219+
220+
impl Retries {
221+
/// Increases the number of retries and quits if it reaches `MAX_SPAWN_RETRIES`.
222+
fn inc_and_check(&mut self, t: ContainerType) {
223+
let value = self.t.entry(t).or_insert(0);
224+
*value += 1;
225+
if *value > MAX_SPAWN_RETRIES {
226+
println!(
227+
"We had {value} many times to spawn a runner/builder ({t:?}). It is not happening."
228+
);
229+
std::process::exit(-1);
230+
}
231+
}
232+
233+
fn reset(&mut self, t: ContainerType) {
234+
self.t.entry(t).insert_entry(0);
235+
}
236+
}
237+
210238
fn main() -> anyhow::Result<()> {
211239
env_logger::init();
212240
info!("Starting monitor for selfhosted docker-based github runners!");
@@ -232,6 +260,7 @@ fn main() -> anyhow::Result<()> {
232260
let mut running_containers: Vec<DockerContainer> = vec![];
233261
// Todo: implement something to reserve devices for the duration of the docker run child process.
234262

263+
let mut retries = Retries::default();
235264
loop {
236265
let exiting = EXITING.load(Ordering::Relaxed);
237266
for container_type in ContainerType::iter() {
@@ -254,13 +283,17 @@ fn main() -> anyhow::Result<()> {
254283
};
255284

256285
match spawn_runner(config) {
257-
Ok(container) => running_containers.push(container),
286+
Ok(container) => {
287+
retries.reset(container_type);
288+
running_containers.push(container)
289+
}
258290
Err(SpawnRunnerError::GhApiError(_, message))
259291
if message.contains("gh: Already exists") =>
260292
{
261293
info!("Runner name already taken - Will retry with new name later")
262294
}
263295
Err(e) => {
296+
retries.inc_and_check(container_type);
264297
error!("Failed to spawn JIT runner: {e:?}");
265298
}
266299
}
@@ -319,7 +352,7 @@ fn main() -> anyhow::Result<()> {
319352
}
320353

321354
running_containers = still_running;
322-
thread::sleep(Duration::from_millis(500));
355+
thread::sleep(Duration::from_millis(LOOP_SLEEP));
323356
}
324357

325358
info!("Exiting....");

0 commit comments

Comments
 (0)