Assume the following pseudo-Rust pseudocode implementation of handle, which streams contents of a file represented by some descriptor fd using read-via-stream in response to an incoming request
async fn handle(req: Request) -> Result<Response, ErrorCode> {
let (fd_data, fd_result) = fd.read_via_stream(0).await?;
let (body, tx_result) = Body::new(fd_data, None);
spawn({
if fd_result.await.is_err() {
// where to report result?
}
});
return Ok(Response::new(headers.new(), Some(body)));
}
An I/O error might have occurred reading from fd after handle has returned, however there is no way for the application to report that error to the caller other that somehow use the "application layer", i.e. HTTP body or trailers, to communicate it.
Refs #163
Potential solutions we've discussed with @lukewagner and @dicej look like:
// option 1
async fn handle(req: Request) -> Result<(Response, Future<Result<(), ErrorCode>>), ErrorCode> {
let (fd_data, fd_result) = fd.read_via_stream(0).await?;
let (body, tx_result) = Body::new(fd_data, None);
let (res_tx, res_rx) = future::new();
spawn({
if let Err(err) = fd_result.await {
res_tx.send(Err(err.into()));
} else {
res_tx.send(Ok(()));
}
});
return Ok((Response::new(headers.new(), Some(body)), res_rx));
}
// option 2
async fn handle(req: Request) -> Result<Response, ErrorCode> {
let (fd_data, fd_result) = fd.read_via_stream(0).await?;
let (res_tx, res_rx) = future::new();
let (body, tx_result) = Body::new(fd_data, None, res_rx);
spawn({
if let Err(err) = fd_result.await {
res_tx.send(Err(err.into()));
} else {
res_tx.send(tx_result.await);
}
});
return Ok(Response::new(headers.new(), Some(body)));
}