@jbrowse/core
Version:
JBrowse 2 core libraries used by plugins
77 lines (76 loc) • 2.77 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.RemoteFileWithRangeCache = void 0;
exports.clearCache = clearCache;
const http_range_fetcher_1 = require("@gmod/http-range-fetcher");
const generic_filehandle2_1 = require("generic-filehandle2");
const fetchers = {};
function binaryRangeFetch(url, start, end, options = {}) {
const fetcher = fetchers[url];
if (!fetcher) {
throw new Error(`fetch not registered for ${url}`);
}
return fetcher(url, start, end, options);
}
const globalRangeCache = new http_range_fetcher_1.HttpRangeFetcher({
fetch: binaryRangeFetch,
size: 500 * 1024 ** 2,
chunkSize: 128 * 1024,
maxFetchSize: 100 * 1024 ** 2,
minimumTTL: 24 * 60 * 60 * 1000,
});
function clearCache() {
globalRangeCache.reset();
}
class RemoteFileWithRangeCache extends generic_filehandle2_1.RemoteFile {
async fetch(url, init) {
const str = String(url);
if (!fetchers[str]) {
fetchers[str] = this.fetchBinaryRange.bind(this);
}
const range = new Headers(init === null || init === void 0 ? void 0 : init.headers).get('range');
if (range) {
const rangeParse = /bytes=(\d+)-(\d+)/.exec(range);
if (rangeParse) {
const [, start, end] = rangeParse;
const s = Number.parseInt(start, 10);
const e = Number.parseInt(end, 10);
const len = e - s;
const { buffer, headers } = (await globalRangeCache.getRange(`${url}`, s, len + 1));
return new Response(buffer, {
status: 206,
headers,
});
}
}
return super.fetch(url, init);
}
async fetchBinaryRange(url, start, end, options = {}) {
const requestDate = new Date();
const res = await super.fetch(url, {
...options,
headers: {
...options.headers,
range: `bytes=${start}-${end}`,
},
});
const responseDate = new Date();
if (!res.ok) {
const errorMessage = `HTTP ${res.status} fetching ${url} bytes ${start}-${end}`;
const hint = ' (should be 206 for range requests)';
throw new Error(`${errorMessage}${res.status === 200 ? hint : ''}`);
}
const headers = {};
for (const [k, v] of res.headers.entries()) {
headers[k] = v;
}
const arrayBuffer = await res.arrayBuffer();
return {
headers,
requestDate,
responseDate,
buffer: new Uint8Array(arrayBuffer),
};
}
}
exports.RemoteFileWithRangeCache = RemoteFileWithRangeCache;