Skip to content

Commit 78129b8

Browse files
Sujay JayakarConvex, Inc.
authored andcommitted
Use tokio's oneshot everywhere (#30516)
Switch our oneshots from `futures` to `tokio` so they're coop budget aware -- if a Tokio task has exhausted its coop budget, `oneshot::Receivers` will preempt the task if awaited. This does require that our futures are all executed within the Tokio runtime, however. GitOrigin-RevId: da8f8017fd0f07f8e50332682c43ce514ba8c3d4
1 parent 2839c16 commit 78129b8

File tree

27 files changed

+108
-98
lines changed

27 files changed

+108
-98
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,3 +193,11 @@ codegen-units = 16
193193
[profile.dev.package.num-bigint-dig]
194194
opt-level = 3
195195
codegen-units = 16
196+
197+
[profile.dev.package.tokio]
198+
opt-level = 3
199+
codegen-units = 16
200+
201+
[profile.dev.package.tokio-stream]
202+
opt-level = 3
203+
codegen-units = 16

crates/application/src/function_log.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ use common::{
5252
},
5353
};
5454
use float_next_after::NextAfter;
55-
use futures::channel::oneshot;
5655
use http::{
5756
Method,
5857
StatusCode,
@@ -74,6 +73,7 @@ use serde_json::{
7473
json,
7574
Value as JsonValue,
7675
};
76+
use tokio::sync::oneshot;
7777
use url::Url;
7878
use usage_tracking::{
7979
AggregatedFunctionUsageStats,

crates/application/src/lib.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,7 @@ use function_log::{
135135
FunctionExecutionPart,
136136
};
137137
use function_runner::FunctionRunner;
138-
use futures::{
139-
channel::oneshot,
140-
stream::BoxStream,
141-
};
138+
use futures::stream::BoxStream;
142139
use headers::{
143140
ContentLength,
144141
ContentType,
@@ -283,6 +280,7 @@ use table_summary_worker::{
283280
TableSummaryClient,
284281
TableSummaryWorker,
285282
};
283+
use tokio::sync::oneshot;
286284
use usage_tracking::{
287285
FunctionUsageStats,
288286
FunctionUsageTracker,

crates/application/src/table_summary_worker.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ use database::{
2222
TableSummaryWriter,
2323
};
2424
use futures::{
25-
channel::oneshot,
2625
pin_mut,
2726
select_biased,
2827
FutureExt,
2928
};
3029
use parking_lot::Mutex;
30+
use tokio::sync::oneshot;
3131

3232
use crate::metrics::log_worker_starting;
3333

crates/common/src/bounded_thread_pool.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
use std::sync::Arc;
22

33
use futures::{
4-
channel::{
5-
mpsc,
6-
oneshot,
7-
},
4+
channel::mpsc,
85
future::{
96
self,
107
BoxFuture,
@@ -17,6 +14,7 @@ use futures::{
1714
StreamExt,
1815
};
1916
use parking_lot::Mutex;
17+
use tokio::sync::oneshot;
2018

2119
use crate::{
2220
codel_queue::{

crates/common/src/runtime/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ use std::{
2020
use anyhow::Context;
2121
use async_trait::async_trait;
2222
use futures::{
23-
channel::oneshot,
2423
future::{
2524
BoxFuture,
2625
FusedFuture,
@@ -52,6 +51,7 @@ use proptest::prelude::*;
5251
use rand::RngCore;
5352
use serde::Serialize;
5453
use thiserror::Error;
54+
use tokio::sync::oneshot;
5555
use uuid::Uuid;
5656
use value::heap_size::HeapSize;
5757

@@ -203,6 +203,7 @@ pub trait Runtime: Clone + Sync + Send + 'static {
203203
/// Spawn a future on a reserved OS thread. This is only really necessary
204204
/// for libraries like `V8` that care about being called from a
205205
/// particular thread.
206+
#[must_use = "Threads are canceled when their `SpawnHandle` is dropped."]
206207
fn spawn_thread<Fut: Future<Output = ()>, F: FnOnce() -> Fut + Send + 'static>(
207208
&self,
208209
f: F,

crates/common/src/runtime/testing/mod.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use std::{
1818
};
1919

2020
use futures::{
21-
channel::oneshot,
2221
future::{
2322
self,
2423
BoxFuture,
@@ -34,10 +33,13 @@ use rand::{
3433
SeedableRng,
3534
};
3635
use rand_chacha::ChaCha12Rng;
37-
use tokio::runtime::{
38-
Builder,
39-
RngSeed,
40-
UnhandledPanic,
36+
use tokio::{
37+
runtime::{
38+
Builder,
39+
RngSeed,
40+
UnhandledPanic,
41+
},
42+
sync::oneshot,
4143
};
4244

4345
use super::{

crates/common/src/sync/mod.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
pub mod split_rw_lock;
22
pub mod state_channel;
33

4-
// It's safe to use these `tokio` sync primitives in our runtime-generic code
5-
// since they don't internally depend on the `tokio` runtime. Feel free to add
6-
// more if you need them, but generally prefer using `futures`-based primitives
7-
// if sufficient.
4+
use futures::future;
5+
use tokio::sync::oneshot;
86
pub use tokio::sync::{
97
broadcast,
10-
// This channel is useful over `futures::channel::mpsc` since it doesn't require `&mut self` on
11-
// `try_send`. The `futures` implementation conforms to their `Sink` trait which unnecessarily
12-
// requires mutability.
138
mpsc,
149
watch,
1510
Mutex,
1611
MutexGuard,
1712
Notify,
1813
};
14+
15+
/// Wait until a sender's corresponding receiver has been closed.
16+
pub async fn oneshot_receiver_closed<T>(sender: &mut oneshot::Sender<T>) {
17+
future::poll_fn(|cx| sender.poll_closed(cx)).await
18+
}

crates/convex/examples/convex_chat_client.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ use convex::{
2121
Value,
2222
};
2323
use futures::{
24-
channel::oneshot,
2524
pin_mut,
2625
select_biased,
2726
FutureExt,
2827
StreamExt,
2928
};
3029
use maplit::btreemap;
30+
use tokio::sync::oneshot;
3131

3232
const SETUP_MSG: &str = r"
3333
Please run this Convex Chat client from an initialized Convex project.

crates/convex/src/client/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ use convex_sync_types::{
1212
#[cfg(doc)]
1313
use futures::Stream;
1414
use futures::{
15-
channel::{
16-
mpsc,
17-
oneshot,
18-
},
15+
channel::mpsc,
1916
SinkExt,
2017
StreamExt,
2118
};
2219
use tokio::{
23-
sync::broadcast,
20+
sync::{
21+
broadcast,
22+
oneshot,
23+
},
2424
task::JoinHandle,
2525
};
2626
use tokio_stream::wrappers::BroadcastStream;

crates/convex/src/client/worker.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ use convex_sync_types::{
1010
UdfPath,
1111
};
1212
use futures::{
13-
channel::{
14-
mpsc,
15-
oneshot,
16-
},
13+
channel::mpsc,
1714
select_biased,
1815
FutureExt,
1916
StreamExt,
2017
};
21-
use tokio::sync::broadcast;
18+
use tokio::sync::{
19+
broadcast,
20+
oneshot,
21+
};
2222
use tokio_stream::wrappers::BroadcastStream;
2323

2424
use crate::{

crates/convex/src/sync/web_socket_manager.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,15 @@ use convex_sync_types::{
1616
Timestamp,
1717
};
1818
use futures::{
19-
channel::{
20-
mpsc,
21-
oneshot,
22-
},
19+
channel::mpsc,
2320
select_biased,
2421
FutureExt,
2522
SinkExt,
2623
StreamExt,
2724
};
2825
use tokio::{
2926
net::TcpStream,
27+
sync::oneshot,
3028
task::JoinHandle,
3129
time::{
3230
Instant,

crates/database/src/committer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ use errors::{
7171
ErrorMetadataAnyhowExt,
7272
};
7373
use futures::{
74-
channel::oneshot,
7574
future::{
7675
BoxFuture,
7776
Either,
@@ -86,6 +85,7 @@ use indexing::index_registry::IndexRegistry;
8685
use minitrace::prelude::*;
8786
use parking_lot::Mutex;
8887
use prometheus::VMHistogram;
88+
use tokio::sync::oneshot;
8989
use usage_tracking::FunctionUsageTracker;
9090
use value::{
9191
heap_size::WithHeapSize,

crates/database/src/index_workers/search_flusher.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ impl<RT: Runtime, T: SearchIndex + 'static> SearchFlusher<RT, T> {
455455
let rate_limit_pages_per_second = job.build_reason.read_max_pages_per_second();
456456
let developer_config = job.index_config.developer_config.clone();
457457
let params = self.params.clone();
458-
self.runtime.spawn_thread(move || async move {
458+
let mut handle = self.runtime.spawn_thread(move || async move {
459459
let result = Self::build_multipart_segment_on_thread(
460460
params,
461461
rate_limit_pages_per_second,
@@ -469,8 +469,9 @@ impl<RT: Runtime, T: SearchIndex + 'static> SearchFlusher<RT, T> {
469469
build_index_args,
470470
)
471471
.await;
472-
_ = tx.send(result);
472+
let _ = tx.send(result);
473473
});
474+
handle.join().await?;
474475
rx.await?
475476
}
476477

@@ -612,10 +613,11 @@ impl<RT: Runtime, T: SearchIndex + 'static> SearchFlusher<RT, T> {
612613
let (tx, rx) = oneshot::channel();
613614
let rt = self.runtime.clone();
614615
let storage = self.storage.clone();
615-
self.runtime.spawn_thread(move || async move {
616+
let mut handle = self.runtime.spawn_thread(move || async move {
616617
let result = T::upload_new_segment(&rt, storage, new_segment).await;
617618
let _ = tx.send(result);
618619
});
620+
handle.join().await?;
619621
rx.await?
620622
}
621623
}

crates/database/src/subscription.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,7 @@ use common::{
3333
},
3434
};
3535
use futures::{
36-
channel::{
37-
mpsc,
38-
oneshot,
39-
},
36+
channel::mpsc,
4037
select_biased,
4138
FutureExt,
4239
StreamExt,
@@ -47,6 +44,7 @@ use parking_lot::Mutex;
4744
use prometheus::VMHistogram;
4845
use search::query::TextSearchSubscriptions;
4946
use slab::Slab;
47+
use tokio::sync::oneshot;
5048

5149
use crate::{
5250
metrics,

crates/database/src/write_log.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,9 @@ use errors::{
2828
ErrorMetadata,
2929
ErrorMetadataAnyhowExt,
3030
};
31-
use futures::{
32-
channel::oneshot,
33-
Future,
34-
};
31+
use futures::Future;
3532
use parking_lot::RwLock;
33+
use tokio::sync::oneshot;
3634
use value::heap_size::{
3735
HeapSize,
3836
WithHeapSize,
@@ -156,7 +154,7 @@ impl WriteLog {
156154
// Notify waiters
157155
let mut i = 0;
158156
while i < self.waiters.len() {
159-
if ts > self.waiters[i].0 || self.waiters[i].1.is_canceled() {
157+
if ts > self.waiters[i].0 || self.waiters[i].1.is_closed() {
160158
// Remove from the waiters.
161159
let w = self.waiters.swap_remove_back(i).expect("checked above");
162160
// Notify. Ignore if receiver has dropped.

crates/function_runner/src/isolate_worker.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use common::pause::PauseClient;
77
use common::{
88
errors::report_error,
99
runtime::Runtime,
10+
sync::oneshot_receiver_closed,
1011
types::UdfType,
1112
};
1213
use futures::FutureExt;
@@ -108,7 +109,7 @@ impl<RT: Runtime> IsolateWorker<RT> for FunctionRunnerIsolateWorker<RT> {
108109
client_id,
109110
isolate,
110111
isolate_clean,
111-
response.cancellation().boxed(),
112+
oneshot_receiver_closed(&mut response).boxed(),
112113
)
113114
.await;
114115
let status = match &r {
@@ -158,7 +159,7 @@ impl<RT: Runtime> IsolateWorker<RT> for FunctionRunnerIsolateWorker<RT> {
158159
isolate,
159160
isolate_clean,
160161
request.params.clone(),
161-
response.cancellation().boxed(),
162+
oneshot_receiver_closed(&mut response).boxed(),
162163
)
163164
.await;
164165

@@ -211,7 +212,7 @@ impl<RT: Runtime> IsolateWorker<RT> for FunctionRunnerIsolateWorker<RT> {
211212
request.http_module_path,
212213
request.routed_path,
213214
request.http_request,
214-
response.cancellation().boxed(),
215+
oneshot_receiver_closed(&mut response).boxed(),
215216
)
216217
.await;
217218
let status = match &r {

0 commit comments

Comments
 (0)