This commit is contained in:
Ondrej Vlach 2023-12-07 22:02:36 +01:00
parent 2fb24dda9b
commit 3d7f1331c0
Signed by: ovlach
GPG Key ID: 4FF1A23B4914DE70
9 changed files with 24 additions and 27 deletions

View File

@ -25,3 +25,5 @@ Intermediate = pokročilá znalost
Beginer = malá znalost Beginer = malá znalost
tools = nástroje tools = nástroje
operating-systems = operační systémy operating-systems = operační systémy
skills-frameworks = Frameworky
skills-databases = Databáze

View File

@ -25,3 +25,5 @@ Intermediate = intermediate
Beginer = beginer Beginer = beginer
tools = tools tools = tools
operating-systems = operating systems operating-systems = operating systems
skills-frameworks = Frameworks
skills-databases = Databases

View File

@ -41,7 +41,7 @@ pub struct ChromiumCoordinator {
impl ChromiumCoordinator { impl ChromiumCoordinator {
const NUMBER_OF_INSTANCES: usize = 1; // TODO: make this configurable const NUMBER_OF_INSTANCES: usize = 1; // TODO: make this configurable
pub async fn new() -> Self { pub async fn new() -> Self {
let instances: Arc<Mutex<Vec<BrowserHolder>>> = Arc::new(Mutex::new(Vec::with_capacity(Self::NUMBER_OF_INSTANCES))); let instances: Arc<Mutex<Vec<BrowserHolder>>> = Arc::new(Mutex::new(Vec::with_capacity(Self::NUMBER_OF_INSTANCES)));
trace!("creating {} Chromium instances", Self::NUMBER_OF_INSTANCES); trace!("creating {} Chromium instances", Self::NUMBER_OF_INSTANCES);
@ -63,7 +63,7 @@ impl ChromiumCoordinator {
} }
fn spawn_browser(&self) { fn spawn_browser(&self) {
let instances = self.instances.clone(); let instances = self.instances.clone();
tokio::spawn(async move { tokio::spawn(async move {
debug!("spawn new instance of browser"); debug!("spawn new instance of browser");
// Create new instance // Create new instance
@ -133,7 +133,7 @@ impl<'r> FromRequest<'r> for BrowserHolder {
let coordinator = request.rocket().state::<ChromiumCoordinator>().unwrap(); let coordinator = request.rocket().state::<ChromiumCoordinator>().unwrap();
let get_instance = coordinator.get_browser(); let get_instance = coordinator.get_browser();
pin_mut!(get_instance); // TODO: wth? pin_mut!(get_instance); // TODO: wth?
let result = match tokio::time::timeout(std::time::Duration::from_secs(10), &mut get_instance).await { match tokio::time::timeout(std::time::Duration::from_secs(10), &mut get_instance).await {
Ok(maybebrowser) => match maybebrowser { Ok(maybebrowser) => match maybebrowser {
Ok(browser) => Outcome::<BrowserHolder, ()>::Success(browser), Ok(browser) => Outcome::<BrowserHolder, ()>::Success(browser),
Err(_) => { Err(_) => {
@ -145,9 +145,6 @@ impl<'r> FromRequest<'r> for BrowserHolder {
error!("Can't create new instance of browser (timeout)"); error!("Can't create new instance of browser (timeout)");
Outcome::<BrowserHolder, ()>::Error((Status::InternalServerError, ())) Outcome::<BrowserHolder, ()>::Error((Status::InternalServerError, ()))
} }
}; }
result
} }
} }

View File

@ -18,8 +18,9 @@ pub struct CVBackendConfig {
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(crate = "rocket::serde")] #[serde(crate = "rocket::serde")]
#[allow(dead_code)]
pub struct DefaultPerson { pub struct DefaultPerson {
default_person_name: String, pub(crate) default_person_name: String,
} }
pub fn rocket_builder() -> Rocket<Build> { pub fn rocket_builder() -> Rocket<Build> {

View File

@ -1,9 +1,5 @@
use std::{panic, fs::File, io::Write};
use log::error;
use nanobyte_opentelemetry::{default_filter_layer, LogLevel, install_panic_handler}; use nanobyte_opentelemetry::{default_filter_layer, LogLevel, install_panic_handler};
use ovlach_pdf::rocket_builder; use ovlach_pdf::rocket_builder;
use tracing::Level;
#[rocket::main] #[rocket::main]

View File

@ -1,16 +1,14 @@
use headless_chrome::Browser; use headless_chrome::Browser;
use headless_chrome::types::PrintToPdfOptions; use headless_chrome::types::PrintToPdfOptions;
use nanobyte_opentelemetry::rocket::{TracingSpan, RequestId, OtelReqwestClient}; use nanobyte_opentelemetry::rocket::{TracingSpan, OtelReqwestClient};
use nanobyte_tera::l18n::LanguageDescription; use nanobyte_tera::l18n::LanguageDescription;
use ovlach_data::cv::data::CV; use ovlach_data::cv::data::CV;
use reqwest::Client;
use rocket::fs::NamedFile; use rocket::fs::NamedFile;
use ::rocket::{State, http::Status}; use ::rocket::{State, http::Status};
use ::rocket::get; use ::rocket::get;
use tempfile::NamedTempFile; use tempfile::NamedTempFile;
use tera::Context; use tera::Context;
use tracing::{info_span, error, debug, Instrument}; use tracing::{info_span, error, debug, Instrument};
use crate::DefaultPerson;
use crate::{chromium::rocket::BrowserHolder, tools::{tera::NanoTera, pdf::PdfStream, rocket::RequestLanguage}, services::cv::fetch_cv_data_from_backend, CVBackendConfig}; use crate::{chromium::rocket::BrowserHolder, tools::{tera::NanoTera, pdf::PdfStream, rocket::RequestLanguage}, services::cv::fetch_cv_data_from_backend, CVBackendConfig};
// TODO: request-id // TODO: request-id
@ -36,11 +34,9 @@ fn generate_pdf(browser: Browser, file: &NamedTempFile) -> Vec<u8> {
//thread::sleep(Duration::from_secs(10)); //thread::sleep(Duration::from_secs(10));
let bytes = info_span!("print_pdf").in_scope(|| { info_span!("print_pdf").in_scope(|| {
tab.print_to_pdf(Some(options)).unwrap() tab.print_to_pdf(Some(options)).unwrap()
}); })
return bytes;
} }
#[tracing::instrument] #[tracing::instrument]
@ -62,10 +58,9 @@ fn render_template(template_name: &str, file: &NamedTempFile, tera: NanoTera, cv
#[get("/cv/<username>/<language>/output.pdf")] #[get("/cv/<username>/<language>/output.pdf")]
pub async fn render_pdf_cv(username: &str, tera: NanoTera, tracing: TracingSpan, request_client: OtelReqwestClient, pub async fn render_pdf_cv(username: &str, tera: NanoTera, tracing: TracingSpan, request_client: OtelReqwestClient,
cv_config: &State<CVBackendConfig>, language: RequestLanguage, browser: BrowserHolder, cv_config: &State<CVBackendConfig>, language: RequestLanguage, browser: BrowserHolder) -> Result<PdfStream, Status> {
default_person: &State<DefaultPerson>) -> Result<PdfStream, Status> {
async move { async move {
match fetch_cv_data_from_backend(&cv_config.cv_backend_path, &default_person.inner().default_person_name, &request_client.0).await { match fetch_cv_data_from_backend(&cv_config.cv_backend_path, &username.to_string(), &request_client.0).await {
Ok(cv_data) => { Ok(cv_data) => {
let file = tempfile::Builder::new().suffix(".html").tempfile().unwrap(); let file = tempfile::Builder::new().suffix(".html").tempfile().unwrap();
render_template("two_column", &file, tera, cv_data, language.language); render_template("two_column", &file, tera, cv_data, language.language);
@ -86,10 +81,9 @@ pub async fn render_pdf_cv(username: &str, tera: NanoTera, tracing: TracingSpan,
/// Route only for debuging /// Route only for debuging
#[get("/cv/<username>/<language>/output.html")] #[get("/cv/<username>/<language>/output.html")]
pub async fn render_html_cv(username: &str, tera: NanoTera, tracing: TracingSpan, request_client: OtelReqwestClient, pub async fn render_html_cv(username: &str, tera: NanoTera, tracing: TracingSpan, request_client: OtelReqwestClient,
cv_config: &State<CVBackendConfig>, language: RequestLanguage, cv_config: &State<CVBackendConfig>, language: RequestLanguage) -> Result<NamedFile, Status> {
default_person: &State<DefaultPerson>) -> Result<NamedFile, Status> {
async move { async move {
match fetch_cv_data_from_backend(&cv_config.cv_backend_path, &default_person.inner().default_person_name, &request_client.0).await { match fetch_cv_data_from_backend(&cv_config.cv_backend_path, &username.to_string(), &request_client.0).await {
Ok(cv_data) => { Ok(cv_data) => {
let file = tempfile::Builder::new().suffix(".html").tempfile().unwrap(); let file = tempfile::Builder::new().suffix(".html").tempfile().unwrap();
render_template("two_column", &file, tera, cv_data, language.language); render_template("two_column", &file, tera, cv_data, language.language);

View File

@ -1,4 +1,4 @@
use rocket::{response::{Responder, self}, Request, Response, http::{Header, ContentType}}; use rocket::{response::{Responder, self}, Request, Response, http::ContentType};
use std::io::Cursor; use std::io::Cursor;

View File

@ -14,7 +14,7 @@ pub struct NanoTera(pub Tera);
impl<'r> FromRequest<'r> for NanoTera { impl<'r> FromRequest<'r> for NanoTera {
type Error = (); type Error = ();
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, ()> { async fn from_request(_request: &'r Request<'_>) -> Outcome<Self, ()> {
let mut tera = Tera::new("templates/*").unwrap(); let mut tera = Tera::new("templates/*").unwrap();
tera.register_filter("translate", translate_filter); tera.register_filter("translate", translate_filter);
tera.register_filter("calculate_age", calculate_age); tera.register_filter("calculate_age", calculate_age);

View File

@ -174,6 +174,11 @@
<img alt="Phone" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNNi4xNzYgMS4zMjJsMi44NDQtMS4zMjIgNC4wNDEgNy44OS0yLjcyNCAxLjM0MWMtLjUzOCAxLjI1OSAyLjE1OSA2LjI4OSAzLjI5NyA2LjM3Mi4wOS0uMDU4IDIuNjcxLTEuMzI4IDIuNjcxLTEuMzI4bDQuMTEgNy45MzJzLTIuNzY0IDEuMzU0LTIuODU0IDEuMzk2Yy03Ljg2MiAzLjU5MS0xOS4xMDMtMTguMjU4LTExLjM4NS0yMi4yODF6bTEuOTI5IDEuMjc0bC0xLjAyMy41MDRjLTUuMjk0IDIuNzYyIDQuMTc3IDIxLjE4NSA5LjY0OCAxOC42ODZsLjk3MS0uNDc0LTIuMjcxLTQuMzgzLTEuMDI2LjVjLTMuMTYzIDEuNTQ3LTguMjYyLTguMjE5LTUuMDU1LTkuOTM4bDEuMDA3LS40OTctMi4yNTEtNC4zOTh6Ii8+PC9zdmc+" class="icon"> <img alt="Phone" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNNi4xNzYgMS4zMjJsMi44NDQtMS4zMjIgNC4wNDEgNy44OS0yLjcyNCAxLjM0MWMtLjUzOCAxLjI1OSAyLjE1OSA2LjI4OSAzLjI5NyA2LjM3Mi4wOS0uMDU4IDIuNjcxLTEuMzI4IDIuNjcxLTEuMzI4bDQuMTEgNy45MzJzLTIuNzY0IDEuMzU0LTIuODU0IDEuMzk2Yy03Ljg2MiAzLjU5MS0xOS4xMDMtMTguMjU4LTExLjM4NS0yMi4yODF6bTEuOTI5IDEuMjc0bC0xLjAyMy41MDRjLTUuMjk0IDIuNzYyIDQuMTc3IDIxLjE4NSA5LjY0OCAxOC42ODZsLjk3MS0uNDc0LTIuMjcxLTQuMzgzLTEuMDI2LjVjLTMuMTYzIDEuNTQ3LTguMjYyLTguMjE5LTUuMDU1LTkuOTM4bDEuMDA3LS40OTctMi4yNTEtNC4zOTh6Ii8+PC9zdmc+" class="icon">
+{{cv.person.phone | insert_space_every(times=3)}} +{{cv.person.phone | insert_space_every(times=3)}}
</i> </i>
<i class="fa-web web">
{% if cv.person.web %}
{{cv.person.web}}
{% endif %}
</i>
<div class="about-me-title">{{ "about-me" | translate(lang=lang) }}</div> <div class="about-me-title">{{ "about-me" | translate(lang=lang) }}</div>
<div class="about-me">{{ cv.person.about | lang_entity(lang=lang) }}</div> <div class="about-me">{{ cv.person.about | lang_entity(lang=lang) }}</div>
</div> </div>