QuickBEAM.Context (QuickBEAM v0.10.3)

Copy Markdown View Source

A lightweight JS execution context on a shared runtime thread.

Unlike a full runtime, a context does not spawn a dedicated OS thread. Many contexts share a single JSRuntime thread managed by a QuickBEAM.ContextPool. This makes each context ~58 KB (bare) to ~429 KB (full browser APIs) vs ~2 MB+ for a full runtime — ideal for per-connection state in Phoenix LiveView.

Example

{:ok, pool} = QuickBEAM.ContextPool.start_link()
{:ok, ctx} = QuickBEAM.Context.start_link(pool: pool)
{:ok, 3} = QuickBEAM.Context.eval(ctx, "1 + 2")
QuickBEAM.Context.stop(ctx)

With LiveView

def mount(_params, _session, socket) do
  {:ok, ctx} = QuickBEAM.Context.start_link(
    pool: MyApp.JSPool,
    handlers: %{"db.query" => &MyApp.query/1}
  )
  {:ok, assign(socket, js: ctx)}
end

def handle_event("click", params, socket) do
  {:ok, html} = QuickBEAM.Context.call(socket.assigns.js, "handleClick", [params])
  {:noreply, push_event(socket, "update", %{html: html})}
end

start_link/1 links the context to the calling process, so it automatically terminates (and cleans up its JS context) when the LiveView process exits. No explicit terminate callback needed.

Summary

Types

t()

@type t() :: %QuickBEAM.Context{
  context_id: pos_integer(),
  handlers: map(),
  next_worker_id: pos_integer(),
  pending: map(),
  pool: GenServer.server() | nil,
  pool_resource: reference(),
  websockets: map(),
  workers: map()
}

Functions

call(server, fn_name, args \\ [], opts \\ [])

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

dom_find(server, selector)

@spec dom_find(GenServer.server(), String.t()) :: {:ok, tuple() | nil}

dom_find_all(server, selector)

@spec dom_find_all(GenServer.server(), String.t()) :: {:ok, list()}

dom_html(server)

@spec dom_html(GenServer.server()) :: {:ok, String.t()}

dom_text(server, selector)

@spec dom_text(GenServer.server(), String.t()) :: {:ok, String.t()}

eval(server, code, opts \\ [])

@spec eval(GenServer.server(), String.t(), keyword()) ::
  {:ok, term()} | {:error, String.t()}

get_global(server, name)

@spec get_global(GenServer.server(), String.t()) :: {:ok, term()}

memory_usage(server)

@spec memory_usage(GenServer.server()) :: {:ok, map()}

reset(server)

@spec reset(GenServer.server()) :: :ok | {:error, String.t()}

send_message(server, message)

@spec send_message(GenServer.server(), term()) :: :ok

set_global(server, name, value)

@spec set_global(GenServer.server(), String.t(), term()) :: :ok

start_link(opts)

@spec start_link(keyword()) :: GenServer.on_start()

stop(server)

@spec stop(GenServer.server()) :: :ok