diff --git a/Cargo.toml b/Cargo.toml index 0e384e7..7586878 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,3 +28,6 @@ lto = true # Enable link-time optimization codegen-units = 1 # Reduce number of codegen units to increase optimizations panic = 'abort' # Abort on panic strip = true # Strip symbols from binary +# for performance profiling +# strip = false +# debug = true diff --git a/README.md b/README.md index aebc2c3..095fd45 100644 --- a/README.md +++ b/README.md @@ -21,15 +21,24 @@ to export data into (CSV) files or import data from (CSV) files. ## Installation ### With Cargo ([Rust toolchain](https://www.rust-lang.org/learn/get-started)) + ```bash cargo install sw-sync-cli ``` Same command can be used for updates. See [crate](https://crates.io/crates/sw-sync-cli) ### Manual + head to [GitHub releases](https://github.com/MalteJanz/sw-sync-cli/releases) and download the right binary for your operating system. Then either execute the binary directly or put it in your `PATH`. +### Build it from this repository + +1. Clone this repository +2. Have the latest [Rust toolchain](https://www.rust-lang.org/learn/get-started) installed +3. Run `cargo build --release` inside the repository root folder +4. You will get your executable here `./target/release/sw-sync-cli` + ## Usage 1. Set up an [integration](https://docs.shopware.com/en/shopware-6-en/settings/system/integrationen?category=shopware-6-en/settings/system) inside shopware. diff --git a/src/api/mod.rs b/src/api/mod.rs index 1cef6f3..139a915 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -248,12 +248,12 @@ impl SwClient { } async fn deserialize Deserialize<'a>>(response: Response) -> Result { - let text = response.text().await?; + let bytes = response.bytes().await?; - match serde_json::from_str(&text) { + match serde_json::from_slice(&bytes) { Ok(t) => Ok(t), Err(_e) => { - let body: serde_json::Value = serde_json::from_str(&text)?; + let body: serde_json::Value = serde_json::from_slice(&bytes)?; Err(SwApiError::DeserializeIntoSchema( serde_json::to_string_pretty(&body)?, )) diff --git a/src/cli.rs b/src/cli.rs index c229554..2e67733 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -52,7 +52,7 @@ pub enum Commands { // #[arg(short, long, action = ArgAction::SetTrue)] // verbose: bool, /// How many requests can be "in-flight" at the same time - #[arg(short, long, default_value = "8")] + #[arg(short, long, default_value = "10")] in_flight_limit: usize, }, } diff --git a/src/data/transform/mod.rs b/src/data/transform/mod.rs index b5ccfef..c6519a6 100644 --- a/src/data/transform/mod.rs +++ b/src/data/transform/mod.rs @@ -26,10 +26,12 @@ pub fn deserialize_row( let column_index = headers .iter() .position(|header| header == path_mapping.file_column) - .context(format!( - "Can't find column '{}' in CSV headers", - path_mapping.file_column - ))?; + .with_context(|| { + format!( + "Can't find column '{}' in CSV headers", + path_mapping.file_column + ) + })?; let raw_value = row .get(column_index) @@ -56,10 +58,10 @@ pub fn serialize_entity(entity: Entity, context: &SyncContext) -> anyhow::Result match mapping { Mapping::ByPath(path_mapping) => { let value = entity.get_by_path(&path_mapping.entity_path) - .context(format!( + .with_context(|| format!( "could not get field path '{}' specified in mapping (you might try the optional chaining operator '?.' to fallback to null), entity attributes:\n{}", path_mapping.entity_path, - serde_json::to_string_pretty(&entity).unwrap()) + serde_json::to_string_pretty(&entity).unwrap()) // expensive for big entities )?; let value_str = match value { @@ -72,10 +74,12 @@ pub fn serialize_entity(entity: Entity, context: &SyncContext) -> anyhow::Result Mapping::ByScript(script_mapping) => { let value = script_row .get(script_mapping.key.as_str()) - .context(format!( - "failed to retrieve script key '{}' of row", - script_mapping.key - ))?; + .with_context(|| { + format!( + "failed to retrieve script key '{}' of row", + script_mapping.key + ) + })?; let value_str = serde_json::to_string(value)?; row.push(value_str); diff --git a/src/data/transform/script.rs b/src/data/transform/script.rs index f5190be..6379aa3 100644 --- a/src/data/transform/script.rs +++ b/src/data/transform/script.rs @@ -6,7 +6,7 @@ use crate::SyncContext; use anyhow::Context; use csv::StringRecord; use rhai::packages::{BasicArrayPackage, CorePackage, MoreStringPackage, Package}; -use rhai::{Engine, Position, Scope, AST}; +use rhai::{Engine, OptimizationLevel, Position, Scope, AST}; #[derive(Debug)] pub struct ScriptingEnvironment { @@ -37,10 +37,9 @@ impl ScriptingEnvironment { let column_index = headers .iter() .position(|h| h == mapping.file_column) - .context(format!( - "Can't find column '{}' in CSV headers", - mapping.file_column - ))?; + .with_context(|| { + format!("Can't find column '{}' in CSV headers", mapping.file_column) + })?; let value = row .get(column_index) @@ -78,7 +77,11 @@ impl ScriptingEnvironment { }; let mut scope = Scope::new(); + + // this is potentially expensive for big entities! + // we might only want to pass some data into the script... let script_entity = rhai::serde::to_dynamic(entity)?; + scope.push_dynamic("entity", script_entity); let row_dynamic = rhai::Map::new(); scope.push("row", row_dynamic); @@ -124,6 +127,8 @@ pub fn prepare_scripting_environment( fn get_base_engine() -> Engine { let mut engine = Engine::new_raw(); + engine.set_optimization_level(OptimizationLevel::Full); + // Default print/debug implementations engine.on_print(|text| println!("{text}")); engine.on_debug(|text, source, pos| match (source, pos) {