Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Erase Work, Preserve Results

One MPSC channel has one item type, but submissions may return unrelated types:

Future<Output = Result<User, HttpError>>
Future<Output = Result<u64, DbError>>

The runner erases the wrapper’s output to ():

type ErasedJob = Pin<Box<dyn Future<Output = ()> + Send + 'static>>;

Inside submit, the typed future and typed sender are captured together:

let (result_tx, result_rx) = oneshot::channel();

let erased = Box::pin(async move {
    let result: Result<T, E> = job.await;
    let _ = result_tx.send(result);
});

work_sender.send(erased).await?;
return JobHandle { receiver: result_rx };

The queue sees only Future<Output = ()>. The type relationship between T, E, and that caller’s handle remains inside the captured sender/receiver pair. We erase what the shared collection must homogenize and preserve what the caller needs.

The bounds explain ownership:

  • 'static: queued work cannot borrow a caller stack frame that may disappear;
  • Send: Tokio may move the future, result, or error between worker threads;
  • no Sync is required merely to transfer exclusive ownership.