fix(notify): openclaw CLI cold-start 7-10s 대비해 timeout 25s + 디버그 로그

발견: 첫 E2E 테스트에서 4 자매 중 하랑이만 notify 성공, 나머지 3 자매는
"openclaw timeout" 으로 실패. 직접 측정해 보니 narang LXC 의
`openclaw message send` 가 7.258s (gateway connect + auth cold start).
기존 8s timeout 이 빡빡해서 가끔 들어오고 가끔 죽었음.

수정:
- discord-notify.ts: timeoutMs 기본값 8000 → 25000ms. fire-and-forget
  호출이라 메인 파이프라인 latency 영향 없음.
- spawn.ts: notify.start 호출 결과를 명시적 로그로 남김 (성공/실패/error
  각각 가시화). 다음 디버깅을 빠르게.
- server.ts: invoke.start 로그에 notifyChannelId 표시.

검증: 파이프라인 01KNW0ADA5CBFBVGCRV7VN1YTF 에서 4 자매 모두 notify.start
ok:true 확인.
This commit is contained in:
2026-04-11 00:37:36 +09:00
parent 809d5b94c4
commit 13b2c00048
3 changed files with 43 additions and 5 deletions

View File

@@ -41,12 +41,17 @@ export async function notifyDiscord(opts: {
const child = spawn(bin, args, { stdio: ["ignore", "pipe", "pipe"] });
let stderr = "";
let settled = false;
// OpenClaw CLI cold-start (gateway connect + auth) can take 7-10s
// even on a healthy LXC. Use a generous timeout — this call is
// fire-and-forget from spawn.ts so a longer timer doesn't block the
// pipeline; it only matters if the openclaw process is genuinely
// stuck.
const timer = setTimeout(() => {
if (settled) return;
settled = true;
child.kill("SIGKILL");
resolveFn({ ok: false, error: `openclaw timeout` });
}, opts.timeoutMs ?? 8000);
}, opts.timeoutMs ?? 25000);
child.stderr.on("data", (b: Buffer) => (stderr += b.toString()));
child.on("error", (err) => {

View File

@@ -76,6 +76,7 @@ const server = createServer(async (req, res) => {
log("info", "invoke.start", {
pipelineId: req2.pipelineId,
stage: req2.stage,
notifyChannelId: req2.notifyChannelId || "(none)",
});
try {

View File

@@ -105,16 +105,48 @@ export async function executeInvocation(
// Discord stage-start ping (best-effort, fire-and-forget)
if (req.notifyChannelId) {
void notifyDiscord({
notifyDiscord({
channelId: req.notifyChannelId,
message: renderStageStart({
agentName,
stage: req.stage,
taskTitle: req.task.title,
}),
}).catch(() => {
/* swallow — discord notify must never break the pipeline */
});
})
.then((r) => {
console.log(
JSON.stringify({
ts: new Date().toISOString(),
level: r.ok ? "info" : "warn",
agent: agentName,
msg: "notify.start",
channel: req.notifyChannelId,
ok: r.ok,
error: r.error,
}),
);
})
.catch((err) => {
console.error(
JSON.stringify({
ts: new Date().toISOString(),
level: "error",
agent: agentName,
msg: "notify.start.threw",
error: err instanceof Error ? err.message : String(err),
}),
);
});
} else {
console.log(
JSON.stringify({
ts: new Date().toISOString(),
level: "info",
agent: agentName,
msg: "notify.skipped",
reason: "no notifyChannelId in invoke request",
}),
);
}
try {