unfix nonexistent deadlock and improve error reporting

This commit is contained in:
slonkazoid 2024-12-16 02:56:43 +03:00
parent 8f58c573ab
commit e5cc685b0a
Signed by: slonk
SSH key fingerprint: SHA256:tbZfJX4IOvZ0LGWOWu5Ijo8jfMPi78TU7x1VoEeCIjM
3 changed files with 35 additions and 51 deletions

View file

@ -7,11 +7,11 @@ use tracing::error;
#[derive(Error, Debug)]
#[allow(clippy::enum_variant_names)]
pub enum PostError {
#[error(transparent)]
#[error("io error: {0}")]
IoError(#[from] std::io::Error),
#[error("{0}")]
#[error("failed to parse post metadata: {0}")]
ParseError(String),
#[error("{0}")]
#[error("failed to render post: {0}")]
RenderError(String),
#[error("post {0:?} not found")]
NotFound(String),

View file

@ -14,7 +14,6 @@ mod templates;
use std::future::IntoFuture;
use std::net::SocketAddr;
use std::path::PathBuf;
use std::process::exit;
use std::sync::Arc;
use std::time::Duration;
@ -114,7 +113,7 @@ async fn main() -> eyre::Result<()> {
}
Engine::Blag => Arc::new(Blag::new(
config.dirs.posts.clone().into(),
Some(PathBuf::from("blag").into()),
config.blag.bin.clone().into(),
)),
};

View file

@ -1,8 +1,5 @@
use std::future::Future;
use std::mem;
use std::path::{Path, PathBuf};
use std::pin::Pin;
use std::process::{ExitStatus, Stdio};
use std::path::Path;
use std::process::Stdio;
use std::sync::Arc;
use axum::async_trait;
@ -25,11 +22,8 @@ pub struct Blag {
}
impl Blag {
pub fn new(root: Arc<Path>, blag_bin: Option<Arc<Path>>) -> Blag {
Self {
root,
blag_bin: blag_bin.unwrap_or_else(|| PathBuf::from("blag").into()),
}
pub fn new(root: Arc<Path>, blag_bin: Arc<Path>) -> Blag {
Self { root, blag_bin }
}
}
@ -43,10 +37,24 @@ impl PostManager for Blag {
let mut meow = Vec::new();
let mut files = tokio::fs::read_dir(&self.root).await?;
while let Ok(Some(entry)) = files.next_entry().await {
loop {
let entry = match files.next_entry().await {
Ok(Some(v)) => v,
Ok(None) => break,
Err(err) => {
error!("error while getting next entry: {err}");
continue;
}
};
let file_type = entry.file_type().await?;
if file_type.is_file() {
let name = entry.file_name().into_string().unwrap();
let name = match entry.file_name().into_string() {
Ok(v) => v,
Err(_) => {
continue;
}
};
if name.ends_with(".sh") {
set.push(async move { self.get_post(name.trim_end_matches(".sh")).await });
@ -115,7 +123,11 @@ impl PostManager for Blag {
let mut cmd = tokio::process::Command::new(&*self.blag_bin)
.arg(path)
.stdout(Stdio::piped())
.spawn()?;
.spawn()
.map_err(|err| {
error!("failed to spawn {:?}: {err}", self.blag_bin);
err
})?;
let stdout = cmd.stdout.take().unwrap();
@ -125,44 +137,17 @@ impl PostManager for Blag {
let mut meta: PostMetadata = serde_json::from_str(&buf)?;
meta.name = name.to_string();
enum Return {
Read(String),
Exit(ExitStatus),
}
let mut futures: FuturesUnordered<
Pin<Box<dyn Future<Output = Result<Return, std::io::Error>> + Send>>,
> = FuturesUnordered::new();
buf.clear();
let mut fut_buf = mem::take(&mut buf);
reader.read_to_string(&mut buf).await?;
futures.push(Box::pin(async move {
reader
.read_to_string(&mut fut_buf)
.await
.map(|_| Return::Read(fut_buf))
}));
futures.push(Box::pin(async move { cmd.wait().await.map(Return::Exit) }));
debug!("read output: {} bytes", buf.len());
while let Some(res) = futures.next().await {
match res? {
Return::Read(fut_buf) => {
buf = fut_buf;
debug!("read output: {} bytes", buf.len());
}
Return::Exit(exit_status) => {
debug!("exited: {exit_status}");
if !exit_status.success() {
return Err(PostError::RenderError(exit_status.to_string()));
}
}
}
let exit_status = cmd.wait().await?;
debug!("exited: {exit_status}");
if !exit_status.success() {
return Err(PostError::RenderError(exit_status.to_string()));
}
drop(futures);
let elapsed = start.elapsed();
Ok(ReturnedPost::Rendered(