Skip to content

Commit 131b963

Browse files
authored
fix: bind InternalRPC and heartbeat tasks to the provided runtime (#454)
* bind InternalRPC and heartbeat tasks to the runtime provided to connect_with_runtime * rustfmt * Bump async-rs
1 parent 4f0deb6 commit 131b963

3 files changed

Lines changed: 73 additions & 3 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ version = "^10.0.1"
5656
default-features = false
5757

5858
[dependencies.async-rs]
59-
version = "^0.8.1"
59+
version = "^0.8.2"
6060
default-features = false
6161

6262
[dependencies.backon]
@@ -106,6 +106,10 @@ required-features = ["smol"]
106106
name = "tokio"
107107
required-features = ["tokio"]
108108

109+
[[test]]
110+
name = "runtime_isolation"
111+
required-features = ["tokio"]
112+
109113
[[test]]
110114
name = "smol"
111115
required-features = ["smol"]

tests/runtime_isolation.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
use async_rs::Runtime;
2+
use lapin::{
3+
BasicProperties, Confirmation, Connection, ConnectionProperties, options::*, types::FieldTable,
4+
};
5+
6+
/// Connections created via `connect_with_runtime` must outlive the runtime they
7+
/// were called from: `InternalRPC::run` must be bound to the supplied runtime,
8+
/// not the caller's ambient runtime.
9+
#[test]
10+
fn connection_survives_caller_runtime_shutdown() {
11+
let _ = tracing_subscriber::fmt::try_init();
12+
13+
let addr = std::env::var("AMQP_ADDR").unwrap_or_else(|_| "amqp://127.0.0.1:5672/%2f".into());
14+
15+
let static_rt = tokio::runtime::Runtime::new().unwrap();
16+
let lapin_runtime = Runtime::tokio_with_handle(static_rt.handle().clone());
17+
18+
let caller_rt = tokio::runtime::Runtime::new().unwrap();
19+
let connection = caller_rt.block_on(async {
20+
Connection::connect_with_runtime(&addr, ConnectionProperties::default(), lapin_runtime)
21+
.await
22+
.expect("connection error")
23+
});
24+
25+
// Drop the caller runtime — kills any tasks mistakenly spawned on it.
26+
drop(caller_rt);
27+
28+
static_rt.block_on(async {
29+
let channel = connection
30+
.create_channel()
31+
.await
32+
.expect("create_channel after caller runtime shutdown");
33+
34+
channel
35+
.confirm_select(ConfirmSelectOptions::default())
36+
.await
37+
.expect("confirm_select");
38+
39+
channel
40+
.queue_declare(
41+
"runtime-isolation-test".into(),
42+
QueueDeclareOptions {
43+
auto_delete: true,
44+
..Default::default()
45+
},
46+
FieldTable::default(),
47+
)
48+
.await
49+
.expect("queue_declare");
50+
51+
let confirm = channel
52+
.basic_publish(
53+
"".into(),
54+
"runtime-isolation-test".into(),
55+
BasicPublishOptions::default(),
56+
b"hello",
57+
BasicProperties::default(),
58+
)
59+
.await
60+
.expect("basic_publish")
61+
.await
62+
.expect("publisher confirm");
63+
64+
assert_eq!(confirm, Confirmation::Ack(None));
65+
});
66+
}

0 commit comments

Comments
 (0)