March Docs

ClusterLoad

ClusterLoad: per-node CPU/memory headroom for capacity-aware RPC routing.

Each node samples its own resources with local/1 (backed by the System.* builtins). Samples are shared across the cluster (e.g. gossiped or pulled on demand) and collected into a candidate list; pick_by/2 then routes to the node your scoring function rates highest. Raw metrics are exposed — you choose what "headroom" means.

Wire transfer: to_ints/1 / from_ints/2 marshal a NodeLoad to/from a flat Int list (node_id stays caller-side, since the caller knows which node it queried), suitable for MessagePack or any int-array codec.

  let me   = ClusterLoad.local("node-a")
  -- ... collect peers' NodeLoad into `candidates` ...
  match ClusterLoad.pick_by(candidates, ClusterLoad.spare_cpu_milli) do
    Some(node) -> -- route the expensive call to node.node_id
    None       -> -- cluster view empty; fall back to local
  end

Types

typeNodeLoadNodeLoad = {#

Functions

fnfrom_intsfrom_ints(node_id : String, xs : List(Int)) : NodeLoad#

Rebuild a NodeLoad from a wire Int list plus the known node_id. Missing fields default to 0.

fnlocallocal(node_id : String, now_ms : Int) : NodeLoad#

Sample the local node's current CPU/memory headroom at [now_ms].

fnpick_bypick_by(candidates : List(NodeLoad), score : NodeLoad -> Int) : Option(NodeLoad)#

Pick the candidate your score function rates highest (argmax). Ties keep the earlier candidate. Returns None for an empty list.

fnspare_cpu_millispare_cpu_milli(nl : NodeLoad) : Int#

Spare CPU as load-millis below saturation: cpu_count*1000 - load. Higher = more idle.

fnspare_mem_mbspare_mem_mb(nl : NodeLoad) : Int#

Available memory in MB (a ready-made score for memory-bound work).

fnto_intsto_ints(nl : NodeLoad) : List(Int)#

Marshal a NodeLoad's metrics to a flat Int list for the wire (node_id excluded). [cpu_count, cpu_load_milli, mem_total_mb, mem_avail_mb, sampled_at].