#registry #back-end #registration #discovery #plexus #health-check #hubs #storage-config #config-file #file-config

bin+lib plexus-registry

Backend discovery and registration service for Plexus hubs

1 unstable release

0.1.0 Feb 5, 2026

#3 in #plexus


Used in 2 crates (via plexus-substrate)

AGPL-3.0-only

38KB
669 lines

Registry

Backend discovery and registration service for Plexus hubs.

Overview

Registry is a standalone service that enables dynamic discovery of Plexus backend instances. It stores backend connection information and provides a simple API for registration, discovery, and health checks.

Key features:

  • SQLite storage with TOML configuration
  • Auto-registration of local Plexus instance
  • Manual registration via RPC
  • Health check timestamps
  • Config file hot-reloading

Quick Start

Running the Registry

cd registry
cargo run

By default, the registry starts on port 4445 (4444 is reserved for the main Plexus instance).

Configuration

The registry looks for configuration at ~/.config/plexus/backends.toml:

[[backend]]
name = "plexus"
host = "127.0.0.1"
port = 4444
protocol = "ws"
description = "Local Plexus instance"

[[backend]]
name = "prod"
host = "plexus.example.com"
port = 4444
protocol = "wss"
description = "Production Plexus hub"

Environment Variables

  • REGISTRY_PORT - WebSocket server port (default: 4445)
  • RUST_LOG - Logging level (default: info)

API Methods

All methods are in the registry namespace:

register

Register a new backend.

Parameters:

  • name (string, required) - Unique backend name
  • host (string, required) - Host address
  • port (number, required) - Port number
  • protocol (string, optional) - Protocol ("ws" or "wss", default: "ws")
  • description (string, optional) - Human-readable description
  • namespace (string, optional) - Routing namespace

Example:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "registry.register",
  "params": {
    "name": "dev",
    "host": "192.168.1.100",
    "port": 4444,
    "protocol": "ws",
    "description": "Development server"
  }
}

list

List all registered backends.

Parameters:

  • active_only (boolean, optional) - Filter to active backends only (default: true)

Example:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "registry.list",
  "params": {
    "active_only": true
  }
}

get

Get a specific backend by name.

Parameters:

  • name (string, required) - Backend name

Example:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "registry.get",
  "params": {
    "name": "plexus"
  }
}

update

Update an existing backend.

Parameters:

  • name (string, required) - Backend name to update
  • host (string, optional) - New host address
  • port (number, optional) - New port number
  • protocol (string, optional) - New protocol
  • description (string, optional) - New description
  • namespace (string, optional) - New namespace

Example:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "registry.update",
  "params": {
    "name": "dev",
    "host": "192.168.1.101"
  }
}

delete

Remove a backend from the registry.

Parameters:

  • name (string, required) - Backend name to delete

Example:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "registry.delete",
  "params": {
    "name": "old-server"
  }
}

ping

Update the health check timestamp for a backend.

Parameters:

  • name (string, required) - Backend name

Example:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "registry.ping",
  "params": {
    "name": "plexus"
  }
}

reload

Reload backends from the configuration file.

Example:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "registry.reload",
  "params": {}
}

Testing with websocat

# Start the registry
cargo run &

# Connect with websocat
websocat ws://localhost:4445

# List backends
{"jsonrpc":"2.0","id":1,"method":"registry.list","params":{"active_only":true}}

# Register a new backend
{"jsonrpc":"2.0","id":2,"method":"registry.register","params":{"name":"test","host":"127.0.0.1","port":8888}}

Integration with Synapse

Synapse can discover backends from the registry:

# Synapse will query the registry for available backends
synapse hub2 cone list

# This internally:
# 1. Connects to registry at localhost:4445
# 2. Calls registry.get("hub2")
# 3. Connects to the discovered backend
# 4. Executes cone.list

Architecture

Data Flow

┌──────────┐         ┌──────────┐         ┌──────────┐
│ Synapse  │────────>│ Registry │────────>│  SQLite  │
│  Client  │ discover│  Service │  store  │ Database │
└──────────┘         └──────────┘         └──────────┘
                          │
                          │ load
                          ▼
                     ┌──────────┐
                     │   TOML   │
                     │  Config  │
                     └──────────┘

Storage Priority

  1. Runtime registrations (via register RPC)
  2. Database (persisted from previous runs)
  3. Config file (~/.config/plexus/backends.toml)
  4. Auto-registration (self at localhost:4444)

Source Types

  • Auto - Automatically registered at startup (e.g., plexus @ localhost:4444)
  • File - Loaded from TOML configuration file
  • Manual - Registered via RPC call
  • Env - Loaded from environment variables (future)

Development

Building

cargo build --release

Running Tests

cargo test

As a Library

use registry::{Registry, RegistryStorageConfig};
use plexus_transport::TransportServer;
use std::sync::Arc;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Create registry with custom config
    let config = RegistryStorageConfig {
        db_path: "custom.db".into(),
        config_path: Some("backends.toml".into()),
    };

    let registry = Registry::new(config).await?;
    let registry_arc = Arc::new(registry);

    // Host via hub-transport
    let rpc_converter = |arc: Arc<Registry>| Ok(arc.into_rpc_methods());

    TransportServer::builder(registry_arc, rpc_converter)
        .with_websocket(4445)
        .build().await?
        .serve().await?;

    Ok(())
}

License

AGPL-3.0-only

Dependencies

~58–78MB
~1.5M SLoC