use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll, ready};
use tokio::sync::oneshot;
pub struct PublishFuture {
pub(crate) rx: oneshot::Receiver<std::result::Result<String, crate::error::PublishError>>,
}
impl Future for PublishFuture {
type Output = std::result::Result<String, Arc<crate::Error>>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let result = ready!(Pin::new(&mut self.rx).poll(cx));
match result {
Ok(result) => Poll::Ready(result.map_err(convert_error)),
Err(_) => Poll::Ready(Err(Arc::new(google_cloud_gax::error::Error::io(
"publisher is shutdown",
)))),
}
}
}
fn convert_error(e: crate::error::PublishError) -> Arc<crate::Error> {
match e {
crate::error::PublishError::SendError(s) => s,
crate::error::PublishError::OrderingKeyPaused(e) => Arc::new(crate::Error::io(
crate::error::PublishError::OrderingKeyPaused(e),
)),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn resolve_publish_future_success() -> anyhow::Result<()> {
let (tx, rx) = oneshot::channel();
let handle = PublishFuture { rx };
let _ = tx.send(Ok("message_id".to_string()));
assert_eq!(handle.await?, "message_id");
Ok(())
}
#[tokio::test]
async fn resolve_publish_future_error() -> anyhow::Result<()> {
use std::error::Error as _;
let (tx, rx) = oneshot::channel();
let fut = PublishFuture { rx };
let _ = tx.send(Err(crate::error::PublishError::OrderingKeyPaused(())));
let err = fut
.await
.expect_err("errors on channel should resolve to error");
let err = err
.source()
.unwrap()
.downcast_ref::<crate::error::PublishError>()
.unwrap();
match err {
crate::error::PublishError::OrderingKeyPaused(_) => {}
_ => panic!("expected OrderingKeyPaused error"),
}
Ok(())
}
#[tokio::test]
async fn resolve_publish_future_error_send_error() -> anyhow::Result<()> {
let (tx, rx) = oneshot::channel();
let fut = PublishFuture { rx };
drop(tx);
let err = fut
.await
.expect_err("dropped channel should resolve to error");
assert!(err.to_string().contains("shutdown"));
Ok(())
}
}