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:
@@ -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) => {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user