use super::JobResult;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::fmt;
use std::time::Duration;
use uuid::Uuid;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct JobId(Uuid);
impl JobId {
#[must_use]
pub fn new() -> Self {
Self(Uuid::new_v4())
}
#[must_use]
pub const fn as_uuid(&self) -> &Uuid {
&self.0
}
}
impl Default for JobId {
fn default() -> Self {
Self::new()
}
}
impl fmt::Display for JobId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<Uuid> for JobId {
fn from(uuid: Uuid) -> Self {
Self(uuid)
}
}
impl From<JobId> for Uuid {
fn from(id: JobId) -> Self {
id.0
}
}
#[async_trait]
pub trait Job: Send + Sync + Serialize + for<'de> Deserialize<'de> + 'static {
type Result: Send + Sync;
async fn execute(&self, ctx: &super::JobContext) -> JobResult<Self::Result>;
fn max_retries(&self) -> u32 {
3
}
fn timeout(&self) -> Duration {
Duration::from_secs(300)
}
fn priority(&self) -> i32 {
0
}
fn job_type(&self) -> &'static str {
std::any::type_name::<Self>()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_job_id_creation() {
let id1 = JobId::new();
let id2 = JobId::new();
assert_ne!(id1, id2);
}
#[test]
fn test_job_id_display() {
let id = JobId::new();
let display = format!("{id}");
assert!(!display.is_empty());
assert!(Uuid::parse_str(&display).is_ok());
}
#[test]
fn test_job_id_uuid_conversion() {
let uuid = Uuid::new_v4();
let job_id = JobId::from(uuid);
let converted: Uuid = job_id.into();
assert_eq!(uuid, converted);
}
}