MCPcopy
hub / github.com/coder/mux / MigratedBackgroundHandle

Class MigratedBackgroundHandle

src/node/services/backgroundProcessExecutor.ts:423–577  ·  view source on GitHub ↗

* Handle for a migrated foreground process. * * Unlike RuntimeBackgroundHandle which uses runtime.exec for file operations, * this handle uses local filesystem directly because the streams are already * being piped to the local machine (even for SSH runtime). * * Both stdout and stderr are wri

Source from the content-addressed store, hash-verified

421 * Both stdout and stderr are written to a unified output.log file.
422 */
423class MigratedBackgroundHandle implements BackgroundHandle {
424 private exitCodeValue: number | null = null;
425 private consuming = false;
426 private outputFd: fs.FileHandle | null = null;
427
428 constructor(
429 private readonly execStream: ExecStream,
430 public readonly outputDir: string,
431 private readonly outputPath: string
432 ) {}
433
434 /**
435 * Start consuming remaining output from streams and writing to unified file.
436 * Called after handle is created to begin background file writing.
437 */
438 startConsuming(): void {
439 if (this.consuming) return;
440 this.consuming = true;
441
442 // Open output file once, consume both streams to it
443 void this.consumeStreams();
444
445 // Track exit code
446 void this.execStream.exitCode.then((code) => {
447 this.exitCodeValue = code;
448 // Write exit code to file
449 void this.writeExitCode(code);
450 });
451 }
452
453 /**
454 * Consume both stdout and stderr streams and append to unified output file.
455 */
456 private async consumeStreams(): Promise<void> {
457 try {
458 this.outputFd = await fs.open(this.outputPath, "a");
459
460 // Consume both streams concurrently, both writing to same file
461 await Promise.all([
462 this.consumeStream(this.execStream.stdout),
463 this.consumeStream(this.execStream.stderr),
464 ]);
465 } catch (error) {
466 log.debug(`MigratedBackgroundHandle.consumeStreams: ${errorMsg(error)}`);
467 } finally {
468 if (this.outputFd) {
469 await this.outputFd.close();
470 this.outputFd = null;
471 }
472 }
473 }
474
475 /**
476 * Consume a stream and append to the shared output file.
477 */
478 private async consumeStream(stream: ReadableStream<Uint8Array>): Promise<void> {
479 try {
480 const reader = stream.getReader();

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected