fix(voice-call): drain tailscale tunnel output · openclaw/openclaw@47fdd6b
vincentkoc
·
2026-05-28
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
@@ -187,6 +187,25 @@ describe("voice-call tunnels", () => {
|
187 | 187 | ); |
188 | 188 | }); |
189 | 189 | |
| 190 | +it("drains and bounds Tailscale startup failure output", async () => { |
| 191 | +mocks.getTailscaleDnsName.mockResolvedValue("host.tailnet.ts.net"); |
| 192 | +const proc = nextProcess(); |
| 193 | +const result = startTailscaleTunnel({ |
| 194 | +mode: "funnel", |
| 195 | +port: 3334, |
| 196 | +path: "/voice/webhook", |
| 197 | +}); |
| 198 | + |
| 199 | +await vi.waitFor(() => expect(mocks.spawn).toHaveBeenCalled()); |
| 200 | +proc.stderr.emit("data", Buffer.from(`start-${"x".repeat(20_000)}-end`)); |
| 201 | +proc.close(1); |
| 202 | + |
| 203 | +await expect(result).rejects.toThrow("Tailscale funnel failed with code 1"); |
| 204 | +await expect(result).rejects.toThrow("[output truncated]"); |
| 205 | +await expect(result).rejects.toThrow("-end"); |
| 206 | +await expect(result).rejects.not.toThrow("start-"); |
| 207 | +}); |
| 208 | + |
190 | 209 | it("rejects Tailscale tunnel startup when the DNS name is unavailable", async () => { |
191 | 210 | mocks.getTailscaleDnsName.mockResolvedValue(null); |
192 | 211 | |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -240,12 +240,21 @@ export async function startTailscaleTunnel(config: {
|
240 | 240 | const proc = spawn("tailscale", [config.mode, "--bg", "--yes", "--set-path", path, localUrl], { |
241 | 241 | stdio: ["ignore", "pipe", "pipe"], |
242 | 242 | }); |
| 243 | +let stdout = emptyBoundedChildOutput(); |
| 244 | +let stderr = emptyBoundedChildOutput(); |
243 | 245 | |
244 | 246 | const timeout = setTimeout(() => { |
245 | 247 | proc.kill("SIGKILL"); |
246 | 248 | reject(new Error(`Tailscale ${config.mode} timed out`)); |
247 | 249 | }, 10000); |
248 | 250 | |
| 251 | +proc.stdout.on("data", (data) => { |
| 252 | +stdout = appendBoundedChildOutput(stdout, data.toString()); |
| 253 | +}); |
| 254 | +proc.stderr.on("data", (data) => { |
| 255 | +stderr = appendBoundedChildOutput(stderr, data.toString()); |
| 256 | +}); |
| 257 | + |
249 | 258 | proc.on("close", (code) => { |
250 | 259 | clearTimeout(timeout); |
251 | 260 | if (code === 0) { |
@@ -260,7 +269,9 @@ export async function startTailscaleTunnel(config: {
|
260 | 269 | }, |
261 | 270 | }); |
262 | 271 | } else { |
263 | | -reject(new Error(`Tailscale ${config.mode} failed with code ${code}`)); |
| 272 | +const output = stderr.text ? stderr : stdout; |
| 273 | +const detail = output.text ? `: ${formatBoundedChildOutput(output)}` : ""; |
| 274 | +reject(new Error(`Tailscale ${config.mode} failed with code ${code}${detail}`)); |
264 | 275 | } |
265 | 276 | }); |
266 | 277 | |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。