@gmod/tabix 3.5.4 → 3.5.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/indexFile.d.ts +35 -2
- package/dist/indexFile.js +79 -7
- package/dist/indexFile.js.map +1 -1
- package/dist/tabix-bundle.js +1 -1
- package/dist/util.d.ts +18 -0
- package/dist/util.js +71 -1
- package/dist/util.js.map +1 -1
- package/esm/indexFile.d.ts +35 -2
- package/esm/indexFile.js +80 -8
- package/esm/indexFile.js.map +1 -1
- package/esm/util.d.ts +18 -0
- package/esm/util.js +70 -1
- package/esm/util.js.map +1 -1
- package/package.json +1 -2
- package/src/indexFile.ts +80 -8
- package/src/util.ts +74 -1
package/dist/util.d.ts
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
import Chunk from './chunk.ts';
|
|
2
2
|
import VirtualOffset from './virtualOffset.ts';
|
|
3
|
+
/**
|
|
4
|
+
* `signal.throwIfAborted()`, without requiring either that method or `reason`.
|
|
5
|
+
*
|
|
6
|
+
* Two reasons not to call the built-in directly. It assumes a *real*
|
|
7
|
+
* `AbortSignal`, and callers pass duck-typed ones, where calling a missing
|
|
8
|
+
* method is a `TypeError` rather than the cancellation the caller asked for —
|
|
9
|
+
* a strictly worse failure.
|
|
10
|
+
*
|
|
11
|
+
* And it sets a browser floor. `AbortSignal.prototype.throwIfAborted` and
|
|
12
|
+
* `AbortSignal.reason` are Safari 15.4 / Chrome 100 / Firefox 97 (March 2022),
|
|
13
|
+
* higher than anything else here needs: this package otherwise touches only
|
|
14
|
+
* `.aborted`, and `generic-filehandle2` only forwards a signal to `fetch`.
|
|
15
|
+
*
|
|
16
|
+
* Faithful to the spec otherwise: an aborted signal throws its `reason`
|
|
17
|
+
* whatever that is, and only synthesizes an `AbortError` when there is none.
|
|
18
|
+
* Kept in sync with the copy in `@gmod/bam`'s `src/util.ts`.
|
|
19
|
+
*/
|
|
20
|
+
export declare function throwIfAborted(signal?: AbortSignal): void;
|
|
3
21
|
export declare function optimizeChunks(chunks: Chunk[], lowest?: VirtualOffset): Chunk[];
|
|
4
22
|
export declare function clampChunkEnds(chunks: Chunk[], extraBoundaries?: number[]): void;
|
|
5
23
|
/**
|
package/dist/util.js
CHANGED
|
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.throwIfAborted = throwIfAborted;
|
|
6
7
|
exports.optimizeChunks = optimizeChunks;
|
|
7
8
|
exports.clampChunkEnds = clampChunkEnds;
|
|
8
9
|
exports.minVirtualOffset = minVirtualOffset;
|
|
@@ -15,6 +16,36 @@ const chunk_ts_1 = __importDefault(require("./chunk.js"));
|
|
|
15
16
|
const long_ts_1 = require("./long.js");
|
|
16
17
|
const virtualOffset_ts_1 = __importDefault(require("./virtualOffset.js"));
|
|
17
18
|
// SYNC: ~/src/gmod/bam-js/src/util.ts optimizeChunks
|
|
19
|
+
/**
|
|
20
|
+
* `signal.throwIfAborted()`, without requiring either that method or `reason`.
|
|
21
|
+
*
|
|
22
|
+
* Two reasons not to call the built-in directly. It assumes a *real*
|
|
23
|
+
* `AbortSignal`, and callers pass duck-typed ones, where calling a missing
|
|
24
|
+
* method is a `TypeError` rather than the cancellation the caller asked for —
|
|
25
|
+
* a strictly worse failure.
|
|
26
|
+
*
|
|
27
|
+
* And it sets a browser floor. `AbortSignal.prototype.throwIfAborted` and
|
|
28
|
+
* `AbortSignal.reason` are Safari 15.4 / Chrome 100 / Firefox 97 (March 2022),
|
|
29
|
+
* higher than anything else here needs: this package otherwise touches only
|
|
30
|
+
* `.aborted`, and `generic-filehandle2` only forwards a signal to `fetch`.
|
|
31
|
+
*
|
|
32
|
+
* Faithful to the spec otherwise: an aborted signal throws its `reason`
|
|
33
|
+
* whatever that is, and only synthesizes an `AbortError` when there is none.
|
|
34
|
+
* Kept in sync with the copy in `@gmod/bam`'s `src/util.ts`.
|
|
35
|
+
*/
|
|
36
|
+
function throwIfAborted(signal) {
|
|
37
|
+
if (signal?.aborted) {
|
|
38
|
+
const reason = signal.reason;
|
|
39
|
+
// Spec-faithful: throwIfAborted throws `reason` verbatim, and `reason` is
|
|
40
|
+
// whatever the caller passed to abort() — `controller.abort('too slow')`
|
|
41
|
+
// makes it a string. Coercing it to an Error here would hide that from a
|
|
42
|
+
// consumer who set it deliberately.
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/only-throw-error
|
|
44
|
+
throw reason === undefined
|
|
45
|
+
? new DOMException('This operation was aborted', 'AbortError')
|
|
46
|
+
: reason;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
18
49
|
function optimizeChunks(chunks, lowest) {
|
|
19
50
|
const n = chunks.length;
|
|
20
51
|
if (n === 0) {
|
|
@@ -73,7 +104,46 @@ function optimizeChunks(chunks, lowest) {
|
|
|
73
104
|
lastMaxBlock = chunkMaxBlock;
|
|
74
105
|
}
|
|
75
106
|
}
|
|
76
|
-
return mergedChunks;
|
|
107
|
+
return makeDisjoint(mergedChunks);
|
|
108
|
+
}
|
|
109
|
+
// SYNC: ~/src/gmod/bam-js/src/util.ts makeDisjoint
|
|
110
|
+
/**
|
|
111
|
+
* Trim any chunk that starts before its predecessor ends, so the spans a query
|
|
112
|
+
* reads never overlap.
|
|
113
|
+
*
|
|
114
|
+
* Merging alone does not guarantee this. Two chunks from different bins can
|
|
115
|
+
* overlap inside a single BGZF block while the merge above still declines to
|
|
116
|
+
* join them, because the combined span would exceed its 5MB cap. The shared
|
|
117
|
+
* bytes are then fetched, decompressed and decoded by both chunks, and every
|
|
118
|
+
* line in the overlap is returned TWICE from getLines — a duplicated VCF
|
|
119
|
+
* record or GFF feature, with a duplicated fileOffset.
|
|
120
|
+
*
|
|
121
|
+
* Safe because a chunk's `maxv` is the virtual offset just past its last
|
|
122
|
+
* record — a record boundary — so no record begins inside the trimmed span and
|
|
123
|
+
* the union of the chunks is unchanged.
|
|
124
|
+
*
|
|
125
|
+
* No fixture here reproduces it (@gmod/bam found it on an 18MB BAM, where
|
|
126
|
+
* out.bam returned 5 of its 6551 records twice); this keeps the two copies of
|
|
127
|
+
* optimizeChunks in step and pins the invariant.
|
|
128
|
+
*/
|
|
129
|
+
function makeDisjoint(chunks) {
|
|
130
|
+
const out = [chunks[0]];
|
|
131
|
+
for (let i = 1; i < chunks.length; i++) {
|
|
132
|
+
const chunk = chunks[i];
|
|
133
|
+
const prevMax = out.at(-1).maxv;
|
|
134
|
+
const cmp = chunk.minv.blockPosition - prevMax.blockPosition ||
|
|
135
|
+
chunk.minv.dataPosition - prevMax.dataPosition;
|
|
136
|
+
if (cmp >= 0) {
|
|
137
|
+
out.push(chunk);
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
const stillHasData = chunk.maxv.blockPosition - prevMax.blockPosition ||
|
|
141
|
+
chunk.maxv.dataPosition - prevMax.dataPosition;
|
|
142
|
+
if (stillHasData > 0) {
|
|
143
|
+
out.push(new chunk_ts_1.default(prevMax, chunk.maxv, chunk.bin, chunk.endPosition));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return out;
|
|
77
147
|
}
|
|
78
148
|
// Tighten each chunk's endPosition (default: a full max-size BGZF block past
|
|
79
149
|
// maxv) down to the next known block boundary. Every chunk min/maxv blockPosition
|
package/dist/util.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"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"}
|
package/esm/indexFile.d.ts
CHANGED
|
@@ -50,6 +50,13 @@ export interface IndexData {
|
|
|
50
50
|
export default abstract class IndexFile {
|
|
51
51
|
filehandle: GenericFilehandle;
|
|
52
52
|
private parseP?;
|
|
53
|
+
/**
|
|
54
|
+
* The signal `parseP` was started under, while it is still in flight. The
|
|
55
|
+
* index is parsed once and shared by every query against the file, so without
|
|
56
|
+
* this the first query to arrive would own a read all the others depend on —
|
|
57
|
+
* see {@link parse}.
|
|
58
|
+
*/
|
|
59
|
+
private parseSignal?;
|
|
53
60
|
constructor({ filehandle }: {
|
|
54
61
|
filehandle: GenericFilehandle;
|
|
55
62
|
});
|
|
@@ -111,8 +118,34 @@ export default abstract class IndexFile {
|
|
|
111
118
|
* @internal
|
|
112
119
|
*/
|
|
113
120
|
blocksForRange(refName: string, min: number, max: number, opts?: Options): Promise<Chunk[]>;
|
|
114
|
-
/**
|
|
115
|
-
|
|
121
|
+
/**
|
|
122
|
+
* Parse the index, or join the parse already running.
|
|
123
|
+
*
|
|
124
|
+
* The index is downloaded and parsed once for the life of this object, so it
|
|
125
|
+
* is the one read here that is shared between queries — and therefore the one
|
|
126
|
+
* place a cancellation can leak from the query that asked for it to a query
|
|
127
|
+
* that did not. `_parse` hands `opts` straight to `readIndexBytes`, so
|
|
128
|
+
* without this the first query to arrive owns a read every other query
|
|
129
|
+
* depends on: when it pans away, every concurrent query fails with its abort.
|
|
130
|
+
*
|
|
131
|
+
* A caller that joined someone else's parse and saw it fail because *they*
|
|
132
|
+
* aborted starts over rather than inheriting the failure — once, then
|
|
133
|
+
* propagates. Bounding it at one attempt is what jbrowse's
|
|
134
|
+
* `RemoteFileWithRangeCache.joinChunk` does with the same retry one layer
|
|
135
|
+
* down, and for the reason it gives: the pathological case becomes one
|
|
136
|
+
* duplicate parse rather than a recursion whose depth depends on how the
|
|
137
|
+
* aborts interleave.
|
|
138
|
+
*
|
|
139
|
+
* A retry rather than the reference count `chunkCache` gets from
|
|
140
|
+
* `@gmod/abortable-promise-cache`, because the index is parsed once for the
|
|
141
|
+
* life of the object: there is no repeated waste to recover, and this is a
|
|
142
|
+
* dozen lines against restructuring the memo. `@gmod/bam`'s `IndexFile` and
|
|
143
|
+
* `@gmod/cram`'s `CraiIndex` make the same split for the same reason.
|
|
144
|
+
*
|
|
145
|
+
* @internal
|
|
146
|
+
*/
|
|
147
|
+
parse(opts?: Options, retried?: boolean): Promise<IndexData>;
|
|
148
|
+
private startParse;
|
|
116
149
|
/** @internal */
|
|
117
150
|
hasRefSeq(seqId: number, opts?: Options): Promise<boolean>;
|
|
118
151
|
}
|
package/esm/indexFile.js
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import { unzip } from '@gmod/bgzf-filehandle';
|
|
2
|
-
import { optimizeChunks } from "./util.js";
|
|
2
|
+
import { optimizeChunks, throwIfAborted } from "./util.js";
|
|
3
3
|
export default class IndexFile {
|
|
4
4
|
filehandle;
|
|
5
5
|
parseP;
|
|
6
|
+
/**
|
|
7
|
+
* The signal `parseP` was started under, while it is still in flight. The
|
|
8
|
+
* index is parsed once and shared by every query against the file, so without
|
|
9
|
+
* this the first query to arrive would own a read all the others depend on —
|
|
10
|
+
* see {@link parse}.
|
|
11
|
+
*/
|
|
12
|
+
parseSignal;
|
|
6
13
|
constructor({ filehandle }) {
|
|
7
14
|
this.filehandle = filehandle;
|
|
8
15
|
}
|
|
@@ -66,13 +73,78 @@ export default class IndexFile {
|
|
|
66
73
|
}
|
|
67
74
|
return optimizeChunks(chunks, this.lowestOffset(ba, min, indexData));
|
|
68
75
|
}
|
|
69
|
-
/**
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Parse the index, or join the parse already running.
|
|
78
|
+
*
|
|
79
|
+
* The index is downloaded and parsed once for the life of this object, so it
|
|
80
|
+
* is the one read here that is shared between queries — and therefore the one
|
|
81
|
+
* place a cancellation can leak from the query that asked for it to a query
|
|
82
|
+
* that did not. `_parse` hands `opts` straight to `readIndexBytes`, so
|
|
83
|
+
* without this the first query to arrive owns a read every other query
|
|
84
|
+
* depends on: when it pans away, every concurrent query fails with its abort.
|
|
85
|
+
*
|
|
86
|
+
* A caller that joined someone else's parse and saw it fail because *they*
|
|
87
|
+
* aborted starts over rather than inheriting the failure — once, then
|
|
88
|
+
* propagates. Bounding it at one attempt is what jbrowse's
|
|
89
|
+
* `RemoteFileWithRangeCache.joinChunk` does with the same retry one layer
|
|
90
|
+
* down, and for the reason it gives: the pathological case becomes one
|
|
91
|
+
* duplicate parse rather than a recursion whose depth depends on how the
|
|
92
|
+
* aborts interleave.
|
|
93
|
+
*
|
|
94
|
+
* A retry rather than the reference count `chunkCache` gets from
|
|
95
|
+
* `@gmod/abortable-promise-cache`, because the index is parsed once for the
|
|
96
|
+
* life of the object: there is no repeated waste to recover, and this is a
|
|
97
|
+
* dozen lines against restructuring the memo. `@gmod/bam`'s `IndexFile` and
|
|
98
|
+
* `@gmod/cram`'s `CraiIndex` make the same split for the same reason.
|
|
99
|
+
*
|
|
100
|
+
* @internal
|
|
101
|
+
*/
|
|
102
|
+
async parse(opts = {}, retried = false) {
|
|
103
|
+
throwIfAborted(opts.signal);
|
|
104
|
+
const pending = this.parseP;
|
|
105
|
+
if (!pending) {
|
|
106
|
+
return this.startParse(opts);
|
|
107
|
+
}
|
|
108
|
+
// read before awaiting: the owner is forgotten as soon as the parse settles
|
|
109
|
+
const ownerSignal = this.parseSignal;
|
|
110
|
+
try {
|
|
111
|
+
return await pending;
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
if (retried || !ownerSignal?.aborted || opts.signal?.aborted) {
|
|
115
|
+
throw e;
|
|
116
|
+
}
|
|
117
|
+
return this.parse(opts, true);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
startParse(opts) {
|
|
121
|
+
const pending = this._parse(opts);
|
|
122
|
+
this.parseP = pending;
|
|
123
|
+
this.parseSignal = opts.signal;
|
|
124
|
+
// Drop a rejection rather than keeping it, so one transient failure does not
|
|
125
|
+
// poison the index for the lifetime of the file. Identity-checked so a retry
|
|
126
|
+
// started after this settles is not cleared by the attempt it replaced.
|
|
127
|
+
//
|
|
128
|
+
// Written as one try/catch rather than `.then(onFulfilled, onRejected)`
|
|
129
|
+
// because `unicorn/prefer-then-catch` rewrites the two-argument form to
|
|
130
|
+
// `.then(...).catch(...)`, which is not the same thing — that catch would
|
|
131
|
+
// also swallow anything the fulfilment handler threw.
|
|
132
|
+
void (async () => {
|
|
133
|
+
let failed = false;
|
|
134
|
+
try {
|
|
135
|
+
await pending;
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
failed = true;
|
|
139
|
+
}
|
|
140
|
+
if (this.parseP === pending) {
|
|
141
|
+
if (failed) {
|
|
142
|
+
this.parseP = undefined;
|
|
143
|
+
}
|
|
144
|
+
this.parseSignal = undefined;
|
|
145
|
+
}
|
|
146
|
+
})();
|
|
147
|
+
return pending;
|
|
76
148
|
}
|
|
77
149
|
/** @internal */
|
|
78
150
|
async hasRefSeq(seqId, opts = {}) {
|
package/esm/indexFile.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"indexFile.js","sourceRoot":"","sources":["../src/indexFile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAA;AAE7C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"indexFile.js","sourceRoot":"","sources":["../src/indexFile.ts"],"names":[],"mappings":"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"}
|
package/esm/util.d.ts
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
import Chunk from './chunk.ts';
|
|
2
2
|
import VirtualOffset from './virtualOffset.ts';
|
|
3
|
+
/**
|
|
4
|
+
* `signal.throwIfAborted()`, without requiring either that method or `reason`.
|
|
5
|
+
*
|
|
6
|
+
* Two reasons not to call the built-in directly. It assumes a *real*
|
|
7
|
+
* `AbortSignal`, and callers pass duck-typed ones, where calling a missing
|
|
8
|
+
* method is a `TypeError` rather than the cancellation the caller asked for —
|
|
9
|
+
* a strictly worse failure.
|
|
10
|
+
*
|
|
11
|
+
* And it sets a browser floor. `AbortSignal.prototype.throwIfAborted` and
|
|
12
|
+
* `AbortSignal.reason` are Safari 15.4 / Chrome 100 / Firefox 97 (March 2022),
|
|
13
|
+
* higher than anything else here needs: this package otherwise touches only
|
|
14
|
+
* `.aborted`, and `generic-filehandle2` only forwards a signal to `fetch`.
|
|
15
|
+
*
|
|
16
|
+
* Faithful to the spec otherwise: an aborted signal throws its `reason`
|
|
17
|
+
* whatever that is, and only synthesizes an `AbortError` when there is none.
|
|
18
|
+
* Kept in sync with the copy in `@gmod/bam`'s `src/util.ts`.
|
|
19
|
+
*/
|
|
20
|
+
export declare function throwIfAborted(signal?: AbortSignal): void;
|
|
3
21
|
export declare function optimizeChunks(chunks: Chunk[], lowest?: VirtualOffset): Chunk[];
|
|
4
22
|
export declare function clampChunkEnds(chunks: Chunk[], extraBoundaries?: number[]): void;
|
|
5
23
|
/**
|
package/esm/util.js
CHANGED
|
@@ -3,6 +3,36 @@ import Chunk from "./chunk.js";
|
|
|
3
3
|
import { longFromBytesToUnsigned } from "./long.js";
|
|
4
4
|
import VirtualOffset from "./virtualOffset.js";
|
|
5
5
|
// SYNC: ~/src/gmod/bam-js/src/util.ts optimizeChunks
|
|
6
|
+
/**
|
|
7
|
+
* `signal.throwIfAborted()`, without requiring either that method or `reason`.
|
|
8
|
+
*
|
|
9
|
+
* Two reasons not to call the built-in directly. It assumes a *real*
|
|
10
|
+
* `AbortSignal`, and callers pass duck-typed ones, where calling a missing
|
|
11
|
+
* method is a `TypeError` rather than the cancellation the caller asked for —
|
|
12
|
+
* a strictly worse failure.
|
|
13
|
+
*
|
|
14
|
+
* And it sets a browser floor. `AbortSignal.prototype.throwIfAborted` and
|
|
15
|
+
* `AbortSignal.reason` are Safari 15.4 / Chrome 100 / Firefox 97 (March 2022),
|
|
16
|
+
* higher than anything else here needs: this package otherwise touches only
|
|
17
|
+
* `.aborted`, and `generic-filehandle2` only forwards a signal to `fetch`.
|
|
18
|
+
*
|
|
19
|
+
* Faithful to the spec otherwise: an aborted signal throws its `reason`
|
|
20
|
+
* whatever that is, and only synthesizes an `AbortError` when there is none.
|
|
21
|
+
* Kept in sync with the copy in `@gmod/bam`'s `src/util.ts`.
|
|
22
|
+
*/
|
|
23
|
+
export function throwIfAborted(signal) {
|
|
24
|
+
if (signal?.aborted) {
|
|
25
|
+
const reason = signal.reason;
|
|
26
|
+
// Spec-faithful: throwIfAborted throws `reason` verbatim, and `reason` is
|
|
27
|
+
// whatever the caller passed to abort() — `controller.abort('too slow')`
|
|
28
|
+
// makes it a string. Coercing it to an Error here would hide that from a
|
|
29
|
+
// consumer who set it deliberately.
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/only-throw-error
|
|
31
|
+
throw reason === undefined
|
|
32
|
+
? new DOMException('This operation was aborted', 'AbortError')
|
|
33
|
+
: reason;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
6
36
|
export function optimizeChunks(chunks, lowest) {
|
|
7
37
|
const n = chunks.length;
|
|
8
38
|
if (n === 0) {
|
|
@@ -61,7 +91,46 @@ export function optimizeChunks(chunks, lowest) {
|
|
|
61
91
|
lastMaxBlock = chunkMaxBlock;
|
|
62
92
|
}
|
|
63
93
|
}
|
|
64
|
-
return mergedChunks;
|
|
94
|
+
return makeDisjoint(mergedChunks);
|
|
95
|
+
}
|
|
96
|
+
// SYNC: ~/src/gmod/bam-js/src/util.ts makeDisjoint
|
|
97
|
+
/**
|
|
98
|
+
* Trim any chunk that starts before its predecessor ends, so the spans a query
|
|
99
|
+
* reads never overlap.
|
|
100
|
+
*
|
|
101
|
+
* Merging alone does not guarantee this. Two chunks from different bins can
|
|
102
|
+
* overlap inside a single BGZF block while the merge above still declines to
|
|
103
|
+
* join them, because the combined span would exceed its 5MB cap. The shared
|
|
104
|
+
* bytes are then fetched, decompressed and decoded by both chunks, and every
|
|
105
|
+
* line in the overlap is returned TWICE from getLines — a duplicated VCF
|
|
106
|
+
* record or GFF feature, with a duplicated fileOffset.
|
|
107
|
+
*
|
|
108
|
+
* Safe because a chunk's `maxv` is the virtual offset just past its last
|
|
109
|
+
* record — a record boundary — so no record begins inside the trimmed span and
|
|
110
|
+
* the union of the chunks is unchanged.
|
|
111
|
+
*
|
|
112
|
+
* No fixture here reproduces it (@gmod/bam found it on an 18MB BAM, where
|
|
113
|
+
* out.bam returned 5 of its 6551 records twice); this keeps the two copies of
|
|
114
|
+
* optimizeChunks in step and pins the invariant.
|
|
115
|
+
*/
|
|
116
|
+
function makeDisjoint(chunks) {
|
|
117
|
+
const out = [chunks[0]];
|
|
118
|
+
for (let i = 1; i < chunks.length; i++) {
|
|
119
|
+
const chunk = chunks[i];
|
|
120
|
+
const prevMax = out.at(-1).maxv;
|
|
121
|
+
const cmp = chunk.minv.blockPosition - prevMax.blockPosition ||
|
|
122
|
+
chunk.minv.dataPosition - prevMax.dataPosition;
|
|
123
|
+
if (cmp >= 0) {
|
|
124
|
+
out.push(chunk);
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
const stillHasData = chunk.maxv.blockPosition - prevMax.blockPosition ||
|
|
128
|
+
chunk.maxv.dataPosition - prevMax.dataPosition;
|
|
129
|
+
if (stillHasData > 0) {
|
|
130
|
+
out.push(new Chunk(prevMax, chunk.maxv, chunk.bin, chunk.endPosition));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return out;
|
|
65
134
|
}
|
|
66
135
|
// Tighten each chunk's endPosition (default: a full max-size BGZF block past
|
|
67
136
|
// maxv) down to the next known block boundary. Every chunk min/maxv blockPosition
|
package/esm/util.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gmod/tabix",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.7",
|
|
4
4
|
"packageManager": "pnpm@11.15.1",
|
|
5
5
|
"description": "Read Tabix-indexed files, supports both .tbi and .csi indexes",
|
|
6
6
|
"type": "module",
|
|
@@ -60,7 +60,6 @@
|
|
|
60
60
|
"@vitest/coverage-v8": "^4.1.10",
|
|
61
61
|
"eslint": "^10.7.0",
|
|
62
62
|
"eslint-plugin-import-x": "^4.17.1",
|
|
63
|
-
"eslint-plugin-unicorn": "^72.0.0",
|
|
64
63
|
"git-cliff": "^2.13.1",
|
|
65
64
|
"prettier": "^3.9.6",
|
|
66
65
|
"rimraf": "^6.1.3",
|
package/src/indexFile.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { unzip } from '@gmod/bgzf-filehandle'
|
|
2
2
|
|
|
3
|
-
import { optimizeChunks } from './util.ts'
|
|
3
|
+
import { optimizeChunks, throwIfAborted } from './util.ts'
|
|
4
4
|
|
|
5
5
|
import type Chunk from './chunk.ts'
|
|
6
6
|
import type VirtualOffset from './virtualOffset.ts'
|
|
@@ -52,6 +52,13 @@ export interface IndexData {
|
|
|
52
52
|
export default abstract class IndexFile {
|
|
53
53
|
public filehandle: GenericFilehandle
|
|
54
54
|
private parseP?: Promise<IndexData>
|
|
55
|
+
/**
|
|
56
|
+
* The signal `parseP` was started under, while it is still in flight. The
|
|
57
|
+
* index is parsed once and shared by every query against the file, so without
|
|
58
|
+
* this the first query to arrive would own a read all the others depend on —
|
|
59
|
+
* see {@link parse}.
|
|
60
|
+
*/
|
|
61
|
+
private parseSignal?: AbortSignal
|
|
55
62
|
|
|
56
63
|
constructor({ filehandle }: { filehandle: GenericFilehandle }) {
|
|
57
64
|
this.filehandle = filehandle
|
|
@@ -151,13 +158,78 @@ export default abstract class IndexFile {
|
|
|
151
158
|
return optimizeChunks(chunks, this.lowestOffset(ba, min, indexData))
|
|
152
159
|
}
|
|
153
160
|
|
|
154
|
-
/**
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
+
/**
|
|
162
|
+
* Parse the index, or join the parse already running.
|
|
163
|
+
*
|
|
164
|
+
* The index is downloaded and parsed once for the life of this object, so it
|
|
165
|
+
* is the one read here that is shared between queries — and therefore the one
|
|
166
|
+
* place a cancellation can leak from the query that asked for it to a query
|
|
167
|
+
* that did not. `_parse` hands `opts` straight to `readIndexBytes`, so
|
|
168
|
+
* without this the first query to arrive owns a read every other query
|
|
169
|
+
* depends on: when it pans away, every concurrent query fails with its abort.
|
|
170
|
+
*
|
|
171
|
+
* A caller that joined someone else's parse and saw it fail because *they*
|
|
172
|
+
* aborted starts over rather than inheriting the failure — once, then
|
|
173
|
+
* propagates. Bounding it at one attempt is what jbrowse's
|
|
174
|
+
* `RemoteFileWithRangeCache.joinChunk` does with the same retry one layer
|
|
175
|
+
* down, and for the reason it gives: the pathological case becomes one
|
|
176
|
+
* duplicate parse rather than a recursion whose depth depends on how the
|
|
177
|
+
* aborts interleave.
|
|
178
|
+
*
|
|
179
|
+
* A retry rather than the reference count `chunkCache` gets from
|
|
180
|
+
* `@gmod/abortable-promise-cache`, because the index is parsed once for the
|
|
181
|
+
* life of the object: there is no repeated waste to recover, and this is a
|
|
182
|
+
* dozen lines against restructuring the memo. `@gmod/bam`'s `IndexFile` and
|
|
183
|
+
* `@gmod/cram`'s `CraiIndex` make the same split for the same reason.
|
|
184
|
+
*
|
|
185
|
+
* @internal
|
|
186
|
+
*/
|
|
187
|
+
async parse(opts: Options = {}, retried = false): Promise<IndexData> {
|
|
188
|
+
throwIfAborted(opts.signal)
|
|
189
|
+
const pending = this.parseP
|
|
190
|
+
if (!pending) {
|
|
191
|
+
return this.startParse(opts)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// read before awaiting: the owner is forgotten as soon as the parse settles
|
|
195
|
+
const ownerSignal = this.parseSignal
|
|
196
|
+
try {
|
|
197
|
+
return await pending
|
|
198
|
+
} catch (e) {
|
|
199
|
+
if (retried || !ownerSignal?.aborted || opts.signal?.aborted) {
|
|
200
|
+
throw e
|
|
201
|
+
}
|
|
202
|
+
return this.parse(opts, true)
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
private startParse(opts: Options) {
|
|
207
|
+
const pending = this._parse(opts)
|
|
208
|
+
this.parseP = pending
|
|
209
|
+
this.parseSignal = opts.signal
|
|
210
|
+
// Drop a rejection rather than keeping it, so one transient failure does not
|
|
211
|
+
// poison the index for the lifetime of the file. Identity-checked so a retry
|
|
212
|
+
// started after this settles is not cleared by the attempt it replaced.
|
|
213
|
+
//
|
|
214
|
+
// Written as one try/catch rather than `.then(onFulfilled, onRejected)`
|
|
215
|
+
// because `unicorn/prefer-then-catch` rewrites the two-argument form to
|
|
216
|
+
// `.then(...).catch(...)`, which is not the same thing — that catch would
|
|
217
|
+
// also swallow anything the fulfilment handler threw.
|
|
218
|
+
void (async () => {
|
|
219
|
+
let failed = false
|
|
220
|
+
try {
|
|
221
|
+
await pending
|
|
222
|
+
} catch {
|
|
223
|
+
failed = true
|
|
224
|
+
}
|
|
225
|
+
if (this.parseP === pending) {
|
|
226
|
+
if (failed) {
|
|
227
|
+
this.parseP = undefined
|
|
228
|
+
}
|
|
229
|
+
this.parseSignal = undefined
|
|
230
|
+
}
|
|
231
|
+
})()
|
|
232
|
+
return pending
|
|
161
233
|
}
|
|
162
234
|
|
|
163
235
|
/** @internal */
|