stop using redundant gql update of trans. message

This commit is contained in:
Djkáťo 2024-05-17 15:43:59 +02:00
parent 753154a584
commit 36a26d5627
11 changed files with 242 additions and 114 deletions

5
.env
View file

@ -1,13 +1,14 @@
## COMMON VARIABLES FOR ALL APPS ## COMMON VARIABLES FOR ALL APPS
REQUIRED_SALEOR_VERSION="^3.13" 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 # 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_API_BASE_URL="http://10.100.110.21:3000"
APP_IFRAME_BASE_URL="http://app-name.site.com" APP_IFRAME_BASE_URL="http://10.100.110.21:3000"
APL="Redis" APL="Redis"
APL_URL="redis://localhost:6380/2" APL_URL="redis://localhost:6380/2"
LOG_LEVEL="DEBUG" LOG_LEVEL="DEBUG"
## THESE VARIABLES ARE FOR SITEMAP-GENERATOR APP ## THESE VARIABLES ARE FOR SITEMAP-GENERATOR APP
CHANNEL_SLUG="zakladny"
SITEMAP_TARGET_FOLDER="./temp" SITEMAP_TARGET_FOLDER="./temp"
# Available fields can be found in ./sitemap-generator/src/queries/event_subjects_updated.rs: ProductUpdate # 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}" SITEMAP_PRODUCT_TEMPLATE="https://example.com/{product.category.slug}/{product.slug}"

2
Cargo.lock generated
View file

@ -2677,7 +2677,7 @@ checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
[[package]] [[package]]
name = "saleor-app-sdk" name = "saleor-app-sdk"
version = "0.2.0" version = "0.2.1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",

View file

@ -1,3 +1,3 @@
pub mod event_transactions; pub mod event_transactions;
pub mod mutation_order_payment_method_update;
pub mod mutation_transaction_update; pub mod mutation_transaction_update;

View file

@ -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<MetadataInput<'a>>,
}
#[derive(cynic::QueryFragment, Debug)]
#[cynic(
graphql_type = "Mutation",
variables = "SetOrderPaymentMethodVariables"
)]
pub struct SetOrderPaymentMethod {
#[arguments(id: $id, input: $metadata)]
pub update_metadata: Option<UpdateMetadata>,
}
#[derive(cynic::QueryFragment, Debug)]
pub struct UpdateMetadata {
pub errors: Vec<MetadataError>,
}
#[derive(cynic::QueryFragment, Debug)]
pub struct MetadataError {
pub field: Option<String>,
pub message: Option<String>,
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,
}

View file

@ -1,4 +1,5 @@
#[cynic::schema("saleor")] #[cynic::schema("saleor")]
mod schema {} mod schema {}
/* /*
mutation transactionUpdate($id: ID!, $transaction: TransactionUpdateInput) { mutation transactionUpdate($id: ID!, $transaction: TransactionUpdateInput) {
@ -17,7 +18,6 @@ mutation transactionUpdate($id: ID!, $transaction: TransactionUpdateInput) {
} }
} }
*/ */
#[derive(cynic::QueryVariables, Debug)] #[derive(cynic::QueryVariables, Debug)]
pub struct TransactionUpdateVariables<'a> { pub struct TransactionUpdateVariables<'a> {
pub id: &'a cynic::Id, pub id: &'a cynic::Id,

View file

@ -1,6 +1,5 @@
use anyhow::Context; use anyhow::Context;
use axum::{extract::State, http::HeaderMap, Json}; use axum::{extract::State, http::HeaderMap, Json};
use cynic::{http::SurfExt, MutationBuilder};
use rust_decimal::{prelude::FromPrimitive, Decimal}; use rust_decimal::{prelude::FromPrimitive, Decimal};
use saleor_app_sdk::{ use saleor_app_sdk::{
headers::SALEOR_API_URL_HEADER, headers::SALEOR_API_URL_HEADER,
@ -25,16 +24,10 @@ use crate::{
AppError, AppState, PaymentGatewayInitializeSessionData, PaymentMethodType, AppError, AppState, PaymentGatewayInitializeSessionData, PaymentMethodType,
TransactionInitializeSessionData, TransactionInitializeSessionData,
}, },
queries::{ queries::event_transactions::{
event_transactions::{ DeliveryMethod, OrderOrCheckout, PaymentGatewayInitializeSession2,
DeliveryMethod, OrderOrCheckout, PaymentGatewayInitializeSession2, TransactionCancelationRequested2, TransactionChargeRequested2, TransactionFlowStrategyEnum,
TransactionCancelationRequested2, TransactionChargeRequested2, TransactionInitializeSession2, TransactionProcessSession2, TransactionRefundRequested2,
TransactionFlowStrategyEnum, TransactionInitializeSession2, TransactionProcessSession2,
TransactionRefundRequested2,
},
mutation_transaction_update::{
TransactionUpdate, TransactionUpdateInput, TransactionUpdateVariables,
},
}, },
}; };
@ -153,12 +146,12 @@ async fn create_response(
let str_payment_method = let str_payment_method =
serde_json::to_string(&TransactionInitializeSessionData { payment_method })?; serde_json::to_string(&TransactionInitializeSessionData { payment_method })?;
update_transaction_message( // update_transaction_message(
session_data.transaction.id, // session_data.transaction.id,
str_payment_method.clone(), // str_payment_method.clone(),
apl_token, // apl_token,
saleor_api_url.to_owned(), // saleor_api_url.to_owned(),
); // );
Json::from(serde_json::to_value( Json::from(serde_json::to_value(
TransactionInitializeSessionResponse::<u8> { TransactionInitializeSessionResponse::<u8> {
@ -246,48 +239,96 @@ async fn create_response(
}) })
} }
fn update_transaction_message( // fn set_order_payment_method(
trans_id: cynic::Id, // order_id: cynic::Id,
str_payment_method: String, // str_payment_method: String,
apl_token: String, // apl_token: String,
saleor_api_url: String, // saleor_api_url: String,
) { // ) {
tokio::spawn(async move { // tokio::spawn(async move {
let operation = TransactionUpdate::build(TransactionUpdateVariables { // let operation = SetOrderPaymentMethod::build(SetOrderPaymentMethodVariables {
id: &trans_id, // id: &trans_id,
transaction: Some(TransactionUpdateInput { // transaction: Some(TransactionUpdateInput {
message: Some(&str_payment_method), // message: Some(&str_payment_method),
..Default::default() // ..Default::default()
}), // }),
}); // });
//
debug!("operation: {:?}", serde_json::to_string(&operation)); // debug!("operation: {:?}", serde_json::to_string(&operation));
//
let mut res = surf::post(saleor_api_url) // let mut res = surf::post(saleor_api_url)
.header("authorization-bearer", apl_token) // .header("authorization-bearer", apl_token)
.run_graphql(operation) // .run_graphql(operation)
.await; // .await;
//
match &mut res { // match &mut res {
Ok(r) => { // Ok(r) => {
if let Some(data) = &mut r.data // if let Some(data) = &mut r.data
&& let Some(q_res) = &mut data.transaction_update // && let Some(q_res) = &mut data.transaction_update
{ // {
if !q_res.errors.is_empty() { // if !q_res.errors.is_empty() {
q_res // q_res
.errors // .errors
.iter() // .iter()
.for_each(|e| error!("failed update transaction, {:?}", e)); // .for_each(|e| error!("failed update transaction, {:?}", e));
} else if q_res.transaction.is_some() { // } else if q_res.transaction.is_some() {
debug!("sucessfully set transactions message to payment method"); // debug!("sucessfully set transactions message to payment method");
} // }
} // }
} // }
Err(e) => error!("Failed updating transaction through gql: {:?}", e), // 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 { enum WebhookResult {
Success, Success,
// NeedsMessageUpdate(&'a str), // NeedsMessageUpdate(&'a str),

View file

@ -59,6 +59,7 @@ pub struct AppState {
pub xml_cache: Arc<tokio::sync::Mutex<XmlCache>>, pub xml_cache: Arc<tokio::sync::Mutex<XmlCache>>,
pub saleor_app: Arc<tokio::sync::Mutex<SaleorApp>>, pub saleor_app: Arc<tokio::sync::Mutex<SaleorApp>>,
pub config: Config, pub config: Config,
pub target_channel: String,
pub sitemap_config: SitemapConfig, pub sitemap_config: SitemapConfig,
pub manifest: AppManifest, pub manifest: AppManifest,
} }

View file

@ -18,7 +18,7 @@ use saleor_app_sdk::{
}; };
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::Mutex; use tokio::sync::Mutex;
use tracing::{debug, info}; use tracing::{debug, error, info};
use crate::{ use crate::{
app::{trace_to_std, AppState, SitemapConfig, XmlCache}, app::{trace_to_std, AppState, SitemapConfig, XmlCache},
@ -36,7 +36,6 @@ async fn main() -> anyhow::Result<()> {
let saleor_app = SaleorApp::new(&config)?; let saleor_app = SaleorApp::new(&config)?;
debug!("Creating saleor App..."); debug!("Creating saleor App...");
let app_manifest = AppManifestBuilder::new(&config, cargo_info!()) let app_manifest = AppManifestBuilder::new(&config, cargo_info!())
.add_permissions(vec![ .add_permissions(vec![
AppPermission::ManageProducts, AppPermission::ManageProducts,
@ -71,6 +70,13 @@ async fn main() -> anyhow::Result<()> {
)?)), )?)),
manifest: app_manifest, manifest: app_manifest,
config: config.clone(), 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)), saleor_app: Arc::new(Mutex::new(saleor_app)),
}; };
debug!("Created AppState..."); debug!("Created AppState...");

View file

@ -39,12 +39,12 @@ query getCategoriesNext($after: String) {
} }
} }
query getCategoryProductsInitial($id: ID!) { query getCategoryProductsInitial($id: ID!, $channel: String!) {
category(id: $id) { category(id: $id) {
slug slug
id id
updatedAt updatedAt
products(first: 50) { products(first: 50, channel: $channel) {
pageInfo { pageInfo {
hasNextPage hasNextPage
endCursor 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) { category(id: $id) {
products(first: 50, after: $after) { products(first: 50, after: $after, channel: $channel) {
pageInfo { pageInfo {
hasNextPage hasNextPage
endCursor 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)] #[derive(cynic::QueryVariables, Debug)]
pub struct GetCategoryProductsInitialVariables<'a> { pub struct GetCategoryProductsInitialVariables<'a> {
pub channel: &'a str,
pub id: &'a cynic::Id, pub id: &'a cynic::Id,
} }
#[derive(cynic::QueryVariables, Debug)] #[derive(cynic::QueryVariables, Debug)]
pub struct GetCategoryProductsNextVariables<'a> { pub struct GetCategoryProductsNextVariables<'a> {
pub after: &'a str, pub after: &'a str,
pub channel: &'a str,
pub id: &'a cynic::Id, pub id: &'a cynic::Id,
} }
#[derive(cynic::QueryVariables, Debug)]
pub struct GetCategoriesNextVariables<'a> {
pub after: Option<&'a str>,
}
#[derive(cynic::QueryFragment, Debug)] #[derive(cynic::QueryFragment, Debug)]
#[cynic( #[cynic(
graphql_type = "Query", graphql_type = "Query",
@ -155,11 +157,12 @@ pub struct Category3 {
} }
#[derive(cynic::QueryFragment, Debug)] #[derive(cynic::QueryFragment, Debug)]
#[cynic(variables = "GetCategoryProductsInitialVariables")]
pub struct Category { pub struct Category {
pub slug: String, pub slug: String,
pub id: cynic::Id, pub id: cynic::Id,
pub updated_at: DateTime, pub updated_at: DateTime,
#[arguments(first: 50)] #[arguments(first: 50, channel: $channel)]
pub products: Option<ProductCountableConnection>, pub products: Option<ProductCountableConnection>,
} }
@ -176,7 +179,7 @@ pub struct ProductCountableConnection {
variables = "GetCategoryProductsNextVariables" variables = "GetCategoryProductsNextVariables"
)] )]
pub struct Category2 { pub struct Category2 {
#[arguments(first: 50, after: $after)] #[arguments(first: 50, after: $after, channel: $channel)]
pub products: Option<ProductCountableConnection2>, pub products: Option<ProductCountableConnection2>,
} }

View file

@ -86,8 +86,27 @@ pub async fn regenerate(state: AppState, saleor_api_url: String) -> anyhow::Resu
.map(|c| (c, vec![])) .map(|c| (c, vec![]))
.collect(); .collect();
let mut products = vec![]; let mut products = vec![];
// If there are no products, append this empty array
let mut empty_products = vec![];
for category in categories.iter_mut() { 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 pages = get_all_pages(&saleor_api_url, &auth_data.token).await?;
let collections = get_all_collections(&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::<Vec<_>>(), .collect::<Vec<_>>(),
); );
debug!( debug!(
"fetched first categories, eg.:{:?}", "fetched next categories, eg.:{:?}",
&categories.edges.first() &categories.edges.first()
); );
next_cursor.clone_from(&categories.page_info.end_cursor); 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( async fn get_all_products(
saleor_api_url: &str, saleor_api_url: &str,
channel: &str,
token: &str, token: &str,
main_category: &mut (Category3, Vec<Arc<CategorisedProduct>>), main_category: &mut (Category3, Vec<Arc<CategorisedProduct>>),
) -> anyhow::Result<Vec<Arc<CategorisedProduct>>> { ) -> anyhow::Result<Vec<Arc<CategorisedProduct>>> {
debug!("Collecting all products..."); debug!("Collecting all products...");
let operation = GetCategoryProductsInitial::build(GetCategoryProductsInitialVariables { let operation = GetCategoryProductsInitial::build(GetCategoryProductsInitialVariables {
id: &main_category.0.id, id: &main_category.0.id,
channel,
}); });
let mut all_categorised_products: Vec<Arc<CategorisedProduct>> = vec![]; let mut all_categorised_products: Vec<Arc<CategorisedProduct>> = vec![];
let res = surf::post(saleor_api_url) let res = surf::post(saleor_api_url)
@ -473,40 +494,39 @@ async fn get_all_products(
//Keep fetching next page //Keep fetching next page
debug!("fetched first products, eg: {:?}", products.edges.first()); debug!("fetched first products, eg: {:?}", products.edges.first());
let mut next_cursor = products.page_info.end_cursor.clone(); let mut next_cursor = products.page_info.end_cursor.clone();
loop { while let Some(cursor) = &mut next_cursor {
while let Some(cursor) = &mut next_cursor { let res = surf::post(saleor_api_url)
let res = surf::post(saleor_api_url) .header("authorization-bearer", token)
.header("authorization-bearer", token) .run_graphql(GetCategoryProductsNext::build(
.run_graphql(GetCategoryProductsNext::build( GetCategoryProductsNextVariables {
GetCategoryProductsNextVariables { id: &main_category.0.id,
id: &main_category.0.id, after: cursor,
after: cursor, channel,
}, },
)) ))
.await; .await;
if let Ok(query) = &res if let Ok(query) = &res
&& let Some(data) = &query.data && let Some(data) = &query.data
&& let Some(category) = &data.category && let Some(category) = &data.category
&& let Some(products) = &category.products && let Some(products) = &category.products
{ {
all_categorised_products.append( all_categorised_products.append(
&mut products &mut products
.edges .edges
.iter() .iter()
.map(|p| { .map(|p| {
Arc::new(CategorisedProduct { Arc::new(CategorisedProduct {
product: p.node.clone(), product: p.node.clone(),
category_id: main_category.0.id.clone(), category_id: main_category.0.id.clone(),
})
}) })
.collect::<Vec<_>>(), })
); .collect::<Vec<_>>(),
debug!("fetched next products, eg: {:?}", products.edges.first()); );
next_cursor.clone_from(&products.page_info.end_cursor); debug!("fetched next products, eg: {:?}", products.edges.first());
} else { next_cursor.clone_from(&products.page_info.end_cursor);
error!("Failed fetching initial products! {:?}", &res); } else {
anyhow::bail!("Failed fetching initial products! {:?}", res); error!("Failed fetching initial products! {:?}", &res);
} anyhow::bail!("Failed fetching initial products! {:?}", res);
} }
} }
} }

View file

@ -582,7 +582,7 @@ async fn update_sitemap_index(state: &AppState) -> anyhow::Result<()> {
if path if path
.extension() .extension()
.map_or(false, |ext| ext == "xml" || ext == "gz") .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) Some(path)
} else { } else {
@ -609,7 +609,7 @@ async fn update_sitemap_index(state: &AppState) -> anyhow::Result<()> {
}), }),
)) ))
} else { } else {
error!("file dissapeared or broke during sitemap-index construction"); error!("file dissapeared or broke during sitemap_index construction");
None None
} }
}) })
@ -619,7 +619,7 @@ async fn update_sitemap_index(state: &AppState) -> anyhow::Result<()> {
.create(true) .create(true)
.write(true) .write(true)
.open(format!( .open(format!(
"{}/sitemap-index.xml", "{}/sitemap_index.xml",
state.sitemap_config.target_folder state.sitemap_config.target_folder
)) ))
.await?; .await?;