Vix.cpp docs moved to vixcpp.com
Skip to content

Discovery ​

Discovery is the part of the Softadastra JavaScript SDK that lets a local node find peers.

The core rule is:

txt
Discovery finds peers.
Transport connects peers.
Sync sends operations.

Discovery is optional. A Softadastra client can still write, read, persist, and track sync work without discovery.

Why discovery exists ​

Without discovery, peers must be configured manually:

js
const peer = new Peer("node-b", "127.0.0.1", 4042);

Discovery exists to find peers dynamically, answering: which peers are available, where can I reach them, which node id do they use, and which transport port do they expose?

Discovery is optional ​

js
options.enableDiscovery = false;

The client can still open, put, get, remove, syncStateInfo, tick, startTransport, connect to manually configured peers, and close.

Basic discovery configuration ​

js
const options = ClientOptions.local("node-discovery-a");

options.enableWal = true;
options.walPath = "data/sdk-discovery.wal";
options.autoFlush = true;

options.enableTransport = true;
options.transportHost = "127.0.0.1";
options.transportPort = 4051;

options.enableDiscovery = true;
options.discoveryHost = "127.0.0.1";
options.discoveryPort = 5051;
options.discoveryBroadcastHost = "127.0.0.1";
options.discoveryBroadcastPort = 5052;

Basic discovery example ​

js
import { Client, ClientOptions } from "@softadastra/sdk";

const options = ClientOptions.local("node-discovery-a");

options.enableWal = true;
options.walPath = "data/sdk-discovery.wal";
options.autoFlush = true;

options.enableTransport = true;
options.transportHost = "127.0.0.1";
options.transportPort = 4051;

options.enableDiscovery = true;
options.discoveryHost = "127.0.0.1";
options.discoveryPort = 5051;
options.discoveryBroadcastHost = "127.0.0.1";
options.discoveryBroadcastPort = 5052;

const client = new Client(options);

const openResult = await client.open();

if (openResult.isErr()) {
  console.error(`failed to open client: ${openResult.error().message}`);
  process.exit(1);
}

const discoveryResult = await client.startDiscovery();

if (discoveryResult.isErr()) {
  console.error(`failed to start discovery: ${discoveryResult.error().message}`);
  await client.close();
  process.exit(1);
}

const peersResult = await client.peers();

console.log("discovery");
console.log(`  running : ${client.discoveryRunning() ? "yes" : "no"}`);
console.log(`  bind    : ${options.discoveryHost}:${options.discoveryPort}`);
console.log(`  target  : ${options.discoveryBroadcastHost}:${options.discoveryBroadcastPort}`);

console.log("\npeers");

if (peersResult.isOk() && peersResult.value().length === 0) {
  console.log("  no peer discovered yet");
} else if (peersResult.isOk()) {
  for (const peer of peersResult.value()) {
    console.log(`  ${peer.nodeId} ${peer.host}:${peer.port}`);
  }
}

await client.close();

Expected output when no other node is running:

txt
discovery
  running : yes
  bind    : 127.0.0.1:5051
  target  : 127.0.0.1:5052

peers
  no peer discovered yet

No discovered peer is normal. The local client can still write and read local data.

Start discovery ​

js
const result = await client.startDiscovery();

if (result.isErr()) {
  console.error(`failed to start discovery: ${result.error().message}`);
  await client.close();
  process.exit(1);
}

Snake_case alias, if exposed: await client.start_discovery().

Check discovery status ​

js
if (client.discoveryRunning()) {
  console.log("discovery is running");
}

List peers ​

js
const peers = await client.peers();

if (peers.isOk()) {
  for (const peer of peers.value()) {
    console.log(`${peer.nodeId} ${peer.host}:${peer.port}`);
  }
}

if (peers.isOk() && peers.value().length === 0) {
  console.log("no peer discovered yet");
}

Two-node discovery shape ​

Node A:

js
options.discoveryPort = 5051;
options.discoveryBroadcastPort = 5052;
options.transportPort = 4051;

Node B:

js
options.discoveryPort = 5052;
options.discoveryBroadcastPort = 5051;
options.transportPort = 4052;

Each node targets the other node's discovery listener.

Discovery and transport together ​

js
const peers = await client.peers();

if (peers.isOk()) {
  for (const peer of peers.value()) {
    const connected = await client.connect(peer);

    if (connected.isOk()) {
      console.log(`connected to ${peer.nodeId}`);
    }
  }
}

Discovery API reference ​

MethodPurpose
startDiscovery()Start peer discovery
start_discovery()Snake_case alias, if exposed
stopDiscovery()Stop discovery, if exposed
stop_discovery()Snake_case alias, if exposed
discoveryRunning()Check discovery state
discovery_running()Snake_case alias, if exposed
peers()List known peers

Discovery option reference ​

OptionPurpose
enableDiscoveryEnable discovery support
discoveryHostLocal discovery bind host
discoveryPortLocal discovery bind port
discoveryBroadcastHostDiscovery target host
discoveryBroadcastPortDiscovery target port

Peer reference ​

FieldPurpose
nodeIdPeer node id
hostPeer transport host
portPeer transport port

Common issues ​

Port already in use ​

sh
ss -lunp | grep 5051

Use another discovery port: options.discoveryPort = 5053.

Wrong discovery target ​

For local two-node tests, check that each node targets the other node's discovery port.

No peers found ​

Possible causes: no other node is running, other node uses a different discovery port, or discovery is disabled on the other node.

Common mistakes ​

Expecting discovery to connect peers ​

Discovery finds peers. Transport connects peers.

Expecting peers immediately ​

If only one node is running, there may be no peers.

Treating no peers as local failure ​

No peers only means no remote node is currently known. Local store can still work.

Run the SDK example ​

sh
cd ~/softadastra/sdk-js
npm install
mkdir -p data
npm run examples:discovery

Summary ​

Discovery is the peer discovery layer of the JavaScript SDK.

It gives you startDiscovery, discoveryRunning, peers, and optional stopDiscovery.

The key idea is: discovery finds peers, transport connects peers, sync sends operations, and store remains local-first.

Next step ​

Continue with metadata:

Go to Metadata

Released under the Apache License 2.0.