apalis_core/task/
task_id.rs

1use std::{
2    fmt::{Debug, Display},
3    str::FromStr,
4};
5
6use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer};
7use ulid::Ulid;
8
9use crate::{error::Error, request::Request, service_fn::FromRequest};
10
11/// A wrapper type that defines a task id.
12#[derive(Debug, Clone, Eq, Hash, PartialEq)]
13pub struct TaskId(Ulid);
14
15impl TaskId {
16    /// Generate a new [`TaskId`]
17    pub fn new() -> Self {
18        Self(Ulid::new())
19    }
20    /// Get the inner [`Ulid`]
21    pub fn inner(&self) -> Ulid {
22        self.0
23    }
24}
25
26impl Default for TaskId {
27    fn default() -> Self {
28        Self::new()
29    }
30}
31
32impl FromStr for TaskId {
33    type Err = ulid::DecodeError;
34    fn from_str(s: &str) -> Result<Self, Self::Err> {
35        Ok(TaskId(Ulid::from_str(s)?))
36    }
37}
38
39impl Display for TaskId {
40    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41        Display::fmt(&self.0, f)
42    }
43}
44
45impl Serialize for TaskId {
46    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
47    where
48        S: Serializer,
49    {
50        serializer.serialize_str(&self.to_string())
51    }
52}
53
54impl<'de> Deserialize<'de> for TaskId {
55    fn deserialize<D>(deserializer: D) -> Result<TaskId, D::Error>
56    where
57        D: Deserializer<'de>,
58    {
59        deserializer.deserialize_str(TaskIdVisitor)
60    }
61}
62
63impl<Req, Ctx> FromRequest<Request<Req, Ctx>> for TaskId {
64    fn from_request(req: &Request<Req, Ctx>) -> Result<Self, Error> {
65        Ok(req.parts.task_id.clone())
66    }
67}
68
69struct TaskIdVisitor;
70
71impl Visitor<'_> for TaskIdVisitor {
72    type Value = TaskId;
73
74    fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75        formatter.write_str("a `ulid`")
76    }
77
78    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
79    where
80        E: serde::de::Error,
81    {
82        TaskId::from_str(value).map_err(serde::de::Error::custom)
83    }
84}
85
86#[cfg(test)]
87mod tests {
88    use super::*;
89
90    #[test]
91    fn can_parse_id() {
92        let id = "01GWSGFS40RHST0FFZ6V1E1116";
93        TaskId::from_str(id).unwrap();
94    }
95}