Skip to content

Commit 369a2f1

Browse files
Rust: Make api method future implement Send/Sync
The `Request::execute` method captures a `url::form_urlencoded::Serializer` in the generator, which causes the overall future to be !Send/!Sync To avoid capturing this, I've explicitly introduced a new scope (just using `drop` doesn't work). I've also added a test to make sure that this doesn't regress.
1 parent 974d40a commit 369a2f1

File tree

2 files changed

+29
-10
lines changed

2 files changed

+29
-10
lines changed

rust/src/api.rs

+15
Original file line numberDiff line numberDiff line change
@@ -1284,3 +1284,18 @@ impl<'a> Statistics<'a> {
12841284
statistics_api::v1_statistics_aggregate_event_types(self.cfg).await
12851285
}
12861286
}
1287+
1288+
#[cfg(test)]
1289+
mod tests {
1290+
use crate::api::Svix;
1291+
1292+
#[test]
1293+
fn test_future_send_sync() {
1294+
fn require_send_sync<T: Send + Sync>(_: T) {}
1295+
1296+
let svix = Svix::new(String::new(), None);
1297+
let message_api = svix.message();
1298+
let fut = message_api.expunge_content(String::new(), String::new());
1299+
require_send_sync(fut);
1300+
}
1301+
}

rust/src/request.rs

+14-10
Original file line numberDiff line numberDiff line change
@@ -85,24 +85,28 @@ impl Request {
8585
}
8686

8787
pub async fn execute<T: DeserializeOwned>(self, conf: &Configuration) -> Result<T, Error> {
88-
let mut query_string = ::url::form_urlencoded::Serializer::new("".to_owned());
89-
9088
let mut path = self.path;
9189
for (k, v) in self.path_params {
9290
// replace {id} with the value of the id path param
9391
path = path.replace(&format!("{{{k}}}"), &v);
9492
}
9593

96-
for (key, val) in self.query_params {
97-
query_string.append_pair(&key, &val);
98-
}
99-
10094
let mut uri = format!("{}{}", conf.base_path, path);
10195

102-
let query_string_str = query_string.finish();
103-
if !query_string_str.is_empty() {
104-
uri += "?";
105-
uri += &query_string_str;
96+
// Work around rustc issue - we need to make sure that `query_string` is not captured
97+
// by the outer `async` generator. Using `drop(query_string)` is insufficient, so we
98+
// create a new scope
99+
{
100+
let mut query_string = ::url::form_urlencoded::Serializer::new("".to_owned());
101+
for (key, val) in self.query_params {
102+
query_string.append_pair(&key, &val);
103+
}
104+
105+
let query_string_str = query_string.finish();
106+
if !query_string_str.is_empty() {
107+
uri += "?";
108+
uri += &query_string_str;
109+
}
106110
}
107111

108112
let mut req_builder = http1::Request::builder().uri(uri).method(self.method);

0 commit comments

Comments
 (0)