feat(runtime): SIGHUP hot-reload of room bindings (no full restart)

Registering/deregistering a channel via a DB write from a non-main room did not
take effect until a full restart, and restarting from inside an agent turn is
unreliable (the agent is a child of ejclaw.service, so `systemctl restart` kills
it mid-command and it can't be confirmed) — the source of repeated "auto-restart
missing / claimed restart but it didn't happen" failures.

Add a SIGHUP handler that calls runtimeState.reloadRoomBindings(), which re-reads
ONLY room bindings from the DB (cursors/sessions untouched, no re-processing).
`kill -HUP <MainPID>` then makes a registration live instantly with no restart
and no agent death, so it is verifiable in the same turn.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Codex
2026-08-23 19:42:03 +09:00
parent e752524252
commit 9020d2c8c5
3 changed files with 55 additions and 0 deletions

View File

@@ -20,6 +20,13 @@ import type { AgentType, RegisteredGroup } from './types.js';
export interface RuntimeState {
loadState: () => void;
/**
* Re-read ONLY the room bindings from the DB (not cursors/sessions), so a
* channel registered/deregistered via a DB write takes effect live without a
* full process restart. Safe to call at runtime — it does not touch the
* message cursors, so no re-processing risk.
*/
reloadRoomBindings: () => void;
saveState: () => void;
clearSession: (groupFolder: string, opts?: { allRoles?: boolean }) => void;
assignRoomForIpc: (jid: string, input: AssignRoomInput) => void;
@@ -96,6 +103,14 @@ export function createRuntimeState(): RuntimeState {
);
};
const reloadRoomBindings = (): void => {
roomBindings = getAllRoomBindings();
logger.info(
{ groupCount: Object.keys(roomBindings).length },
'Room bindings reloaded',
);
};
const assignRoomForIpc = (jid: string, input: AssignRoomInput): void => {
const assignedGroup = assignRoom(jid, input);
if (!assignedGroup) {
@@ -121,6 +136,7 @@ export function createRuntimeState(): RuntimeState {
return {
loadState,
reloadRoomBindings,
saveState,
clearSession,
assignRoomForIpc,