Docs contents

Async functions and scopes

Use async def for functions that wait for timers, database operations, or other async work. Use await to wait for the result. Other async work can run during that wait.

async def main() -> Result[unit, Error]:
    await sleep(10)
    return ok(print("Finished waiting"))

sleep takes milliseconds. This program prints after the wait. For an operation that can fail, use try await db_open(...) to handle its Result as well.

On this page

Starting multiple operations

Inside async with scope, spawn starts child work. Leaving the scope waits for every child to finish.

async def main() -> Result[unit, Error]:
    async with scope:
        spawn sleep(10)
        spawn sleep(15)
    return ok(print("Done"))

The scope checks child results after its body finishes. If a child returns a Result error or panics, it cancels the remaining children and waits for them. A child failure does not interrupt the body while it runs. Spawned work must return unit or Result[unit, Error]. Returning from inside a scope and passing a view to a child are not supported.

Arguments are evaluated at the spawn statement, and the resulting values are passed to the child. With spawn work(copy(part)), the child receives an owned copy, so the parent can keep using the original data. Copying a list does not make it safe to pass if its elements still contain views.

A function using a scope returns Result[T, Error]. A custom error class needs a Rust adapter implementing From<nagi_runtime::Error>. The build checks that child failures can be converted to that class.

If the parent operation itself is dropped, or the scope body panics, cancellation is requested without a guarantee that every child has already stopped. See Concurrency for CPU work and cancellation.

Call a function stored in a variable

An async function name can be assigned to a variable and called through it. This example prints 42.

async def answer(value: i64) -> i64:
    return value + 1

async def main():
    selected = answer
    print(await selected(41))

This assignment stores the function itself. Storing a call result with pending = answer(41) is unsupported; await the call directly. See types and inference for supported function signatures.

You cannot reassign a different async function to that variable. Use a separate variable or call each function in a branch. Reassigning the same function, and replacing a synchronous function, are supported.

Nagi 0.1 documentationPage source