@gmod/tabix 3.6.0 → 3.6.1

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.
@@ -49,14 +49,11 @@ export interface IndexData {
49
49
  }
50
50
  export default abstract class IndexFile {
51
51
  filehandle: GenericFilehandle;
52
- private parseP?;
53
52
  /**
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}.
53
+ * The parsed index, as a shared read — see {@link parse}. One entry, never
54
+ * evicted, which is what a memo is.
58
55
  */
59
- private parseSignal?;
56
+ private parseCache;
60
57
  constructor({ filehandle }: {
61
58
  filehandle: GenericFilehandle;
62
59
  });
@@ -124,28 +121,27 @@ export default abstract class IndexFile {
124
121
  * The index is downloaded and parsed once for the life of this object, so it
125
122
  * is the one read here that is shared between queries — and therefore the one
126
123
  * 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.
124
+ * that did not. `_parse` hands `opts` straight to `readIndexBytes`, so a bare
125
+ * memoized promise makes the first query to arrive the owner of a read every
126
+ * other query depends on: when it pans away, every concurrent query fails
127
+ * with its abort.
130
128
  *
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.
129
+ * The same cache `ChunkCache` uses, for the same reason and with the same
130
+ * rule: the parse runs under a signal of its own and is cancelled only once
131
+ * every caller waiting on it has given up, so one query's abort is reported
132
+ * to that query alone and a bystander gets the parse already in flight rather
133
+ * than having to re-read the index. A rejection is dropped rather than
134
+ * cached, so a transient failure does not poison the index for the life of
135
+ * the file.
138
136
  *
139
- * A retry rather than the reference count `ChunkCache` uses, because the
140
- * index is parsed once for the life of the object: there is no repeated waste
141
- * to recover, and this is a dozen lines against restructuring the memo.
142
- * `@gmod/bam`'s `IndexFile` and `@gmod/cram`'s `CraiIndex` make the same
143
- * split for the same reason.
137
+ * The fill is per call rather than on the cache so that the caller who starts
138
+ * the parse has its `onProgress` reach `readIndexBytes` — the index is a
139
+ * whole-file read, and a determinate "downloading index" bar is what that
140
+ * callback exists for.
144
141
  *
145
142
  * @internal
146
143
  */
147
- parse(opts?: Options, retried?: boolean): Promise<IndexData>;
148
- private startParse;
144
+ parse(opts?: Options): Promise<IndexData>;
149
145
  /** @internal */
150
146
  hasRefSeq(seqId: number, opts?: Options): Promise<boolean>;
151
147
  }
package/dist/indexFile.js CHANGED
@@ -1,17 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const bgzf_filehandle_1 = require("@gmod/bgzf-filehandle");
4
+ const shared_read_cache_1 = require("@gmod/shared-read-cache");
4
5
  const util_ts_1 = require("./util.js");
5
6
  class IndexFile {
6
7
  filehandle;
7
- parseP;
8
8
  /**
9
- * The signal `parseP` was started under, while it is still in flight. The
10
- * index is parsed once and shared by every query against the file, so without
11
- * this the first query to arrive would own a read all the others depend on —
12
- * see {@link parse}.
9
+ * The parsed index, as a shared read — see {@link parse}. One entry, never
10
+ * evicted, which is what a memo is.
13
11
  */
14
- parseSignal;
12
+ parseCache = new shared_read_cache_1.SharedReadCache({});
15
13
  constructor({ filehandle }) {
16
14
  this.filehandle = filehandle;
17
15
  }
@@ -75,71 +73,36 @@ class IndexFile {
75
73
  }
76
74
  return (0, util_ts_1.optimizeChunks)(chunks, this.lowestOffset(ba, min, indexData));
77
75
  }
78
- // SYNC: ~/src/gmod/bam-js/src/indexFile.ts parse — same owner-signal
79
- // tracking and one-attempt retry, and the same reasoning below.
76
+ // SYNC: ~/src/gmod/bam-js/src/indexFile.ts parse — same shape and the same
77
+ // reasoning below.
80
78
  /**
81
79
  * Parse the index, or join the parse already running.
82
80
  *
83
81
  * The index is downloaded and parsed once for the life of this object, so it
84
82
  * is the one read here that is shared between queries — and therefore the one
85
83
  * place a cancellation can leak from the query that asked for it to a query
86
- * that did not. `_parse` hands `opts` straight to `readIndexBytes`, so
87
- * without this the first query to arrive owns a read every other query
88
- * depends on: when it pans away, every concurrent query fails with its abort.
84
+ * that did not. `_parse` hands `opts` straight to `readIndexBytes`, so a bare
85
+ * memoized promise makes the first query to arrive the owner of a read every
86
+ * other query depends on: when it pans away, every concurrent query fails
87
+ * with its abort.
89
88
  *
90
- * A caller that joined someone else's parse and saw it fail because *they*
91
- * aborted starts over rather than inheriting the failure — once, then
92
- * propagates. Bounding it at one attempt is what jbrowse's
93
- * `RemoteFileWithRangeCache.joinChunk` does with the same retry one layer
94
- * down, and for the reason it gives: the pathological case becomes one
95
- * duplicate parse rather than a recursion whose depth depends on how the
96
- * aborts interleave.
89
+ * The same cache `ChunkCache` uses, for the same reason and with the same
90
+ * rule: the parse runs under a signal of its own and is cancelled only once
91
+ * every caller waiting on it has given up, so one query's abort is reported
92
+ * to that query alone and a bystander gets the parse already in flight rather
93
+ * than having to re-read the index. A rejection is dropped rather than
94
+ * cached, so a transient failure does not poison the index for the life of
95
+ * the file.
97
96
  *
98
- * A retry rather than the reference count `ChunkCache` uses, because the
99
- * index is parsed once for the life of the object: there is no repeated waste
100
- * to recover, and this is a dozen lines against restructuring the memo.
101
- * `@gmod/bam`'s `IndexFile` and `@gmod/cram`'s `CraiIndex` make the same
102
- * split for the same reason.
97
+ * The fill is per call rather than on the cache so that the caller who starts
98
+ * the parse has its `onProgress` reach `readIndexBytes` — the index is a
99
+ * whole-file read, and a determinate "downloading index" bar is what that
100
+ * callback exists for.
103
101
  *
104
102
  * @internal
105
103
  */
106
- async parse(opts = {}, retried = false) {
107
- (0, util_ts_1.throwIfAborted)(opts.signal);
108
- const pending = this.parseP;
109
- if (!pending) {
110
- return this.startParse(opts);
111
- }
112
- // read before awaiting: the owner is forgotten as soon as the parse settles
113
- const ownerSignal = this.parseSignal;
114
- try {
115
- return await pending;
116
- }
117
- catch (e) {
118
- if (retried || !ownerSignal?.aborted || opts.signal?.aborted) {
119
- throw e;
120
- }
121
- return this.parse(opts, true);
122
- }
123
- }
124
- startParse(opts) {
125
- const pending = this._parse(opts);
126
- this.parseP = pending;
127
- this.parseSignal = opts.signal;
128
- // Drop a rejection rather than keeping it, so one transient failure does not
129
- // poison the index for the lifetime of the file. Both branches are
130
- // identity-checked so a retry started after this settles is not cleared by
131
- // the attempt it already replaced.
132
- pending.then(() => {
133
- if (this.parseP === pending) {
134
- this.parseSignal = undefined;
135
- }
136
- }, () => {
137
- if (this.parseP === pending) {
138
- this.parseP = undefined;
139
- this.parseSignal = undefined;
140
- }
141
- });
142
- return pending;
104
+ parse(opts = {}) {
105
+ return this.parseCache.get('index', opts.signal, signal => this._parse({ ...opts, signal }));
143
106
  }
144
107
  /** @internal */
145
108
  async hasRefSeq(seqId, opts = {}) {
@@ -1 +1 @@
1
- {"version":3,"file":"indexFile.js","sourceRoot":"","sources":["../src/indexFile.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"indexFile.js","sourceRoot":"","sources":["../src/indexFile.ts"],"names":[],"mappings":";;AAAA,2DAA6C;AAC7C,+DAAyD;AAEzD,uCAA0C;AAiD1C,MAA8B,SAAS;IAC9B,UAAU,CAAmB;IACpC;;;OAGG;IACK,UAAU,GAAG,IAAI,mCAAe,CAAoB,EAAE,CAAC,CAAA;IAE/D,YAAY,EAAE,UAAU,EAAqC;QAC3D,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;IAC9B,CAAC;IAyBD;;;OAGG;IACO,KAAK,CAAC,cAAc,CAAC,IAAa;QAC1C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;YACzC,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,UAAU,EAAE,IAAI,CAAC,UAAU;SAC5B,CAAC,CAAA;QACF,MAAM,KAAK,GAAG,MAAM,IAAA,uBAAK,EAAC,GAAG,CAAC,CAAA;QAC9B,OAAO;YACL,KAAK;YACL,QAAQ,EAAE,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC;SACzE,CAAA;IACH,CAAC;IAED,gBAAgB;IACT,KAAK,CAAC,SAAS,CAAC,OAAe,EAAE,OAAgB,EAAE;QACxD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QACxC,MAAM,KAAK,GAAG,SAAS,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;QAC5C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,CAAC,CAAC,CAAA;QACX,CAAC;QACD,OAAO,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,SAAS,IAAI,CAAC,CAAC,CAAA;IACzD,CAAC;IAED,gBAAgB;IACT,KAAK,CAAC,WAAW,CAAC,OAAgB,EAAE;QACzC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAC7D,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,cAAc,CACzB,OAAe,EACf,GAAW,EACX,GAAW,EACX,OAAgB,EAAE;QAElB,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QACxC,MAAM,KAAK,GAAG,SAAS,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;QAC5C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,EAAE,CAAA;QACX,CAAC;QACD,MAAM,EAAE,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QACnC,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,OAAO,EAAE,CAAA;QACX,CAAC;QAED,6DAA6D;QAC7D,MAAM,MAAM,GAAY,EAAE,CAAA;QAC1B,KAAK,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,SAAS,CAAC,EAAE,CAAC;YAC9D,KAAK,IAAI,GAAG,GAAG,KAAK,EAAE,GAAG,IAAI,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC;gBACxC,MAAM,SAAS,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;gBAClC,IAAI,SAAS,EAAE,CAAC;oBACd,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;wBAC1B,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;oBAChB,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,IAAA,wBAAc,EAAC,MAAM,EAAE,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC,CAAA;IACtE,CAAC;IAED,2EAA2E;IAC3E,mBAAmB;IACnB;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,KAAK,CAAC,OAAgB,EAAE;QACtB,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CACxD,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,CAAC,CACjC,CAAA;IACH,CAAC;IAED,gBAAgB;IAChB,KAAK,CAAC,SAAS,CAAC,KAAa,EAAE,OAAgB,EAAE;QAC/C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAClC,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAA;IACvC,CAAC;CACF;AAjJD,4BAiJC"}