diff options
Diffstat (limited to 'makima/src/daemon/api')
| -rw-r--r-- | makima/src/daemon/api/chain.rs | 52 | ||||
| -rw-r--r-- | makima/src/daemon/api/client.rs | 42 | ||||
| -rw-r--r-- | makima/src/daemon/api/mod.rs | 1 |
3 files changed, 95 insertions, 0 deletions
diff --git a/makima/src/daemon/api/chain.rs b/makima/src/daemon/api/chain.rs new file mode 100644 index 0000000..7f7826f --- /dev/null +++ b/makima/src/daemon/api/chain.rs @@ -0,0 +1,52 @@ +//! Chain API methods. + +use uuid::Uuid; + +use super::client::{ApiClient, ApiError}; +use super::supervisor::JsonValue; +use crate::db::models::CreateChainRequest; + +impl ApiClient { + /// Create a new chain with contracts. + pub async fn create_chain(&self, req: CreateChainRequest) -> Result<JsonValue, ApiError> { + self.post("/api/v1/chains", &req).await + } + + /// List all chains for the authenticated user. + pub async fn list_chains( + &self, + status: Option<&str>, + limit: i32, + ) -> Result<JsonValue, ApiError> { + let mut params = Vec::new(); + if let Some(s) = status { + params.push(format!("status={}", s)); + } + params.push(format!("limit={}", limit)); + let query_string = format!("?{}", params.join("&")); + self.get(&format!("/api/v1/chains{}", query_string)).await + } + + /// Get a chain by ID. + pub async fn get_chain(&self, chain_id: Uuid) -> Result<JsonValue, ApiError> { + self.get(&format!("/api/v1/chains/{}", chain_id)).await + } + + /// Get contracts in a chain. + pub async fn get_chain_contracts(&self, chain_id: Uuid) -> Result<JsonValue, ApiError> { + self.get(&format!("/api/v1/chains/{}/contracts", chain_id)) + .await + } + + /// Get chain DAG structure for visualization. + pub async fn get_chain_graph(&self, chain_id: Uuid) -> Result<JsonValue, ApiError> { + self.get(&format!("/api/v1/chains/{}/graph", chain_id)) + .await + } + + /// Archive a chain. + pub async fn archive_chain(&self, chain_id: Uuid) -> Result<JsonValue, ApiError> { + self.delete_with_response(&format!("/api/v1/chains/{}", chain_id)) + .await + } +} diff --git a/makima/src/daemon/api/client.rs b/makima/src/daemon/api/client.rs index 4ba4778..dbf3101 100644 --- a/makima/src/daemon/api/client.rs +++ b/makima/src/daemon/api/client.rs @@ -276,6 +276,48 @@ impl ApiClient { Err(last_error.unwrap()) } + /// Make a DELETE request with response and retry. + pub async fn delete_with_response<T: DeserializeOwned>(&self, path: &str) -> Result<T, ApiError> { + let url = format!("{}{}", self.base_url, path); + let mut last_error = None; + + for attempt in 0..MAX_RETRIES { + if attempt > 0 { + tokio::time::sleep(Self::backoff_delay(attempt - 1)).await; + } + + let result = self.client + .delete(&url) + .header("X-Makima-Tool-Key", &self.api_key) + .header("X-Makima-API-Key", &self.api_key) + .send() + .await; + + match result { + Ok(response) => { + match self.handle_response(response).await { + Ok(value) => return Ok(value), + Err(e) if Self::is_retryable(&e) && attempt < MAX_RETRIES - 1 => { + last_error = Some(e); + continue; + } + Err(e) => return Err(e), + } + } + Err(e) => { + let error = ApiError::Request(e); + if Self::is_retryable(&error) && attempt < MAX_RETRIES - 1 { + last_error = Some(error); + continue; + } + return Err(error); + } + } + } + + Err(last_error.unwrap()) + } + /// Handle API response. async fn handle_response<T: DeserializeOwned>( &self, diff --git a/makima/src/daemon/api/mod.rs b/makima/src/daemon/api/mod.rs index 49d80e0..7868907 100644 --- a/makima/src/daemon/api/mod.rs +++ b/makima/src/daemon/api/mod.rs @@ -1,5 +1,6 @@ //! HTTP API client for makima CLI commands. +pub mod chain; pub mod client; pub mod contract; pub mod supervisor; |
