Agent skill

Rust Async Tokio

by rocky-data in rocky-data/rocky

“Tokio,”

— description from SKILL.md by rocky-data
Apache-2.0Auto-check passedDatabases

Install Rust Async Tokio

skills CLI
$ npx skills add rocky-data/rocky --skill rust-async-tokio -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install rocky-data/rocky rust-async-tokio --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/rocky-data/rocky.git skills-src && mkdir -p .claude/skills && cp -r skills-src/engine/.claude/skills/rust-async-tokio .claude/skills/rust-async-tokio && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
rust-async-tokio
GitHub stars
304
Token cost
~2k tokens
SKILL.md length
806 words
Files
1
Skills in repo
22
Repo updated
First seen
Licence
Apache-2.0

At a glance

  • Works in 3 steps: Create one AdaptiveThrottle per… → Acquire a permit via a… → On the result of each request
  • SKILL.md covers Runtime setup, Async trait rule, Backpressure: the AIMD pattern and Structured logging: tracing,…, plus 5 more sections
  • Calls cargo

About this skill

Rust Async Tokio is a skill in rocky-data/rocky (304 stars). Its SKILL.md is about 2k tokens. Licence: Apache-2.0.

Workflow steps

3 steps, taken from the first numbered list in SKILL.md.

  1. Create one AdaptiveThrottle per warehouse/endpoint at adapter construction.
  2. Acquire a permit via a tokio::sync::Semaphore whose available_permits() is refreshed from throttle.current() before each batch.
  3. On the result of each request

What it can do on your machine

Read from SKILL.md and the folder at commit 46be77e. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • cargo

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Rust Async Tokio loads about 2k tokens when it runs. Until then it costs about 6 tokens; SKILL.md has 806 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~6
When it runs · the whole SKILL.md, loaded when a task matches
~2k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from rocky-data/rocky at commit 46be77e, republished under its Apache-2.0 licence (© rocky-data). 806 words, ~2,011 tokens.

Download SKILL.mdSave it as .claude/skills/rust-async-tokio/SKILL.md (or your agent's skills folder).
name
rust-async-tokio
description
Tokio,

Async Rust in Rocky

Rocky is async end-to-end. Tokio is the only runtime; there's a single #[tokio::main] entrypoint at engine/rocky/src/main.rs:471. Adapter I/O (Databricks REST, Snowflake REST, Fivetran REST, Valkey, webhooks) all runs on the same runtime.

Runtime setup

  • Workspace dep — tokio = { version = "1", features = ["full"] } (from engine/Cargo.toml). The "full" feature is deliberate: we use macros, rt-multi-thread, time, fs, net, sync, and process across the workspace, and pinning a narrower feature set per crate creates friction when async code moves between crates.
  • Entrypoint — engine/rocky/src/main.rs:471 has #[tokio::main] on async fn main() -> anyhow::Result<()>. Library crates never spawn their own runtime — they take &self on async methods and trust the binary to drive the reactor.
  • Library crates depend on the workspace tokio re-export. Don't cargo add tokio in a sub-crate; inherit from [workspace.dependencies] in engine/Cargo.toml.

Async trait rule

Every async trait uses #[async_trait] from the async-trait crate (async-trait = "0.1" in [workspace.dependencies]). This is a hard rule from engine/CLAUDE.md.

rust
// DO — matches the pattern used throughout rocky-adapter-sdk
#[async_trait::async_trait]
pub trait WarehouseAdapter: Send + Sync {
    async fn execute(&self, sql: &str) -> Result<StatementResult, AdapterError>;
    async fn describe_table(&self, qname: &QualifiedName) -> Result<TableSchema, AdapterError>;
}

// DON'T — native async-in-traits still has object-safety gaps in 2024 edition
pub trait WarehouseAdapter: Send + Sync {
    async fn execute(&self, sql: &str) -> Result<StatementResult, AdapterError>;
}

Concrete examples: crates/rocky-adapter-sdk/src/traits.rs has four #[async_trait] trait definitions at lines 219, 333, 346, 372 — those are the shapes adapters must match.

When in doubt, read how rocky-databricks or rocky-fivetran implement the trait — both are full end-to-end examples.

Backpressure: the AIMD pattern

Rocky uses adaptive concurrency on remote calls that can be rate-limited. The canonical implementation is crates/rocky-databricks/src/throttle.rs::AdaptiveThrottle:

  • Slow start — below half of max, increase by 2 every increase_interval successes.
  • Congestion avoidance — above half of max, increase by 1.
  • Multiplicative decrease — on on_rate_limit() (triggered by 429 / 503 / "TEMPORARILY_UNAVAILABLE"), halve the current concurrency down to min_concurrency.
  • Clamped — never goes below min_concurrency (≥ 1) or above max_concurrency.
  • Atomic shared state — the inner counters are AtomicUsize + AtomicU64 inside an Arc<ThrottleInner>, so .clone() shares state across tasks. No locks on the hot path.

When to reach for this pattern: any new adapter that talks to a rate-limited remote API. Don't re-invent it; either reuse AdaptiveThrottle directly (if it's a Databricks-family API) or copy its shape. The tests at crates/rocky-databricks/src/throttle.rs:122 cover the invariants you'd want to preserve (starts at max, halves on rate limit, never below min, never above max, clone shares state).

