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

You are reading the development version (master). For the latest release (v3.5.0) see the stable docs.

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.