Skip to content

Commit

Permalink
feat(runtime): add .retry() method and print retries on error (#58)
Browse files Browse the repository at this point in the history
  • Loading branch information
c4spar authored Jul 10, 2022
1 parent 7c06a04 commit a04d370
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 14 deletions.
5 changes: 1 addition & 4 deletions src/runtime/exec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,10 @@ import { ProcessError } from "./process_error.ts";
import { ProcessOutput } from "./process_output.ts";
import { quote } from "./quote.ts";

let runningProcesses = 0;

export function exec(
pieces: TemplateStringsArray,
...args: Array<string | number | ProcessOutput>
): Promise<ProcessOutput> {
runningProcesses++;
): Process {
const cmd = quote(
pieces,
...args.map((
Expand Down
40 changes: 32 additions & 8 deletions src/runtime/process.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ export interface ProcessOptions {
export class Process implements Promise<ProcessOutput> {
readonly [Symbol.toStringTag] = "Process";
readonly #cmd: string;
#proc?: Deno.Process;
#proc: Deno.Process | null = null;
#deferred?: Deferred<ProcessOutput>;
#stdin: Deno.RunOptions["stdin"] = "inherit";
#stdout: Deno.RunOptions["stdout"] = $.stdout;
#stderr: Deno.RunOptions["stderr"] = $.stderr;
#baseError: ProcessError;
#maxRetries = 0;
#retries = 0;

constructor(cmd: string, { errorContext }: ProcessOptions = {}) {
this.#cmd = cmd;
Expand All @@ -26,6 +28,7 @@ export class Process implements Promise<ProcessOutput> {
stderr: "",
stdout: "",
status: { code: 1, success: false, signal: undefined },
retries: 0,
});
Error.captureStackTrace(this.#baseError, errorContext);
}
Expand All @@ -43,6 +46,11 @@ export class Process implements Promise<ProcessOutput> {
return this.#proc;
}

retry(retries: number): this {
this.#maxRetries = retries;
return this;
}

then<TResult1 = ProcessOutput, TResult2 = never>(
onfulfilled?:
| ((value: ProcessOutput) => TResult1 | PromiseLike<TResult1>)
Expand Down Expand Up @@ -82,7 +90,7 @@ export class Process implements Promise<ProcessOutput> {
return this.#deferred;
}

async #run() {
async #run(): Promise<ProcessOutput> {
const stdout: Array<string> = [];
const stderr: Array<string> = [];
const combined: Array<string> = [];
Expand All @@ -95,25 +103,41 @@ export class Process implements Promise<ProcessOutput> {
this.#process.stderr &&
read(this.#process.stderr, [stderr, combined], Deno.stderr),
]);

const output = new ProcessOutput({
stdout: stdout.join(""),
stderr: stderr.join(""),
combined: combined.join(""),
status,
retries: this.#retries,
});

if (!status.success) {
throw ProcessError.merge(this.#baseError, new ProcessError(output));
throw ProcessError.merge(
this.#baseError,
new ProcessError(output),
);
}
this.#close();

return output;
} finally {
this.#process.close();
this.#process.stdin?.close();
this.#process.stdout?.close();
this.#process.stderr?.close();
} catch (error) {
this.#close();
if (this.#retries < this.#maxRetries) {
this.#retries++;
this.#proc = null;
return this.#run();
}
throw error;
}
}

#close() {
this.#process.close();
this.#process.stdin?.close();
this.#process.stdout?.close();
this.#process.stderr?.close();
}
}

async function read(
Expand Down
16 changes: 15 additions & 1 deletion src/runtime/process_error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export class ProcessError extends Error {
#stderr!: string;
#combined!: string;
#status!: Deno.ProcessStatus;
#retries!: number;

static merge(target: ProcessError, source: ProcessError): ProcessError {
target.#name = source.name;
Expand Down Expand Up @@ -43,13 +44,18 @@ export class ProcessError extends Error {
return this.#status;
}

get retries(): number {
return this.#retries;
}

#merge(
{ stdout, stderr, combined, status }: ProcessErrorOptions,
{ stdout, stderr, combined, status, retries }: ProcessErrorOptions,
): void {
this.#stdout = stdout;
this.#stderr = stderr;
this.#combined = combined;
this.#status = status;
this.#retries = retries;
this.message = this.#getErrorMessage();
}

Expand Down Expand Up @@ -78,6 +84,14 @@ export class ProcessError extends Error {
);
}

if (this.#retries > 0) {
message += colors.bold(
`\n${colors.white("Retries:")} ${
colors.yellow(this.#retries.toString())
}`,
);
}

return colors.red(message);
}
}
2 changes: 2 additions & 0 deletions src/runtime/process_error_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ function createError(): ProcessError {
stdout: "foo",
stderr: "bar",
combined: "baz",
retries: 0,
status: {
code: 1,
success: false,
Expand All @@ -35,6 +36,7 @@ Deno.test({
assertEquals(error.stdout, "foo");
assertEquals(error.stderr, "bar");
assertEquals(error.combined, "baz");
assertEquals(error.retries, 0);
assertObjectMatch(error.status, {
code: 1,
success: false,
Expand Down
7 changes: 6 additions & 1 deletion src/runtime/process_output.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,24 @@ export interface ProcessOutputOptions {
stderr: string;
combined: string;
status: Deno.ProcessStatus;
retries: number;
}

export class ProcessOutput {
readonly stdout: string;
readonly stderr: string;
readonly combined: string;
readonly status: Deno.ProcessStatus;
readonly retries: number;

constructor({ stdout, stderr, combined, status }: ProcessOutputOptions) {
constructor(
{ stdout, stderr, combined, status, retries }: ProcessOutputOptions,
) {
this.stdout = stdout;
this.stderr = stderr;
this.combined = combined;
this.status = status;
this.retries = retries;
}

toString(): string {
Expand Down
3 changes: 3 additions & 0 deletions src/runtime/process_output_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ function createOutput(): ProcessOutput {
stdout: "foo",
stderr: "bar",
combined: "foobaz",
retries: 0,
status: {
code: 0,
success: true,
Expand All @@ -21,6 +22,7 @@ Deno.test({
stdout: "foo",
stderr: "bar",
combined: "foobaz",
retries: 0,
status: {
code: 0,
success: true,
Expand All @@ -45,6 +47,7 @@ Deno.test({
stdout: "foo\n",
stderr: "bar\n",
combined: "foo\nbar\n",
retries: 0,
status: {
code: 0,
success: true,
Expand Down

0 comments on commit a04d370

Please sign in to comment.