use std::thread;
use std::time::Duration;
use json::JsonValue;
use connection::APIConnection;
use error::Result;
pub struct Resource {
pub id: String,
pub conn: Box<APIConnection>,
pub base_url: String,
pub status_url: String,
pub finished: bool,
pub succeeded: bool,
pub failed: bool,
pub error: Option<String>,
}
impl Resource {
pub fn new<I>(
service_name: &str,
resources_name: &str,
id: I,
conn: Box<APIConnection>,
) -> Self
where I: Into<String>,
{
let id = id.into();
let base_url = format!(
"{}/{}/{}/{}",
conn.api_url(),
service_name,
resources_name,
id
);
let status_url = format!("{}/status", base_url);
Resource {
id: id,
conn: conn,
base_url: base_url,
status_url: status_url,
finished: false,
succeeded: false,
failed: false,
error: None,
}
}
pub fn update_status(&mut self) -> Result<JsonValue> {
let err = format!("{} returned invalid JSON response", self.status_url);
let response = self.conn.send_get_request_without_args(&self.status_url)?;
let status = response.body_as_json()?;
self.finished = status["finished"].as_bool().ok_or_else(|| err.clone())?;
self.succeeded = status["succeeded"].as_bool().ok_or_else(|| err.clone())?;
self.failed = status["failed"].as_bool().ok_or_else(|| err.clone())?;
if let Some(error) = status["error"].as_str() {
self.error = Some(error.to_string());
}
Ok(status)
}
pub fn has_finished(&mut self) -> Result<bool> {
self.update_status_if_not_finished()?;
Ok(self.finished)
}
pub fn has_succeeded(&mut self) -> Result<bool> {
self.update_status_if_not_finished()?;
Ok(self.succeeded)
}
pub fn has_failed(&mut self) -> Result<bool> {
self.update_status_if_not_finished()?;
Ok(self.failed)
}
pub fn error(&self) -> Option<&str> {
self.error.as_ref().map(String::as_str)
}
pub fn get_error(&mut self) -> Result<Option<&str>> {
self.update_status_if_not_finished()?;
Ok(self.error())
}
pub fn wait_for(&self, duration: Duration) {
thread::sleep(duration);
}
pub fn ensure_has_succeeded(&mut self, resource_name: &str) -> Result<()> {
if self.has_succeeded()? {
Ok(())
} else {
bail!("{} has not succeeded", resource_name)
}
}
fn update_status_if_not_finished(&mut self) -> Result<()> {
if !self.finished {
self.update_status()?;
}
Ok(())
}
}