apalis_core/task/
task_id.rs1use 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#[derive(Debug, Clone, Eq, Hash, PartialEq)]
13pub struct TaskId(Ulid);
14
15impl TaskId {
16 pub fn new() -> Self {
18 Self(Ulid::new())
19 }
20 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}