yq 0.4.1

Yet another job queue
Documentation
use crate::helper::{encode_job, read_redis_value_as_int, read_redis_value_as_str};
use crate::{Job, Queue, YqResult};
use redis::{FromRedisValue, RedisResult, Script, ScriptInvocation};

#[derive(Clone)]
pub struct EnqueueAtAction {
    script: Script,
    queue: Queue,
}

impl EnqueueAtAction {
    pub fn new(queue: Queue) -> Self {
        Self {
            script: Script::new(crate::lua::ENQUEUE_AT),
            queue,
        }
    }

    pub fn prepare_invoke<J: Job>(&self, job: &J, run_at: i64) -> YqResult<ScriptInvocation> {
        let mut invoke = self.script.prepare_invoke();
        invoke
            .key(self.queue.mid_seq_key.as_str())
            .key(self.queue.messages_key.as_str())
            .key(self.queue.schedule_key.as_str());

        let job_data = encode_job(job)?;
        invoke.arg(&job_data).arg(run_at);

        Ok(invoke)
    }
}

#[derive(Debug)]
pub enum EnqueueAtStatus {
    Added(i64),
    Unknown(String),
}

impl FromRedisValue for EnqueueAtStatus {
    fn from_redis_value(v: &redis::Value) -> RedisResult<Self> {
        match v {
            redis::Value::Bulk(bulk) => EnqueueAtStatus::try_from(bulk.as_slice()),
            _ => Err(redis::RedisError::from((
                redis::ErrorKind::ResponseError,
                "invalid dequeue status - invalid value type",
                format!("{v:?}"),
            ))),
        }
    }
}

impl TryFrom<&[redis::Value]> for EnqueueAtStatus {
    type Error = redis::RedisError;

    fn try_from(values: &[redis::Value]) -> Result<Self, Self::Error> {
        let mut iter = values.iter();
        let action =
            read_redis_value_as_str(iter.next(), "invalid enqueue at status - invalid action")?;

        let status = match action.as_ref() {
            "added" => {
                let mid = read_redis_value_as_int(
                    iter.next(),
                    "invalid enqueue at status - invalid mid",
                )?;
                EnqueueAtStatus::Added(mid)
            }
            _ => EnqueueAtStatus::Unknown(format!("{values:?}")),
        };

        Ok(status)
    }
}