Skip to content

Instantly share code, notes, and snippets.

@EduardoAC
Last active September 5, 2023 14:06
Show Gist options
  • Save EduardoAC/fde30d1d04086013525f62545cdd24a7 to your computer and use it in GitHub Desktop.
Save EduardoAC/fde30d1d04086013525f62545cdd24a7 to your computer and use it in GitHub Desktop.
Handling concurrent access to resource
type PendingRequests = { [url: string]: Function[] }
// Initialize an object to track pending resource requests
let pendingRequests: PendingRequests = {};
/**
* Check if there is a pending request for a given URL.
* @param {string} url - The URL to check for pending requests.
* @returns {boolean} - True if there are pending requests, false otherwise.
*/
export function hasPendingRequest(url: string) {
return pendingRequests.hasOwnProperty(url);
}
/**
* Lock a resource to prevent concurrent requests for the same URL.
* @param {string} url - The URL of the resource to lock.
*/
export function lockResource(url: string) {
if (!pendingRequests[url]) {
// Create a queue for pending requests for this URL if it doesn't exist
pendingRequests[url] = [];
}
}
/**
* Wait for a resource request to complete. This function returns a promise that
* resolves when the request finishes.
* @param {string} url - The URL of the resource being requested.
* @returns {Promise<Response>} - A promise that resolves when the request completes.
*/
export function waitForResourceCompletion(url: string): Promise<Response> {
// We wait until the ongoing request finishes by queuing the promise until completion
const waitForRequestPromise = new Promise<Response>((resolve) => {
// Add the resolve from promise to the queue for this URL
pendingRequests[url].push(resolve);
});
return waitForRequestPromise;
}
/**
* Notify that a resource request has completed and resolve any pending requests
* for the same URL.
* @param {string} url - The URL of the completed resource request.
* @param {Response} response - The response of the completed request.
*/
export function notifyResourceCompletion(url: string, response: Response) {
// Notify other requests in the queue and remove the URL entry
if (pendingRequests[url]?.length > 0) {
pendingRequests[url].forEach((resolve) => {
// Resolve each pending request with a clone of the response
resolve(response.clone());
});
}
// Remove the URL entry as all requests are now resolved
delete pendingRequests[url];
}
/**
* Clear the queue of pending resource requests.
*/
export function clearPendingRequestQueue() {
// Reset the pendingRequests object to clear all pending requests
pendingRequests = {};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment