From 7f483af9cf435593775a87a45d90ad41d370253f Mon Sep 17 00:00:00 2001 From: Michal Vanko Date: Fri, 6 Sep 2024 14:43:04 +0200 Subject: [PATCH] Improve image generation perf --- axum_server/src/components/site_header.rs | 8 +-- axum_server/src/main.rs | 1 - axum_server/src/pages/blog_post_page.rs | 2 +- .../src/picture_generator/image_generator.rs | 1 + .../picture_markup_generator.rs | 66 ++++++++++++------- axum_server/src/post_utils/post_listing.rs | 2 +- axum_server/src/post_utils/post_parser.rs | 47 +++++++++---- axum_server/src/projects/featured_projects.rs | 2 +- .../components/blog_post_preview.html | 2 +- 9 files changed, 82 insertions(+), 49 deletions(-) diff --git a/axum_server/src/components/site_header.rs b/axum_server/src/components/site_header.rs index d485709..d6fb953 100644 --- a/axum_server/src/components/site_header.rs +++ b/axum_server/src/components/site_header.rs @@ -3,21 +3,15 @@ pub struct Link { pub label: String, } +#[derive(Default)] pub struct HeaderProps { pub back_link: Option, } -impl Default for HeaderProps { - fn default() -> Self { - Self { back_link: None } - } -} - impl HeaderProps { pub fn with_back_link(link: Link) -> Self { Self { back_link: Some(link), - ..Default::default() } } } diff --git a/axum_server/src/main.rs b/axum_server/src/main.rs index bf3115d..7ea01f8 100644 --- a/axum_server/src/main.rs +++ b/axum_server/src/main.rs @@ -48,7 +48,6 @@ async fn main() { axum::serve(listener, app).await.unwrap(); } -// TODO footer // TODO Display blog posts // TODO responsive design // TODO go live pipeline diff --git a/axum_server/src/pages/blog_post_page.rs b/axum_server/src/pages/blog_post_page.rs index 3993379..e7dc5f8 100644 --- a/axum_server/src/pages/blog_post_page.rs +++ b/axum_server/src/pages/blog_post_page.rs @@ -21,7 +21,7 @@ pub struct BlogPostTemplate { pub async fn render_blog_post(Path(post_id): Path) -> Result { let path = format!("../_posts/blog/{}.md", post_id); - let parse_post = parse_post::(&path); + let parse_post = parse_post::(&path, true); let parsed = parse_post.await?; Ok(BlogPostTemplate { diff --git a/axum_server/src/picture_generator/image_generator.rs b/axum_server/src/picture_generator/image_generator.rs index aba0519..58d5e19 100644 --- a/axum_server/src/picture_generator/image_generator.rs +++ b/axum_server/src/picture_generator/image_generator.rs @@ -24,6 +24,7 @@ pub fn generate_images( .with_extension(format.get_extension()); if save_path.exists() { + debug!("Skip generating {save_path:?} - Already exists"); return; } diff --git a/axum_server/src/picture_generator/picture_markup_generator.rs b/axum_server/src/picture_generator/picture_markup_generator.rs index 82218f4..1ca1860 100644 --- a/axum_server/src/picture_generator/picture_markup_generator.rs +++ b/axum_server/src/picture_generator/picture_markup_generator.rs @@ -1,12 +1,11 @@ use std::{ cmp::Ordering, path::{Path, PathBuf}, - str::FromStr as _, sync::Arc, }; use anyhow::Context; -use image::{GenericImageView, ImageReader}; +use image::{image_dimensions, ImageReader}; use super::{export_format::ExportFormat, image_generator::generate_images}; @@ -17,23 +16,27 @@ pub fn generate_picture_markup( width: u32, height: u32, alt_text: &str, + generate_image: bool, ) -> Result { + if !orig_img_path.starts_with("/") { + return Ok(format!( + r#"{alt_text}"# + )); + } + let exported_formats = get_export_formats(orig_img_path); let path_to_generated = get_generated_file_name(orig_img_path); // TODO This should get removed when we move the project structure #move - let dev_only_img_path = Path::new("../static/").join(orig_img_path.strip_prefix("/").unwrap()); + let dev_only_img_path = + Path::new("../static/").join(orig_img_path.strip_prefix("/").unwrap_or(orig_img_path)); - let orig_img = ImageReader::open(&dev_only_img_path) - .with_context(|| format!("Failed to read instrs from {:?}", &dev_only_img_path))? - .decode()?; - let orig_img_dimensions = orig_img.dimensions(); + let orig_img_dimensions = image_dimensions(&dev_only_img_path).unwrap(); let resolutions = get_resolutions(orig_img_dimensions, width, height); - // TODO lets generate images - - let orig_img_arc = Arc::new(orig_img); - let orig_img_clone = Arc::clone(&orig_img_arc); let path_to_generated_arc = Arc::new(path_to_generated); let path_to_generated_clone = Arc::clone(&path_to_generated_arc); let resolutions_arc = Arc::new(resolutions); @@ -41,18 +44,25 @@ pub fn generate_picture_markup( let exported_formats_arc = Arc::new(exported_formats); let exported_formats_clone = Arc::clone(&exported_formats_arc); - tokio::spawn(async move { - let orig_img = orig_img_clone.as_ref(); - let path_to_generated = path_to_generated_clone.as_ref(); - let resolutions = resolutions_clone.as_ref(); - let exported_formats = exported_formats_clone.as_ref(); + if generate_image { + rayon::spawn(move || { + let orig_img = ImageReader::open(&dev_only_img_path) + .with_context(|| format!("Failed to read instrs from {:?}", &dev_only_img_path)) + .unwrap() + .decode() + .unwrap(); + let path_to_generated = path_to_generated_clone.as_ref(); + let resolutions = resolutions_clone.as_ref(); + let exported_formats = exported_formats_clone.as_ref(); - let result = generate_images(orig_img, path_to_generated, resolutions, exported_formats) - .with_context(|| "Failed to generate images".to_string()); - if let Err(e) = result { - tracing::error!("Error: {}", e); - } - }); + let result = + generate_images(&orig_img, path_to_generated, resolutions, exported_formats) + .with_context(|| "Failed to generate images".to_string()); + if let Err(e) = result { + tracing::error!("Error: {}", e); + } + }); + } let exported_formats = Arc::clone(&exported_formats_arc); let path_to_generated = Arc::clone(&path_to_generated_arc); @@ -232,7 +242,11 @@ fn get_generated_file_name(orig_img_path: &str) -> PathBuf { .file_stem() .expect("There should be a name for every img"); let result = Path::new("/generated_images/") - .join(parent.strip_prefix("/").unwrap()) + .join( + parent + .strip_prefix("/") + .unwrap_or(Path::new("/generated_images/")), + ) .join(file_name); result } @@ -287,7 +301,9 @@ fn test_get_export_formats() { } #[test] fn test_generate_srcset() { - let orig_img_path = PathBuf::from_str("/generated_images/images/uploads/img_name").unwrap(); + let orig_img_path = + ::from_str("/generated_images/images/uploads/img_name") + .unwrap(); let export_format = ExportFormat::Avif; let resolutions = vec![ (320, 200, 1.), @@ -325,7 +341,7 @@ fn test_generate_picture_markup() { > "#; assert_eq!( - generate_picture_markup(orig_img_path, width, height, "Testing image alt") + generate_picture_markup(orig_img_path, width, height, "Testing image alt", false) .expect("picture markup has to be generated"), result ); diff --git a/axum_server/src/post_utils/post_listing.rs b/axum_server/src/post_utils/post_listing.rs index e484007..0aa9c6a 100644 --- a/axum_server/src/post_utils/post_listing.rs +++ b/axum_server/src/post_utils/post_listing.rs @@ -22,7 +22,7 @@ pub async fn get_post_list<'de, Metadata: DeserializeOwned>( let file_path = file.path(); let file_path_str = file_path.to_str().unwrap(); info!(":{}", file_path_str); - let post = parse_post::(file_path_str).await?; + let post = parse_post::(file_path_str, false).await?; posts.push(post); } diff --git a/axum_server/src/post_utils/post_parser.rs b/axum_server/src/post_utils/post_parser.rs index 99e66c7..4c6a017 100644 --- a/axum_server/src/post_utils/post_parser.rs +++ b/axum_server/src/post_utils/post_parser.rs @@ -6,6 +6,9 @@ use gray_matter::{engine::YAML, Matter}; use pulldown_cmark::{Event, Options, Parser, Tag, TagEnd}; use serde::{de::DeserializeOwned, Deserialize, Deserializer}; use tokio::fs; +use tracing::debug; + +use crate::picture_generator::picture_markup_generator::generate_picture_markup; pub fn deserialize_date<'de, D>(deserializer: D) -> Result, D::Error> where @@ -29,6 +32,7 @@ pub struct ParseResult { pub async fn parse_post<'de, Metadata: DeserializeOwned>( path: &str, + generate_images: bool, ) -> Result, StatusCode> { let file_contents = fs::read_to_string(path) .await @@ -43,7 +47,7 @@ pub async fn parse_post<'de, Metadata: DeserializeOwned>( StatusCode::INTERNAL_SERVER_ERROR })?; - let body = parse_html(&metadata.content); + let body = parse_html(&metadata.content, generate_images); let filename = Path::new(path) .file_stem() @@ -59,7 +63,7 @@ pub async fn parse_post<'de, Metadata: DeserializeOwned>( }) } -pub fn parse_html(markdown: &str) -> String { +pub fn parse_html(markdown: &str, generate_images: bool) -> String { let mut options = Options::empty(); options.insert(Options::ENABLE_TABLES); options.insert(Options::ENABLE_FOOTNOTES); @@ -80,22 +84,41 @@ pub fn parse_html(markdown: &str) -> String { title, id, }) => { - println!( + // TODO Get image resolution + + // Place image into the content with scaled reso to a boundary + let picture_markup = + generate_picture_markup(&dest_url, 500, 500, &title, generate_images).unwrap_or( + format!( + r#" + {alt}"#, + alt = title, + src = dest_url, + ), + ); + // let picture_markup = format!( + // r#" + // {alt}"#, + // alt = title, + // src = dest_url, + // ); + + debug!( "Image link_type: {:?} url: {} title: {} id: {}", link_type, dest_url, title, id ); - // TODO src set Event::Html( format!( r#"
- {alt} -
- "#, - alt = title, - src = dest_url, + {picture_markup} +
+ "#, ) .into(), ) diff --git a/axum_server/src/projects/featured_projects.rs b/axum_server/src/projects/featured_projects.rs index 6bc9837..7763bcc 100644 --- a/axum_server/src/projects/featured_projects.rs +++ b/axum_server/src/projects/featured_projects.rs @@ -14,7 +14,7 @@ pub async fn get_featured_projects() -> Result> .into_iter() .filter(|post| post.metadata.featured) .map(|mut post| { - post.metadata.description = parse_html(&post.metadata.description); + post.metadata.description = parse_html(&post.metadata.description, false); post }) .collect(); diff --git a/axum_server/templates/components/blog_post_preview.html b/axum_server/templates/components/blog_post_preview.html index cf5ecc9..21e0807 100644 --- a/axum_server/templates/components/blog_post_preview.html +++ b/axum_server/templates/components/blog_post_preview.html @@ -2,7 +2,7 @@