jono_core 0.1.5

Shared core utilities for Jono queue libraries
Documentation
use crate::error::{Error, Result};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

/// Metadata for a job in the Jono system
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JobMetadata {
    /// Unique identifier for the job
    pub id: String,

    /// The job JSON payload
    pub payload: serde_json::Value,

    /// The maximum number of attempts allowed
    pub max_attempts: u32,

    /// Priority; lower values are processed first
    pub initial_priority: i64,

    /// Current number of attempts made
    pub attempt_count: u32,

    // Keeping track what made attempts fail
    pub attempt_history: Vec<serde_json::Value>,

    // Result on job completion from the worker
    pub outcome: Option<serde_json::Value>,
}

impl JobMetadata {
    /// Convert a Redis hash into more structured job metadata
    pub fn from_hash(hash: HashMap<String, String>) -> Result<Self> {
        let id = hash
            .get("id")
            .ok_or_else(|| Error::InvalidJob("Missing id field".to_string()))?
            .clone();

        let payload_str = hash
            .get("payload")
            .ok_or_else(|| Error::InvalidJob("Missing payload field".to_string()))?;
        let payload = serde_json::from_str(payload_str)
            .map_err(|_| Error::InvalidJob("Invalid payload JSON".to_string()))?;

        let max_attempts = hash
            .get("max_attempts")
            .ok_or_else(|| Error::InvalidJob("Missing max_attempts field".to_string()))?
            .parse::<u32>()
            .map_err(|_| Error::InvalidJob("Invalid max_attempts".to_string()))?;

        let attempt_count = hash
            .get("attempt_count")
            .and_then(|s| s.parse::<u32>().ok())
            .unwrap_or(0);

        let initial_priority = hash
            .get("initial_priority")
            .ok_or_else(|| Error::InvalidJob("Missing initial_priority field".to_string()))?
            .parse::<i64>()
            .map_err(|_| Error::InvalidJob("Invalid initial_priority".to_string()))?;

        let outcome_str = hash
            .get("outcome")
            .ok_or_else(|| Error::InvalidJob("Missing outcome field".to_string()))?;
        let outcome = serde_json::from_str(outcome_str)
            .map_err(|_| Error::InvalidJob("Invalid outcome JSON".to_string()))?;

        Ok(Self {
            id,
            payload,
            max_attempts,
            attempt_count,
            initial_priority,
            attempt_history: vec![],
            outcome,
        })
    }
}