From b57c0944460ecbc712e40b4fca8c41f9e26d4a11 Mon Sep 17 00:00:00 2001 From: Lars Kemper Date: Thu, 25 Jul 2024 11:34:42 +0200 Subject: [PATCH 1/2] NEXT-37316 - add trigger indexing command --- src/api/mod.rs | 25 +++++++++++++++++++++++++ src/cli.rs | 7 +++++++ src/config_file.rs | 12 ++++++++++++ src/main.rs | 19 +++++++++++++++---- 4 files changed, 59 insertions(+), 4 deletions(-) diff --git a/src/api/mod.rs b/src/api/mod.rs index 09b1981..69472d7 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -255,6 +255,26 @@ impl SwClient { Ok(res) } + pub async fn index(&self, skip: Vec) -> anyhow::Result<()> { + let access_token = self.access_token.lock().unwrap().clone(); + + let response = self + .client + .post(format!("{}/api/_action/index", self.credentials.base_url)) + .bearer_auth(access_token) + .json(&IndexBody { skip }) + .send() + .await?; + + if !response.status().is_success() { + let status = response.status(); + let body: SwErrorBody = Self::deserialize(response).await?; + return Err(SwApiError::Server(status, body).into()); + } + + Ok(()) + } + async fn deserialize(response: Response) -> Result where T: for<'a> Deserialize<'a> + Debug + Send + 'static, @@ -281,6 +301,11 @@ impl SwClient { } } +#[derive(Debug, Serialize)] +struct IndexBody { + skip: Vec, +} + #[derive(Debug, Serialize)] struct AuthBody { grant_type: String, diff --git a/src/cli.rs b/src/cli.rs index 2e67733..2c0199c 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -14,6 +14,13 @@ pub struct Cli { #[derive(Subcommand)] pub enum Commands { + /// Trigger indexing of all registered indexer in shopware asynchronously. + Index { + // Array of indexer names to be skipped + #[arg(short, long)] + skip: Vec, + }, + /// Authenticate with a given shopware shop via integration admin API. /// Credentials are stored in .credentials.toml in the current working directory. Auth { diff --git a/src/config_file.rs b/src/config_file.rs index a88205f..807eddf 100644 --- a/src/config_file.rs +++ b/src/config_file.rs @@ -6,6 +6,7 @@ //! Utilizes https://serde.rs/ use crate::api::filter::{CriteriaFilter, CriteriaSorting}; +use anyhow::Context; use serde::{Deserialize, Serialize}; use std::collections::HashSet; @@ -16,6 +17,17 @@ pub struct Credentials { pub access_key_secret: String, } +impl Credentials { + pub async fn read_credentials() -> anyhow::Result { + let serialized_credentials = tokio::fs::read_to_string("./.credentials.toml") + .await + .context("No .credentials.toml found. Call command auth first.")?; + + let credentials: Credentials = toml::from_str(&serialized_credentials)?; + Ok(credentials) + } +} + #[derive(Debug, Deserialize)] pub struct Schema { pub entity: String, diff --git a/src/main.rs b/src/main.rs index d42fd04..7509ad8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -33,6 +33,10 @@ async fn main() -> anyhow::Result<()> { let cli = Cli::parse(); match cli.command { + Commands::Index { skip } => { + index(skip).await?; + println!("Successfully triggered indexing."); + } Commands::Auth { domain, id, secret } => { auth(domain, id, secret).await?; println!("Successfully authenticated. You can continue with other commands now.") @@ -71,6 +75,16 @@ async fn main() -> anyhow::Result<()> { Ok(()) } +async fn index(skip: Vec) -> anyhow::Result<()> { + let credentials = Credentials::read_credentials().await?; + + // TODO: change in flight limit handling? Hardcoded default value? + let sw_client = SwClient::new(credentials, 8).await?; + sw_client.index(skip).await?; + + Ok(()) +} + async fn auth(domain: String, id: String, secret: String) -> anyhow::Result<()> { let credentials = Credentials { base_url: domain.trim_end_matches('/').to_string(), @@ -107,10 +121,7 @@ async fn create_context( } } - let serialized_credentials = tokio::fs::read_to_string("./.credentials.toml") - .await - .context("No .credentials.toml found. Call command auth first.")?; - let credentials: Credentials = toml::from_str(&serialized_credentials)?; + let credentials = Credentials::read_credentials().await?; let sw_client = SwClient::new(credentials, in_flight_limit).await?; let api_schema = sw_client.entity_schema().await; From 6bce91d0e7ac704657e6bcb51c3912f80100e5cf Mon Sep 17 00:00:00 2001 From: Lars Kemper Date: Mon, 29 Jul 2024 09:27:23 +0200 Subject: [PATCH 2/2] NEXT-37316 - add default in flight constant --- src/api/mod.rs | 2 ++ src/main.rs | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/api/mod.rs b/src/api/mod.rs index 69472d7..81ff416 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -25,6 +25,8 @@ pub struct SwClient { } impl SwClient { + pub const DEFAULT_IN_FLIGHT: usize = 8; + pub async fn new(credentials: Credentials, in_flight_limit: usize) -> anyhow::Result { let mut default_headers = HeaderMap::default(); // This header is needed, otherwise the response would be "application/vnd.api+json" (by default) diff --git a/src/main.rs b/src/main.rs index 7509ad8..3c05096 100644 --- a/src/main.rs +++ b/src/main.rs @@ -78,8 +78,7 @@ async fn main() -> anyhow::Result<()> { async fn index(skip: Vec) -> anyhow::Result<()> { let credentials = Credentials::read_credentials().await?; - // TODO: change in flight limit handling? Hardcoded default value? - let sw_client = SwClient::new(credentials, 8).await?; + let sw_client = SwClient::new(credentials, SwClient::DEFAULT_IN_FLIGHT).await?; sw_client.index(skip).await?; Ok(()) @@ -93,7 +92,7 @@ async fn auth(domain: String, id: String, secret: String) -> anyhow::Result<()> }; // check if credentials work - let _ = SwClient::new(credentials.clone(), 8).await?; + let _ = SwClient::new(credentials.clone(), SwClient::DEFAULT_IN_FLIGHT).await?; // write them to file let serialized = toml::to_string(&credentials)?;