@zgeoff/atc 2.26.2 → 2.26.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/daemon/imp-client-port.ts +47 -10
package/package.json
CHANGED
|
@@ -248,16 +248,8 @@ export class ImpClientPort implements ImpPort {
|
|
|
248
248
|
};
|
|
249
249
|
|
|
250
250
|
// oxlint-disable-next-line prefer-readonly-parameter-types -- the command's input bytes have no readonly form
|
|
251
|
-
readonly runCommand =
|
|
252
|
-
|
|
253
|
-
client.run(name, command.argv, {
|
|
254
|
-
...(command.cwd === undefined ? {} : { cwd: command.cwd }),
|
|
255
|
-
...(command.stdin === undefined ? {} : { stdin: command.stdin }),
|
|
256
|
-
}),
|
|
257
|
-
);
|
|
258
|
-
|
|
259
|
-
return { code: result.code, stdout: result.stdout, stderr: result.stderr };
|
|
260
|
-
};
|
|
251
|
+
readonly runCommand = (name: string, command: ImpCommand): Promise<ImpCommandResult> =>
|
|
252
|
+
this.tryCall((client) => runCommandInChunks(client, name, command));
|
|
261
253
|
|
|
262
254
|
readonly openReverseForward = (
|
|
263
255
|
name: string,
|
|
@@ -425,6 +417,51 @@ async function waitForSessionOutcome(outcome: Promise<ExecOutcome>): Promise<Imp
|
|
|
425
417
|
return ended;
|
|
426
418
|
}
|
|
427
419
|
|
|
420
|
+
// impd takes no WebSocket message over its size limit and closes the exec
|
|
421
|
+
// when one arrives, so a command's input goes over in pieces well below it.
|
|
422
|
+
const STDIN_CHUNK_BYTES = 1024 * 1024;
|
|
423
|
+
|
|
424
|
+
// Runs a command with its input sent a piece at a time. A command that ends
|
|
425
|
+
// before it takes all its input answers with its own exit, or with the
|
|
426
|
+
// failure that ended it, never with the refused write.
|
|
427
|
+
async function runCommandInChunks(
|
|
428
|
+
client: ImpClient,
|
|
429
|
+
name: string,
|
|
430
|
+
|
|
431
|
+
// oxlint-disable-next-line prefer-readonly-parameter-types -- the command's input bytes have no readonly form
|
|
432
|
+
command: ImpCommand,
|
|
433
|
+
): Promise<ImpCommandResult> {
|
|
434
|
+
const options = command.cwd === undefined ? {} : { cwd: command.cwd };
|
|
435
|
+
|
|
436
|
+
const handle = await client.openExec(name, command.argv, options);
|
|
437
|
+
|
|
438
|
+
const output = Promise.all([
|
|
439
|
+
new Response(handle.stdout).bytes(),
|
|
440
|
+
new Response(handle.stderr).bytes(),
|
|
441
|
+
]);
|
|
442
|
+
|
|
443
|
+
try {
|
|
444
|
+
const stdin = command.stdin ?? new Uint8Array(0);
|
|
445
|
+
|
|
446
|
+
for (let at = 0; at < stdin.byteLength; at += STDIN_CHUNK_BYTES) {
|
|
447
|
+
await handle.write(stdin.subarray(at, at + STDIN_CHUNK_BYTES));
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
await handle.closeStdin();
|
|
451
|
+
} catch {
|
|
452
|
+
// A write fails once the exec has ended, and the exit holds why: the
|
|
453
|
+
// command's own exit, or the failure that ended it, which rethrows
|
|
454
|
+
// here. Closing first ends an exec the failed write left running.
|
|
455
|
+
handle.close();
|
|
456
|
+
|
|
457
|
+
await handle.exit;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
const [exit, [stdout, stderr]] = await Promise.all([handle.exit, output]);
|
|
461
|
+
|
|
462
|
+
return { code: exit.code, stdout, stderr };
|
|
463
|
+
}
|
|
464
|
+
|
|
428
465
|
// oxlint-disable-next-line prefer-readonly-parameter-types -- a promise is a live handle
|
|
429
466
|
async function waitForListening(listening: Promise<unknown>): Promise<void> {
|
|
430
467
|
await listening;
|