К основному содержанию
скилл Claude Code CX Codex Cursor GitHub Copilot

async-io-model — скилл для Claude Code: что делает и как установить

Обучает агента архитектуре асинхронного ввода-вывода в Turso: явным стейт-машинам, типу IOResult и защите от багов повторного входа.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add tursodatabase/turso --skill async-io-model -a claude-code
Открыть на GitHub

Что делает async-io-model

В ядре Turso разработчики отказались от Rust async/await в пользу кооперативной многозадачности на явных стейт-машинах. Скилл передаёт агенту правила работы с типом IOResult, структурами Completion и CompletionGroup, а также макросами return_if_io! и io_yield_one!. ИИ начинает строить функции, возвращающие Done или IO, как это принято в репозитории проекта.

Главная проблема этой схемы — баги повторного входа. Если метод увеличивает счётчик или добавляет элемент в вектор до макроса return_if_io!, при возобновлении операции после завершения ввода-вывода эта мутация выполнится ещё раз. Инструкции скилла требуют менять состояние только после завершения I/O либо хранить шаг выполнения внутри полей перечисления стейт-машины.

Паттерны строго привязаны к модулю core базы Turso, а проверять такой код авторы советуют через детерминированные тесты в testing/simulator/. В проектах на стандартном рантайме Tokio или чистом async/await эти правила бесполезны.

Какие задачи решает

  • переписать асинхронную логику на стейт-машину с типом IOResult
  • найти мутации состояния перед точками возврата return_if_io!
  • объединить несколько операций ввода-вывода через CompletionGroup
  • спроектировать варианты enum для безопасного сохранения прогресса

Примеры запросов агенту

  • Спроектируй стейт-машину для чтения страниц через IOResult без мутаций до yield
  • Проверь эту функцию в core на ошибки повторного входа перед вызовом return_if_io!
  • Собери несколько Completion в один вызов с помощью CompletionGroup

Как установить async-io-model

1Через Skills CLI (Vercel)

npx skills add tursodatabase/turso --skill async-io-model -a claude-code

2Вручную: положить файлы

~/.claude/skills/async-io-model/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/async-io-model/

Из того же набора10

Весь набор →
code-quality tursodatabase Набор правил корректности, Rust-паттернов и принципов без переусложнения для агентов, которые пишут код в вашем проекте. Claude Code CX Codex Cursor +1 1 800установок storage-format tursodatabase Справочник по формату файла SQLite: заголовок, страницы, B-деревья, ячейки, overflow и freelist, с привязкой к коду Turso. Claude Code CX Codex Cursor +1 1 300установок testing tursodatabase Скилл помогает писать тесты для SQL и Rust: учит выбирать между форматами .sqltest, TCL и интеграционными тестами, показывает команды для запуска. Claude Code CX Codex Cursor +1 1 300установок debugging tursodatabase Скилл по отладке tursodb: сравнить байткод с SQLite, включить трейс-логи, прогнать ThreadSanitizer, воспроизвести баг по seed и замерить стек. Claude Code CX Codex Cursor +1 1 300установок index-knowledge tursodatabase Скилл автоматически создаёт иерархическую документацию AGENTS.md для кодовой базы. Анализирует структуру проекта, оценивает сложность каждой папки и генерирует файлы с инструкциями для ИИ-агентов. Claude Code CX Codex Cursor +1 1 300установок mvcc tursodatabase Справочник по экспериментальному MVCC в кодовой базе Turso: многоверсионность строк, изоляция снимков и ограничения памяти. Пригодится при отладке и разработке ядра базы данных. Claude Code CX Codex Cursor +1 1 200установок differential-fuzzer tursodatabase Скилл помогает запускать дифференциальный фаззер Turso и разбирать расхождения с SQLite. Нужен при поиске ошибок корректности в сгенерированных SQL-запросах. Claude Code CX Codex Cursor +1 1 200установок transaction-correctness tursodatabase Объясняет механику транзакций в Turso: как работает WAL, чекпоинты, восстановление после сбоя и правила конкурентного доступа. Claude Code CX Codex Cursor +1 1 200установок

Похожие

