plushie/runtime

Runtime: the Elm architecture update loop.

Owns the app model, executes init/update/view, diffs trees, and sends patches to the bridge. Commands returned from update are executed before the next view render.

Types

Health status snapshot from a running runtime.

pub type HealthStatus {
  HealthStatus(
    errors: Int,
    consecutive_view_errors: Int,
    prop_warning_count: Int,
    view_desynced: Bool,
  )
}

Constructors

  • HealthStatus(
      errors: Int,
      consecutive_view_errors: Int,
      prop_warning_count: Int,
      view_desynced: Bool,
    )

    Arguments

    errors

    Consecutive update/view errors since the last successful update cycle or renderer restart. Resets to zero on either.

    consecutive_view_errors

    Number of consecutive view failures without a successful render. Resets to zero on successful view render.

    prop_warning_count

    Number of accumulated prop validation warnings from the renderer.

    view_desynced

    True when the UI is stale due to repeated view failures (consecutive_view_errors > 0).

Prop validation warning from the renderer for a specific node.

pub type PropWarning {
  PropWarning(
    node_id: String,
    node_type: String,
    warnings: List(String),
  )
}

Constructors

  • PropWarning(
      node_id: String,
      node_type: String,
      warnings: List(String),
    )

Messages handled by the runtime.

pub type RuntimeMessage {
  FromBridge(bridge.RuntimeNotification)
  InternalEvent(event.Event)
  InternalMsg(dynamic.Dynamic, Int)
  DispatchedMsg(dynamic.Dynamic, Int)
  TimerFired(tag: String)
  AsyncComplete(
    tag: String,
    nonce: Int,
    result: Result(dynamic.Dynamic, dynamic.Dynamic),
  )
  StreamEmit(tag: String, nonce: Int, value: dynamic.Dynamic)
  EffectTimeout(request_id: String)
  InteractTimeout(request_id: String)
  CoalesceFlush
  ProcessDown(process.Down)
  ForceRerender
  Shutdown
  GetModel(reply: process.Subject(dynamic.Dynamic))
  GetTree(reply: process.Subject(option.Option(node.Node)))
  GetFocused(reply: process.Subject(option.Option(String)))
  IsViewDesynced(reply: process.Subject(Bool))
  RegisterEffectStub(
    kind: String,
    response: node.PropValue,
    reply: process.Subject(Result(Nil, String)),
  )
  UnregisterEffectStub(
    kind: String,
    reply: process.Subject(Result(Nil, String)),
  )
  GetPropWarnings(reply: process.Subject(List(PropWarning)))
  AwaitAsync(tag: String, reply: process.Subject(Nil))
  Interact(
    action: String,
    selector: dict.Dict(String, node.PropValue),
    payload: dict.Dict(String, node.PropValue),
    reply: process.Subject(Result(Nil, String)),
  )
  GetHealth(reply: process.Subject(HealthStatus))
  SetDevOverlay(message: option.Option(String))
}

Constructors

  • Notification from the bridge.

  • InternalEvent(event.Event)

    Internal event dispatch (timer ticks, etc.).

  • InternalMsg(dynamic.Dynamic, Int)

    Internal msg dispatch (Done, SendAfter, already mapped to msg). The nonce distinguishes current from stale timer deliveries.

  • DispatchedMsg(dynamic.Dynamic, Int)

    Msg dispatched by Command.dispatch with the current chain depth attached. The runtime bumps the counter per chained dispatch and drops the msg once it reaches the configured cap, emitting a typed DispatchLoopExceeded diagnostic.

  • TimerFired(tag: String)

    Subscription timer fired.

  • AsyncComplete(
      tag: String,
      nonce: Int,
      result: Result(dynamic.Dynamic, dynamic.Dynamic),
    )

    Async task completed with nonce for freshness validation.

  • StreamEmit(tag: String, nonce: Int, value: dynamic.Dynamic)

    Stream emitted a value with nonce for freshness validation.

  • EffectTimeout(request_id: String)

    Effect request timed out.

  • InteractTimeout(request_id: String)

    Interact request timed out.

  • CoalesceFlush

    Flush deferred coalescable events (zero-delay timer).

  • ProcessDown(process.Down)

    Monitored async task process exited.

  • ForceRerender

    Force a re-render without resetting state (dev-mode live reload).

  • Shutdown

    Shutdown.

  • GetModel(reply: process.Subject(dynamic.Dynamic))

    Query the current model (replies with dynamic model value).

  • Query the current tree (replies with the latest normalized tree).

  • GetFocused(reply: process.Subject(option.Option(String)))

    Query the currently focused widget ID.

  • IsViewDesynced(reply: process.Subject(Bool))

    Check if the tree is stale due to consecutive view errors.

  • RegisterEffectStub(
      kind: String,
      response: node.PropValue,
      reply: process.Subject(Result(Nil, String)),
    )

    Register an effect stub with the renderer. The renderer sends an ack after storing the stub; the reply Subject is notified.

  • UnregisterEffectStub(
      kind: String,
      reply: process.Subject(Result(Nil, String)),
    )

    Remove a previously registered effect stub. The renderer sends an ack after removing the stub; the reply Subject is notified.

  • GetPropWarnings(reply: process.Subject(List(PropWarning)))

    Query accumulated prop validation warnings and clear them.

  • AwaitAsync(tag: String, reply: process.Subject(Nil))

    Wait for an async task to complete. Replies when the task with the given tag finishes, or immediately if already done.

  • Interact(
      action: String,
      selector: dict.Dict(String, node.PropValue),
      payload: dict.Dict(String, node.PropValue),
      reply: process.Subject(Result(Nil, String)),
    )

    Synchronous interact request (click, type_text, press, etc.). Sends the interact to the renderer and replies when complete.

  • GetHealth(reply: process.Subject(HealthStatus))

    Query runtime health status.

  • SetDevOverlay(message: option.Option(String))

    Set or clear the dev overlay message. Sent by the dev server to show rebuild status, or by view error tracking for frozen UI.

Start options for the runtime.

pub type RuntimeOpts {
  RuntimeOpts(
    format: protocol.Format,
    session: String,
    daemon: Bool,
    app_opts: dynamic.Dynamic,
    required_native_widgets: List(String),
    renderer_args: List(String),
    token: option.Option(String),
  )
}

Constructors

Values

pub fn default_opts() -> RuntimeOpts

Default runtime options.

pub fn start_supervised(
  app: app.App(model, msg),
  bridge_subject: process.Subject(bridge.BridgeMessage),
  opts: RuntimeOpts,
  binary_path: String,
  name: process.Name(RuntimeMessage),
) -> Result(
  actor.Started(process.Subject(RuntimeMessage)),
  actor.StartError,
)

Start the runtime as an OTP actor under a supervisor.

The bridge is already running. The runtime registers its notification subject with the bridge, initializes the app (settings, snapshot, subscriptions, windows), and enters the actor message loop.

Search Document