use redis::AsyncCommands;
use serde::Serialize;
use uuid::Uuid;
use crate::redis::RedisPool;
pub const DEFAULT_QUEUE_KEY: &str = "test_runs:queued";
#[derive(Debug, Serialize)]
pub struct EnqueuedJob<'a> {
pub run_id: Uuid,
pub org_id: Uuid,
pub source_id: Uuid,
pub kind: &'a str,
pub payload: serde_json::Value,
}
pub async fn enqueue(redis: Option<&RedisPool>, job: EnqueuedJob<'_>) -> redis::RedisResult<()> {
let Some(redis) = redis else {
tracing::warn!(
run_id = %job.run_id,
kind = job.kind,
"Redis not configured — test_run will sit in 'queued' until a runner connects",
);
return Ok(());
};
let raw = match serde_json::to_string(&job) {
Ok(s) => s,
Err(e) => {
tracing::error!(error = %e, "failed to serialize queue job; not enqueueing");
return Ok(());
}
};
let mut conn = (*redis.get_connection()).clone();
let _: () = conn.lpush(DEFAULT_QUEUE_KEY, raw).await?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn enqueued_job_serializes_to_runner_wire_format() {
let run_id = Uuid::new_v4();
let org_id = Uuid::new_v4();
let source_id = Uuid::new_v4();
let job = EnqueuedJob {
run_id,
org_id,
source_id,
kind: "unit",
payload: json!({ "synthetic_steps": 5 }),
};
let raw = serde_json::to_string(&job).unwrap();
let parsed: serde_json::Value = serde_json::from_str(&raw).unwrap();
assert_eq!(parsed["run_id"], run_id.to_string());
assert_eq!(parsed["org_id"], org_id.to_string());
assert_eq!(parsed["source_id"], source_id.to_string());
assert_eq!(parsed["kind"], "unit");
assert_eq!(parsed["payload"]["synthetic_steps"], 5);
}
}