scaffolding-oracle-to-postgres-migration-test-project официальный github Создаёт пустой xUnit-проект интеграционных тестов для Oracle в .NET-решении. Нужен перед написанием базовых тестов на этапе Phase 3. GitHub Copilot 1 700установок bigquery-troubleshooting официальный google Скилл разбирает сбои, медленные задания и неожиданный рост расходов в BigQuery. Он помогает найти узкое место и выбрать шаги для исправления. Claude Code Gemini CLI CX Codex 1 400установок bigquery-optimization официальный google Скилл помогает находить способы снизить расходы BigQuery, настроить хранение и переписать SQL. Подходит для планирования capacity и изменений таблиц. Claude Code Gemini CLI CX Codex 1 400установок agent-memory-systems sickn33 Скилл для проектирования памяти агентов с разделением по пользователям и тенантам. Помогает построить RAG, историю диалогов и хранилище векторов так, чтобы данные одного клиента не утекали к другому. Claude Code CX Codex Cursor +1 2 000установок database-lookup K-Dense-AI Находит факты в 80 внешних базах данных через API с контролем пагинации и источников. Пригодится, когда научные или финансовые данные нужно подтвердить первоисточником. Claude Code CX Codex Cursor +1 2 100установок seaborn K-Dense-AI Скилл для Claude Code и других агентов: тот строит статистические графики на seaborn из pandas DataFrame, с готовыми рецептами под распределения, регрессии и тепловые карты. Claude Code CX Codex Cursor +1 2 100установок xlsx официальный anthropics Работает с табличными файлами: создаёт, читает, правит и преобразует книги. Подходит, когда итогом должен стать файл Excel или другой табличный формат. Claude Code Claude.ai 187 223установок google-agents-cli-observability официальный Google Помогает настроить трассировку и сбор данных о работе ИИ-агентов, включая агентов на ADK. Пригодится, когда нужно разбирать выполнение запросов или наблюдать за агентом после развёртывания. Claude Code CX Codex Cursor +1 509 900установок

Вопросы о async-io-model

Как установить async-io-model в Claude Code?

Выполните в терминале команду npx skills add tursodatabase/turso --skill async-io-model -a claude-code.

Что делает скилл async-io-model?

Он передаёт языковой модели соглашения ядра Turso по асинхронному вводу-выводу, где вместо async/await используются тип IOResult, макрос return_if_io! и конечные автоматы.

Чем опасны мутации состояния до yield в этой модели?

При возврате варианта IO вызывающая сторона позже запускает функцию повторно. Любое изменение вектора или индекса до прерывания сработает дважды и повредит данные.

Исходный текст

SKILL.md · MIT
---
name: async-io-model
description: Explanations of common asynchronous patterns used in tursodb. Involves IOResult, state machines, re-entrancy pitfalls, CompletionGroup. Always use these patterns in `core` when doing anything IO
---
# Async I/O Model Guide

Turso uses cooperative yielding with explicit state machines instead of Rust async/await.

## Core Types

```rust
pub enum IOCompletions {
    Single(Completion),
}

#[must_use]
pub enum IOResult<T> {
    Done(T),      // Operation complete, here's the result
    IO(IOCompletions),  // Need I/O, call me again after completions finish
}
```

Functions returning `IOResult` must be called repeatedly until `Done`.

## Completion and CompletionGroup

A `Completion` tracks a single I/O operation:

```rust
pub struct Completion { /* ... */ }

impl Completion {
    pub fn finished(&self) -> bool;
    pub fn succeeded(&self) -> bool;
    pub fn get_error(&self) -> Option<CompletionError>;
}
```

To wait for multiple I/O operations, use `CompletionGroup`:

```rust
let mut group = CompletionGroup::new(|_| {});

// Add individual completions
group.add(&completion1);
group.add(&completion2);

// Build into single completion that finishes when all complete
let combined = group.build();
io_yield_one!(combined);
```

