@jspm/generator
Version: 
Package Import Map Generation Tool
75 lines (73 loc) • 2.33 kB
JavaScript
let retryCount = 5, poolSize = 100;
function setRetryCount(count) {
    retryCount = count;
}
/**
 * Wraps a fetch request with pooling, and retry logic on exceptions (emfile / network errors).
 */ function wrappedFetch(fetch) {
    const wrappedFetch = async function(url, ...args) {
        url = url.toString();
        let retries = 0;
        try {
            await pushFetchPool();
            while(true){
                try {
                    return await fetch(url, ...args);
                } catch (e) {
                    if (retries++ >= retryCount) throw e;
                }
            }
        } finally{
            popFetchPool();
        }
    };
    wrappedFetch.arrayBuffer = async function(url, ...args) {
        url = url.toString();
        let retries = 0;
        try {
            await pushFetchPool();
            while(true){
                try {
                    var res = await fetch(url, ...args);
                } catch (e) {
                    if (retries++ >= retryCount) throw e;
                    continue;
                }
                switch(res.status){
                    case 200:
                    case 304:
                        break;
                    // not found = null
                    case 404:
                        return null;
                    default:
                        throw new Error(`Invalid status code ${res.status}`);
                }
                try {
                    return await res.arrayBuffer();
                } catch (e) {
                    if (retries++ >= retryCount && e.code === "ERR_SOCKET_TIMEOUT" || e.code === "ETIMEOUT" || e.code === "ECONNRESET" || e.code === "FETCH_ERROR") {}
                }
            }
        } finally{
            popFetchPool();
        }
    };
    wrappedFetch.text = async function(url, ...args) {
        const arrayBuffer = await this.arrayBuffer(url, ...args);
        if (!arrayBuffer) return null;
        return new TextDecoder().decode(arrayBuffer);
    };
    return wrappedFetch;
}
// restrict in-flight fetches to a pool of 100
let p = [];
let c = 0;
function pushFetchPool() {
    if (++c > poolSize) return new Promise((r)=>p.push(r));
}
function popFetchPool() {
    c--;
    if (p.length) p.shift()();
}
export { setRetryCount as s, wrappedFetch as w };