unfix nonexistent deadlock and improve error reporting
This commit is contained in:
parent
8f58c573ab
commit
e5cc685b0a
3 changed files with 35 additions and 51 deletions
|
@ -7,11 +7,11 @@ use tracing::error;
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
#[allow(clippy::enum_variant_names)]
|
#[allow(clippy::enum_variant_names)]
|
||||||
pub enum PostError {
|
pub enum PostError {
|
||||||
#[error(transparent)]
|
#[error("io error: {0}")]
|
||||||
IoError(#[from] std::io::Error),
|
IoError(#[from] std::io::Error),
|
||||||
#[error("{0}")]
|
#[error("failed to parse post metadata: {0}")]
|
||||||
ParseError(String),
|
ParseError(String),
|
||||||
#[error("{0}")]
|
#[error("failed to render post: {0}")]
|
||||||
RenderError(String),
|
RenderError(String),
|
||||||
#[error("post {0:?} not found")]
|
#[error("post {0:?} not found")]
|
||||||
NotFound(String),
|
NotFound(String),
|
||||||
|
|
|
@ -14,7 +14,6 @@ mod templates;
|
||||||
|
|
||||||
use std::future::IntoFuture;
|
use std::future::IntoFuture;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
@ -114,7 +113,7 @@ async fn main() -> eyre::Result<()> {
|
||||||
}
|
}
|
||||||
Engine::Blag => Arc::new(Blag::new(
|
Engine::Blag => Arc::new(Blag::new(
|
||||||
config.dirs.posts.clone().into(),
|
config.dirs.posts.clone().into(),
|
||||||
Some(PathBuf::from("blag").into()),
|
config.blag.bin.clone().into(),
|
||||||
)),
|
)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
use std::future::Future;
|
use std::path::Path;
|
||||||
use std::mem;
|
use std::process::Stdio;
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
use std::pin::Pin;
|
|
||||||
use std::process::{ExitStatus, Stdio};
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use axum::async_trait;
|
use axum::async_trait;
|
||||||
|
@ -25,11 +22,8 @@ pub struct Blag {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Blag {
|
impl Blag {
|
||||||
pub fn new(root: Arc<Path>, blag_bin: Option<Arc<Path>>) -> Blag {
|
pub fn new(root: Arc<Path>, blag_bin: Arc<Path>) -> Blag {
|
||||||
Self {
|
Self { root, blag_bin }
|
||||||
root,
|
|
||||||
blag_bin: blag_bin.unwrap_or_else(|| PathBuf::from("blag").into()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,10 +37,24 @@ impl PostManager for Blag {
|
||||||
let mut meow = Vec::new();
|
let mut meow = Vec::new();
|
||||||
let mut files = tokio::fs::read_dir(&self.root).await?;
|
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?;
|
let file_type = entry.file_type().await?;
|
||||||
if file_type.is_file() {
|
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") {
|
if name.ends_with(".sh") {
|
||||||
set.push(async move { self.get_post(name.trim_end_matches(".sh")).await });
|
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)
|
let mut cmd = tokio::process::Command::new(&*self.blag_bin)
|
||||||
.arg(path)
|
.arg(path)
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
.spawn()?;
|
.spawn()
|
||||||
|
.map_err(|err| {
|
||||||
|
error!("failed to spawn {:?}: {err}", self.blag_bin);
|
||||||
|
err
|
||||||
|
})?;
|
||||||
|
|
||||||
let stdout = cmd.stdout.take().unwrap();
|
let stdout = cmd.stdout.take().unwrap();
|
||||||
|
|
||||||
|
@ -125,44 +137,17 @@ impl PostManager for Blag {
|
||||||
|
|
||||||
let mut meta: PostMetadata = serde_json::from_str(&buf)?;
|
let mut meta: PostMetadata = serde_json::from_str(&buf)?;
|
||||||
meta.name = name.to_string();
|
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();
|
buf.clear();
|
||||||
let mut fut_buf = mem::take(&mut buf);
|
reader.read_to_string(&mut buf).await?;
|
||||||
|
|
||||||
futures.push(Box::pin(async move {
|
debug!("read output: {} bytes", buf.len());
|
||||||
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) }));
|
|
||||||
|
|
||||||
while let Some(res) = futures.next().await {
|
let exit_status = cmd.wait().await?;
|
||||||
match res? {
|
debug!("exited: {exit_status}");
|
||||||
Return::Read(fut_buf) => {
|
if !exit_status.success() {
|
||||||
buf = fut_buf;
|
return Err(PostError::RenderError(exit_status.to_string()));
|
||||||
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()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
drop(futures);
|
|
||||||
|
|
||||||
let elapsed = start.elapsed();
|
let elapsed = start.elapsed();
|
||||||
|
|
||||||
Ok(ReturnedPost::Rendered(
|
Ok(ReturnedPost::Rendered(
|
||||||
|
|
Loading…
Reference in a new issue