Skip to content

Commit

Permalink
feat: Add back the addToBeginning to the PoolManagers (#558)
Browse files Browse the repository at this point in the history
  • Loading branch information
sedghi authored Oct 1, 2021
1 parent 03cdd71 commit 42a8aec
Showing 1 changed file with 88 additions and 69 deletions.
157 changes: 88 additions & 69 deletions src/requestPool/RequestPoolManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand All @@ -75,30 +83,37 @@ type AdditionalDetails = {
requestFn: () => Promise<void>,
type: string,
additionalDetails: Record<string, unknown>,
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
Expand All @@ -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.
Expand All @@ -131,110 +146,114 @@ 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 = {
// interaction: Math.max(maxSimultaneousRequests, 1),
// 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<number> {
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.
Expand All @@ -243,7 +262,7 @@ type AdditionalDetails = {
* @category requestPool
*/
getRequestPool(): RequestPool {
return this.requestPool
return this.requestPool;
}
}

Expand Down

0 comments on commit 42a8aec

Please sign in to comment.