Skip to content

Instantly share code, notes, and snippets.

@junkor-1011
Last active March 18, 2023 13:59
Show Gist options
  • Save junkor-1011/71fd265383028051e03afd2a533f78bf to your computer and use it in GitHub Desktop.
Save junkor-1011/71fd265383028051e03afd2a533f78bf to your computer and use it in GitHub Desktop.
retry-function(TypeScript)
{
"compilerOptions": {
"allowJs": false,
"jsx": "react",
"lib": ["deno.window"],
"strict": true
},
"lint": {
"files": {
// "include": ["src"],
"include": ["."],
"exclude": ["public"]
},
"rules": {
"tags": ["recommended"],
"exclude": []
}
},
"fmt": {
"files": {
// "include": ["src/"],
"include": ["./"],
"exclude": [".vscode", ".env"]
},
"options": {
"useTabs": false,
"lineWidth": 100,
"indentWidth": 2,
"singleQuote": true,
"proseWrap": "preserve"
}
},
// "importMap": "import_map.json",
"tasks": {
"test": "deno test"
}
}
import { retry } from './retry.ts';
// deno-lint-ignore require-await
const throwError = async (): Promise<string> => {
throw new Error('test error');
// deno-lint-ignore no-unreachable
return 'success';
};
// no wait
console.log('test: retryCounts');
console.time();
const resultA = await retry(
throwError,
{
retryCounts: 5,
},
);
console.timeEnd();
if (resultA.errors.length !== 5) throw new Error('unknown error');
console.log('resultA', resultA);
console.log(`
=================================================
`);
// wait time
console.log('test: retry wait time');
console.time();
const resultB = await retry(
throwError,
{
retryCounts: 3,
retryWaitMsec: 500,
},
);
console.timeEnd();
if (resultB.errors.length !== 3) throw new Error('unknown error');
console.log('resultB', resultB);
console.log(`
=================================================
`);
// success with retry
console.log('test: success with retry & reporter');
const genSuccessWithRetry = (n: number): () => Promise<string> => {
let count = 0;
const fetchIp = async (): Promise<string> => {
if (count < n) {
count++;
throw new Error('failed to fetch ip');
}
const ip = await fetch('https://checkip.amazonaws.com/').then((res) => res.text());
return ip;
};
return fetchIp;
};
const fetchIp3 = genSuccessWithRetry(3);
console.time();
const resultC = await retry(
fetchIp3,
{
retryCounts: 10,
retryWaitMsec: 700,
errorReporter: console.warn,
},
);
console.timeEnd();
if (resultC.errors.length !== 3) throw new Error('implement error');
console.log('resultC', resultC);
import { retry } from './retry.ts';
const excution = () => fetch('https://checkip.amazonaws.com/').then((response) => response.text());
console.time();
const result = await retry(
excution,
{
retryCounts: 3,
retryWaitMsec: 3000,
errorReporter: console.error,
},
);
console.timeEnd();
if (!result.success) throw new Error('failed');
const { data, errors } = result;
console.log(data, errors);
export type TRetryResult<T> = {
success: true;
data: T;
errors: unknown[];
} | {
success: false;
data: null;
errors: unknown[];
};
export type TRetryOptions = {
retryCounts: number;
retryWaitMsec?: number;
errorReporter?: <T extends unknown[]>(...massages: readonly [...T]) => void;
};
export const retry = async <T>(
execution: () => Promise<T>,
opts: TRetryOptions,
): Promise<TRetryResult<T>> => {
const errors: unknown[] = [];
while (errors.length < opts.retryCounts) {
try {
const data = await execution();
return {
success: true,
data,
errors,
};
} catch (error) {
if (opts.errorReporter != null) {
opts.errorReporter(error);
}
errors.push(error);
}
await new Promise((resolve) => setTimeout(resolve, opts.retryWaitMsec ?? 0));
}
return {
success: false,
data: null,
errors,
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment