glimr/loom/live_dispatch
Loom Live Dispatch
Generated template modules are determined at runtime by the client’s init message, so the live_socket actor can’t call them directly — Gleam requires compile-time module references. This module uses Erlang’s apply/3 via FFI to bridge that gap, letting the runtime invoke handle_json and render_json on any generated module by name.
Values
pub fn call_handle_json(
module: String,
handler_id: String,
props_json: String,
value: String,
checked: String,
key: String,
) -> Result(String, String)
The live_socket actor needs to invoke the generated handle_json function to process events, but the module is only known at runtime. This wrapper marshals the handler ID, current props, and special variables into dynamic args for the FFI call.
pub fn call_render_json(
module: String,
props_json: String,
) -> Result(String, String)
After handle_json updates the props, the actor needs fresh HTML to send as a patch. Calling render_json dynamically lets the runtime re-render any template module without compile-time coupling to it.
pub fn call_render_tree_json(
module: String,
props_json: String,
) -> Result(String, String)
After handle_json updates the props, the actor needs a fresh tree JSON to diff against the previous tree. Calling render_tree_json dynamically produces the statics/dynamics JSON for any template module.
pub fn is_live_module(module: String) -> Bool
The registry needs to distinguish live modules from static ones at startup. Probing for the is_live export via apply avoids maintaining a separate manifest — the generated module itself declares its liveness through the presence (or absence) of this function.
pub fn module_to_atom(module: String) -> atom.Atom
Erlang’s apply/3 expects module names as atoms, but Gleam uses forward-slash paths (compiled/loom/counter). The BEAM convention replaces slashes with @ for module atoms, so this conversion is needed before every dynamic call.