cronback_api_model/
attempt.rs1use std::time::Duration;
2
3use chrono::{DateTime, Utc};
4#[cfg(feature = "dto")]
5use dto::FromProto;
6use serde::{Deserialize, Serialize};
7use serde_with::{serde_as, skip_serializing_none, DurationSecondsWithFrac};
8use strum::Display;
9
10#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
11#[cfg_attr(
12 feature = "dto",
13 derive(FromProto),
14 proto(target = "proto::attempt_proto::Attempt")
15)]
16#[skip_serializing_none]
17pub struct Attempt {
18 pub status: AttemptStatus,
19 #[cfg_attr(feature = "dto", proto(required))]
20 pub details: AttemptDetails,
21 pub attempt_num: u32,
22 #[cfg_attr(feature = "dto", proto(required))]
23 pub created_at: DateTime<Utc>,
24}
25
26#[serde_as]
27#[skip_serializing_none]
28#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
29#[cfg_attr(
30 feature = "dto",
31 derive(FromProto),
32 proto(target = "proto::attempt_proto::WebhookAttemptDetails")
33)]
34pub struct WebhookAttemptDetails {
35 pub response_code: Option<i32>,
36 #[cfg_attr(feature = "dto", from_proto(map = "Duration::from_secs_f64"))]
37 #[serde_as(as = "DurationSecondsWithFrac")]
38 pub response_latency_s: Duration,
39 pub error_message: Option<String>,
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
43#[cfg_attr(feature = "client", non_exhaustive)]
44#[cfg_attr(
45 feature = "dto",
46 derive(FromProto),
47 proto(target = "proto::attempt_proto::AttemptDetails", oneof = "details")
48)]
49#[serde(untagged)]
50pub enum AttemptDetails {
51 #[cfg_attr(feature = "dto", proto(name = "Webhook"))]
52 WebhookAttemptDetails(WebhookAttemptDetails),
53}
54
55impl AttemptDetails {
56 pub fn status_message(&self) -> String {
57 match self {
58 | Self::WebhookAttemptDetails(details) => {
59 format!(
60 "{}{}",
61 details
62 .response_code
63 .map(|a| format!("{} ", a))
64 .unwrap_or_default(),
65 details.error_message.as_deref().unwrap_or_default()
66 )
67 }
68 }
69 }
70}
71
72#[non_exhaustive]
73#[derive(Debug, Display, Clone, Copy, Serialize, Deserialize, PartialEq)]
74#[cfg_attr(
75 feature = "dto",
76 derive(FromProto),
77 proto(target = "proto::attempt_proto::AttemptStatus")
78)]
79#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
80#[cfg_attr(feature = "clap", clap(rename_all = "snake_case"))]
81#[serde(rename_all = "snake_case")]
82#[strum(serialize_all = "snake_case")]
85pub enum AttemptStatus {
86 Succeeded,
87 Failed,
88}
89
90#[cfg(test)]
91mod test {
92 use crate::AttemptStatus;
93
94 #[test]
95 fn attempt_status_to_string() {
96 assert_eq!("succeeded", AttemptStatus::Succeeded.to_string());
98 assert_eq!("failed", AttemptStatus::Failed.to_string());
99 }
100}