dlslime-ctrl
dlslime-ctrl is the control plane for DLSlime microservice governance. It provides a Redis-backed registry for discoverable services, heartbeat-based liveness, scope-based isolation, PeerAgent coordination, RDMA memory-region lookup, and declarative peer topology management.
dlslime-ctrl intentionally treats services generically. A cache service, RPC worker, prefill service, decode service, router, or future DLSlime component all register through the same entity lifecycle API and put service-specific fields inside JSON metadata.
Responsibilities
| Area | Responsibility |
|---|---|
| Service registry | Register, discover, heartbeat, and unregister generic entities |
| Microservice governance | Track service kind, endpoint, metadata, resource hints, and TTL |
| Scope isolation | Partition Redis keys by scope so multiple jobs can share one dlslime-ctrl |
| PeerAgent control | Register PeerAgents, publish resource records, and clean stale state |
| RDMA metadata | Store and query memory-region metadata for remote access |
| Topology control | Store desired PeerAgent topology and push connection intents |
| Redis access | Expose the Redis address that remote DLSlime clients should use |
Concepts
Entity
An entity is a discoverable object managed by dlslime-ctrl. The default
entity_type is service.
{
"entity_type": "service",
"entity_id": "cache:0",
"kind": "cache",
"endpoint": {
"host": "127.0.0.1",
"port": 8765,
"protocol": "http"
},
"metadata": {
"p2p_host": "127.0.0.1",
"p2p_port": 8765
}
}
dlslime-ctrl stores the entity as JSON and does not interpret the contents of
endpoint, metadata, or resource beyond preserving them for discovery.
Kind
kind is the service category used for discovery and filtering. Examples:
cacherpc-workerprefilldecoderouter
Scope
scope is an optional namespace. When present, all Redis keys are prefixed with
{scope}:. This lets multiple jobs, tests, or applications share one dlslime-ctrl
and Redis instance without colliding.
Prerequisites
- Redis server
- Rust toolchain when building dlslime-ctrl from source
- Python 3.8+ when using the
dlslime-ctrlPython client package
Build
cd dlslime-ctrl
cargo build --release
# Build a Python wheel that includes the Rust dlslime-ctrl binary
maturin build --release
Run
# Default: Redis at redis://127.0.0.1:6379
cargo run --release -- server
# Specify Redis explicitly
cargo run --release -- server --redis-url redis://your-redis-host:6379
# Or use the environment
export DLSLIME_CTRL_REDIS_URL=redis://your-redis-host:6379
cargo run --release -- server
The HTTP server listens on http://0.0.0.0:4479 by default.
Background Lifecycle
dlslime-ctrl includes a service-style CLI:
pip install -e dlslime-ctrl/
dlslime-ctrl start
dlslime-ctrl status
dlslime-ctrl stop
Useful options:
dlslime-ctrl start --redis-url redis://your-redis-host:6379 --log-file /tmp/dlslime-ctrl.log
dlslime-ctrl server --host 0.0.0.0 --port 3000
dlslime-ctrl stop --force
Runtime metadata is stored under $DLSLIME_CTRL_RUNTIME_DIR, or
$XDG_RUNTIME_DIR/dlslime-ctrl, or /tmp/dlslime-ctrl.
API
Service Registry
| Endpoint | Description |
|---|---|
POST /register |
Register or refresh a generic entity |
POST /unregister |
Remove a registered entity |
POST /heartbeat |
Refresh an entity TTL |
POST /get_entity_info |
Fetch one entity by type and ID |
POST /list_entities |
List entities, optionally filtered by type and kind |
PeerAgent and RDMA
| Endpoint | Description |
|---|---|
POST /start_peer_agent |
Register a PeerAgent and return Redis information |
POST /query |
List PeerAgents visible in the scope |
POST /cleanup |
Clean PeerAgent state and notify peers |
POST /v1/desired_topology/:agent_id |
Set desired PeerAgent topology |
POST /register_mr |
Register a memory region |
POST /get_mr_info |
Query a remote memory region |
Utility
| Endpoint | Description |
|---|---|
POST /get_redis_address |
Return the Redis address remote clients should use |
GET / |
Health check |
Entity API Examples
Register a Cache Service
curl http://127.0.0.1:4479/register \
-H "Content-Type: application/json" \
-d '{
"entity_type": "service",
"entity_id": "cache:0",
"kind": "cache",
"endpoint": {
"host": "127.0.0.1",
"port": 8765,
"protocol": "http"
},
"metadata": {
"p2p_host": "127.0.0.1",
"p2p_port": 8765
},
"scope": "job-a"
}'
Register a ZMQ Service
curl http://127.0.0.1:4479/register \
-H "Content-Type: application/json" \
-d '{
"entity_id": "prefill:0",
"kind": "prefill",
"endpoint": {
"host": "10.0.0.2",
"port": 6001,
"protocol": "zmq"
},
"metadata": {
"world_size": 8,
"num_blocks": 15000,
"peer_addrs": ["10.0.0.2:5000"]
}
}'
entity_type defaults to service when omitted.
Heartbeat
curl http://127.0.0.1:4479/heartbeat \
-H "Content-Type: application/json" \
-d '{
"entity_type": "service",
"entity_id": "cache:0",
"scope": "job-a"
}'
Discover Cache Services
curl http://127.0.0.1:4479/list_entities \
-H "Content-Type: application/json" \
-d '{
"entity_type": "service",
"kind": "cache",
"scope": "job-a"
}'
Response:
{
"status": "ok",
"entities": [
{
"entity_type": "service",
"entity_id": "cache:0",
"id": "cache:0",
"kind": "cache",
"endpoint": {
"host": "127.0.0.1",
"port": 8765,
"protocol": "http"
},
"metadata": {
"p2p_host": "127.0.0.1",
"p2p_port": 8765
},
"resource": null
}
]
}
Python Client
The Python client lives in the dlslime package (see dlslime.ctrl.NanoCtrlClient).
from dlslime.ctrl import NanoCtrlClient
client = NanoCtrlClient("127.0.0.1:4479", scope="job-a")
client.check_connection()
def register_cache() -> bool:
return client.register(
"cache:0",
"cache",
endpoint={"host": "127.0.0.1", "port": 8765, "protocol": "http"},
metadata={"p2p_host": "127.0.0.1", "p2p_port": 8765},
)
if register_cache():
client.start_heartbeat(on_not_found=register_cache)
cache = client.get_entity_info("cache:0")
caches = client.list_entities(kind="cache")
client.stop()
Client Methods
| Method | Description |
|---|---|
register(entity_id, kind, endpoint=None, metadata=None, resource=None, entity_type="service") |
Register a generic entity |
unregister() |
Unregister the entity registered by this client |
heartbeat() |
Refresh the entity TTL |
start_heartbeat(interval=15.0, on_not_found=None, name="dlslime-ctrl-hb") |
Start background heartbeat |
stop_heartbeat(timeout=2.0) |
Stop background heartbeat |
stop(timeout=2.0) |
Stop heartbeat and unregister |
get_entity_info(entity_id, entity_type="service") |
Query one entity |
list_entities(entity_type="service", kind=None) |
List entities |
get_redis_url() |
Resolve Redis URL through dlslime-ctrl |
PeerAgent helpers are also available on the same client:
register_peer(...)cleanup_peer(agent_name)heartbeat_peer(agent_name)set_desired_topology(...)query_peers()
DLSlimeCache Registration
dlslime-cache start --ctrl ... registers itself as a generic service:
{
"entity_type": "service",
"entity_id": "cache:0",
"kind": "cache",
"endpoint": {
"host": "<advertised-host>",
"port": 8765,
"protocol": "http"
},
"metadata": {
"p2p_host": "<advertised-host>",
"p2p_port": 8765
}
}
Clients discover it with list_entities(kind="cache") or
get_entity_info("cache:0").
Redis Key Structure
With scope:
{scope}:{entity_type}:{entity_id}
{scope}:nano_meta:{entity_type}_revision
{scope}:nano_events:{entity_type}_update
{scope}:agent:{agent_id}
{scope}:mr:{agent_id}:{mr_name}
{scope}:spec:topology:{agent_id}
{scope}:stream:{agent_id}
{scope}:inbox:{agent_id}
Without scope, the same keys are used without the prefix, for example
service:cache:0.
Environment Variables
| Variable | Description |
|---|---|
DLSLIME_CTRL_REDIS_URL |
Redis URL used by dlslime-ctrl |
DLSLIME_CTRL_RUST_LOG |
Rust log level, default info |
REDIS_PUBLIC_ADDRESS |
Optional public Redis host:port returned to remote clients |
DLSLIME_CTRL_SCOPE |
Optional client-side scope used by DLSlime services |
Notes
- dlslime-ctrl is stateless; Redis is the source of truth.
- Registered entities expire if they stop heartbeating.
- Service-specific fields belong in
metadata; dlslime-ctrl should not grow kind-specific schemas. - Use
scopefor tests, multiple jobs, and multi-tenant deployments.
Metadata
Release files for dlslime-ctrl 0.1.23
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| dlslime_ctrl-0.1.23-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | Python 3 | none | Linux glibc 2.17+ x86-64 | Details |
Release files / dlslime_ctrl-0.1.23-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | dlslime_ctrl-0.1.23-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 2.4 MB |
| Tags | Linux glibc 2.17+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
7338826b1873c17d8b9838af897143b493491b098ab8e797ab9d371833e0ae04
|
|
BLAKE2b-256 checksum How to use checksums |
d16fc8b454a11b9565456c6cba24088c630d1df81165ff31b9abcb449f0bd1b7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 1, 2026.
Transparency log