@celo/base
Advanced tools
Comparing version 1.1.0 to 1.1.1
@@ -8,2 +8,3 @@ import { Logger } from './logger'; | ||
export declare const selectiveRetryAsyncWithBackOff: <T extends any[], U>(inFunction: InFunction<T, U>, tries: number, dontRetry: string[], params: T, delay?: number, factor?: number, logger?: Logger | null) => Promise<U>; | ||
export declare const retryAsyncWithBackOffAndTimeout: <T extends any[], U>(inFunction: InFunction<T, U>, tries: number, params: T, delayMs?: number, factor?: number, timeoutMs?: number, logger?: Logger | null) => Promise<U>; | ||
/** | ||
@@ -25,2 +26,11 @@ * Map an async function over a list xs with a given concurrency level | ||
export declare function concurrentValuesMap<IN extends any, OUT extends any>(concurrency: number, x: Record<string, IN>, mapFn: (val: IN, key: string) => Promise<OUT>): Promise<Record<string, OUT>>; | ||
/** | ||
* Wraps an async function in a timeout before calling it. | ||
* | ||
* @param inFunction The async function to call | ||
* @param params The parameters of the async function | ||
* @param timeoutMs The timeout in milliseconds | ||
* @param timeoutError The value to which the returned Promise should reject to | ||
*/ | ||
export declare const timeout: <T extends any[], U>(inFunction: InFunction<T, U>, params: T, timeoutMs: number, timeoutError: any, timeoutLogMsg?: string | null, logger?: Logger | null) => Promise<U>; | ||
export {}; |
@@ -171,2 +171,16 @@ "use strict"; | ||
}; | ||
// Retries an async function when it raises an exeption | ||
// Terminates any ongoing request when the timeout is reached | ||
// if all the tries fail it raises the last thrown exeption | ||
exports.retryAsyncWithBackOffAndTimeout = function (inFunction, tries, params, delayMs, factor, timeoutMs, logger) { | ||
if (delayMs === void 0) { delayMs = 100; } | ||
if (factor === void 0) { factor = 1.5; } | ||
if (timeoutMs === void 0) { timeoutMs = 2000; } | ||
if (logger === void 0) { logger = null; } | ||
return __awaiter(void 0, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
return [2 /*return*/, exports.timeout(exports.retryAsyncWithBackOff, [inFunction, tries, params, delayMs, factor, logger], timeoutMs, new Error("Timed out after " + timeoutMs + "ms"), TAG + "/@retryAsyncWithBackOffAndTimeout, Timed out after " + timeoutMs + "ms", logger)]; | ||
}); | ||
}); | ||
}; | ||
/** | ||
@@ -247,2 +261,28 @@ * Map an async function over a list xs with a given concurrency level | ||
exports.concurrentValuesMap = concurrentValuesMap; | ||
/** | ||
* Wraps an async function in a timeout before calling it. | ||
* | ||
* @param inFunction The async function to call | ||
* @param params The parameters of the async function | ||
* @param timeoutMs The timeout in milliseconds | ||
* @param timeoutError The value to which the returned Promise should reject to | ||
*/ | ||
exports.timeout = function (inFunction, params, timeoutMs, timeoutError, timeoutLogMsg, logger) { | ||
if (timeoutLogMsg === void 0) { timeoutLogMsg = null; } | ||
if (logger === void 0) { logger = null; } | ||
var timer; | ||
return Promise.race([ | ||
inFunction.apply(void 0, params), | ||
new Promise(function (_resolve, reject) { | ||
timer = setTimeout(function () { | ||
if (logger) { | ||
logger(timeoutLogMsg || TAG + "/@timeout Timed out after " + timeoutMs + "ms"); | ||
} | ||
reject(timeoutError); | ||
}, timeoutMs); | ||
}), | ||
]).finally(function () { | ||
clearTimeout(timer); | ||
}); | ||
}; | ||
//# sourceMappingURL=async.js.map |
@@ -111,2 +111,87 @@ "use strict"; | ||
}); | ||
describe('retryAsyncWithBackOffAndTimeout()', function () { | ||
test('tries once if it works', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var mockFunction, result; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
mockFunction = jest.fn(function () { return __awaiter(void 0, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, async_1.sleep(10)]; | ||
case 1: | ||
_a.sent(); | ||
return [2 /*return*/, true]; | ||
} | ||
}); | ||
}); }); | ||
return [4 /*yield*/, async_1.retryAsyncWithBackOffAndTimeout(mockFunction, 3, [], 1)]; | ||
case 1: | ||
result = _a.sent(); | ||
expect(result).toBeTruthy(); | ||
expect(mockFunction).toHaveBeenCalledTimes(1); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); }); | ||
test('retries n times on failure', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var mockFunction, error_2; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
mockFunction = jest.fn(function () { | ||
throw new Error('forced error'); | ||
}); | ||
_a.label = 1; | ||
case 1: | ||
_a.trys.push([1, 3, , 4]); | ||
return [4 /*yield*/, async_1.retryAsyncWithBackOffAndTimeout(mockFunction, 3, [], 1, 1, 100)]; | ||
case 2: | ||
_a.sent(); | ||
expect(false).toBeTruthy(); | ||
return [3 /*break*/, 4]; | ||
case 3: | ||
error_2 = _a.sent(); | ||
expect(error_2.message).toContain('forced error'); | ||
return [3 /*break*/, 4]; | ||
case 4: | ||
expect(mockFunction).toHaveBeenCalledTimes(3); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); }); | ||
test('fails on timeout', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var mockFunction, error_3; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
mockFunction = jest.fn(function () { return __awaiter(void 0, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, async_1.sleep(1000)]; | ||
case 1: | ||
_a.sent(); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); }); | ||
_a.label = 1; | ||
case 1: | ||
_a.trys.push([1, 3, , 4]); | ||
return [4 /*yield*/, async_1.retryAsyncWithBackOffAndTimeout(mockFunction, 3, [], 1, 1, 100)]; | ||
case 2: | ||
_a.sent(); | ||
expect(false).toBeTruthy(); | ||
return [3 /*break*/, 4]; | ||
case 3: | ||
error_3 = _a.sent(); | ||
expect(error_3.message).toContain('Timed out'); | ||
return [3 /*break*/, 4]; | ||
case 4: | ||
expect(mockFunction).toHaveBeenCalledTimes(1); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); }); | ||
}); | ||
var counter = function () { | ||
@@ -206,2 +291,38 @@ var value = 0; | ||
}); | ||
describe('timeout()', function () { | ||
test('fails on timeout', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var mockFunction, timeoutError, error_4; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
mockFunction = jest.fn(function () { return __awaiter(void 0, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, async_1.sleep(1000)]; | ||
case 1: | ||
_a.sent(); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); }); | ||
timeoutError = Symbol(); | ||
_a.label = 1; | ||
case 1: | ||
_a.trys.push([1, 3, , 4]); | ||
return [4 /*yield*/, async_1.timeout(mockFunction, [], 900, timeoutError)]; | ||
case 2: | ||
_a.sent(); | ||
expect(false).toBeTruthy(); | ||
return [3 /*break*/, 4]; | ||
case 3: | ||
error_4 = _a.sent(); | ||
expect(error_4).toBe(timeoutError); | ||
return [3 /*break*/, 4]; | ||
case 4: | ||
expect(mockFunction).toHaveBeenCalledTimes(1); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); }); | ||
}); | ||
//# sourceMappingURL=async.test.js.map |
@@ -198,6 +198,3 @@ "use strict"; | ||
case 0: | ||
pollCondition = jest | ||
.fn() | ||
.mockResolvedValueOnce(false) | ||
.mockResolvedValueOnce(true); | ||
pollCondition = jest.fn().mockResolvedValueOnce(false).mockResolvedValueOnce(true); | ||
onSuccess = jest.fn(); | ||
@@ -278,6 +275,3 @@ task = task_1.conditionWatcher({ | ||
maxAttemps: 2, | ||
tryGetValue: jest | ||
.fn() | ||
.mockResolvedValueOnce(null) | ||
.mockResolvedValueOnce('HELLO'), | ||
tryGetValue: jest.fn().mockResolvedValueOnce(null).mockResolvedValueOnce('HELLO'), | ||
timeInBetweenMS: 7, | ||
@@ -284,0 +278,0 @@ }); |
{ | ||
"name": "@celo/base", | ||
"version": "1.1.0", | ||
"version": "1.1.1", | ||
"description": "Celo base common utils, no dependencies", | ||
@@ -5,0 +5,0 @@ "author": "Celo", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
189948
2904