`CompletionGroup` features:
- Aggregates multiple completions into one
- Calls callback when all complete (or any errors)
- Can nest groups (add a group's completion to another group)
- Cancellable via `group.cancel()`

## Helper Macros

### `return_if_io!`
Unwraps `IOResult`, propagates IO variant up the call stack:
```rust
let result = return_if_io!(some_io_operation());
// Only reaches here if operation returned Done
```

### `io_yield_one!`
Yields a single completion:
```rust
io_yield_one!(completion);  // Returns Ok(IOResult::IO(Single(completion)))
```

## State Machine Pattern

Operations that may yield use explicit state enums:

```rust
enum MyOperationState {
    Start,
    WaitingForRead { page: PageRef },
    Processing { data: Vec<u8> },
    Done,
}
```

The function loops, matching on state and transitioning:

```rust
fn my_operation(&mut self) -> Result<IOResult<Output>> {
    loop {
        match &mut self.state {
            MyOperationState::Start => {
                let (page, completion) = start_read();
                self.state = MyOperationState::WaitingForRead { page };
                io_yield_one!(completion);
            }
            MyOperationState::WaitingForRead { page } => {
                let data = page.get_contents();
                self.state = MyOperationState::Processing { data: data.to_vec() };
                // No yield, continue loop
            }
            MyOperationState::Processing { data } => {
                let result = process(data);
                self.state = MyOperationState::Done;
                return Ok(IOResult::Done(result));
            }
            MyOperationState::Done => unreachable!(),
        }
    }
}
```

## Re-Entrancy: The Critical Pitfall

**State mutations before yield points cause bugs on re-entry.**

### Wrong
```rust
fn bad_example(&mut self) -> Result<IOResult<()>> {
    self.counter += 1;  // Mutates state
    return_if_io!(something_that_might_yield());  // If yields, re-entry will increment again!
    Ok(IOResult::Done(()))
}
```

If `something_that_might_yield()` returns `IO`, caller waits for completion, then calls `bad_example()` again. `counter` gets incremented twice (or more).

### Correct: Mutate After Yield
```rust
fn good_example(&mut self) -> Result<IOResult<()>> {
    return_if_io!(something_that_might_yield());
    self.counter += 1;  // Only reached once, after IO completes
    Ok(IOResult::Done(()))
}
```

### Correct: Use State Machine
```rust
enum State { Start, AfterIO }

fn good_example(&mut self) -> Result<IOResult<()>> {
    loop {
        match self.state {
            State::Start => {
                // Don't mutate shared state here
                self.state = State::AfterIO;
                return_if_io!(something_that_might_yield());
            }
            State::AfterIO => {
                self.counter += 1;  // Safe: only entered once
                return Ok(IOResult::Done(()));
            }
        }
    }
}
```

## Common Re-Entrancy Bugs

| Pattern | Problem |
|---------|---------|
| `vec.push(x); return_if_io!(...)` | Vec grows on each re-entry |
| `idx += 1; return_if_io!(...)` | Index advances multiple times |
| `map.insert(k,v); return_if_io!(...)` | Duplicate inserts or overwrites |
| `flag = true; return_if_io!(...)` | Usually ok, but check logic |

## State Enum Design

Encode progress in state variants:

```rust
// Good: index is part of state, preserved across yields
enum ProcessState {
    Start,
    ProcessingItem { idx: usize, items: Vec<Item> },
    Done,
}

// Loop advances idx only when transitioning states
ProcessingItem { idx, items } => {
    return_if_io!(process_item(&items[idx]));
    if idx + 1 < items.len() {
        self.state = ProcessingItem { idx: idx + 1, items };
    } else {
        self.state = Done;
    }
}
```

## Turso Implementation

Key files:
- `core/types.rs` - `IOResult`, `IOCompletions`, `return_if_io!`, `return_and_restore_if_io!`
- `core/io/completions.rs` - `Completion`, `CompletionGroup`
- `core/util.rs` - `io_yield_one!` macro
- `core/state_machine.rs` - Generic `StateMachine` wrapper
- `core/storage/btree.rs` - Many state machine examples
- `core/storage/pager.rs` - `CompletionGroup` usage examples

## Testing Async Code

Re-entrancy bugs often only manifest under specific IO timing. Use:
- Deterministic simulation (`testing/simulator/`)
- Whopper concurrent DST (`testing/concurrent-simulator/`)
- Fault injection to force yields at different points

## References

- `docs/manual.md` section on I/O

© tursodatabase · MIT · tursodatabase/turso

Смотрите также

Спонсоры проекта

Компании, которые помогают держать аналитику открытой