From 29bba7be530d2e11c56de021fc67a9641b2e6e0d Mon Sep 17 00:00:00 2001 From: Shinigami Date: Fri, 22 Apr 2022 14:45:35 +0200 Subject: feat: resettable unique store (#800) --- src/utils/unique.ts | 47 ++++++++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 17 deletions(-) (limited to 'src/utils') diff --git a/src/utils/unique.ts b/src/utils/unique.ts index 4e7fadce..df1b827e 100644 --- a/src/utils/unique.ts +++ b/src/utils/unique.ts @@ -4,7 +4,7 @@ export type RecordKey = string | number | symbol; /** * Global store of unique values. - * This means that faker should *never* return duplicate values across all API methods when using `Faker.unique`. + * This means that faker should *never* return duplicate values across all API methods when using `Faker.unique` without passing `options.store`. */ const GLOBAL_UNIQUE_STORE: Record = {}; @@ -14,11 +14,6 @@ const GLOBAL_UNIQUE_STORE: Record = {}; */ const GLOBAL_UNIQUE_EXCLUDE: RecordKey[] = []; -/** - * Current iteration or retries of `unique.exec` (current loop depth). - */ -const currentIterations = 0; - /** * Uniqueness compare function. * Default behavior is to check value as key against object hash. @@ -43,15 +38,21 @@ function defaultCompare( * @param startTime The time the execution started. * @param now The current time. * @param code The error code. + * @param store The store of unique entries. + * @param currentIterations Current iteration or retries of `unique.exec` (current loop depth). * * @throws The given error code with additional text. */ -function errorMessage(startTime: number, now: number, code: string): never { +function errorMessage( + startTime: number, + now: number, + code: string, + store: Record, + currentIterations: number +): never { console.error('Error', code); console.log( - `Found ${ - Object.keys(GLOBAL_UNIQUE_STORE).length - } unique entries before throwing error. + `Found ${Object.keys(store).length} unique entries before throwing error. retried: ${currentIterations} total time: ${now - startTime}ms` ); @@ -77,6 +78,7 @@ Try adjusting maxTime or maxRetries parameters for faker.unique().` * @param options.currentIterations The current attempt. Defaults to `0`. * @param options.exclude The value or values that should be excluded/skipped. Defaults to `[]`. * @param options.compare The function used to determine whether a value was already returned. Defaults to check the existence of the key. + * @param options.store The store of unique entries. Defaults to `GLOBAL_UNIQUE_STORE`. */ export function exec RecordKey>( method: Method, @@ -88,6 +90,7 @@ export function exec RecordKey>( currentIterations?: number; exclude?: RecordKey | RecordKey[]; compare?: (obj: Record, key: RecordKey) => 0 | -1; + store?: Record; } = {} ): ReturnType { const now = new Date().getTime(); @@ -97,6 +100,7 @@ export function exec RecordKey>( maxTime = 50, maxRetries = 50, compare = defaultCompare, + store = GLOBAL_UNIQUE_STORE, } = options; let { exclude = GLOBAL_UNIQUE_EXCLUDE } = options; options.currentIterations = options.currentIterations ?? 0; @@ -112,22 +116,31 @@ export function exec RecordKey>( // console.log(now - startTime) if (now - startTime >= maxTime) { - return errorMessage(startTime, now, `Exceeded maxTime: ${maxTime}`); + return errorMessage( + startTime, + now, + `Exceeded maxTime: ${maxTime}`, + store, + options.currentIterations + ); } if (options.currentIterations >= maxRetries) { - return errorMessage(startTime, now, `Exceeded maxRetries: ${maxRetries}`); + return errorMessage( + startTime, + now, + `Exceeded maxRetries: ${maxRetries}`, + store, + options.currentIterations + ); } // Execute the provided method to find a potential satisfied value. const result: ReturnType = method.apply(this, args); // If the result has not been previously found, add it to the found array and return the value as it's unique. - if ( - compare(GLOBAL_UNIQUE_STORE, result) === -1 && - exclude.indexOf(result) === -1 - ) { - GLOBAL_UNIQUE_STORE[result] = result; + if (compare(store, result) === -1 && exclude.indexOf(result) === -1) { + store[result] = result; options.currentIterations = 0; return result; } else { -- cgit v1.2.3