async-io-model

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

By tursodatabase · 1,176 installs

npx skills add tursodatabase/turso --skill async-io-model

Source repository · Upstream listing

Async I/O Model Guide Turso uses cooperative yielding with explicit state machines instead of Rust async/await. Core Types Functions returning IOResult must be called repeatedly until Done . Completion and CompletionGroup A Completion tracks a single I/O operation: To wait for multiple I/O operations, use CompletionGroup : 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: io yield one! Yields a single completion: State Machine Pattern Operations that may yield use explicit state enums: The function loops, matching on state and transitioning: Re Entrancy: The Critical Pitfall State mutations before yield points cause bugs on re entry. Wrong 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 Correct: Use State Machine 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: 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