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}