use azure_core::{Error, Result};
use azure_core::http::{Method, Pipeline, Request, StatusCode, Url};
use crate::client::poller::utils::{self, get_provisioning_state};
use super::utils::result_helper;
use super::PollingHandler;
use super::{utils::LROStatus, Response};
pub struct Poller {
pl: Pipeline,
resp: Response,
poll_url: Url,
cur_state: LROStatus,
}
impl Poller {
pub fn new(pl: Pipeline, req: &Request, resp: Response) -> Result<Self> {
let provision_state = get_provisioning_state(&resp)?;
let cur_state = match resp.status_code {
StatusCode::Created => {
if let Some(state) = provision_state {
state
} else {
LROStatus::InProgress
}
}
StatusCode::Ok => {
if let Some(state) = provision_state {
state
} else {
LROStatus::Succeeded
}
}
StatusCode::NoContent => LROStatus::Succeeded,
_ => LROStatus::InProgress,
};
Ok(Self {
pl,
resp: resp.clone(),
poll_url: req.url().clone(),
cur_state,
})
}
}
impl PollingHandler for Poller {
fn applicable(req: &Request, _: &Response) -> bool {
req.method() == Method::Put || req.method() == Method::Patch
}
async fn poll(&mut self, ctx: &azure_core::http::Context<'_>) -> Result<Response> {
if self.done() {
return Ok(self.resp.clone());
}
let mut req = Request::new(self.poll_url.clone(), Method::Get);
let resp = self.pl.send(ctx, &mut req).await?;
let resp = Response::from_raw_response(resp).await?;
if !utils::is_valid_status_code(resp.status_code) {
self.resp = resp.clone();
return Err(Error::message(resp.into(), "invalid response status code"));
}
if resp.status_code == StatusCode::NoContent {
self.resp = resp.clone();
self.cur_state = LROStatus::Succeeded;
return Ok(resp);
}
if resp.body.is_empty() {
return Err(Error::message(
resp.into(),
"non-204 response has no response body",
));
}
let state = match get_provisioning_state(&resp)? {
Some(state) => state,
None => LROStatus::Succeeded,
};
self.cur_state = state;
self.resp = resp.clone();
Ok(resp)
}
fn done(&self) -> bool {
self.cur_state.is_terminal()
}
async fn result(&self, _: &azure_core::http::Context<'_>) -> Result<Response> {
result_helper(&self.resp, self.cur_state.is_failed(), None)
}
}