Skip to main content

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() returns true between successful bootstrapServer and the moment shutdown() resolves (or process teardown). It is the single source of truth — do not look at handle.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 next bootstrapServer({...}) call with the same config will build a fresh server, re-running onPopulate.

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.