Stopping the server explicitly
Goal
Drive an explicit shutdown from a flow — for example, to release the port for an external test, or to swap the running server out of the way before changing a construction-time option.
For most flows you do not need this. Process exit (SIGINT / SIGTERM / Node-RED stopping) and config changes on redeploy are already handled by the bootstrap helper. This page is for the cases where you want a "Stop Server" button.
Wire the handle into flow context
The boot Function pattern from Creating an OPC UA server ends with:
flow.set("$opcuaHandle", handle);
That cached handle is what the Stop Function reaches for.
The Stop Function
const sterfive = global.get("sterfive");
if (!sterfive) {
node.error("global.get('sterfive') is not set — is the Sterfive OPC UA palette loaded?");
} else {
const handle = flow.get("$opcuaHandle");
if (!handle || !handle.isRunning()) {
node.warn("OPC UA server is not running");
} else {
await handle.shutdown(2000);
flow.set("$opcuaHandle", undefined);
flow.set("$myVariable", undefined);
node.send({ payload: "OPC UA Server stopped" });
}
}
What it does:
handle.isRunning()returnstruebetween successfulbootstrapServerand the momentshutdown()resolves (or process teardown). It is the single source of truth — do not look athandle.server.isRunning()or anything underneath.handle.shutdown(timeoutMs)is idempotent and concurrent-safe: a second call while shutdown is in flight returns the same promise. The argument is the maximum time to wait for graceful client disconnects before forcing channels closed.- After
shutdown()resolves, the handle's registry slot is released. The nextbootstrapServer({...})call with the same config will build a fresh server, re-runningonPopulate.
Clearing the cached references
Always pair await handle.shutdown(...) with flow.set("$opcuaHandle", undefined) and clear any other $<varName> flow-context keys that point at UA variables — those references are now attached to a torn-down address space and will throw AddressSpace has been disposed if reused.
Re-booting after stop
After the Stop Function has run, simply re-trigger your boot Inject. The boot Function calls bootstrapServer({...}), the registry slot is empty, and a fresh server is built (with onPopulate re-running and a fresh handle.exposed bag).
Stopping all servers in one shot
If you have multiple servers running under different ownerKey values (see Scaling and limits), bootstrap.shutdownAllServers(timeoutMs) shuts every registered server down concurrently:
const sterfive = global.get("sterfive");
const { shutdownAllServers } = sterfive.bootstrap;
await shutdownAllServers(2000);
This is what the palette itself calls on SIGINT / SIGTERM / exit, so you rarely need it from a flow.