[services/retry] add onRetryBlock function to run before each retry (#34434)

* [services/retry] add onFaliureBlock function to run before each retry
This commit is contained in:
Dmitry Lemeshko 2019-04-03 23:04:20 +02:00 committed by GitHub
parent a5b18e81d3
commit 1af565973f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 27 additions and 6 deletions

View file

@ -26,41 +26,54 @@ export function RetryProvider({ getService }: FtrProviderContext) {
const log = getService('log');
return new class Retry {
public async tryForTime<T>(timeout: number, block: () => Promise<T>) {
public async tryForTime<T>(
timeout: number,
block: () => Promise<T>,
onFailureBlock?: () => Promise<T>
) {
return await retryForSuccess(log, {
timeout,
methodName: 'retry.tryForTime',
block,
onFailureBlock,
});
}
public async try<T>(block: () => Promise<T>) {
public async try<T>(block: () => Promise<T>, onFailureBlock?: () => Promise<T>) {
return await retryForSuccess(log, {
timeout: config.get('timeouts.try'),
methodName: 'retry.try',
block,
onFailureBlock,
});
}
public async waitForWithTimeout(
description: string,
timeout: number,
block: () => Promise<boolean>
block: () => Promise<boolean>,
onFailureBlock?: () => Promise<any>
) {
await retryForTruthy(log, {
timeout,
methodName: 'retry.waitForWithTimeout',
description,
block,
onFailureBlock,
});
}
public async waitFor(description: string, block: () => Promise<boolean>) {
public async waitFor(
description: string,
block: () => Promise<boolean>,
onFailureBlock?: () => Promise<any>
) {
await retryForTruthy(log, {
timeout: config.get('timeouts.waitFor'),
methodName: 'retry.waitFor',
description,
block,
onFailureBlock,
});
}
}();

View file

@ -50,12 +50,13 @@ interface Options<T> {
timeout: number;
methodName: string;
block: () => Promise<T>;
onFailureBlock?: () => Promise<T>;
onFailure?: ReturnType<typeof defaultOnFailure>;
accept?: (v: T) => boolean;
}
export async function retryForSuccess<T>(log: ToolingLog, options: Options<T>) {
const { timeout, methodName, block, accept = returnTrue } = options;
const { timeout, methodName, block, onFailureBlock, accept = returnTrue } = options;
const { onFailure = defaultOnFailure(methodName) } = options;
const start = Date.now();
@ -66,6 +67,11 @@ export async function retryForSuccess<T>(log: ToolingLog, options: Options<T>) {
if (lastError && Date.now() - start > timeout) {
await onFailure(lastError);
throw new Error('expected onFailure() option to throw an error');
} else if (lastError && onFailureBlock) {
const before = await runAttempt(onFailureBlock);
if ('error' in before) {
log.debug(`--- onRetryBlock error: ${before.error.message}`);
}
}
const attempt = await runAttempt(block);

View file

@ -26,11 +26,12 @@ interface Options {
methodName: string;
description: string;
block: () => Promise<boolean>;
onFailureBlock?: () => Promise<any>;
}
export async function retryForTruthy(
log: ToolingLog,
{ timeout, methodName, description, block }: Options
{ timeout, methodName, description, block, onFailureBlock }: Options
) {
log.debug(`Waiting up to ${timeout}ms for ${description}...`);
@ -38,6 +39,7 @@ export async function retryForTruthy(
timeout,
methodName,
block,
onFailureBlock,
onFailure: lastError => {
let msg = `timed out waiting for ${description}`;