UNPKG

@jbrowse/core

Version:

JBrowse 2 core libraries used by plugins

77 lines (76 loc) 2.77 kB
"use strict"; 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;