azure_core/
lro.rs
1use crate::headers::Headers;
2use std::time::Duration;
3use time::OffsetDateTime;
4
5const DEFAULT_RETRY_TIME: Duration = Duration::from_secs(30);
10
11#[derive(Debug)]
15pub enum LroStatus {
16 InProgress,
17 Succeeded,
18 Failed,
19 Canceled,
20 Other(String),
21}
22
23impl From<&str> for LroStatus {
24 fn from(s: &str) -> Self {
25 match s {
26 "InProgress" => LroStatus::InProgress,
27 "Succeeded" => LroStatus::Succeeded,
28 "Failed" => LroStatus::Failed,
29 "Canceled" | "Cancelled" => LroStatus::Canceled,
35 _ => LroStatus::Other(s.to_owned()),
36 }
37 }
38}
39
40pub fn get_retry_after(headers: &Headers) -> Duration {
41 crate::get_retry_after(headers, OffsetDateTime::now_utc).unwrap_or(DEFAULT_RETRY_TIME)
42}
43
44pub mod location {
45 use crate::{
46 from_json,
47 headers::{Headers, AZURE_ASYNCOPERATION, LOCATION, OPERATION_LOCATION},
48 lro::LroStatus,
49 Url,
50 };
51
52 #[derive(Debug, Clone, Copy)]
53 pub enum FinalState {
54 AzureAsyncOperation,
55 Location,
56 OperationLocation,
57 }
58
59 pub fn get_location(headers: &Headers, final_state: FinalState) -> crate::Result<Option<Url>> {
60 match final_state {
61 FinalState::AzureAsyncOperation => headers.get_optional_as(&AZURE_ASYNCOPERATION),
62 FinalState::Location => headers.get_optional_as(&LOCATION),
63 FinalState::OperationLocation => headers.get_optional_as(&OPERATION_LOCATION),
64 }
65 }
66
67 pub fn get_provisioning_state(body: &[u8]) -> Option<LroStatus> {
68 #[derive(serde::Deserialize)]
69 struct Body {
70 status: String,
71 }
72 let body: Body = from_json(body).ok()?;
73 Some(LroStatus::from(body.status.as_str()))
74 }
75}
76
77pub mod body_content {
78 use crate::{from_json, lro::LroStatus, to_json, StatusCode};
79 use serde::{Deserialize, Serialize};
80
81 pub fn get_provisioning_state<S>(status_code: StatusCode, body: &S) -> crate::Result<LroStatus>
85 where
86 S: Serialize,
87 {
88 match status_code {
89 StatusCode::Accepted => Ok(LroStatus::InProgress),
90 StatusCode::Created => {
91 Ok(get_provisioning_state_from_body(body).unwrap_or(LroStatus::InProgress))
92 }
93 StatusCode::Ok => {
94 Ok(get_provisioning_state_from_body(body).unwrap_or(LroStatus::Succeeded))
95 }
96 StatusCode::NoContent => Ok(LroStatus::Succeeded),
97 _ => Err(crate::error::Error::from(
98 crate::error::ErrorKind::HttpResponse {
99 status: status_code,
100 error_code: Some("invalid status found in LRO response".to_owned()),
101 },
102 )),
103 }
104 }
105
106 #[derive(Deserialize)]
107 #[serde(rename_all = "snake_case")]
108 struct Properties {
109 provisioning_state: String,
110 }
111
112 #[derive(Deserialize)]
113 struct Body {
114 properties: Properties,
115 }
116
117 fn get_provisioning_state_from_body<S>(body: &S) -> Option<LroStatus>
118 where
119 S: Serialize,
120 {
121 let body: Body = from_json(to_json(&body).ok()?).ok()?;
122 Some(LroStatus::from(body.properties.provisioning_state.as_str()))
123 }
124}