From 42a8aec00adcee5c04677266dfe078e6cd908481 Mon Sep 17 00:00:00 2001 From: Alireza Date: Fri, 1 Oct 2021 03:17:11 -0400 Subject: [PATCH] feat: Add back the addToBeginning to the PoolManagers (#558) --- src/requestPool/RequestPoolManager.ts | 157 +++++++++++++++----------- 1 file changed, 88 insertions(+), 69 deletions(-) diff --git a/src/requestPool/RequestPoolManager.ts b/src/requestPool/RequestPoolManager.ts index 3268951a..88c38013 100644 --- a/src/requestPool/RequestPoolManager.ts +++ b/src/requestPool/RequestPoolManager.ts @@ -14,49 +14,57 @@ type AdditionalDetails = { thumbnail: { [key: number]: [] } prefetch: { [key: number]: [] } } - + class RequestPoolManager { // priority is fixed for interaction and thumbnail to be 0, however, // the priority of prefetch can be configured and it can have priorities other // than 0 (highest priority) - + // TODO: Some of this stuff shouldn't be public but it's easier right now private requestPool: RequestPool; private awake: boolean; - private numRequests: { interaction: number, thumbnail: number, prefetch: number }; - public maxNumRequests: { interaction: number, thumbnail: number, prefetch: number }; + private numRequests: { + interaction: number; + thumbnail: number; + prefetch: number; + }; + public maxNumRequests: { + interaction: number; + thumbnail: number; + prefetch: number; + }; public grabDelay: number; private timeoutHandle: number; - + constructor() { this.requestPool = { interaction: { 0: [] }, thumbnail: { 0: [] }, prefetch: { 0: [] }, - } - + }; + this.awake = false; this.grabDelay = 5; - - this.numRequests = { + + this.numRequests = { interaction: 0, thumbnail: 0, prefetch: 0, }; - + this.maxNumRequests = { interaction: 6, thumbnail: 6, prefetch: 5, - } + }; } - + destroy() { if (this.timeoutHandle) { - window.clearTimeout(this.timeoutHandle) + window.clearTimeout(this.timeoutHandle); } } - + /** * Adds the requests to the pool of requests. * @@ -75,30 +83,37 @@ type AdditionalDetails = { requestFn: () => Promise, type: string, additionalDetails: Record, - priority = 0 + priority = 0, + addToBeginning = false ): void { // Describe the request const requestDetails: RequestDetailsInterface = { requestFn, type, additionalDetails, - } - + }; + // Check if the priority group exists on the request type if (this.requestPool[type][priority] === undefined) { - this.requestPool[type][priority] = [] + this.requestPool[type][priority] = []; } - + // Adding the request to the correct priority group of the request type - this.requestPool[type][priority].push(requestDetails) - + if (addToBeginning) { + // Add it to the beginning of the stack + this.requestPool[type][priority].unshift(requestDetails); + } else { + // Add it to the end of the stack + this.requestPool[type][priority].push(requestDetails); + } + // Wake up if (!this.awake) { - this.awake = true - this.startGrabbing() + this.awake = true; + this.startGrabbing(); } } - + /** * Filter the requestPoolManager's pool of request based on the result of * provided filter function. The provided filter function needs to return false or true @@ -110,17 +125,17 @@ type AdditionalDetails = { filterFunction: (requestDetails: RequestDetailsInterface) => boolean ): void { Object.keys(this.requestPool).forEach((type: string) => { - const requestType = this.requestPool[type] + const requestType = this.requestPool[type]; Object.keys(requestType).forEach((priority) => { requestType[priority] = requestType[priority].filter( (requestDetails: RequestDetailsInterface) => { - return filterFunction(requestDetails) + return filterFunction(requestDetails); } - ) - }) - }) + ); + }); + }); } - + /** * Clears the requests specific to the provided type. For instance, the * pool of requests of type 'interaction' can be cleared via this function. @@ -131,26 +146,26 @@ type AdditionalDetails = { */ clearRequestStack(type: string): void { if (!this.requestPool[type]) { - throw new Error(`No category for the type ${type} found`) + throw new Error(`No category for the type ${type} found`); } - this.requestPool[type] = { 0: [] } + this.requestPool[type] = { 0: [] }; } - + sendRequest({ requestFn, type }: RequestDetailsInterface) { // Increment the number of current requests of this type - this.numRequests[type]++ - this.awake = true - + this.numRequests[type]++; + this.awake = true; + requestFn().finally(() => { - this.numRequests[type]-- - - this.startAgain() - }) + this.numRequests[type]--; + + this.startAgain(); + }); } - + startGrabbing(): void { // Begin by grabbing X images - + // TODO: This is the reason things aren't going as fast as expected // const maxSimultaneousRequests = getMaxSimultaneousRequests() // this.maxNumRequests = { @@ -158,83 +173,87 @@ type AdditionalDetails = { // thumbnail: Math.max(maxSimultaneousRequests - 2, 1), // prefetch: Math.max(maxSimultaneousRequests - 1, 1), // } - + const maxRequests = - this.maxNumRequests.interaction + this.maxNumRequests.thumbnail + this.maxNumRequests.prefetch + this.maxNumRequests.interaction + + this.maxNumRequests.thumbnail + + this.maxNumRequests.prefetch; const currentRequests = - this.numRequests.interaction + this.numRequests.thumbnail + this.numRequests.prefetch - const requestsToSend = maxRequests - currentRequests + this.numRequests.interaction + + this.numRequests.thumbnail + + this.numRequests.prefetch; + const requestsToSend = maxRequests - currentRequests; for (let i = 0; i < requestsToSend; i++) { - const requestDetails = this.getNextRequest() + const requestDetails = this.getNextRequest(); if (requestDetails === false) { break; } else if (requestDetails) { - this.sendRequest(requestDetails) + this.sendRequest(requestDetails); } } } - + startAgain(): void { if (!this.awake) { - return + return; } - + if (this.grabDelay) { this.timeoutHandle = window.setTimeout(() => { - this.startGrabbing() - }, this.grabDelay) + this.startGrabbing(); + }, this.grabDelay); } else { - this.startGrabbing() + this.startGrabbing(); } } - + getSortedPriorityGroups(type: string): Array { const priorities = Object.keys(this.requestPool[type]) .map(Number) .filter((priority) => this.requestPool[type][priority].length) - .sort() - return priorities + .sort(); + return priorities; } - + getNextRequest(): RequestDetailsInterface | false { - const interactionPriorities = this.getSortedPriorityGroups('interaction') + const interactionPriorities = this.getSortedPriorityGroups('interaction'); for (const priority of interactionPriorities) { if ( this.requestPool.interaction[priority].length && this.numRequests.interaction < this.maxNumRequests.interaction ) { - return this.requestPool.interaction[priority].shift() + return this.requestPool.interaction[priority].shift(); } } - const thumbnailPriorities = this.getSortedPriorityGroups('thumbnail') + const thumbnailPriorities = this.getSortedPriorityGroups('thumbnail'); for (const priority of thumbnailPriorities) { if ( this.requestPool.thumbnail[priority].length && this.numRequests.thumbnail < this.maxNumRequests.thumbnail ) { - return this.requestPool.thumbnail[priority].shift() + return this.requestPool.thumbnail[priority].shift(); } } - const prefetchPriorities = this.getSortedPriorityGroups('prefetch') + const prefetchPriorities = this.getSortedPriorityGroups('prefetch'); for (const priority of prefetchPriorities) { if ( this.requestPool.prefetch[priority].length && this.numRequests.prefetch < this.maxNumRequests.prefetch ) { - return this.requestPool.prefetch[priority].shift() + return this.requestPool.prefetch[priority].shift(); } } - + if ( !interactionPriorities.length && !thumbnailPriorities.length && !prefetchPriorities.length ) { - this.awake = false + this.awake = false; } - return false + return false; } - + /** * Returns the request pool containing different categories, their priority and * the added request details. @@ -243,7 +262,7 @@ type AdditionalDetails = { * @category requestPool */ getRequestPool(): RequestPool { - return this.requestPool + return this.requestPool; } }