Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Effects Guide

Overview

Effects are declarative descriptions of side effects. update() never performs IO directly. Instead, it returns a list of effects. They are executed via the capability gateway only when the app is driven through an EffectExecutor (see Effect Lifecycle).

Effect Structure

type Effect { kind: String, payload: String, callback_tag: String }
  • kind — which effect to execute (see table below)
  • payload — data for the effect (URL, query, path, etc.)
  • callback_tag — message tag for the result delivery

Built-in Effect Kinds

KindCapabilityDescription
http_requestnet.fetchHTTP GET/POST request
db_querydb.queryDatabase query
fs_readfs.readRead file
fs_writefs.writeWrite file
timertime.nowGet current time
randomrandomGet random value
spawn_actoractor.spawnSpawn child actor (see ACTORS_GUIDE.md)
send_to_actoractor.sendSend message to actor (not executed by any actor runtime)
llm_callllm.callLLM call
emit_uiui.renderEmit UI tree to host

Returning Effects From update()

fn update(state: State, msg: Msg) -> UpdateResult {
    if msg.tag == "fetch" {
        UpdateResult {
            state: state,
            effects: [
                Effect {
                    kind: "http_request",
                    payload: "https://api.example.com/data",
                    callback_tag: "data_received",
                },
            ],
        }
    } else {
        UpdateResult { state: state, effects: [] }
    }
}

Effect Lifecycle

  1. update() returns UpdateResult { state, effects }.
  2. Framework validates effects against the policy.
  3. Plain AppRuntime::send stops here and returns the effects to the caller. boruna framework test likewise lists the effects without executing them.
  4. With AppRuntime::send_with_executor (or TestHarness::send_with_effects), an EffectExecutor runs each effect: HostEffectExecutor via the capability gateway, MockEffectExecutor with stub results.
  5. Effect results are returned as new messages with callback_tag as the tag.
  6. The caller feeds them back; update() handles them in the next cycle.

Multiple Effects Per Cycle

Return multiple effects in the list. They execute in order.

effects: [
    Effect { kind: "http_request", payload: "url1", callback_tag: "result" },
    Effect { kind: "http_request", payload: "url2", callback_tag: "result" },
    Effect { kind: "http_request", payload: "url3", callback_tag: "result" },
]

Policy Constraints

Effects are checked against the app’s PolicySet:

  • Only listed capabilities are allowed.
  • max_effects_per_cycle limits how many effects per update.
  • Violations produce FrameworkError::PolicyViolation.

Determinism

Effects themselves are deterministic data. Their execution results are logged by the capability gateway. Replay substitutes recorded results, making the entire execution deterministic.