Address review: identity-check on removeActiveClient

Use removeActiveClientIfMatch to only deregister the active client if
it matches the instance owned by the stopping monitor. Prevents a
reconnect race where the first monitor's stop() would deregister the
second monitor's healthy client.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tio 2026-03-14 07:03:44 -04:00
parent 922cba6775
commit 7d72001bb9
2 changed files with 15 additions and 2 deletions

View File

@ -22,3 +22,14 @@ export function getActiveClient(accountId: string): IrcClient | undefined {
export function removeActiveClient(accountId: string): void {
activeClients.delete(accountId);
}
/**
* Only remove the active client if it matches the expected instance.
* Prevents a stopping monitor from deregistering a newer monitor's
* healthy client during reconnect races.
*/
export function removeActiveClientIfMatch(accountId: string, expected: IrcClient): void {
if (activeClients.get(accountId) === expected) {
activeClients.delete(accountId);
}
}

View File

@ -1,6 +1,6 @@
import { resolveLoggerBackedRuntime } from "openclaw/plugin-sdk/extension-shared";
import { resolveIrcAccount } from "./accounts.js";
import { setActiveClient, removeActiveClient } from "./active-clients.js";
import { setActiveClient, removeActiveClientIfMatch } from "./active-clients.js";
import { connectIrcClient, type IrcClient } from "./client.js";
import { buildIrcConnectOptions } from "./connect-options.js";
import { handleIrcInbound } from "./inbound.js";
@ -141,7 +141,9 @@ export async function monitorIrcProvider(opts: IrcMonitorOptions): Promise<{ sto
return {
stop: () => {
removeActiveClient(account.accountId);
if (client) {
removeActiveClientIfMatch(account.accountId, client);
}
client?.quit("shutdown");
client = null;
},