Service discovery for MoonBit: the contract a registry implements, an in-process registry, a conformance suite, and clients for Redis, etcd and Consul.
async fn greeter(registry : @memory.Registry) -> Unit {
@async.with_task_group(group => {
// A service announces itself for as long as this task runs, and leaves on the way out.
group.spawn_bg(() =>
@moonsd.hold(registry, "greeter", @moonsd.Endpoint::new("10.0.0.1", 12000))
)
// A caller follows the service in one task and reads the list on the request path.
let view = @moonsd.View::new()
group.spawn_bg(() => view.follow(registry, "greeter"))
@async.sleep(50)
println(view.endpoints().map(e => e.address()).join(", "))
})
}moon add moonbitstack/moonsd| Trait | Methods | What it promises |
|---|---|---|
| Registrar | register, renew, deregister | An endpoint is known for ttl milliseconds from its last renewal. renew raises Refused::Expired once the registry has let it go; deregister is harmless on a lease already gone. |
| Discovery | resolve, watch | resolve answers once, and an unknown service has no endpoints. |
| Watcher | next, close | The first next gives the service as it stands; each later one waits for a change. |
| Package | Contents |
|---|---|
| moonsd | Endpoint, Lease, Update, Refused, the three traits, hold, renew_after, View |
| moonsd/memory | Registry, the contract in this process: leases when given a clock, revisions, snapshot and restore |
| moonsd/conformance | check, every behaviour the contract promises, run against any backend |
| Module | Directory | sd package | Page |
|---|---|---|---|
| moonbitstack/moonredis | drivers/redis | Keys that expire, watched by reading again | redis |
| moonbitstack/moonetcd | drivers/etcd | Keys on leases, watched by revision | etcd |
| moonbitstack/moonconsul | drivers/consul | Services with ttl checks, watched by blocking queries | consul |
async test "my backend keeps the contract" {
let backend = connect()
@conformance.check(backend, backend)
}| Backend | Verified against | What the suite covers |
|---|---|---|
| moonsd/memory | itself, on every target | the round trip, removal, Expired on a spent lease, a watcher's arrival, departure and empty service, hold with View, and a lease left to lapse |
| moonredis | Redis 8, standalone, cluster and sentinel | the same, with Expired coming from a key whose ttl ran out, and a watcher that sees the change on its next poll |
| moonetcd | etcd 3.5, one node and a three-node cluster with members killed | the same, with Expired coming from a keep-alive that reports no time left, and a watcher that resumes after a compaction |
| moonconsul | Consul 1.20, two agents | the same, with Expired coming from a ttl check that failed, and a watcher that follows a blocking query's index |
pub struct View {
// private fields
}fn renew_after(ttl : Int) -> Intlet retry : Intlet ttl : IntInstall
Download zipService discovery for MoonBit: the contract a registry implements, an in-process registry, a conformance suite, and clients for Redis, etcd and Consul.