Lavash.Lifecycle.AsyncMacro (Lavash v0.4.0-rc.1)

Copy Markdown View Source

Capability: declare a triggerable async task that produces a value into an assigns field.

Structurally an async :foo do ... end block parallels messages do message :foo do ... end end: a named block holds a sequence of ops, and the runtime walks them in order.

Today the body is restricted to a single run fn assigns -> ... end op — the work to perform. The runtime wraps the result in a %Phoenix.LiveView.AsyncResult{} on the named field.

Shape

async :report do
  run fn assigns ->
    {:ok, SlowService.fetch_report(assigns.user_id)}
  end
end

Returning {:ok, value} from the run fn produces AsyncResult.ok(value). Returning a raw value also produces AsyncResult.ok(value) — the wrapper is a convenience for callers that want the explicit shape. Raises / exits produce AsyncResult.failed/2.

Firing

An async declaration on its own DOES NOTHING. It just registers a named computation. To actually fire it, use the fire :foo op inside a lifecycle block (mount do), an action body, or a message body. This decouples the work definition from the trigger — three trigger paths (mount, action, message) all use the same fire op against the same declaration.

Layer

Layer 1: an async declaration is plain Elixir wrapped in %AsyncResult{} plumbing. No reactive graph involvement. For reactive auto-recompute on dep change, see calculate :foo, rx(...), async: true (layer 2).

Summary

Functions

Top-level async :name do <ops> end declaration. Registers a named, triggerable async task. The body is a sequence of ops; today only a single run fn assigns -> ... end is supported.

Functions

async(name, list)

(macro)

Top-level async :name do <ops> end declaration. Registers a named, triggerable async task. The body is a sequence of ops; today only a single run fn assigns -> ... end is supported.

The named field lands on assigns as a %Phoenix.LiveView.AsyncResult{}. Before the first fire it is AsyncResult.loading() with loading == nil (i.e. it's an empty default); after fire :name it transitions to loading() |> with loading: [name], then resolves to ok(value) or failed(reason).