Sign in

    moonbitstack/moonzero/registry does not have a README file

    Resolve

    type Resolve = (String) -> Array[Endpoint]

    The resolve half of go-zero's discovery (← discov.Discovery): a function from a service name to its live endpoints. Any store — the in-memory InMemoryRegistry, the persisted PersistentRegistry, or a future etcd/consul client — exposes one via resolver(), so a balancer and the load-balanced channel are written once against the interface and the backing store swaps by swapping the closure.

    Balancer

    pub(all) enum Balancer {
    RoundRobinBalancer(RoundRobin)
    PickFirst
    WeightedBalancer(WeightedRoundRobin)
    }

    The choice of balancer for a load-balanced channel: round-robin cycles through the resolved instances (spreading load evenly), WeightedBalancer shares them out in proportion to Endpoint::weight, PickFirst pins the head instance (← gRPC's pick_first).

    Balancer::pick

    fn Balancer::pick(self : Balancer, endpoints : Array[Endpoint]) -> Endpoint?

    Pick one endpoint from a resolved set, or None if it is empty.

    Balancer::round_robin

    fn Balancer::round_robin() -> Balancer

    A round-robin balancer, cursor at the first instance.

    Balancer::weighted

    fn Balancer::weighted() -> Balancer

    A weighted balancer, with no credit accrued yet.

    Endpoint

    pub(all) struct Endpoint {
    host : String
    port : Int
    weight : Int
    } derive(Eq,
    Debug
    )

    A service endpoint (← go-zero's discov target): the host and port an instance listens on, plus a routing weight (default 1). The weight is carried through registration and snapshots and is what WeightedRoundRobin shares traffic by; round-robin and pick-first ignore it.

    Endpoint::address

    fn Endpoint::address(self : Endpoint) -> String

    The host:port dial string.

    Endpoint::equal

    fn Endpoint::equal(Endpoint, Endpoint) -> Bool

    Endpoint::new

    fn Endpoint::new(host : String, port : Int, weight? : Int) -> Endpoint

    Build an endpoint; weight defaults to 1, matching an unweighted instance.

    Endpoint::not_equal

    fn Endpoint::not_equal(x : Endpoint, y : Endpoint) -> Bool

    Endpoint::parse

    fn Endpoint::parse(s : String) -> Endpoint?

    Parse a host:port dial string into an Endpoint, splitting on the last colon so IPv6-ish hosts still work; None on a missing or non-numeric port.

    Endpoint::to_repr

    InMemoryRegistry

    pub struct InMemoryRegistry {
    instances : Map[String, Map[String, Endpoint]]
    seq : Int
    revision : Int64
    }

    An in-memory service registry (← go-zero's etcd discov store, minus the network): a two-level map of service -> instance-id -> endpoint and a monotonic revision bumped on every mutation, mirroring etcd's store revision so a watcher could detect change. Instance ids are <service>/<n>, the leaf of the etcd key an instance would lease.

    InMemoryRegistry::deregister

    fn InMemoryRegistry::deregister(self : InMemoryRegistry, service : String, key : String) -> Bool

    Remove the instance at key from service. Returns true if it existed (and bumps the revision), false if the service or key was unknown.

    InMemoryRegistry::new

    A fresh, empty registry at revision 0.

    InMemoryRegistry::register

    fn InMemoryRegistry::register(self : InMemoryRegistry, service : String, endpoint : Endpoint) -> String

    Register endpoint under service and return its instance key. Each call mints a distinct key, so two instances of one service coexist, and bumps the revision.

    InMemoryRegistry::resolve

    fn InMemoryRegistry::resolve(self : InMemoryRegistry, service : String) -> Array[Endpoint]

    The endpoints registered for service, in registration order.

    InMemoryRegistry::resolver

    fn InMemoryRegistry::resolver(self : InMemoryRegistry) -> ((String) -> Array[Endpoint])

    This registry as a Resolve interface value.

    InMemoryRegistry::revision

    fn InMemoryRegistry::revision(self : InMemoryRegistry) -> Int64

    The store revision, incremented on each register/deregister — etcd's mod-revision, the value a watcher compares against to see new state.

    InMemoryRegistry::services

    fn InMemoryRegistry::services(self : InMemoryRegistry) -> Array[String]

    Every service name with at least one live instance.

    LoadBalancedChannel

    pub struct LoadBalancedChannel {
    resolve : (String) -> Array[Endpoint]
    cluster : RpcCluster
    balancer : Balancer
    service : String
    }

    A load-balanced zRPC client (← go-zero's zrpc.Client over a discovery target): it resolves a service through the Resolver, picks a live instance with the Balancer, dials it on the RpcCluster, and makes the call. The whole resolve→balance→dial→call path runs per call, so instances registering or deregistering between calls take effect on the next one.

    LoadBalancedChannel::call

    fn LoadBalancedChannel::call(self : LoadBalancedChannel, path : String, request : Bytes) -> Result[Bytes,
    Status
    ] raise

    Make a unary call to path, resolving and balancing to a live instance first.

    LoadBalancedChannel::call_bidi_streaming

    fn LoadBalancedChannel::call_bidi_streaming(self : LoadBalancedChannel, path : String, requests : Array[Bytes]) -> Result[Array[Bytes],
    Status
    ] raise

    Make a bidirectional-streaming call to path, resolving and balancing to a live instance first, then driving the whole requests exchange to completion.

    LoadBalancedChannel::call_server_streaming

    fn LoadBalancedChannel::call_server_streaming(self : LoadBalancedChannel, path : String, request : Bytes) -> Result[Array[Bytes],
    Status
    ] raise

    Make a server-streaming call to path, resolving and balancing to a live instance first.

    LoadBalancedChannel::new

    fn LoadBalancedChannel::new(resolve : (String) -> Array[Endpoint], cluster : RpcCluster, service : String, balancer? : Balancer) -> LoadBalancedChannel

    Build a load-balanced channel for service over a Resolve interface, dialing through cluster with balancer (round-robin by default).

    PersistentRegistry

    pub struct PersistentRegistry {
    instances : Map[String, Map[String, Endpoint]]
    key_rev : Map[String, Int64]
    seq : Int
    revision : Int64
    events : Array[RegistryEvent]
    watchers : Array[(RegistryEvent) -> Unit]
    }

    A persisted, watchable service registry (← go-zero's etcd discov publisher): the same two-level service -> instance-id -> endpoint store as InMemoryRegistry, plus a per-key mod-revision, an append-only event log for catch-up watchers, live watcher callbacks fired on every mutation, and snapshot/restore that round-trip the whole keyspace through an etcd v3 RangeResponse-shaped JSON document — the bytes a file- or etcd-backed deployment persists and reloads without losing a revision.

    PersistentRegistry::deregister

    fn PersistentRegistry::deregister(self : PersistentRegistry, service : String, key : String) -> Bool

    Remove the instance at key from service. On success bumps the revision and emits a Delete; an unknown service or key is a no-op returning false.

    PersistentRegistry::events_since

    fn PersistentRegistry::events_since(self : PersistentRegistry, revision : Int64) -> Array[RegistryEvent]

    Every event with a revision greater than revision (← etcd's watch start_revision): the catch-up a client replays to reach the current state before switching to live watch callbacks.

    PersistentRegistry::keyed_entries

    fn PersistentRegistry::keyed_entries(self : PersistentRegistry) -> Array[(String, Endpoint, Int64)]

    Every registered instance as (instance-key, endpoint, mod-revision), across all services — the flat keyspace a file- or etcd-backed reader diffs one load against the next to compute the Put/Delete events a change produced.

    PersistentRegistry::new

    A fresh, empty persisted registry at revision 0.

    PersistentRegistry::register

    fn PersistentRegistry::register(self : PersistentRegistry, service : String, endpoint : Endpoint) -> String

    Register endpoint under service, mint a fresh instance key, bump the revision, and emit a Put. Returns the instance key (<service>/<n>).

    PersistentRegistry::resolve

    fn PersistentRegistry::resolve(self : PersistentRegistry, service : String) -> Array[Endpoint]

    The endpoints registered for service, in registration order.

    PersistentRegistry::resolver

    fn PersistentRegistry::resolver(self : PersistentRegistry) -> ((String) -> Array[Endpoint])

    This registry as a Resolve interface value.

    PersistentRegistry::restore

    Rebuild a registry from a snapshot document, preserving instance keys, their endpoints and mod-revisions, the id counter, and the store revision — so a reloaded registry mints the next key exactly where the persisted one left off and a watcher's events_since(old_revision) still lines up.

    PersistentRegistry::revision

    fn PersistentRegistry::revision(self : PersistentRegistry) -> Int64

    The store revision, bumped on each register/deregister.

    PersistentRegistry::services

    fn PersistentRegistry::services(self : PersistentRegistry) -> Array[String]

    Every service name with at least one live instance.

    PersistentRegistry::snapshot

    fn PersistentRegistry::snapshot(self : PersistentRegistry) -> String

    Serialize the whole keyspace as an etcd v3 RangeResponse-shaped JSON document: a header carrying the store revision and the id counter, and one key/value entry per instance carrying its endpoint and mod-revision. This is the exact payload a file- or etcd-backed deployment persists; restore rebuilds an identical registry from it, revisions intact.

    PersistentRegistry::watch

    fn PersistentRegistry::watch(self : PersistentRegistry, on_event : (RegistryEvent) -> Unit) -> Unit

    Register a live watcher fired on every subsequent mutation, in revision order (← etcd's Watch with no start revision). To also see changes already applied, replay events_since first.

    RegistryEvent

    pub(all) enum RegistryEvent {
    Put(key~ : String, endpoint~ : Endpoint, revision~ : Int64)
    Delete(key~ : String, revision~ : Int64)
    } derive(Eq,
    Debug
    )

    A change to the registry keyspace, in etcd v3's watch shape: a Put carries the instance key and its endpoint, a Delete carries the key that went away, and both carry the store revision the change produced. A watcher receives these in revision order, so a client can rebuild the live set incrementally instead of re-resolving the whole service.

    RegistryEvent::equal

    RegistryEvent::not_equal

    fn RegistryEvent::not_equal(x : RegistryEvent, y : RegistryEvent) -> Bool

    RegistryEvent::revision

    fn RegistryEvent::revision(self : RegistryEvent) -> Int64

    The store revision a registry event was produced at.

    RoundRobin

    pub struct RoundRobin {
    cursor : Int
    }

    A round-robin balancer (← go-zero's roundRobinBalancer) over a resolved endpoint set: successive picks cycle through the instances, spreading load evenly. Holds only a cursor, so it is cheap to keep per client.

    RoundRobin::new

    fn RoundRobin::new() -> RoundRobin

    A round-robin balancer starting at the first instance.

    RoundRobin::pick

    fn RoundRobin::pick(self : RoundRobin, endpoints : Array[Endpoint]) -> Endpoint?

    Pick the next endpoint in rotation, or None if the set is empty. The cursor advances modulo the set size, so it stays valid as instances come and go.

    RpcCluster

    pub struct RpcCluster {
    servers : Map[String,
    RpcServer
    ]
    }

    The in-process dial table: an endpoint address maps to the RpcServer listening there. It stands in for DNS resolution plus a socket dial in the in-process h2c transport — a real deployment opens a connection to the address instead of looking the server up here, but the resolve→balance→call path above it is the same.

    RpcCluster::add

    Bind the server reachable at endpoint's address.

    RpcCluster::dial

    Open a channel to the server bound at endpoint, or None if nothing is reachable there (a stale registry entry pointing at a gone instance).

    RpcCluster::new

    fn RpcCluster::new() -> RpcCluster

    An empty cluster.

    WeightedRoundRobin

    pub struct WeightedRoundRobin {
    scores : Map[String, Int]
    }

    A weighted balancer over Endpoint::weight, using smooth weighted round-robin: every pick credits each instance with its own weight, serves the highest-credited one, then charges it the total weight of the set. Across one full cycle each instance is served exactly its share of the traffic, and the picks interleave instead of arriving in runs — a weight-5 instance is not handed five requests back to back.

    Credit is keyed by address(), so an instance that leaves and returns resumes where it was rather than jumping the queue, and two instances sharing an address are treated as one. An instance whose weight is zero or negative is never picked; a set where every weight is non-positive yields None.

    WeightedRoundRobin::new

    A weighted balancer with no credit accrued yet.

    WeightedRoundRobin::pick

    fn WeightedRoundRobin::pick(self : WeightedRoundRobin, endpoints : Array[Endpoint]) -> Endpoint?

    Pick the next endpoint in weight order, or None if nothing is eligible.

    pick_first

    fn pick_first(endpoints : Array[Endpoint]) -> Endpoint?

    Pick the first endpoint (← gRPC's pick_first), or None if the set is empty. A stable choice that only moves when the head instance goes away.

    resolve_one

    fn resolve_one(registry : InMemoryRegistry, service : String, balancer : RoundRobin) -> Endpoint?

    Resolve service on the registry and pick one endpoint with balancer — the resolve-then-balance step a zRPC client runs before each call. An etcd- or consul-backed registry with the same resolve shape drops in unchanged.