@@ -22,7 +22,7 @@ use datafusion::execution::memory_pool::{MemoryConsumer, MemoryReservation};
2222use datafusion:: physical_expr_common:: metrics:: { ExecutionPlanMetricsSet , MetricValue } ;
2323use datafusion:: physical_plan:: metrics:: { MetricBuilder , Time } ;
2424use futures:: stream:: BoxStream ;
25- use futures:: { Stream , StreamExt , TryFutureExt , TryStreamExt } ;
25+ use futures:: { FutureExt , Stream , StreamExt , TryFutureExt , TryStreamExt } ;
2626use http:: Extensions ;
2727use pin_project:: { pin_project, pinned_drop} ;
2828use prost:: Message ;
@@ -160,6 +160,7 @@ struct RemoteWorkerConnection {
160160 cancel_token : CancellationToken ,
161161 per_partition_rx : DashMap < usize , UnboundedReceiver < WorkerMsg > > ,
162162
163+ first_poll_notify : Arc < Notify > ,
163164 // Signals the demux task that buffered memory has been freed by a consumer.
164165 mem_available_notify : Arc < Notify > ,
165166
@@ -246,6 +247,9 @@ impl RemoteWorkerConnection {
246247 let mem_available_notify = Arc :: new ( Notify :: new ( ) ) ;
247248 let mem_available_notify_for_task = Arc :: clone ( & mem_available_notify) ;
248249
250+ let first_poll_notify = Arc :: new ( Notify :: new ( ) ) ;
251+ let first_poll_notify_for_task = Arc :: clone ( & first_poll_notify) ;
252+
249253 // Cancellation token allows us to stop the background task promptly when all partition
250254 // streams are dropped (e.g., when the query is cancelled).
251255 let cancel_token = CancellationToken :: new ( ) ;
@@ -255,6 +259,12 @@ impl RemoteWorkerConnection {
255259 // fan them out to the appropriate `per_partition_rx` based on the "partition" declared
256260 // in each individual record batch flight metadata.
257261 let task = SpawnedTask :: spawn ( async move {
262+ tokio:: select! {
263+ biased;
264+ _ = cancel. cancelled( ) => return ,
265+ _ = first_poll_notify_for_task. notified( ) => { }
266+ }
267+
258268 let mut client = match channel_resolver. get_worker_client_for_url ( & url) . await {
259269 Ok ( v) => v,
260270 Err ( err) => {
@@ -364,6 +374,7 @@ impl RemoteWorkerConnection {
364374 not_consumed_streams : Arc :: new ( AtomicUsize :: new ( per_partition_rx. len ( ) ) ) ,
365375 per_partition_rx,
366376 mem_available_notify,
377+ first_poll_notify,
367378
368379 // metrics stuff
369380 memory_reservation : memory_reservation_clone,
@@ -375,14 +386,17 @@ impl RemoteWorkerConnection {
375386impl WorkerConnection for RemoteWorkerConnection {
376387 /// Streams the provided `partition` from the remote worker.
377388 ///
378- /// Note that this does not issue a network request, the actual network request happened before
379- /// in the init step, and is in charge of handling not only this `partition`, but also all the
380- /// partitions passed in `target_partition_range`. This method just streams all the record
381- /// batches belonging to the provided `partition` from an in-memory queue, but what populates
382- /// this queue is [WorkerConnection::init].
389+ /// This method does not handle any network connection. Instead, the network comms are delegated
390+ /// to the task spawned by [WorkerConnection::init], who is in charge of polling data not only
391+ /// from the requested `partition`, but from any other partition in `target_partition_range`.
392+ /// This method just streams all the record batches belonging to the provided `partition` from
393+ /// an in-memory queue.
394+ ///
395+ /// The task that polls data over the network is held inactive until the first poll to the
396+ /// stream returned by this method.
383397 ///
384398 /// When the returned stream is dropped (e.g., due to query cancellation), the background task
385- /// pulling from the Flight stream will be cancelled promptly.
399+ /// pulling from the Flight stream will be canceled promptly.
386400 fn execute ( & self , partition : usize ) -> Result < BoxStream < ' static , Result < RecordBatch > > > {
387401 let Some ( ( _, partition_receiver) ) = self . per_partition_rx . remove ( & partition) else {
388402 return internal_err ! (
@@ -392,7 +406,13 @@ impl WorkerConnection for RemoteWorkerConnection {
392406 let task = Arc :: clone ( & self . task ) ;
393407 let cancel_token = self . cancel_token . clone ( ) ;
394408
395- let stream = UnboundedReceiverStream :: new ( partition_receiver) ;
409+ let first_poll_notify = Arc :: clone ( & self . first_poll_notify ) ;
410+ let stream = async move {
411+ first_poll_notify. notify_one ( ) ;
412+ UnboundedReceiverStream :: new ( partition_receiver)
413+ }
414+ . flatten_stream ( ) ;
415+
396416 let stream = stream. map_err ( |err| FlightError :: Tonic ( Box :: new ( err) ) ) ;
397417 let reservation = Arc :: clone ( & self . memory_reservation ) ;
398418 let mem_available_notify = Arc :: clone ( & self . mem_available_notify ) ;
0 commit comments