use std::pin::pin;
use std::sync::Arc;
use std::thread;
use std::time::Duration;
use futures::StreamExt;
use ruststream::{
Broker, ConnectedBroker, IncomingMessage, OutgoingMessage, Publisher, Subscriber,
};
use ruststream_amqp::{AmqpAddress, AmqpBroker, AmqpSubscriber, ConnectedAmqpBroker};
use tokio::runtime::Builder;
use tokio::sync::oneshot;
mod live;
const RECV_TIMEOUT: Duration = Duration::from_secs(10);
async fn subscribe_on_a_foreign_runtime(
connected: Arc<ConnectedAmqpBroker>,
address: String,
) -> AmqpSubscriber {
let (done, opened) = oneshot::channel();
thread::spawn(move || {
let runtime = Builder::new_current_thread()
.enable_all()
.build()
.expect("a current-thread runtime builds");
let subscriber = runtime.block_on(connected.subscribe_address(AmqpAddress::queue(address)));
drop(runtime);
let _ = done.send(subscriber);
});
opened
.await
.expect("the foreign runtime's thread finished")
.expect("the subscription opens")
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn a_subscription_opened_from_another_runtime_outlives_it() {
let Some(url) = live::url("AMQP_TEST_URL") else {
return;
};
let address = format!("it.runtime.subscribe.{}", std::process::id());
let connected = Arc::new(
AmqpBroker::new(url)
.container_id(format!("runtime-{}", std::process::id()))
.connect()
.await
.expect("broker connects"),
);
let mut subscriber =
subscribe_on_a_foreign_runtime(Arc::clone(&connected), address.clone()).await;
connected
.publisher()
.publish(OutgoingMessage::new(&address, b"one".as_slice()), None)
.await
.expect("publish succeeds");
{
let mut stream = pin!(subscriber.stream());
let delivery = tokio::time::timeout(RECV_TIMEOUT, stream.next())
.await
.expect("the delivery arrives")
.expect("the subscription is still open")
.expect("the delivery is ok");
assert_eq!(delivery.payload(), b"one");
delivery.ack().await.expect("ack succeeds");
}
drop(subscriber);
let connected = Arc::into_inner(connected).expect("the test holds the only handle");
connected.shutdown().await.expect("shutdown succeeds");
}