Publish hosted VoidBot health to Idunn

This commit is contained in:
Meta Vens 2026-07-15 20:51:16 +01:00
commit 40d96f6541
2 changed files with 41 additions and 6 deletions

View file

@ -3,7 +3,10 @@
const dgram = require("dgram");
const path = require("path");
const cultLibPackages = path.resolve(__dirname, "..", "..", "CultLib", "packages");
const cultLibRoot = process.env.VOIDBOT_CULTLIB_ROOT
? path.resolve(process.env.VOIDBOT_CULTLIB_ROOT)
: path.resolve(__dirname, "..", "..", "CultLib");
const cultLibPackages = path.join(cultLibRoot, "packages");
process.env.NODE_PATH = [cultLibPackages, process.env.NODE_PATH || ""].filter(Boolean).join(path.delimiter);
require("module").Module._initPaths();
@ -14,7 +17,7 @@ const {
encodeRudpPacket,
} = require("cultnet-ts");
const { encode } = require(path.resolve(__dirname, "..", "..", "CultLib", "node_modules", "@msgpack", "msgpack"));
const { encode } = require(path.join(cultLibRoot, "node_modules", "@msgpack", "msgpack"));
const CULTNET_RUDP_PROTOCOL_ID = "cultnet.transport.rudp.v0";
const IDUNN_HEALTH_RUDP_CONNECTION_ID = 0x1d0d0001;
@ -283,7 +286,11 @@ async function closeSocket(socket) {
});
}
main().catch((error) => {
console.error(error?.stack || String(error));
process.exit(1);
});
module.exports = { publishIdunnRudpHealth, parseEndpoint };
if (require.main === module) {
main().catch((error) => {
console.error(error?.stack || String(error));
process.exit(1);
});
}

View file

@ -10,6 +10,7 @@ const {
readSwarmOperatorInputs,
watchSwarmOperatorInputs,
} = require("./voidbot-swarm-operator-view.cjs");
const { parseEndpoint: parseIdunnEndpoint, publishIdunnRudpHealth } = require("./publish-idunn-rudp-health.cjs");
const repoRoot = path.resolve(__dirname, "..");
const defaultStorePath = path.join(repoRoot, ".voidbot", "status", "cultmesh", "voidbot-swarm-state.cc");
@ -32,6 +33,8 @@ const operatorInputPaths = {
const bind = parseBind(args.bind || process.env.VOIDBOT_SWARM_CULTMESH_BIND || defaultBind);
const odinCultMeshUri = args.odinCultMeshUri || args["odin-cultmesh-uri"] || process.env.VOIDBOT_ODIN_CULTMESH_URI || process.env.ODIN_CULTMESH_URI || defaultOdinCultMeshUri;
const odinRudpEndpoint = args.odinRudpEndpoint || args["odin-rudp-endpoint"] || process.env.VOIDBOT_ODIN_RUDP || process.env.CULTMESH_URI_ODIN_RUDP || defaultOdinRudpEndpoint;
const idunnHealthEndpoint = String(process.env.VOIDBOT_IDUNN_RUDP_HEALTH || "").trim();
const idunnHealthIntervalMs = 30_000;
const {
CultMesh,
CultMeshMemoryProviderReceiptStore,
@ -56,6 +59,8 @@ let announceTimer = null;
let liveProviderSession = null;
let stopOperatorWatch = null;
let operatorPublishChain = Promise.resolve();
let idunnHealthTimer = null;
let idunnHealthPublishChain = Promise.resolve();
main().catch((error) => {
console.error(error instanceof Error ? error.stack || error.message : String(error));
@ -97,10 +102,18 @@ async function main() {
});
}, 30_000);
announceTimer.unref?.();
if (idunnHealthEndpoint) {
await queueIdunnHealthPublication();
idunnHealthTimer = setInterval(queueIdunnHealthPublication, idunnHealthIntervalMs);
idunnHealthTimer.unref?.();
} else {
console.log("VoidBot Idunn health publication is disabled because VOIDBOT_IDUNN_RUDP_HEALTH is not configured.");
}
const shutdown = () => {
try {
if (announceTimer) clearInterval(announceTimer);
if (idunnHealthTimer) clearInterval(idunnHealthTimer);
server?.close?.();
stopOperatorWatch?.();
void liveProviderSession?.stop?.();
@ -112,6 +125,21 @@ async function main() {
process.once("SIGTERM", shutdown);
}
function queueIdunnHealthPublication() {
idunnHealthPublishChain = idunnHealthPublishChain
.then(() => publishIdunnRudpHealth({
endpoint: parseIdunnEndpoint(idunnHealthEndpoint),
daemonId: process.env.VOIDBOT_IDUNN_DAEMON || "voidbot",
healthContract: process.env.VOIDBOT_IDUNN_HEALTH_CONTRACT || "voidbot.cultnet-rudp-stack-health",
}, {
state: "healthy",
detail: "VoidBot swarm CultMesh publisher is serving retained runtime state.",
observedAt: new Date().toISOString(),
}))
.catch((error) => console.error(`VoidBot Idunn health publication failed: ${error instanceof Error ? error.message : String(error)}`));
return idunnHealthPublishChain;
}
async function publishCurrentControlState() {
if (!fs.existsSync(controlStorePath)) return;
const controlNode = await CultMesh.createNode(controlStorePath, { documents: [documents.swarmControl] });