Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Principle:Fede1024 Rust rdkafka Custom Async Runtime Integration

From Leeroopedia


Knowledge Sources
Domains Async_Runtime, Runtime_Abstraction, Design_Pattern
Last Updated 2026-02-07 19:00 GMT

Overview

Principle of decoupling a library from a specific async runtime by defining a minimal trait interface (AsyncRuntime) that users implement to integrate with their chosen executor (Tokio, async-std, smol, etc.).

Description

Rust's async ecosystem is fragmented across multiple runtimes (Tokio, async-std, smol, etc.), each with incompatible spawn and timer APIs. The Custom Async Runtime Integration principle solves this by defining a trait with two core capabilities: spawn (launch a background task) and delay_for (create a sleep future). Library internals use only this trait, never calling runtime-specific APIs directly. Users provide a struct implementing the trait, which the library uses as a generic parameter. This enables the library to work with any async runtime without direct dependencies.

Usage

Apply this principle when building an async library that should not force users into a specific runtime. The pattern requires: (1) defining a trait with associated types for runtime-specific futures, (2) parameterizing library types with the runtime trait as a generic, (3) providing a default implementation for the most common runtime (Tokio), and (4) documenting how to implement the trait for alternative runtimes.

Theoretical Basis

The runtime abstraction follows the strategy pattern applied to async executors:

Trait Interface:

// Abstract runtime contract
pub trait AsyncRuntime: Send + Sync + 'static {
    type Delay: Future<Output = ()> + Send;

    fn spawn<T: Future<Output = ()> + Send + 'static>(task: T);
    fn delay_for(duration: Duration) -> Self::Delay;
}

Design Decisions:

  • Associated type for Delay: Allows zero-allocation implementations (smol) while supporting boxed futures (async-std)
  • Static dispatch: Generic parameter R: AsyncRuntime enables monomorphization, avoiding virtual dispatch overhead
  • Minimal surface: Only spawn and delay_for are required; most async operations build on these primitives
  • Send bounds: Ensures compatibility with multi-threaded executors

Implementation Patterns:

// Pattern 1: Boxed future (async-std)
type Delay = Pin<Box<dyn Future<Output = ()> + Send>>;
fn delay_for(d: Duration) -> Self::Delay { Box::pin(async_std::task::sleep(d)) }

// Pattern 2: Concrete type (smol) - zero allocation
type Delay = future::Map<smol::Timer, fn(Instant)>;
fn delay_for(d: Duration) -> Self::Delay { Timer::after(d).map(|_| ()) }

// Pattern 3: Default (Tokio)
type Delay = tokio::time::Sleep;
fn delay_for(d: Duration) -> Self::Delay { tokio::time::sleep(d) }

Related Pages

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment