simple_job_queue/
job.rs

1use std::time::{SystemTime, UNIX_EPOCH};
2
3use redis::{ErrorKind, FromRedisValue, RedisError, ToRedisArgs};
4use serde::{de::DeserializeOwned, Deserialize, Serialize};
5use uuid::Uuid;
6
7#[derive(Serialize, Deserialize)]
8pub struct Job<T> {
9    pub id: Uuid,
10    pub execute_at_epoch: u128,
11    pub data: T,
12}
13
14impl<T> Job<T> {
15    pub fn new(data: T) -> Self {
16        Self {
17            id: Uuid::new_v4(),
18            execute_at_epoch: 0,
19            data,
20        }
21    }
22
23    pub fn new_delayed(data: T, at: u128) -> Self {
24        Self {
25            id: Uuid::new_v4(),
26            execute_at_epoch: at,
27            data,
28        }
29    }
30
31    pub fn should_process(&self) -> bool {
32        SystemTime::now()
33            .duration_since(UNIX_EPOCH)
34            .expect("Time went backwards")
35            .as_millis()
36            > self.execute_at_epoch
37    }
38}
39
40#[cfg(feature = "redis")]
41impl<T> ToRedisArgs for Job<T>
42where
43    T: Serialize,
44{
45    fn write_redis_args<W>(&self, out: &mut W)
46    where
47        W: ?Sized + redis::RedisWrite,
48    {
49        out.write_arg(&serde_json::to_vec(self).expect("Unable to serialize job"))
50    }
51}
52
53#[cfg(feature = "redis")]
54impl<T> FromRedisValue for Job<T>
55where
56    T: DeserializeOwned,
57{
58    fn from_redis_value(v: &redis::Value) -> redis::RedisResult<Self> {
59        match v {
60            redis::Value::Data(data) => serde_json::from_slice(&data).map_err(|e| {
61                RedisError::from((
62                    ErrorKind::TypeError,
63                    "JSON conversion failed.",
64                    e.to_string(),
65                ))
66            }),
67            _ => Err(RedisError::from((
68                ErrorKind::TypeError,
69                "Response type not string compatible.",
70            ))),
71        }
72    }
73}