multiAI Summary Pending

async-patterns-guide

Guides users on modern async patterns including native async fn in traits, async closures, and avoiding async-trait when possible. Activates when users work with async code.

231 stars

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/async-patterns-guide/SKILL.md --create-dirs "https://raw.githubusercontent.com/aiskillstore/marketplace/main/skills/emillindfors/async-patterns-guide/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/async-patterns-guide/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How async-patterns-guide Compares

Feature / Agentasync-patterns-guideStandard Approach
Platform SupportmultiLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Guides users on modern async patterns including native async fn in traits, async closures, and avoiding async-trait when possible. Activates when users work with async code.

Which AI agents support this skill?

This skill is compatible with multi.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Async Patterns Guide Skill

You are an expert at modern Rust async patterns. When you detect async code, proactively suggest modern patterns and help users avoid unnecessary dependencies.

## When to Activate

Activate when you notice:
- Use of async-trait crate
- Async functions in traits
- Async closures with manual construction
- Questions about async patterns or performance

## Key Decision: async-trait vs Native

### Use Native Async Fn (Rust 1.75+)

**When**:
- Static dispatch (generics)
- No dyn Trait needed
- Performance-critical code
- MSRV >= 1.75

**Pattern**:
```rust
// ✅ Modern: No macro needed (Rust 1.75+)
trait UserRepository {
    async fn find_user(&self, id: &str) -> Result<User, Error>;
    async fn save_user(&self, user: &User) -> Result<(), Error>;
}

impl UserRepository for PostgresRepo {
    async fn find_user(&self, id: &str) -> Result<User, Error> {
        self.db.query(id).await  // Native async, no macro!
    }

    async fn save_user(&self, user: &User) -> Result<(), Error> {
        self.db.insert(user).await
    }
}

// Use with generics (static dispatch)
async fn process<R: UserRepository>(repo: R) {
    let user = repo.find_user("123").await.unwrap();
}
```

### Use async-trait Crate

**When**:
- Dynamic dispatch (dyn Trait) required
- Need object safety
- MSRV < 1.75
- Plugin systems or trait objects

**Pattern**:
```rust
use async_trait::async_trait;

#[async_trait]
trait Plugin: Send + Sync {
    async fn execute(&self) -> Result<(), Error>;
}

// Dynamic dispatch requires async-trait
let plugins: Vec<Box<dyn Plugin>> = vec![
    Box::new(PluginA),
    Box::new(PluginB),
];

for plugin in plugins {
    plugin.execute().await?;
}
```

## Migration Examples

### Migrating from async-trait

**Before**:
```rust
use async_trait::async_trait;

#[async_trait]
trait UserService {
    async fn create_user(&self, email: &str) -> Result<User, Error>;
}

#[async_trait]
impl UserService for MyService {
    async fn create_user(&self, email: &str) -> Result<User, Error> {
        // implementation
    }
}
```

**After** (if using static dispatch):
```rust
// Remove async-trait dependency
trait UserService {
    async fn create_user(&self, email: &str) -> Result<User, Error>;
}

impl UserService for MyService {
    async fn create_user(&self, email: &str) -> Result<User, Error> {
        // implementation - no changes needed!
    }
}
```

## Async Closure Patterns

### Modern Async Closures (Rust 1.85+)

```rust
// ✅ Native async closure
async fn process_all<F>(items: Vec<Item>, f: F) -> Result<(), Error>
where
    F: AsyncFn(Item) -> Result<(), Error>,
{
    for item in items {
        f(item).await?;
    }
}

// Usage
process_all(items, async |item| {
    validate(&item).await?;
    save(&item).await
}).await?;
```

## Performance Considerations

### Static vs Dynamic Dispatch

**Static (Generics)**:
```rust
// ✅ Zero-cost abstraction
async fn process<R: Repository>(repo: R) {
    repo.save().await;
}
// Compiler generates specialized version for each type
```

**Dynamic (dyn Trait)**:
```rust
// ⚠️ Runtime overhead (vtable indirection)
async fn process(repo: Box<dyn Repository>) {
    repo.save().await;
}
// Requires async-trait, adds boxing overhead
```

## Your Approach

When you see async traits:
1. Check if dyn Trait is actually needed
2. Suggest removing async-trait if possible
3. Explain performance benefits of native async fn
4. Show migration path

Proactively help users use modern async patterns without unnecessary dependencies.