better io errors

This commit is contained in:
Robin Appelman 2024-08-29 16:50:05 +02:00
commit 542d61d55c
2 changed files with 45 additions and 10 deletions

View file

@ -3,12 +3,20 @@ use async_tempfile::TempFile;
use tokio::fs::read; use tokio::fs::read;
use tokio::io::AsyncWriteExt; use tokio::io::AsyncWriteExt;
use tokio::process::Command; use tokio::process::Command;
use tracing::instrument;
#[instrument(skip(data))]
pub async fn pack(map: &str, data: &[u8]) -> Result<Vec<u8>> { pub async fn pack(map: &str, data: &[u8]) -> Result<Vec<u8>> {
let mut input = TempFile::new_with_name(map.to_string()).await?; let mut input = TempFile::new_with_name(map.to_string()).await?;
let output = TempFile::new_with_name(format!("out_{map}")).await?; let output = TempFile::new_with_name(format!("out_{map}")).await?;
input.write_all(data).await?; input
.write_all(data)
.await
.map_err(|err| ServerError::File {
path: input.file_path().into(),
err,
})?;
let pack_cmd = option_env!("GLTFPACK").unwrap_or("gltfpack"); let pack_cmd = option_env!("GLTFPACK").unwrap_or("gltfpack");
@ -21,7 +29,13 @@ pub async fn pack(map: &str, data: &[u8]) -> Result<Vec<u8>> {
.arg("-o") .arg("-o")
.arg(output.file_path()) .arg(output.file_path())
.output() .output()
.await?; .await
.map_err(|err| ServerError::Pack {
err,
input: input.file_path().into(),
output: output.file_path().into(),
binary: pack_cmd.into(),
})?;
if !out.status.success() { if !out.status.success() {
return Err(ServerError::GltfPack( return Err(ServerError::GltfPack(
@ -29,5 +43,10 @@ pub async fn pack(map: &str, data: &[u8]) -> Result<Vec<u8>> {
)); ));
} }
Ok(read(output.file_path()).await?) read(output.file_path())
.await
.map_err(|err| ServerError::File {
path: output.file_path().into(),
err,
})
} }

View file

@ -51,6 +51,15 @@ pub enum ServerError {
Toml(#[from] toml::de::Error), Toml(#[from] toml::de::Error),
#[error(transparent)] #[error(transparent)]
Io(#[from] std::io::Error), Io(#[from] std::io::Error),
#[error("IO error {err:#} on {}", path.display())]
File { err: std::io::Error, path: PathBuf },
#[error("Error {err:#} while packing {} to {} with {}", input.display(), output.display(), binary)]
Pack {
err: std::io::Error,
input: PathBuf,
output: PathBuf,
binary: String,
},
#[error(transparent)] #[error(transparent)]
Loader(#[from] LoaderError), Loader(#[from] LoaderError),
#[error(transparent)] #[error(transparent)]
@ -111,7 +120,10 @@ fn setup() -> Result<Config> {
.init(); .init();
let args = Args::parse(); let args = Args::parse();
let toml = read_to_string(&args.config)?; let toml = read_to_string(&args.config).map_err(|err| ServerError::File {
path: args.config.into(),
err,
})?;
Ok(from_str(&toml)?) Ok(from_str(&toml)?)
} }
@ -137,10 +149,8 @@ async fn main() -> Result<()> {
.with_state(Arc::new(app)); .with_state(Arc::new(app));
// Run our app with hyper // Run our app with hyper
let listener = TcpListener::bind((Ipv4Addr::LOCALHOST, config.port)) let listener = TcpListener::bind((Ipv4Addr::LOCALHOST, config.port)).await?;
.await info!("listening on {}", listener.local_addr()?);
.unwrap();
tracing::info!("listening on {}", listener.local_addr()?);
let serve = async { let serve = async {
if let Err(e) = axum::serve(listener, app).await { if let Err(e) = axum::serve(listener, app).await {
eprintln!("{e:#?}"); eprintln!("{e:#?}");
@ -170,7 +180,10 @@ impl App {
fn cached(&self, map: &str, options_key: u64) -> Result<Option<Vec<u8>>> { fn cached(&self, map: &str, options_key: u64) -> Result<Option<Vec<u8>>> {
let path = self.cache_path(map, options_key); let path = self.cache_path(map, options_key);
if path.exists() { if path.exists() {
Ok(Some(read(path)?)) Ok(Some(read(&path).map_err(|err| ServerError::File {
path: path.clone(),
err,
})?))
} else { } else {
Ok(None) Ok(None)
} }
@ -178,7 +191,10 @@ impl App {
fn cache(&self, map: &str, data: &[u8], options_key: u64) -> Result<()> { fn cache(&self, map: &str, data: &[u8], options_key: u64) -> Result<()> {
let path = self.cache_path(map, options_key); let path = self.cache_path(map, options_key);
Ok(write(path, data)?) Ok(write(&path, data).map_err(|err| ServerError::File {
path: path.clone(),
err,
})?)
} }
async fn download(&self, map: &str) -> Result<Vec<u8>> { async fn download(&self, map: &str) -> Result<Vec<u8>> {