UNPKG

datum-focus

Version:

Data shape, model, metadata, JSON, JSON Schema, GraphQL, MongoDB query and aggregations, iterator generators

143 lines (123 loc) 4.24 kB
import * as retry from './retry'; import path from 'path'; const log4js = require('log4js'); const logger = log4js.getLogger(path.basename(__filename)); logger.level = 'debug'; export const RETRYABLE_DEFAULTS = { retries: 5, factor: 1, minTimeout: 5 * 1000, maxTimeout: 5 * 1000 }; /** * * RETRYABLE * * @param: promiseFunc - The funtion to retry. The function returns a promise. * @param: retryOptions - See node module "retry" defaults is * { * retries: 5, * factor: 1, * minTimeout: 5 * 1000, * maxTimeout: 5 * 1000 * } * @param: isRetryableErrorCb - if supplied should return true if the error can be retried. * If cannot retry on this error return false; Default retries on all errors; * * */ export let RETRYABLE_PROMISE_WRAPPER = { promiseFuncWrapper: (promiseFunc: any, count: number) => { return promiseFunc(count); } }; export function RETRYABLE(promiseFunc: any, retryOptions: any = RETRYABLE_DEFAULTS, isRetryableErrorCb: any = () => { return true; }) { return new Promise((resolve, reject) => { var operation = retry.operation(retryOptions); operation.attempt(function (count: any) { RETRYABLE_PROMISE_WRAPPER.promiseFuncWrapper(promiseFunc, count) .then((result: any) => { resolve(result); }) .catch((error: any) => { logger.error(`Error occurred in operation => ${error.stack}`); var isRetryable = isRetryableErrorCb(error); let stringError = error + ""; try { stringError = JSON.stringify(error); } catch (e) { } if (isRetryable) { retryOptions['forever'] ? logger.error(`Error: ${stringError}; forever: ${retryOptions['forever']}; retrying-- attempt #${count} `) : logger.error(`Error: ${stringError}; retrying-- attempt #${count}/${retryOptions['retries']}`); if (operation.retry(error)) { return; } } else { logger.error(`Error: Not retyable - ${stringError}`); } reject(error); }); }); }); } class MyError extends Error { constructor(captureStart: any) { super(); Error.prepareStackTrace = (error, structuredStackTrace) => { return structuredStackTrace; }; Error.captureStackTrace(this, captureStart); } } export class RetryableUtil { static getRetryableCallsite(captureStart: any = RETRYABLE): any { let origPrepareStackTrace = Error.prepareStackTrace; const myObject = new MyError(captureStart); const siteList = myObject.stack; Error.prepareStackTrace = origPrepareStackTrace; return siteList; } // eslint-disable-next-line sonarjs/cognitive-complexity static breakOn(options: any = { functionNameRE: undefined, fileNameRE: undefined, lineNumber: undefined, captureStart: undefined, showCallStack: undefined }) { let captureStart = options.captureStart || RETRYABLE; const siteList: any = RetryableUtil.getRetryableCallsite(captureStart); if (siteList.length === 0) { return null; } let functionName = null; let fileName = null; let lineNumber = -1; let matched = false; const callStack: any[] = []; for (let site of siteList) { functionName = site.getFunctionName() || 'anonymouse'; fileName = site.getFileName(); lineNumber = site.getLineNumber(); if (options['showCallStack'] === true) { callStack.push(`functionName: ${functionName} fileName: ${fileName} lineNumber: ${lineNumber}`); } let functionNameREMatched = (options.functionNameRE) ? options.functionNameRE.test(functionName) : true; let fileNameREMatched = (options.fileNameRE) ? options.fileNameRE.test(fileName) : true; let lineNumberMatched = (options.lineNumber) ? options.lineNumber === lineNumber : true; matched = (functionNameREMatched && fileNameREMatched && lineNumberMatched); if (matched) { if (options['showCallStack'] === true) { for (const stack_line of callStack) { logger.info(stack_line); } } return site; } } return null; } }