Skip to main content

AsyncCommandHandler

Trait AsyncCommandHandler 

Source
pub trait AsyncCommandHandler: Send + Sync {
    // Required method
    fn execute<'life0, 'life1, 'life2, 'async_trait>(
        &'life0 self,
        context: &'life1 mut dyn ExecutionContext,
        args: &'life2 HashMap<String, String>,
    ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait;

    // Provided method
    fn validate<'life0, 'life1, 'async_trait>(
        &'life0 self,
        _args: &'life1 HashMap<String, String>,
    ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait { ... }
}
Expand description

Async counterpart of CommandHandler.

Additive to CommandHandler (see DD-022) — it does not replace it. Implementations use this trait when their command body needs to perform async I/O (network calls, streaming, etc.). The signatures deliberately mirror CommandHandler exactly, execute/validate aside from the async keyword, so that migrating a handler from sync to async is a mechanical change.

§Object Safety

Made dyn-compatible via #[async_trait] (which desugars async fn to a boxed, pinned future under the hood). Stored as Box<dyn AsyncCommandHandler> in the registry, exactly like CommandHandler is stored as Box<dyn CommandHandler>.

§Thread Safety

Same constraint as CommandHandler: Send + Sync is required so the handler can be shared across the registry and, transitively, across threads if the application needs it.

§Why a separate trait instead of an async CommandHandler?

Existing sync CommandHandler implementations (including downstream consumers) must keep compiling unchanged. See DD-022 for the full rationale, including why tokio is not a dependency of dynamic-cli itself and why driving the returned future via futures::executor::block_on at the dispatch site is safe.

§Example

use std::collections::HashMap;
use async_trait::async_trait;
use dynamic_cli::executor::AsyncCommandHandler;
use dynamic_cli::context::ExecutionContext;
use dynamic_cli::error::ExecutionError;
use dynamic_cli::Result;

struct FetchCommand;

#[async_trait]
impl AsyncCommandHandler for FetchCommand {
    async fn execute(
        &self,
        _context: &mut dyn ExecutionContext,
        args: &HashMap<String, String>,
    ) -> Result<()> {
        let url = args.get("url").ok_or_else(|| {
            ExecutionError::CommandFailed(anyhow::anyhow!("Missing 'url' argument"))
        })?;
        // Real implementations would `.await` an async HTTP call here.
        println!("Fetching {url}...");
        Ok(())
    }

    async fn validate(&self, args: &HashMap<String, String>) -> Result<()> {
        if !args.contains_key("url") {
            return Err(ExecutionError::CommandFailed(anyhow::anyhow!("url is required")).into());
        }
        Ok(())
    }
}

Required Methods§

Source

fn execute<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, context: &'life1 mut dyn ExecutionContext, args: &'life2 HashMap<String, String>, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Async equivalent of CommandHandler::execute. Same contract: receives the mutable execution context and the parsed arguments, returns Ok(()) on success or a DynamicCliError on failure.

Provided Methods§

Source

fn validate<'life0, 'life1, 'async_trait>( &'life0 self, _args: &'life1 HashMap<String, String>, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Async equivalent of CommandHandler::validate. Same contract and same default (accepts all arguments) — override only for custom validation logic.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§