Skip to content

Commit

Permalink
fix: OutputCollectionState memoization
Browse files Browse the repository at this point in the history
  • Loading branch information
nd0ut committed Jan 29, 2024
1 parent 7170f4b commit 8d38402
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 44 deletions.
59 changes: 28 additions & 31 deletions abstract/buildOutputCollectionState.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// @ts-check

import { memoize } from '../utils/memoize.js';
import { warnOnce } from '../utils/warnOnce.js';

/** @param {string} warning */
function createAsyncAssertWrapper(warning) {
Expand All @@ -10,18 +11,21 @@ function createAsyncAssertWrapper(warning) {
}, 0);

/**
* @template {unknown[]} TArgs
* @template {unknown} TReturn
* @param {(...args: TArgs) => TReturn} fn
* @returns {(...args: TArgs) => TReturn}
* @template {any[]} TArgs
* @template {any} TReturn
* @template {(...args: TArgs) => TReturn} T
* @param {T} fn
* @returns {T}
*/
const withAssert = (fn) => {
return (...args) => {
if (isAsync) {
console.warn(warning);
return /** @type {T} */ (
(...args) => {
if (isAsync) {
warnOnce(warning);
}
return fn(...args);
}
return fn(...args);
};
);
};

return withAssert;
Expand Down Expand Up @@ -54,62 +58,58 @@ export function buildOutputCollectionState(uploaderBlock) {
},

failedCount: () => {
return getters.failedEntries().length;
return state.failedEntries.length;
},

successCount: () => {
return getters.successEntries().length;
return state.successEntries.length;
},

uploadingCount: () => {
return getters.uploadingEntries().length;
return state.uploadingEntries.length;
},

status: () => {
const status = getters.isFailed()
? 'failed'
: getters.isUploading()
? 'uploading'
: getters.isSuccess()
? 'success'
: 'idle';
const status = state.isFailed ? 'failed' : state.isUploading ? 'uploading' : state.isSuccess ? 'success' : 'idle';
return /** @type {TCollectionStatus} */ (status);
},

isSuccess: () => {
return getters.errors().length === 0 && getters.successEntries().length === getters.allEntries().length;
return state.errors.length === 0 && state.successEntries.length === state.allEntries.length;
},

isUploading: () => {
return getters.allEntries().some((entry) => entry.status === 'uploading');
return state.allEntries.some((entry) => entry.status === 'uploading');
},

isFailed: () => {
return getters.errors().length > 0 || getters.failedEntries().length > 0;
return state.errors.length > 0 || state.failedEntries.length > 0;
},

allEntries: () => {
return uploaderBlock.getOutputData();
},

successEntries: () => {
return getters.allEntries().filter((entry) => entry.status === 'success');
return state.allEntries.filter((entry) => entry.status === 'success');
},

failedEntries: () => {
return getters.allEntries().filter((entry) => entry.status === 'failed');
return state.allEntries.filter((entry) => entry.status === 'failed');
},

uploadingEntries: () => {
return getters.allEntries().filter((entry) => entry.status === 'uploading');
return state.allEntries.filter((entry) => entry.status === 'uploading');
},

idleEntries: () => {
return getters.allEntries().filter((entry) => entry.status === 'idle');
return state.allEntries.filter((entry) => entry.status === 'idle');
},
};

const state = {};
const state = /** @type {import('../index.js').OutputCollectionState<TCollectionStatus, TGroupFlag>} */ (
/** @type {unknown} */ ({})
);
const withAssert = createAsyncAssertWrapper(
"You're trying to access the OutputCollectionState asynchronously. " +
'In this case, the data you retrieve will be newer than it was when the ' +
Expand All @@ -121,15 +121,12 @@ export function buildOutputCollectionState(uploaderBlock) {
for (const [key, value] of Object.entries(getters)) {
const name = /** @type {keyof typeof getters} */ (key);
const getter = /** @type {(typeof getters)[name]} */ (value);
// @ts-expect-error
const wrapped = memoize(withAssert(getter));
Object.defineProperty(state, name, {
get: wrapped,
enumerable: true,
});
}

return /** @type {import('../index.js').OutputCollectionState<TCollectionStatus, TGroupFlag>} */ (
/** @type {unknown} */ (state)
);
return state;
}
28 changes: 15 additions & 13 deletions utils/memoize.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
// @ts-check

/**
* @template {unknown[]} TArgs
* @template {unknown} TReturn
* @param {(...args: TArgs) => TReturn} fn
* @returns {(...args: TArgs) => TReturn}
* @template {any[]} TArgs
* @template {any} TReturn
* @template {(...args: TArgs) => TReturn} T
* @param {T} fn
* @returns {T}
*/
export const memoize = (fn) => {
const cache = new Map();
/** @param {TArgs} args */
return (...args) => {
const key = JSON.stringify(args);
if (cache.has(key)) {
return cache.get(key);
return /** @type {T} */ (
(...args) => {
const key = JSON.stringify(args);
if (cache.has(key)) {
return cache.get(key);
}
const result = fn(...args);
cache.set(key, result);
return result;
}
const result = fn(...args);
cache.set(key, result);
return result;
};
);
};

0 comments on commit 8d38402

Please sign in to comment.