Repository navigation
4.3 Fetcher and Disk Cache
Relevant source files
The following files were used as context for generating this wiki page:
The purpose of this page is to document the main-process networking and persistent caching infrastructure implemented in electron/fetcher.js and electron/disk-cache.js. This subsystem handles secure HTTPS requests, per-host rate limiting, streaming size caps, request retries, and file-system-backed caching grouped by gene symbols for VariantScope's desktop target.
Sources: electron/fetcher.js:1-127, electron/disk-cache.js:1-93
The fetcher runs entirely in the Electron main process, exposing a secure IPC handler created by createFetcher electron/fetcher.js:81-127 that processes requests initiated from the preload bridge and renderer.
-
Timeouts: Every request is bounded by a strict timeout (
TIMEOUT_MS = 20_000ms) viaAbortSignal.timeoutelectron/fetcher.js:6, electron/fetcher.js:60. -
Size Caps: Responses are read iteratively through
readCappedelectron/fetcher.js:30-46. If a response exceedsMAX_BYTES(25 MB, well above the largest expected 1.5 MB biological data payload), the reader is canceled and an error is thrown electron/fetcher.js:7, electron/fetcher.js:39-42. -
Redirect Blocking:
net.fetchis explicitly configured withredirect: 'error'to prevent external servers from redirecting requests to hosts outside the security allowlist electron/fetcher.js:56-57. -
No-Store Cache Directive: Chromium's built-in HTTP cache is bypassed (
cache: 'no-store') so that data freshness and disk-cache rules remain fully controlled by VariantScope electron/fetcher.js:58-59.
To respect third-party API usage policies (such as NCBI E-utilities restrictions), electron/fetcher.js enforces per-host throttling using asynchronous request queues electron/fetcher.js:9-27:
-
MIN_INTERVAL_MSspecifies custom gaps per host (e.g.,340ms foreutils.ncbi.nlm.nih.gov, translating to roughly 3 requests per second) and defaults to100ms electron/fetcher.js:10-11. -
acquireSlot(host)maintains a promise chain per hostname to ensure requests are appropriately spaced electron/fetcher.js:18-27.
requestWithRetry wraps HTTP executions to handle transient failures electron/fetcher.js:66-78:
- Status codes
429(Too Many Requests) and5xx(Server Errors) are classified as retryable (retryablecheck at electron/fetcher.js:71). - A single retry is executed after an exponential/fixed delay (
RETRY_DELAY_MS * 2) electron/fetcher.js:76.
Sources: electron/fetcher.js:1-127
The disk cache (electron/disk-cache.js) provides persistent storage for API responses in a dedicated user-data directory. Unlike transient memory caches, files are retained indefinitely for offline use, but are flagged as stale after a fixed window.
-
OUT_OF_DATE_MSdefines the freshness TTL (7 days) tests/unit/disk-cache.test.js:6, tests/unit/disk-cache.test.js:31. -
cache.get(key, group)inspects the stored file metadata; if the file age exceeds 7 days, it is returned withstale: truerather than being deleted tests/unit/disk-cache.test.js:31-41.
Cached files are associated with genomic entities using a group tag (e.g., a gene symbol like TP53) electron/fetcher.js:90-91:
-
isValidGroup(group)validates that group tags conform to strict alphanumeric/hyphen constraints (maximum 20 characters) and rejects path traversal attempts like../or absolute paths tests/unit/disk-cache.test.js:52-61. - Files are written to disk using the format
group~hash.json, where un-grouped or invalidly grouped requests default to a fallback prefix (_~) tests/unit/disk-cache.test.js:43-51.
-
listGroups()scans the cache directory, aggregating entry counts and total byte sizes per gene group tests/unit/disk-cache.test.js:63-73. -
deleteGroups(groups)selectively removes files associated with specified gene arrays or clears the entire cache when passed'all'tests/unit/disk-cache.test.js:75-95.
Sources: electron/disk-cache.js:1-93, tests/unit/disk-cache.test.js:1-96
The following diagram bridges natural language descriptions of the request lifecycle to the actual functions and modules inside the codebase.
graph TD
subgraph "Renderer Process"
A["getJson src/core/http.js"] -->|IPC Invoke| B["window.api.fetchJson electron/preload.cjs"]
end
subgraph "Main Process"
B -->|Calls| C["createFetcher electron/fetcher.js"]
C -->|Validates URL| D["checkApiUrl electron/allowlist.js"]
C -->|Checks Cache| E["createDiskCache electron/disk-cache.js"]
E -->|Hit & Fresh| F["Return Cached Data"]
E -->|Miss or Stale/Refresh| G["acquireSlot electron/fetcher.js"]
G -->|Rate Limited| H["requestWithRetry electron/fetcher.js"]
H -->|Fetch with Net| I["net.fetch electron"]
I -->|Read Body| J["readCapped electron/fetcher.js"]
J -->|Success| K["cache.set electron/disk-cache.js"]
K -->|Store File| L["FileSystem Disk Storage"]
end
Sources: electron/fetcher.js:81-127, electron/disk-cache.js:1-93, electron/allowlist.js:1-1
Sources: electron/fetcher.js:81-127, electron/disk-cache.js:1-93, electron/allowlist.js:1-1
The structural relationship between group validation, disk storage naming, and grouped metrics is mapped out below.
graph LR
subgraph "Input Layer"
M["fetchJson options.group"] --> N["isValidGroup electron/disk-cache.js"]
end
subgraph "Validation & Sanitization"
N -->|Valid Group| O["Prefix: TP53~"]
N -->|Invalid/Missing| P["Prefix: _~"]
end
subgraph "Disk Storage Layout"
O --> Q["file: TP53~hash1.json"]
O --> R["file: TP53~hash2.json"]
P --> S["file: _~hash3.json"]
end
subgraph "Management APIs"
Q & R --> T["listGroups electron/disk-cache.js"]
S --> T
T --> U["Delete Groups / Calculate Bytes"]
end
Sources: electron/disk-cache.js:1-93, tests/unit/disk-cache.test.js:43-74
Sources: electron/disk-cache.js:1-93, tests/unit/disk-cache.test.js:43-74
When network execution fails or access is refused, createFetcher normalizes errors before returning them to the UI layer electron/fetcher.js:121-125:
-
Allowlist Blocks: If
checkApiUrlrejects a URL, the fetcher immediately returns an error object without initiating network activity electron/fetcher.js:83-84. -
Offline Detection: Connection-level errors (such as
TimeoutErroror error messages matchingnet::ERR_) set theofflineflag totrue, allowing the UI to gracefully fall back to cached data or display offline banners electron/fetcher.js:122-124. -
Invalid JSON: If a server responds with status
2xxbut returns malformed body text when JSON parsing is requested, a descriptive error is returned ('The server did not return valid JSON.') electron/fetcher.js:110-117.
Sources: electron/fetcher.js:81-127, tests/unit/http-electron.test.js:62-75
Content imported from DeepWiki.