Backend · Redis
A complete Redis client, and moonredis/sd: the contract
carried by keys that expire. An endpoint is a key with a ttl; an instance that stops
renewing removes itself, because that is what expiry is.
What it is
Redis already knows how to forget things on a schedule, so the registry borrows that instead
of running a sweeper of its own. The endpoint is written as JSON under
moonsd:{service}:{id} with a ttl, and renewing is
PEXPIRE. The braces are a hash tag: a service's keys share a
cluster slot, so a lookup of one service never fans out across the cluster.
The lease
SET key value PX ttl. The token in the lease is the key
itself, so renewing and removing need nothing else.
PEXPIRE key ttl. It answers zero when the key is already
gone, which is the one case the contract calls Refused::Expired.
DEL key, and harmless when the key has already expired —
the same command either way.
The watcher
Keyspace notifications exist and are best effort: a client that subscribes to them can miss
the event of a key expiring while it was disconnected, which is precisely the moment a
registry matters. So watch reads the service again every
poll milliseconds — a second by default — and reports a change
only when the list differs.
The registry takes a lock around its own commands, because a shared connection answers one command at a time and a cancelled task must still read its reply. Give the registry a client of its own; the lock orders the registry's commands, not those of anything else on that connection.
The client behind it
sd is a small package on top of a full client: RESP2 and RESP3,
the command families including the Redis 8 modules, pipelines and transactions, pub/sub with
sharding, client-side caching, cluster routing, sentinel discovery, a pool, retries, TLS and
ACL authentication. A service that already talks to Redis for its cache uses the same client
for its registration.