From a9e93671f696628169442cd3d2c85fbfc45e7173 Mon Sep 17 00:00:00 2001 From: jaxoncreed Date: Tue, 3 Oct 2023 09:46:30 -0400 Subject: [PATCH] Fixed DoubleFetch --- .../solid/src/requester/ContainerRequester.ts | 14 ++-- packages/solid/src/requester/LeafRequester.ts | 24 +++++-- packages/solid/src/requester/Requester.ts | 38 +++++++---- packages/solid/src/util/RequestBatcher.ts | 66 +++++++------------ packages/solid/tsconfig.build.json | 1 + 5 files changed, 77 insertions(+), 66 deletions(-) diff --git a/packages/solid/src/requester/ContainerRequester.ts b/packages/solid/src/requester/ContainerRequester.ts index ea780dc..e6ec2ab 100644 --- a/packages/solid/src/requester/ContainerRequester.ts +++ b/packages/solid/src/requester/ContainerRequester.ts @@ -45,12 +45,16 @@ export class ContainerRequester extends Requester { name: IS_ROOT_CONTAINER_KEY, args: [this.uri as ContainerUri, { fetch: this.context.fetch }], perform: checkRootContainer, - modifyQueue: (queue, isLoading) => { - if (queue.length === 0) { - return isLoading[IS_ROOT_CONTAINER_KEY]; - } else { - return queue[queue.length - 1].name === IS_ROOT_CONTAINER_KEY; + modifyQueue: (queue, currentlyLoading) => { + if ( + queue.length === 0 && + currentlyLoading?.name === IS_ROOT_CONTAINER_KEY + ) { + return currentlyLoading; + } else if (queue[queue.length - 1]?.name === IS_ROOT_CONTAINER_KEY) { + return queue[queue.length - 1]; } + return undefined; }, }); } diff --git a/packages/solid/src/requester/LeafRequester.ts b/packages/solid/src/requester/LeafRequester.ts index 86b605a..02a7760 100644 --- a/packages/solid/src/requester/LeafRequester.ts +++ b/packages/solid/src/requester/LeafRequester.ts @@ -70,14 +70,14 @@ export class LeafRequester extends Requester { { fetch: this.context.fetch, onRollback: () => transaction.rollback() }, ], perform: updateDataResource, - modifyQueue: (queue, isLoading, [, changes]) => { - if (queue[queue.length - 1].name === UPDATE_KEY) { + modifyQueue: (queue, currentlyProcessing, [, changes]) => { + if (queue[queue.length - 1]?.name === UPDATE_KEY) { // Merge Changes const originalChanges = queue[queue.length - 1].args[1]; mergeDatasetChanges(originalChanges, changes); - return true; + return queue[queue.length - 1]; } - return false; + return undefined; }, }); return result; @@ -120,13 +120,23 @@ export class LeafRequester extends Requester { { dataset: transaction, fetch: this.context.fetch }, ], perform: uploadResource, - modifyQueue: (queue, isLoading, args) => { + modifyQueue: (queue, currentlyLoading, args) => { const lastElementInQueue = queue[queue.length - 1]; - return ( + if ( lastElementInQueue && lastElementInQueue.name === UPLOAD_KEY && !!lastElementInQueue.args[3] === !!args[3] - ); + ) { + return lastElementInQueue; + } + if ( + currentlyLoading && + currentlyLoading.name === UPLOAD_KEY && + !!currentlyLoading.args[3] === !!args[3] + ) { + return currentlyLoading; + } + return undefined; }, }); if (!result.isError) { diff --git a/packages/solid/src/requester/Requester.ts b/packages/solid/src/requester/Requester.ts index 7babc92..6144799 100644 --- a/packages/solid/src/requester/Requester.ts +++ b/packages/solid/src/requester/Requester.ts @@ -52,12 +52,13 @@ export abstract class Requester { name: READ_KEY, args: [this.uri, { dataset: transaction, fetch: this.context.fetch }], perform: readResource, - modifyQueue: (queue, isLoading) => { - if (queue.length === 0) { - return isLoading[READ_KEY]; - } else { - return queue[queue.length - 1].name === READ_KEY; + modifyQueue: (queue, currentlyLoading) => { + if (queue.length === 0 && currentlyLoading?.name === READ_KEY) { + return currentlyLoading; + } else if (queue[queue.length - 1]?.name === READ_KEY) { + return queue[queue.length - 1]; } + return undefined; }, }); if (!result.isError) { @@ -75,12 +76,13 @@ export abstract class Requester { name: DELETE_KEY, args: [this.uri, { dataset: transaction, fetch: this.context.fetch }], perform: deleteResource, - modifyQueue: (queue, isLoading) => { - if (queue.length === 0) { - return isLoading[DELETE_KEY]; - } else { - return queue[queue.length - 1].name === DELETE_KEY; + modifyQueue: (queue, currentlyLoading) => { + if (queue.length === 0 && currentlyLoading?.name === DELETE_KEY) { + return currentlyLoading; + } else if (queue[queue.length - 1]?.name === DELETE_KEY) { + return queue[queue.length - 1]; } + return undefined; }, }); if (!result.isError) { @@ -125,13 +127,23 @@ export abstract class Requester { { dataset: transaction, fetch: this.context.fetch }, ], perform: createDataResource, - modifyQueue: (queue, isLoading, args) => { + modifyQueue: (queue, currentlyLoading, args) => { const lastElementInQueue = queue[queue.length - 1]; - return ( + if ( lastElementInQueue && lastElementInQueue.name === CREATE_KEY && !!lastElementInQueue.args[1] === !!args[1] - ); + ) { + return lastElementInQueue; + } + if ( + currentlyLoading && + currentlyLoading.name === CREATE_KEY && + !!currentlyLoading.args[1] === !!args[1] + ) { + return currentlyLoading; + } + return undefined; }, }); if (!result.isError) { diff --git a/packages/solid/src/util/RequestBatcher.ts b/packages/solid/src/util/RequestBatcher.ts index 0f95309..33c6b1f 100644 --- a/packages/solid/src/util/RequestBatcher.ts +++ b/packages/solid/src/util/RequestBatcher.ts @@ -16,21 +16,24 @@ export interface WaitingProcessOptions { /** * * @param processQueue The current process queue - * @param isLoading The current is loading + * @param currentlyProcessing: The Process that is currently executing * @param args provided args - * @returns true if the process queue has been modified and a new process should not be added to the queue + * @returns A WaitingProcess that this request should listen to, or undefined if it should create its own */ modifyQueue: ( processQueue: WaitingProcess[], - isLoading: Record, + currentlyProcessing: WaitingProcess | undefined, args: Args, - ) => boolean; + ) => WaitingProcess | undefined; } +/** + * Request Batcher + */ export class RequestBatcher { private lastRequestTimestampMap: Record = {}; - private loadingMap: Record = {}; - private isWaiting: boolean = false; + private currentlyProcessing: WaitingProcess | undefined = + undefined; private processQueue: WaitingProcess[] = []; public shouldBatchAllRequests: boolean; public batchMillis: number; @@ -46,7 +49,7 @@ export class RequestBatcher { } public isLoading(key: string): boolean { - return !!this.loadingMap[key]; + return this.currentlyProcessing?.name === key; } private triggerOrWaitProcess() { @@ -66,14 +69,14 @@ export class RequestBatcher { const timeSinceLastTrigger = Date.now() - lastRequestTimestamp; const triggerProcess = async () => { - if (this.isWaiting) { + if (this.currentlyProcessing) { return; } this.lastRequestTimestampMap[processName] = Date.now(); this.lastRequestTimestampMap[ANY_KEY] = Date.now(); const processToTrigger = this.processQueue.shift(); if (processToTrigger) { - this.isWaiting = true; + this.currentlyProcessing = processToTrigger; try { const returnValue = await processToTrigger.perform( ...processToTrigger.args, @@ -86,22 +89,9 @@ export class RequestBatcher { callback(err); }); } - this.isWaiting = false; + this.currentlyProcessing = undefined; - // Reset loading - if ( - !this.processQueue.some( - (process) => process.name === processToTrigger.name, - ) - ) { - this.loadingMap[processToTrigger.name] = false; - } - - if (this.processQueue.length > 0) { - this.triggerOrWaitProcess(); - } else { - this.loadingMap[ANY_KEY] = false; - } + this.triggerOrWaitProcess(); } }; @@ -116,22 +106,18 @@ export class RequestBatcher { options: WaitingProcessOptions, ): Promise { return new Promise((resolve, reject) => { - const lastProcessInQueue = - this.processQueue[this.processQueue.length - 1]; - if (lastProcessInQueue) { - const didModifyLast = lastProcessInQueue - ? options.modifyQueue( - this.processQueue, - this.loadingMap, - options.args, - ) - : false; - if (didModifyLast) { - lastProcessInQueue.awaitingResolutions.push(resolve); - lastProcessInQueue.awaitingRejections.push(reject); - return; - } + const shouldAwait = options.modifyQueue( + this.processQueue, + this.currentlyProcessing, + options.args, + ); + + if (shouldAwait) { + shouldAwait.awaitingResolutions.push(resolve); + shouldAwait.awaitingRejections.push(reject); + return; } + const waitingProcess: WaitingProcess = { name: options.name, args: options.args, @@ -143,8 +129,6 @@ export class RequestBatcher { this.processQueue.push( waitingProcess as unknown as WaitingProcess, ); - this.loadingMap[waitingProcess.name] = true; - this.loadingMap[ANY_KEY] = true; this.triggerOrWaitProcess(); }); } diff --git a/packages/solid/tsconfig.build.json b/packages/solid/tsconfig.build.json index 4bd5a5e..1d69ba6 100644 --- a/packages/solid/tsconfig.build.json +++ b/packages/solid/tsconfig.build.json @@ -1,6 +1,7 @@ { "extends": "../../tsconfig.base.json", "compilerOptions": { + "strict": false, "outDir": "./dist", }, "include": ["./src"]