Skip to content

NEXUS v0.12.0

Choose a tag to compare

@github-actions github-actions released this 10 Oct 04:40
· 65 commits to main since this release
5069c44

NEXUS v0.12.0 release notes

Prepared 2026-10-10 (not yet released: v0.11.0 is the latest release).

v0.12.0 is a minor release. It adds Runtime.refusalOf, Mesh.update and a shutdown policy for the work a runtime started (shutdown.grace), fixes one behavior of Selector.combine(...).changes, and moves the peer range of @valancex/mesh-runtime to MESH 0.10.

Changes

  • Runtime.refusalOf(value) returns the Runtime.Refusal in value, or undefined. value may be a Refusal, a Cause, or the FiberFailure that the Promise Runtime.run returns rejects with, so a caller who raced a shutdown can write Runtime.refusalOf(error)?.code === "terminating" instead of unwrapping the failure by hand. It recognizes a refusal by its shape, as isRefusal does, so it works across two installed copies of the package. Anything else, a bug included, gives undefined.
  • Selector.combine(...).changes emits on the first commit of either input. It waited for both inputs to have committed before emitting, so a combined selector whose inputs commit at different times missed the first values of the earlier one. This is a bug fix and a behavior change: a consumer that counted emissions will see one more.
  • Mesh.update(previous, snapshot) is MESH 0.10's update through the adapter: it returns { render, patches }, the new render and the render-patch-v1 operations a renderer applies in place, or fails with MeshDiagnostics (and previous is untouched and still dispatches). Like render, it is the runtime's operation and nothing more: the adapter keeps no render (M2), a rejection from the runtime is a defect, and previous must be a render of the same program, which only the caller knows. New types: Mesh.Updated and Mesh.RenderPatches. VALANCE uses it to draw only what changed.
  • @valancex/mesh-runtime peer range is ^0.10.0 (was ^0.8.0 || ^0.9.0). Mesh.update needs 0.10's update, and a package that names an export the installed runtime lacks does not load, so an application on MESH 0.8 or 0.9 stays on NEXUS 0.11.

Shutdown: the work a runtime started

Until now, ending a runtime released its resources while the effects started with Runtime.run and Runtime.runFork kept running, so an effect could be using a Resource that was released under it, and nothing waited for it. Termination now settles that work:

  • Tracked. An effect started with run or runFork is the runtime's work from the moment it starts until it exits, however it exits.
  • Settled. After new work is refused and the bus is closed, termination waits up to the grace for the work to finish on its own, then interrupts what is left and waits for each effect to exit, so it has run its own finalizers before any resource of the runtime is released. The grace is shutdown: { grace } on Runtime.make and Application.start, or Application.shutdown(running, { grace }) for one call. It defaults to 0: interrupt at once, after one turn of the event loop in which a subscription that ended with the bus ends its consumer. Duration.infinity waits for everything.
  • Streams end first. The changes and values of application-owned State (and a Selector over it) now end when termination begins to wind the runtime down, so a consumer started with run ends normally instead of being interrupted to make room for a release that waits for it.
  • A command may end its application. The effect that asks for the shutdown is not waited for or interrupted.
  • What a caller sees. An interrupted run rejects with Effect's interruption (Cause.isInterruptedOnly; Runtime.refusalOf finds nothing), an interrupted runFork fiber exits interrupted, and work started during the grace is refused with Refusal code terminating.
  • Behavior change. An effect that used to outlive termination is now interrupted. Nothing else about the order of termination changed. Code that needs such an effect to finish passes a grace, or awaits it before ending the runtime.

Compatibility

  • API: additive. No export is removed or changed.
  • Install: breaking for an application on MESH 0.8 or 0.9, which must move to MESH 0.10 with NEXUS 0.12 (the peer range). Nothing else about installing changes.
  • Behavior: the Selector.combine(...).changes change and the shutdown change above; nothing else.
  • MESH, PORT, VALANCE: VALANCE can use refusalOf once it depends on this version.
  • API stability: Runtime.refusalOf and the combine behavior are Stable from 0.12.0.