From 36a26d5627e5548af62aa262724ce700b5e5d7d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Djk=C3=A1=C5=A5o?= Date: Fri, 17 May 2024 15:43:59 +0200 Subject: [PATCH] stop using redundant gql update of trans. message --- .env | 5 +- Cargo.lock | 2 +- simple-payment-gateway/src/queries/mod.rs | 2 +- .../mutation_order_payment_method_update.rs | 56 +++++++ .../queries/mutation_transaction_update.rs | 2 +- simple-payment-gateway/src/routes/webhooks.rs | 157 +++++++++++------- sitemap-generator/src/app.rs | 1 + sitemap-generator/src/main.rs | 10 +- .../queries/get_all_categories_n_products.rs | 25 +-- sitemap-generator/src/routes/register.rs | 90 ++++++---- sitemap-generator/src/routes/webhooks.rs | 6 +- 11 files changed, 242 insertions(+), 114 deletions(-) create mode 100644 simple-payment-gateway/src/queries/mutation_order_payment_method_update.rs diff --git a/.env b/.env index 7838790..c11b76c 100644 --- a/.env +++ b/.env @@ -1,13 +1,14 @@ ## COMMON VARIABLES FOR ALL APPS REQUIRED_SALEOR_VERSION="^3.13" # only sets port, the host is always 0.0.0.0 (listens to everything). Set this to docker-compose service name -APP_API_BASE_URL="http://10.100.110.234:3000" -APP_IFRAME_BASE_URL="http://app-name.site.com" +APP_API_BASE_URL="http://10.100.110.21:3000" +APP_IFRAME_BASE_URL="http://10.100.110.21:3000" APL="Redis" APL_URL="redis://localhost:6380/2" LOG_LEVEL="DEBUG" ## THESE VARIABLES ARE FOR SITEMAP-GENERATOR APP +CHANNEL_SLUG="zakladny" SITEMAP_TARGET_FOLDER="./temp" # Available fields can be found in ./sitemap-generator/src/queries/event_subjects_updated.rs: ProductUpdate SITEMAP_PRODUCT_TEMPLATE="https://example.com/{product.category.slug}/{product.slug}" diff --git a/Cargo.lock b/Cargo.lock index 2a2db6c..4cd00da 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2677,7 +2677,7 @@ checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "saleor-app-sdk" -version = "0.2.0" +version = "0.2.1" dependencies = [ "anyhow", "async-trait", diff --git a/simple-payment-gateway/src/queries/mod.rs b/simple-payment-gateway/src/queries/mod.rs index 41f3df2..de798a2 100644 --- a/simple-payment-gateway/src/queries/mod.rs +++ b/simple-payment-gateway/src/queries/mod.rs @@ -1,3 +1,3 @@ pub mod event_transactions; +pub mod mutation_order_payment_method_update; pub mod mutation_transaction_update; - diff --git a/simple-payment-gateway/src/queries/mutation_order_payment_method_update.rs b/simple-payment-gateway/src/queries/mutation_order_payment_method_update.rs new file mode 100644 index 0000000..81588e9 --- /dev/null +++ b/simple-payment-gateway/src/queries/mutation_order_payment_method_update.rs @@ -0,0 +1,56 @@ +#[cynic::schema("saleor")] +mod schema {} +/* +mutation setOrderPaymentMethod($id:ID!, $metadata: [MetadataInput!]!){ + updateMetadata(id:$id, input: $metadata ){ + errors{ + field + message + code + } + } +} +*/ + +#[derive(cynic::QueryVariables, Debug)] +pub struct SetOrderPaymentMethodVariables<'a> { + pub id: &'a cynic::Id, + pub metadata: Vec>, +} + +#[derive(cynic::QueryFragment, Debug)] +#[cynic( + graphql_type = "Mutation", + variables = "SetOrderPaymentMethodVariables" +)] +pub struct SetOrderPaymentMethod { + #[arguments(id: $id, input: $metadata)] + pub update_metadata: Option, +} + +#[derive(cynic::QueryFragment, Debug)] +pub struct UpdateMetadata { + pub errors: Vec, +} + +#[derive(cynic::QueryFragment, Debug)] +pub struct MetadataError { + pub field: Option, + pub message: Option, + pub code: MetadataErrorCode, +} + +#[derive(cynic::Enum, Clone, Copy, Debug)] +pub enum MetadataErrorCode { + GraphqlError, + Invalid, + NotFound, + Required, + NotUpdated, +} + +#[derive(cynic::InputObject, Debug)] +pub struct MetadataInput<'a> { + pub key: &'a str, + pub value: &'a str, +} diff --git a/simple-payment-gateway/src/queries/mutation_transaction_update.rs b/simple-payment-gateway/src/queries/mutation_transaction_update.rs index 5cc4142..e2b15a0 100644 --- a/simple-payment-gateway/src/queries/mutation_transaction_update.rs +++ b/simple-payment-gateway/src/queries/mutation_transaction_update.rs @@ -1,4 +1,5 @@ #[cynic::schema("saleor")] + mod schema {} /* mutation transactionUpdate($id: ID!, $transaction: TransactionUpdateInput) { @@ -17,7 +18,6 @@ mutation transactionUpdate($id: ID!, $transaction: TransactionUpdateInput) { } } */ - #[derive(cynic::QueryVariables, Debug)] pub struct TransactionUpdateVariables<'a> { pub id: &'a cynic::Id, diff --git a/simple-payment-gateway/src/routes/webhooks.rs b/simple-payment-gateway/src/routes/webhooks.rs index 2dbfd4c..6877501 100644 --- a/simple-payment-gateway/src/routes/webhooks.rs +++ b/simple-payment-gateway/src/routes/webhooks.rs @@ -1,6 +1,5 @@ use anyhow::Context; use axum::{extract::State, http::HeaderMap, Json}; -use cynic::{http::SurfExt, MutationBuilder}; use rust_decimal::{prelude::FromPrimitive, Decimal}; use saleor_app_sdk::{ headers::SALEOR_API_URL_HEADER, @@ -25,16 +24,10 @@ use crate::{ AppError, AppState, PaymentGatewayInitializeSessionData, PaymentMethodType, TransactionInitializeSessionData, }, - queries::{ - event_transactions::{ - DeliveryMethod, OrderOrCheckout, PaymentGatewayInitializeSession2, - TransactionCancelationRequested2, TransactionChargeRequested2, - TransactionFlowStrategyEnum, TransactionInitializeSession2, TransactionProcessSession2, - TransactionRefundRequested2, - }, - mutation_transaction_update::{ - TransactionUpdate, TransactionUpdateInput, TransactionUpdateVariables, - }, + queries::event_transactions::{ + DeliveryMethod, OrderOrCheckout, PaymentGatewayInitializeSession2, + TransactionCancelationRequested2, TransactionChargeRequested2, TransactionFlowStrategyEnum, + TransactionInitializeSession2, TransactionProcessSession2, TransactionRefundRequested2, }, }; @@ -153,12 +146,12 @@ async fn create_response( let str_payment_method = serde_json::to_string(&TransactionInitializeSessionData { payment_method })?; - update_transaction_message( - session_data.transaction.id, - str_payment_method.clone(), - apl_token, - saleor_api_url.to_owned(), - ); + // update_transaction_message( + // session_data.transaction.id, + // str_payment_method.clone(), + // apl_token, + // saleor_api_url.to_owned(), + // ); Json::from(serde_json::to_value( TransactionInitializeSessionResponse:: { @@ -246,48 +239,96 @@ async fn create_response( }) } -fn update_transaction_message( - trans_id: cynic::Id, - str_payment_method: String, - apl_token: String, - saleor_api_url: String, -) { - tokio::spawn(async move { - let operation = TransactionUpdate::build(TransactionUpdateVariables { - id: &trans_id, - transaction: Some(TransactionUpdateInput { - message: Some(&str_payment_method), - ..Default::default() - }), - }); - - debug!("operation: {:?}", serde_json::to_string(&operation)); - - let mut res = surf::post(saleor_api_url) - .header("authorization-bearer", apl_token) - .run_graphql(operation) - .await; - - match &mut res { - Ok(r) => { - if let Some(data) = &mut r.data - && let Some(q_res) = &mut data.transaction_update - { - if !q_res.errors.is_empty() { - q_res - .errors - .iter() - .for_each(|e| error!("failed update transaction, {:?}", e)); - } else if q_res.transaction.is_some() { - debug!("sucessfully set transactions message to payment method"); - } - } - } - Err(e) => error!("Failed updating transaction through gql: {:?}", e), - } - }); -} +// fn set_order_payment_method( +// order_id: cynic::Id, +// str_payment_method: String, +// apl_token: String, +// saleor_api_url: String, +// ) { +// tokio::spawn(async move { +// let operation = SetOrderPaymentMethod::build(SetOrderPaymentMethodVariables { +// id: &trans_id, +// transaction: Some(TransactionUpdateInput { +// message: Some(&str_payment_method), +// ..Default::default() +// }), +// }); +// +// debug!("operation: {:?}", serde_json::to_string(&operation)); +// +// let mut res = surf::post(saleor_api_url) +// .header("authorization-bearer", apl_token) +// .run_graphql(operation) +// .await; +// +// match &mut res { +// Ok(r) => { +// if let Some(data) = &mut r.data +// && let Some(q_res) = &mut data.transaction_update +// { +// if !q_res.errors.is_empty() { +// q_res +// .errors +// .iter() +// .for_each(|e| error!("failed update transaction, {:?}", e)); +// } else if q_res.transaction.is_some() { +// debug!("sucessfully set transactions message to payment method"); +// } +// } +// } +// Err(e) => error!("Failed updating transaction through gql: {:?}", e), +// } +// }); +// } +// +// enum WebhookResult { +// Success, +// // NeedsMessageUpdate(&'a str), +// Failure, +// } +// fn update_transaction_message( +// trans_id: cynic::Id, +// str_payment_method: String, +// apl_token: String, +// saleor_api_url: String, +// ) { +// tokio::spawn(async move { +// let operation = TransactionUpdate::build(TransactionUpdateVariables { +// id: &trans_id, +// transaction: Some(TransactionUpdateInput { +// message: Some(&str_payment_method), +// ..Default::default() +// }), +// }); +// +// debug!("operation: {:?}", serde_json::to_string(&operation)); +// +// let mut res = surf::post(saleor_api_url) +// .header("authorization-bearer", apl_token) +// .run_graphql(operation) +// .await; +// +// match &mut res { +// Ok(r) => { +// if let Some(data) = &mut r.data +// && let Some(q_res) = &mut data.transaction_update +// { +// if !q_res.errors.is_empty() { +// q_res +// .errors +// .iter() +// .for_each(|e| error!("failed update transaction, {:?}", e)); +// } else if q_res.transaction.is_some() { +// debug!("sucessfully set transactions message to payment method"); +// } +// } +// } +// Err(e) => error!("Failed updating transaction through gql: {:?}", e), +// } +// }); +// } +// enum WebhookResult { Success, // NeedsMessageUpdate(&'a str), diff --git a/sitemap-generator/src/app.rs b/sitemap-generator/src/app.rs index 1e3dc4c..1073f18 100644 --- a/sitemap-generator/src/app.rs +++ b/sitemap-generator/src/app.rs @@ -59,6 +59,7 @@ pub struct AppState { pub xml_cache: Arc>, pub saleor_app: Arc>, pub config: Config, + pub target_channel: String, pub sitemap_config: SitemapConfig, pub manifest: AppManifest, } diff --git a/sitemap-generator/src/main.rs b/sitemap-generator/src/main.rs index bb22b22..69555d6 100644 --- a/sitemap-generator/src/main.rs +++ b/sitemap-generator/src/main.rs @@ -18,7 +18,7 @@ use saleor_app_sdk::{ }; use std::sync::Arc; use tokio::sync::Mutex; -use tracing::{debug, info}; +use tracing::{debug, error, info}; use crate::{ app::{trace_to_std, AppState, SitemapConfig, XmlCache}, @@ -36,7 +36,6 @@ async fn main() -> anyhow::Result<()> { let saleor_app = SaleorApp::new(&config)?; debug!("Creating saleor App..."); - let app_manifest = AppManifestBuilder::new(&config, cargo_info!()) .add_permissions(vec![ AppPermission::ManageProducts, @@ -71,6 +70,13 @@ async fn main() -> anyhow::Result<()> { )?)), manifest: app_manifest, config: config.clone(), + target_channel: match dotenvy::var("CHANNEL_SLUG") { + Ok(v) => v, + Err(e) => { + error!("Missing channel slug, Saleor will soon deprecate product queries without channel specified."); + anyhow::bail!(e); + } + }, saleor_app: Arc::new(Mutex::new(saleor_app)), }; debug!("Created AppState..."); diff --git a/sitemap-generator/src/queries/get_all_categories_n_products.rs b/sitemap-generator/src/queries/get_all_categories_n_products.rs index d9d9e06..4e64626 100644 --- a/sitemap-generator/src/queries/get_all_categories_n_products.rs +++ b/sitemap-generator/src/queries/get_all_categories_n_products.rs @@ -39,12 +39,12 @@ query getCategoriesNext($after: String) { } } -query getCategoryProductsInitial($id: ID!) { +query getCategoryProductsInitial($id: ID!, $channel: String!) { category(id: $id) { slug id updatedAt - products(first: 50) { + products(first: 50, channel: $channel) { pageInfo { hasNextPage endCursor @@ -61,9 +61,9 @@ query getCategoryProductsInitial($id: ID!) { } } -query getCategoryProductsNext($id: ID!, $after: String!) { +query getCategoryProductsNext($id: ID!, $after: String!, $channel: String!) { category(id: $id) { - products(first: 50, after: $after) { + products(first: 50, after: $after, channel: $channel) { pageInfo { hasNextPage endCursor @@ -80,22 +80,24 @@ query getCategoryProductsNext($id: ID!, $after: String!) { } */ +#[derive(cynic::QueryVariables, Debug)] +pub struct GetCategoriesNextVariables<'a> { + pub after: Option<&'a str>, +} + #[derive(cynic::QueryVariables, Debug)] pub struct GetCategoryProductsInitialVariables<'a> { + pub channel: &'a str, pub id: &'a cynic::Id, } #[derive(cynic::QueryVariables, Debug)] pub struct GetCategoryProductsNextVariables<'a> { pub after: &'a str, + pub channel: &'a str, pub id: &'a cynic::Id, } -#[derive(cynic::QueryVariables, Debug)] -pub struct GetCategoriesNextVariables<'a> { - pub after: Option<&'a str>, -} - #[derive(cynic::QueryFragment, Debug)] #[cynic( graphql_type = "Query", @@ -155,11 +157,12 @@ pub struct Category3 { } #[derive(cynic::QueryFragment, Debug)] +#[cynic(variables = "GetCategoryProductsInitialVariables")] pub struct Category { pub slug: String, pub id: cynic::Id, pub updated_at: DateTime, - #[arguments(first: 50)] + #[arguments(first: 50, channel: $channel)] pub products: Option, } @@ -176,7 +179,7 @@ pub struct ProductCountableConnection { variables = "GetCategoryProductsNextVariables" )] pub struct Category2 { - #[arguments(first: 50, after: $after)] + #[arguments(first: 50, after: $after, channel: $channel)] pub products: Option, } diff --git a/sitemap-generator/src/routes/register.rs b/sitemap-generator/src/routes/register.rs index f5b317a..0fab652 100644 --- a/sitemap-generator/src/routes/register.rs +++ b/sitemap-generator/src/routes/register.rs @@ -86,8 +86,27 @@ pub async fn regenerate(state: AppState, saleor_api_url: String) -> anyhow::Resu .map(|c| (c, vec![])) .collect(); let mut products = vec![]; + + // If there are no products, append this empty array + let mut empty_products = vec![]; + for category in categories.iter_mut() { - products.append(&mut get_all_products(&saleor_api_url, &auth_data.token, category).await?); + products.append( + match &mut get_all_products( + &saleor_api_url, + &state.target_channel, + &auth_data.token, + category, + ) + .await + { + Ok(p) => p, + Err(e) => { + info!("Category {} has no products, {e}", category.0.slug); + &mut empty_products + } + }, + ); } let pages = get_all_pages(&saleor_api_url, &auth_data.token).await?; let collections = get_all_collections(&saleor_api_url, &auth_data.token).await?; @@ -358,7 +377,7 @@ async fn get_all_categories(saleor_api_url: &str, token: &str) -> anyhow::Result .collect::>(), ); debug!( - "fetched first categories, eg.:{:?}", + "fetched next categories, eg.:{:?}", &categories.edges.first() ); next_cursor.clone_from(&categories.page_info.end_cursor); @@ -441,12 +460,14 @@ async fn get_all_collections(saleor_api_url: &str, token: &str) -> anyhow::Resul */ async fn get_all_products( saleor_api_url: &str, + channel: &str, token: &str, main_category: &mut (Category3, Vec>), ) -> anyhow::Result>> { debug!("Collecting all products..."); let operation = GetCategoryProductsInitial::build(GetCategoryProductsInitialVariables { id: &main_category.0.id, + channel, }); let mut all_categorised_products: Vec> = vec![]; let res = surf::post(saleor_api_url) @@ -473,40 +494,39 @@ async fn get_all_products( //Keep fetching next page debug!("fetched first products, eg: {:?}", products.edges.first()); let mut next_cursor = products.page_info.end_cursor.clone(); - loop { - while let Some(cursor) = &mut next_cursor { - let res = surf::post(saleor_api_url) - .header("authorization-bearer", token) - .run_graphql(GetCategoryProductsNext::build( - GetCategoryProductsNextVariables { - id: &main_category.0.id, - after: cursor, - }, - )) - .await; - if let Ok(query) = &res - && let Some(data) = &query.data - && let Some(category) = &data.category - && let Some(products) = &category.products - { - all_categorised_products.append( - &mut products - .edges - .iter() - .map(|p| { - Arc::new(CategorisedProduct { - product: p.node.clone(), - category_id: main_category.0.id.clone(), - }) + while let Some(cursor) = &mut next_cursor { + let res = surf::post(saleor_api_url) + .header("authorization-bearer", token) + .run_graphql(GetCategoryProductsNext::build( + GetCategoryProductsNextVariables { + id: &main_category.0.id, + after: cursor, + channel, + }, + )) + .await; + if let Ok(query) = &res + && let Some(data) = &query.data + && let Some(category) = &data.category + && let Some(products) = &category.products + { + all_categorised_products.append( + &mut products + .edges + .iter() + .map(|p| { + Arc::new(CategorisedProduct { + product: p.node.clone(), + category_id: main_category.0.id.clone(), }) - .collect::>(), - ); - debug!("fetched next products, eg: {:?}", products.edges.first()); - next_cursor.clone_from(&products.page_info.end_cursor); - } else { - error!("Failed fetching initial products! {:?}", &res); - anyhow::bail!("Failed fetching initial products! {:?}", res); - } + }) + .collect::>(), + ); + debug!("fetched next products, eg: {:?}", products.edges.first()); + next_cursor.clone_from(&products.page_info.end_cursor); + } else { + error!("Failed fetching initial products! {:?}", &res); + anyhow::bail!("Failed fetching initial products! {:?}", res); } } } diff --git a/sitemap-generator/src/routes/webhooks.rs b/sitemap-generator/src/routes/webhooks.rs index a0ef478..a45c408 100644 --- a/sitemap-generator/src/routes/webhooks.rs +++ b/sitemap-generator/src/routes/webhooks.rs @@ -582,7 +582,7 @@ async fn update_sitemap_index(state: &AppState) -> anyhow::Result<()> { if path .extension() .map_or(false, |ext| ext == "xml" || ext == "gz") - && !path.to_string_lossy().to_string().contains("sitemap-index") + && !path.to_string_lossy().to_string().contains("sitemap_index") { Some(path) } else { @@ -609,7 +609,7 @@ async fn update_sitemap_index(state: &AppState) -> anyhow::Result<()> { }), )) } else { - error!("file dissapeared or broke during sitemap-index construction"); + error!("file dissapeared or broke during sitemap_index construction"); None } }) @@ -619,7 +619,7 @@ async fn update_sitemap_index(state: &AppState) -> anyhow::Result<()> { .create(true) .write(true) .open(format!( - "{}/sitemap-index.xml", + "{}/sitemap_index.xml", state.sitemap_config.target_folder )) .await?;