How to wire it:

  1. Create one AdaptiveThrottle per warehouse/endpoint at adapter construction.
  2. Acquire a permit via a tokio::sync::Semaphore whose available_permits() is refreshed from throttle.current() before each batch.
  3. On the result of each request:
    • 2xx → throttle.on_success()
    • 429 / 503 → throttle.on_rate_limit() and retry after a small delay
    • anything else → neither (it's a user error, not a concurrency signal)

Structured logging: tracing, not println!

Hard rule from engine/CLAUDE.md: use tracing, not println! or eprintln!. The subscriber is initialized in crates/rocky-observe/src/tracing_setup.rs and emits structured JSON lines when RUST_LOG / tracing_subscriber::EnvFilter is set.

rust
use tracing::{info, warn, error, debug};

// DO — structured fields, no interpolation in the message
info!(
    connector_id = %connector.id,
    table_count = tables.len(),
    "discover completed"
);

warn!(
    from = old,
    to = new,
    "adaptive throttle: rate limit detected, reducing concurrency"
);

// DON'T — stringify values into the message
info!("discover completed: connector={}, tables={}", connector.id, tables.len());
  • %value → uses Display
  • ?value → uses Debug
  • Bare field = literal → treats as JSON literal

warn! is the level rocky-databricks/src/throttle.rs uses for rate-limit detection — follow that pattern for any adaptive-concurrency event you add.

Show full SKILL.md (346 more words)Show less

Timeouts

Any network call needs a timeout. Use tokio::time::timeout:

rust
use std::time::Duration;
use tokio::time::timeout;

let result = timeout(Duration::from_secs(30), client.execute(sql))
    .await
    .context("databricks execute timed out after 30s")??;
//                                                      ^^ one ? for Elapsed → anyhow, one ? for the inner Result

Rule of thumb: if a function makes an HTTP/SQL/network call and does not have an outer timeout, it's a bug waiting to happen. The anyhow .context layer is what surfaces the timeout reason into the Dagster event log — don't skip it.

Cancellation and select!

tokio::select! is the right tool when you want to race two futures (e.g. "wait for this statement to finish or for the user to ctrl-C"). Guidelines:

  • Every branch must be cancel-safe. Read the tokio::select! docs on which tokio primitives are cancel-safe and which aren't. (Hint: AsyncRead::read_buf is not cancel-safe.)
  • Prefer tokio::sync::oneshot for "signal this future to stop" over manual flags.
  • Don't hold a MutexGuard across an .await in any select! branch.

Spawn vs. join

SituationUse
Fan out N tasks and wait for allfutures::future::try_join_all
Fan out N tasks, take first resultfutures::future::select_ok
Fire-and-forget background workertokio::spawn(...) — but the spawned future must own its data ('static), and you must handle its JoinHandle if it can fail
Parallel CPU-bound chunkstokio::task::spawn_blocking — not spawn. Blocking the reactor starves other adapters.

duckdb and sqlparser operations are CPU-bound and should be wrapped in spawn_blocking if they're called from an async context on a hot path.

What NOT to do

Anti-patternWhy
std::thread::spawn in async codeBypasses the runtime; task never wakes correctly. Use tokio::spawn or spawn_blocking.
std::sync::Mutex held across .awaitCan deadlock the reactor. Use tokio::sync::Mutex or (better) restructure to avoid holding the lock.
Per-crate #[tokio::main] or nested runtimesThere's exactly one runtime, driven by engine/rocky/src/main.rs. Libraries don't own the runtime.
futures::executor::block_on inside async codeNested block_on will panic under tokio::main.
async fn foo(...) -> Box<dyn Future<...>>Use #[async_trait] for trait methods or impl Future for free functions.
Spinning on throttle.current() in a busy loopDrive concurrency off a Semaphore; the throttle is a signal, not a gate.
  • rust-error-handling — async errors follow the same two-tier model (library → thiserror, CLI → anyhow with .context).
  • rust-clippy-triage — the async-family clippy lints (e.g. clippy::unused_async, clippy::await_holding_lock) fire in this surface area.
  • rust-unsafe — duckdb calls are sync/FFI and need spawn_blocking, not direct await.

© rocky-data, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in engine/.claude/skills/rust-async-tokio of rocky-data/rocky.

Open the folder on GitHubat commit 46be77e

Compare with similar skills

Rust Async Tokio next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Rust Async Tokio compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Rust Async Tokio this skillrocky-data/rocky304—~2kAutomated safety check: PassApache-2.0
Databricks Dbsqldatabricks/databricks-agent-skills3451 repos~2.8kAutomated safety check: PassCustom licence
Altimate Data Warehouse DelegateAltimateAI/data-engineering-skills128—~1.4kAutomated safety check: PassMIT
Optimizing Databricks SQLAltimateAI/data-engineering-skills128—~6.7kAutomated safety check: PassMIT
Sea Orm 2FlyinPancake/yoink112—~2.9kAutomated safety check: PassApache-2.0
Qdrant Vector SearchOrchestra-Research/AI-Research-SKILLs13k5 repos~3.4kAutomated safety check: PassMIT

Similar skills

  • Databricks Dbsql

    databricks/databricks-agent-skills

    Official

    Databricks SQL (DBSQL) advanced features and SQL warehouse capabilities.

    345 GitHub starsUsed in 1 repo~2.8k tokens
    DatabasesAuto-check passed
  • Altimate Data Warehouse Delegate

    AltimateAI/data-engineering-skills

    Delegates dbt and warehouse tasks such as lineage, migrations and cost attribution to the altimate-code CLI agent and relays its answer back.

    128 GitHub stars~1.4k tokensUpdated 7 days ago
    DatabasesAuto-check passed
  • Optimizing Databricks SQL

    AltimateAI/data-engineering-skills

    Analyze DBSQL queries, including SQL embedded in notebooks (spark.sql(...), %sql cells), for anti-patterns, lint issues, and performance problems, using Databricks-specific dialect and platform…

    128 GitHub stars~6.7k tokensUpdated 7 days ago
    DatabasesAuto-check passed
  • Sea Orm 2

    FlyinPancake/yoink

    Expert guidance for SeaORM 2.0, Rust's async ORM with strongly-typed columns, nested ActiveModels, Entity Loader API, and entity-first workflow.

    112 GitHub stars~2.9k tokensUpdated 4 days ago
    DatabasesAuto-check passed
  • Qdrant Vector Search

    Orchestra-Research/AI-Research-SKILLs

    Explains how to run Qdrant, a Rust vector database, for RAG and semantic search, covering collections, points, distance metrics and filtered or batched queries.

    13k GitHub starsUsed in 5 repos~3.4k tokens
    DatabasesAuto-check passed
  • Hydra Architect

    streamband/hydra-srt

    A skill your agent uses when designing or evolving Hydra platform architecture across Elixir/Phoenix, SQLite, VictoriaMetrics/VictoriaLogs analytics, native/Rust, and runtime boundaries.

    146 GitHub stars~1.2k tokensUpdated 22 days ago
    DatabasesAuto-check passed

More from rocky-data/rocky

All 22 skills in this repo
  • Fivetran

    rocky-data/rocky

    Fivetran REST API reference for Rocky's source adapter. An agent skill from rocky-data/rocky.

    304 GitHub stars~914 tokensUpdated today
    Auto-check passed
  • Databricks

    rocky-data/rocky

    Databricks REST API and SQL reference for Rocky's warehouse adapter.

    304 GitHub stars~2k tokensUpdated today
    Auto-check passed
  • Rocky Codegen

    rocky-data/rocky

    Rocky CLI JSON-output schema cascade. An agent skill from rocky-data/rocky.

    304 GitHub stars~1.9k tokensUpdated today
    Auto-check passed
  • Rocky Dev

    rocky-data/rocky

    Top-level router for Rocky development tasks. An agent skill from rocky-data/rocky.

    304 GitHub stars~2.1k tokensUpdated today
    Auto-check passed
  • Rocky Dsl Change

    rocky-data/rocky

    Rocky DSL (.rocky file) cross-subproject cascade. An agent skill from rocky-data/rocky.

    304 GitHub stars~1.3k tokensUpdated today
    Auto-check passed
  • Rocky New Adapter

    rocky-data/rocky

    Adding a new warehouse or source adapter crate to the Rocky engine.

    304 GitHub stars~2k tokensUpdated today
    Auto-check passed

Works with

Questions about Rust Async Tokio

How do I install Rust Async Tokio in Claude Code?

Run `npx skills add rocky-data/rocky --skill rust-async-tokio -a claude-code`. Or copy the skill folder (engine/.claude/skills/rust-async-tokio in rocky-data/rocky) into .claude/skills/rust-async-tokio in your project. Claude Code loads it when a task matches its description.

How do I install Rust Async Tokio in Codex?

Run `npx skills add rocky-data/rocky --skill rust-async-tokio -a codex`. Or copy the skill folder (engine/.claude/skills/rust-async-tokio in rocky-data/rocky) into .agents/skills/rust-async-tokio in your project. Codex loads it when a task matches its description.

Can I use Rust Async Tokio in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add rocky-data/rocky --skill rust-async-tokio -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/rust-async-tokio, .gemini/skills/rust-async-tokio, .github/skills/rust-async-tokio and .opencode/skills/rust-async-tokio in your project.

What does Rust Async Tokio need to run?

Going by SKILL.md and its folder, Rust Async Tokio needs the command-line tools its instructions call (cargo).

Does Rust Async Tokio access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Rust Async Tokio safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Rust Async Tokio use?

Rust Async Tokio is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Rust Async Tokio use?

About 2k tokens (SKILL.md is roughly 8k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Rust Async Tokio?

Skills that share tags, products or a category with Rust Async Tokio: Databricks Dbsql (databricks/databricks-agent-skills, 345 stars), Altimate Data Warehouse Delegate (AltimateAI/data-engineering-skills, 128 stars), Optimizing Databricks SQL (AltimateAI/data-engineering-skills, 128 stars) and Sea Orm 2 (FlyinPancake/yoink, 112 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Rust Async Tokio?

rocky-data (a GitHub organization) maintains it in rocky-data/rocky, which has 304 GitHub stars. The repository holds 22 skills in this directory. The repository was last updated on October 8, 2026.

Source: rocky-data/rocky on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.