use std::time::Duration;
use serde_json::Value;
use super::models::*;
use crate::error::{Error, Result};
use crate::solver_status::SolverStatusResponse;
use crate::transport::Transport;
const ROUTE: &str = "/api/v1/solvers/professionalservices/solve";
#[derive(Clone)]
pub struct ProfessionalServicesClient {
transport: Transport,
}
impl ProfessionalServicesClient {
pub(crate) fn new(transport: Transport) -> Self {
Self { transport }
}
pub async fn start(
&self,
request: &ProfessionalServicesRequest,
) -> Result<ProfessionalServicesStartResponse> {
self.transport.post_json(ROUTE, request).await
}
pub async fn get_status(&self, job_id: &str) -> Result<SolverStatusResponse> {
self.transport
.get_json(&format!("{ROUTE}/{job_id}/status"))
.await
}
pub async fn get_result(&self, job_id: &str) -> Result<ProfessionalServicesResultResponse> {
let mut result: ProfessionalServicesResultResponse = self
.transport
.get_json(&format!("{ROUTE}/{job_id}"))
.await?;
result.job_id = Some(job_id.to_string());
Ok(result)
}
pub async fn analyze(&self, job_id: &str) -> Result<Value> {
self.transport
.get_json(&format!("{ROUTE}/{job_id}/analyze"))
.await
}
pub async fn start_and_wait_for_completion(
&self,
request: &ProfessionalServicesRequest,
poll_interval_ms: u64,
max_attempts: u32,
) -> Result<ProfessionalServicesResultResponse> {
let start = self.start(request).await?;
self.wait_for_completion(&start.job_id, poll_interval_ms, max_attempts)
.await
}
pub async fn wait_for_completion(
&self,
job_id: &str,
poll_interval_ms: u64,
max_attempts: u32,
) -> Result<ProfessionalServicesResultResponse> {
if job_id.is_empty() {
return Err(Error::MissingJobId);
}
let poll_interval_ms = if poll_interval_ms == 0 {
5000
} else {
poll_interval_ms
};
let max_attempts = if max_attempts == 0 { 10 } else { max_attempts };
let mut attempts = 0u32;
loop {
tokio::time::sleep(Duration::from_millis(poll_interval_ms)).await;
let status = self.get_status(job_id).await?;
attempts += 1;
let still_solving = status.is_solving();
if !still_solving || attempts >= max_attempts {
if still_solving {
return Err(Error::SolverTimeout);
}
return self.get_result(job_id).await;
}
}
}
}