@milaboratories/pf-driver 1.1.1 → 1.3.0

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.
@@ -32,9 +32,14 @@ import {
32
32
  collectSpecQueryColumns,
33
33
  sortSpecQuery,
34
34
  sortPTableDef,
35
+ resolveAnnotationParents,
35
36
  } from "@milaboratories/pl-model-common";
36
37
  import type { PFrameInternal } from "@milaboratories/pl-model-middle-layer";
37
- import { ConcurrencyLimitingExecutor, type PoolEntry } from "@milaboratories/ts-helpers";
38
+ import {
39
+ ConcurrencyLimitingExecutor,
40
+ PoolEntryGuard,
41
+ type PoolEntry,
42
+ } from "@milaboratories/ts-helpers";
38
43
  import { PFrameFactory } from "@milaboratories/pframes-rs-node";
39
44
  import { tmpdir } from "node:os";
40
45
  import type { AbstractInternalPFrameDriver } from "./driver_decl";
@@ -58,9 +63,8 @@ import {
58
63
  } from "./ptable_cache_plain";
59
64
  import { createPFrame as createSpecFrame } from "@milaboratories/pframes-rs-wasm";
60
65
 
61
- export interface LocalBlobProvider<
62
- TreeEntry extends JsonSerializable,
63
- > extends PoolLocalBlobProvider<TreeEntry> {}
66
+ export interface LocalBlobProvider<TreeEntry extends JsonSerializable>
67
+ extends PoolLocalBlobProvider<TreeEntry>, AsyncDisposable {}
64
68
 
65
69
  export interface RemoteBlobProvider<TreeEntry extends JsonSerializable>
66
70
  extends PoolRemoteBlobProvider<TreeEntry>, AsyncDisposable {}
@@ -149,7 +153,13 @@ export class AbstractPFrameDriver<
149
153
  }
150
154
 
151
155
  async dispose(): Promise<void> {
152
- return await this.remoteBlobProvider[Symbol.asyncDispose]();
156
+ void (await Promise.allSettled([
157
+ this.pTables[Symbol.asyncDispose](),
158
+ this.pTableDefs[Symbol.asyncDispose](),
159
+ this.pFrames[Symbol.asyncDispose](),
160
+ this.localBlobProvider[Symbol.asyncDispose](),
161
+ this.remoteBlobProvider[Symbol.asyncDispose](),
162
+ ]));
153
163
  }
154
164
 
155
165
  async [Symbol.asyncDispose](): Promise<void> {
@@ -162,8 +172,9 @@ export class AbstractPFrameDriver<
162
172
 
163
173
  public createPFrame(def: PFrameDef<PColumn<PColumnData>>): PoolEntry<PFrameHandle> {
164
174
  const ValueTypes = new Set(Object.values(ValueType));
165
-
166
- const supportedColumns = def.filter((column) => ValueTypes.has(column.spec.valueType));
175
+ const supportedColumns = def
176
+ .filter((column) => ValueTypes.has(column.spec.valueType))
177
+ .map((c) => ({ ...c, spec: resolveAnnotationParents(c.spec) }));
167
178
  const uniqueColumns = uniqueBy(supportedColumns, (column) => column.id);
168
179
  const columns = uniqueColumns.map((c) =>
169
180
  mapPObjectData(c, (d) => this.resolveDataInfo(c.spec, d)),
@@ -173,7 +184,7 @@ export class AbstractPFrameDriver<
173
184
  }
174
185
 
175
186
  public createPTable(rawDef: PTableDef<PColumn<PColumnData>>): PoolEntry<PTableHandle> {
176
- const pFrameEntry = this.createPFrame(extractAllColumns(rawDef.src));
187
+ using pFrameGuard = new PoolEntryGuard(this.createPFrame(extractAllColumns(rawDef.src)));
177
188
  const sortedDef = sortPTableDef(
178
189
  migrateTableFilter(
179
190
  mapPTableDef(rawDef, (c) => c.id),
@@ -183,15 +194,16 @@ export class AbstractPFrameDriver<
183
194
  const pTableEntry = this.pTableDefs.acquire({
184
195
  type: "v1",
185
196
  def: sortedDef,
186
- pFrameHandle: pFrameEntry.key,
197
+ pFrameHandle: pFrameGuard.key,
187
198
  });
188
199
  if (logPFrames()) {
189
200
  this.logger(
190
201
  "info",
191
- `Create PTable call (pFrameHandle = ${pFrameEntry.key}; pTableHandle = ${pTableEntry.key})`,
202
+ `Create PTable call (pFrameHandle = ${pFrameGuard.key}; pTableHandle = ${pTableEntry.key})`,
192
203
  );
193
204
  }
194
205
 
206
+ const pFrameEntry = pFrameGuard.keep();
195
207
  const unref = () => {
196
208
  pTableEntry.unref();
197
209
  pFrameEntry.unref();
@@ -211,14 +223,20 @@ export class AbstractPFrameDriver<
211
223
  {} as Record<string, PColumnSpec>,
212
224
  );
213
225
 
214
- const pFrameEntry = this.createPFrame(columns);
215
- const specFrame = createSpecFrame(columnsMap);
226
+ using pFrameGuard = new PoolEntryGuard(this.createPFrame(columns));
227
+ const ValueTypes = new Set(Object.values(ValueType));
228
+ const specColumnsMap = Object.fromEntries(
229
+ Object.entries(columnsMap)
230
+ .filter(([, spec]) => ValueTypes.has(spec.valueType))
231
+ .map(([id, spec]) => [id, resolveAnnotationParents(spec)]),
232
+ );
233
+ const specFrame = createSpecFrame(specColumnsMap);
216
234
  const sortedQuery = sortSpecQuery(mapSpecQueryColumns(def.query, (c) => c.id));
217
235
  const { tableSpec, dataQuery } = specFrame.evaluateQuery(sortedQuery);
218
236
 
219
237
  const pTableEntry = this.pTableDefs.acquire({
220
238
  type: "v2",
221
- pFrameHandle: pFrameEntry.key,
239
+ pFrameHandle: pFrameGuard.key,
222
240
  def: {
223
241
  tableSpec,
224
242
  dataQuery,
@@ -227,10 +245,11 @@ export class AbstractPFrameDriver<
227
245
  if (logPFrames()) {
228
246
  this.logger(
229
247
  "info",
230
- `Create PTable call (pFrameHandle = ${pFrameEntry.key}; pTableHandle = ${pTableEntry.key})`,
248
+ `Create PTable call (pFrameHandle = ${pFrameGuard.key}; pTableHandle = ${pTableEntry.key})`,
231
249
  );
232
250
  }
233
251
 
252
+ const pFrameEntry = pFrameGuard.keep();
234
253
  const unref = () => {
235
254
  pTableEntry.unref();
236
255
  pFrameEntry.unref();
@@ -316,39 +335,36 @@ export class AbstractPFrameDriver<
316
335
  );
317
336
  }
318
337
 
319
- const table = this.pTables.acquire({
320
- type: "v1",
321
- pFrameHandle: handle,
322
- def: sortPTableDef(migrateTableFilter(request, this.logger)),
323
- });
324
- const { pTablePromise, disposeSignal } = table.resource;
338
+ using tableGuard = new PoolEntryGuard(
339
+ this.pTables.acquire({
340
+ type: "v1",
341
+ pFrameHandle: handle,
342
+ def: sortPTableDef(migrateTableFilter(request, this.logger)),
343
+ }),
344
+ );
345
+ const { pTablePromise, disposeSignal } = tableGuard.resource;
325
346
  const pTable = await pTablePromise;
326
347
 
327
348
  const combinedSignal = AbortSignal.any([signal, disposeSignal].filter((s) => !!s));
328
349
  return await this.frameConcurrencyLimiter.run(async () => {
329
- try {
330
- // TODO: throw error when more then 150k rows is requested
331
- // after pf-plots migration to stream API
350
+ // TODO: throw error when more then 150k rows is requested
351
+ // after pf-plots migration to stream API
332
352
 
333
- const spec = pTable.getSpec();
334
- const data = await pTable.getData([...spec.keys()], {
335
- range,
336
- signal: combinedSignal,
337
- });
353
+ const spec = pTable.getSpec();
354
+ const data = await pTable.getData([...spec.keys()], {
355
+ range,
356
+ signal: combinedSignal,
357
+ });
338
358
 
339
- const overallSize = await pTable.getFootprint({
340
- signal: combinedSignal,
341
- });
342
- this.pTableCachePerFrame.cache(table, overallSize);
343
-
344
- return spec.map((spec, i) => ({
345
- spec: spec,
346
- data: data[i],
347
- }));
348
- } catch (err: unknown) {
349
- table.unref();
350
- throw err;
351
- }
359
+ const overallSize = await pTable.getFootprint({
360
+ signal: combinedSignal,
361
+ });
362
+ this.pTableCachePerFrame.cache(tableGuard.keep(), overallSize);
363
+
364
+ return spec.map((spec, i) => ({
365
+ spec: spec,
366
+ data: data[i],
367
+ }));
352
368
  });
353
369
  }
354
370
 
@@ -397,9 +413,9 @@ export class AbstractPFrameDriver<
397
413
 
398
414
  public async getShape(handle: PTableHandle, signal?: AbortSignal): Promise<PTableShape> {
399
415
  const { def, disposeSignal: defDisposeSignal } = this.pTableDefs.getByKey(handle);
400
- const table = this.pTables.acquire(def);
416
+ using tableGuard = new PoolEntryGuard(this.pTables.acquire(def));
401
417
 
402
- const { pTablePromise, disposeSignal } = table.resource;
418
+ const { pTablePromise, disposeSignal } = tableGuard.resource;
403
419
  const pTable = await pTablePromise;
404
420
 
405
421
  const combinedSignal = AbortSignal.any([signal, disposeSignal].filter((s) => !!s));
@@ -415,7 +431,7 @@ export class AbstractPFrameDriver<
415
431
  return { shape, overallSize };
416
432
  });
417
433
 
418
- this.pTableCachePlain.cache(table, overallSize, defDisposeSignal);
434
+ this.pTableCachePlain.cache(tableGuard.keep(), overallSize, defDisposeSignal);
419
435
  return shape;
420
436
  }
421
437
 
@@ -426,9 +442,9 @@ export class AbstractPFrameDriver<
426
442
  signal?: AbortSignal,
427
443
  ): Promise<PTableVector[]> {
428
444
  const { def, disposeSignal: defDisposeSignal } = this.pTableDefs.getByKey(handle);
429
- const table = this.pTables.acquire(def);
445
+ using tableGuard = new PoolEntryGuard(this.pTables.acquire(def));
430
446
 
431
- const { pTablePromise, disposeSignal } = table.resource;
447
+ const { pTablePromise, disposeSignal } = tableGuard.resource;
432
448
  const pTable = await pTablePromise;
433
449
 
434
450
  const combinedSignal = AbortSignal.any([signal, disposeSignal].filter((s) => !!s));
@@ -445,7 +461,7 @@ export class AbstractPFrameDriver<
445
461
  return { data, overallSize };
446
462
  });
447
463
 
448
- this.pTableCachePlain.cache(table, overallSize, defDisposeSignal);
464
+ this.pTableCachePlain.cache(tableGuard.keep(), overallSize, defDisposeSignal);
449
465
  return data;
450
466
  }
451
467
  }
package/src/index.ts CHANGED
@@ -2,4 +2,3 @@ export * from "./driver_decl";
2
2
  export * from "./driver_impl";
3
3
  export * from "./data_info_helpers";
4
4
  export * from "./driver_double";
5
- export * from "../../pl-middle-layer/src/js_render/spec_driver";
@@ -1,43 +0,0 @@
1
- const require_runtime = require('../../../_virtual/_rolldown/runtime.cjs');
2
- let _milaboratories_pframes_rs_wasm = require("@milaboratories/pframes-rs-wasm");
3
- let node_crypto = require("node:crypto");
4
-
5
- //#region ../pl-middle-layer/src/js_render/spec_driver.ts
6
- /**
7
- * Manages spec-only PFrame instances (WASM) with handle-based lifecycle.
8
- *
9
- * All operations are synchronous — WASM computes results immediately.
10
- */
11
- var SpecDriver = class {
12
- frames = /* @__PURE__ */ new Map();
13
- createSpecFrame(specs) {
14
- const frame = (0, _milaboratories_pframes_rs_wasm.createPFrame)(specs);
15
- const handle = (0, node_crypto.randomUUID)();
16
- this.frames.set(handle, frame);
17
- return handle;
18
- }
19
- specFrameDiscoverColumns(handle, request) {
20
- return this.getFrame(handle).discoverColumns(request);
21
- }
22
- disposeSpecFrame(handle) {
23
- const frame = this.frames.get(handle);
24
- if (frame) {
25
- frame[Symbol.dispose]();
26
- this.frames.delete(handle);
27
- }
28
- }
29
- /** Dispose all managed spec frames. */
30
- disposeAll() {
31
- for (const frame of this.frames.values()) frame[Symbol.dispose]();
32
- this.frames.clear();
33
- }
34
- getFrame(handle) {
35
- const frame = this.frames.get(handle);
36
- if (frame === void 0) throw new Error(`No such spec frame: ${handle}`);
37
- return frame;
38
- }
39
- };
40
-
41
- //#endregion
42
- exports.SpecDriver = SpecDriver;
43
- //# sourceMappingURL=spec_driver.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"spec_driver.cjs","names":[],"sources":["../../../../../pl-middle-layer/src/js_render/spec_driver.ts"],"sourcesContent":["import { createPFrame } from \"@milaboratories/pframes-rs-wasm\";\nimport type { PFrameInternal } from \"@milaboratories/pl-model-middle-layer\";\nimport type {\n PColumnSpec,\n PSpecDriver,\n SpecFrameHandle,\n DiscoverColumnsRequest,\n DiscoverColumnsResponse,\n} from \"@milaboratories/pl-model-common\";\nimport { randomUUID } from \"node:crypto\";\n\n/**\n * Manages spec-only PFrame instances (WASM) with handle-based lifecycle.\n *\n * All operations are synchronous — WASM computes results immediately.\n */\nexport class SpecDriver implements PSpecDriver {\n private readonly frames = new Map<string, PFrameInternal.PFrameWasm>();\n\n createSpecFrame(specs: Record<string, PColumnSpec>): SpecFrameHandle {\n const frame = createPFrame(specs);\n const handle = randomUUID() as SpecFrameHandle;\n this.frames.set(handle, frame);\n return handle;\n }\n\n specFrameDiscoverColumns(\n handle: SpecFrameHandle,\n request: DiscoverColumnsRequest,\n ): DiscoverColumnsResponse {\n return this.getFrame(handle).discoverColumns(request);\n }\n\n disposeSpecFrame(handle: SpecFrameHandle): void {\n const frame = this.frames.get(handle);\n if (frame) {\n frame[Symbol.dispose]();\n this.frames.delete(handle);\n }\n }\n\n /** Dispose all managed spec frames. */\n disposeAll(): void {\n for (const frame of this.frames.values()) {\n frame[Symbol.dispose]();\n }\n this.frames.clear();\n }\n\n private getFrame(handle: string): PFrameInternal.PFrameWasm {\n const frame = this.frames.get(handle);\n if (frame === undefined) throw new Error(`No such spec frame: ${handle}`);\n return frame;\n }\n}\n"],"mappings":";;;;;;;;;;AAgBA,IAAa,aAAb,MAA+C;CAC7C,AAAiB,yBAAS,IAAI,KAAwC;CAEtE,gBAAgB,OAAqD;EACnE,MAAM,0DAAqB,MAAM;EACjC,MAAM,sCAAqB;AAC3B,OAAK,OAAO,IAAI,QAAQ,MAAM;AAC9B,SAAO;;CAGT,yBACE,QACA,SACyB;AACzB,SAAO,KAAK,SAAS,OAAO,CAAC,gBAAgB,QAAQ;;CAGvD,iBAAiB,QAA+B;EAC9C,MAAM,QAAQ,KAAK,OAAO,IAAI,OAAO;AACrC,MAAI,OAAO;AACT,SAAM,OAAO,UAAU;AACvB,QAAK,OAAO,OAAO,OAAO;;;;CAK9B,aAAmB;AACjB,OAAK,MAAM,SAAS,KAAK,OAAO,QAAQ,CACtC,OAAM,OAAO,UAAU;AAEzB,OAAK,OAAO,OAAO;;CAGrB,AAAQ,SAAS,QAA2C;EAC1D,MAAM,QAAQ,KAAK,OAAO,IAAI,OAAO;AACrC,MAAI,UAAU,OAAW,OAAM,IAAI,MAAM,uBAAuB,SAAS;AACzE,SAAO"}
@@ -1,20 +0,0 @@
1
- import { DiscoverColumnsRequest, DiscoverColumnsResponse, PColumnSpec, PSpecDriver, SpecFrameHandle } from "@milaboratories/pl-model-common";
2
-
3
- //#region ../pl-middle-layer/src/js_render/spec_driver.d.ts
4
- /**
5
- * Manages spec-only PFrame instances (WASM) with handle-based lifecycle.
6
- *
7
- * All operations are synchronous — WASM computes results immediately.
8
- */
9
- declare class SpecDriver implements PSpecDriver {
10
- private readonly frames;
11
- createSpecFrame(specs: Record<string, PColumnSpec>): SpecFrameHandle;
12
- specFrameDiscoverColumns(handle: SpecFrameHandle, request: DiscoverColumnsRequest): DiscoverColumnsResponse;
13
- disposeSpecFrame(handle: SpecFrameHandle): void;
14
- /** Dispose all managed spec frames. */
15
- disposeAll(): void;
16
- private getFrame;
17
- }
18
- //#endregion
19
- export { SpecDriver };
20
- //# sourceMappingURL=spec_driver.d.ts.map
@@ -1,42 +0,0 @@
1
- import { createPFrame } from "@milaboratories/pframes-rs-wasm";
2
- import { randomUUID } from "node:crypto";
3
-
4
- //#region ../pl-middle-layer/src/js_render/spec_driver.ts
5
- /**
6
- * Manages spec-only PFrame instances (WASM) with handle-based lifecycle.
7
- *
8
- * All operations are synchronous — WASM computes results immediately.
9
- */
10
- var SpecDriver = class {
11
- frames = /* @__PURE__ */ new Map();
12
- createSpecFrame(specs) {
13
- const frame = createPFrame(specs);
14
- const handle = randomUUID();
15
- this.frames.set(handle, frame);
16
- return handle;
17
- }
18
- specFrameDiscoverColumns(handle, request) {
19
- return this.getFrame(handle).discoverColumns(request);
20
- }
21
- disposeSpecFrame(handle) {
22
- const frame = this.frames.get(handle);
23
- if (frame) {
24
- frame[Symbol.dispose]();
25
- this.frames.delete(handle);
26
- }
27
- }
28
- /** Dispose all managed spec frames. */
29
- disposeAll() {
30
- for (const frame of this.frames.values()) frame[Symbol.dispose]();
31
- this.frames.clear();
32
- }
33
- getFrame(handle) {
34
- const frame = this.frames.get(handle);
35
- if (frame === void 0) throw new Error(`No such spec frame: ${handle}`);
36
- return frame;
37
- }
38
- };
39
-
40
- //#endregion
41
- export { SpecDriver };
42
- //# sourceMappingURL=spec_driver.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"spec_driver.js","names":[],"sources":["../../../../../pl-middle-layer/src/js_render/spec_driver.ts"],"sourcesContent":["import { createPFrame } from \"@milaboratories/pframes-rs-wasm\";\nimport type { PFrameInternal } from \"@milaboratories/pl-model-middle-layer\";\nimport type {\n PColumnSpec,\n PSpecDriver,\n SpecFrameHandle,\n DiscoverColumnsRequest,\n DiscoverColumnsResponse,\n} from \"@milaboratories/pl-model-common\";\nimport { randomUUID } from \"node:crypto\";\n\n/**\n * Manages spec-only PFrame instances (WASM) with handle-based lifecycle.\n *\n * All operations are synchronous — WASM computes results immediately.\n */\nexport class SpecDriver implements PSpecDriver {\n private readonly frames = new Map<string, PFrameInternal.PFrameWasm>();\n\n createSpecFrame(specs: Record<string, PColumnSpec>): SpecFrameHandle {\n const frame = createPFrame(specs);\n const handle = randomUUID() as SpecFrameHandle;\n this.frames.set(handle, frame);\n return handle;\n }\n\n specFrameDiscoverColumns(\n handle: SpecFrameHandle,\n request: DiscoverColumnsRequest,\n ): DiscoverColumnsResponse {\n return this.getFrame(handle).discoverColumns(request);\n }\n\n disposeSpecFrame(handle: SpecFrameHandle): void {\n const frame = this.frames.get(handle);\n if (frame) {\n frame[Symbol.dispose]();\n this.frames.delete(handle);\n }\n }\n\n /** Dispose all managed spec frames. */\n disposeAll(): void {\n for (const frame of this.frames.values()) {\n frame[Symbol.dispose]();\n }\n this.frames.clear();\n }\n\n private getFrame(handle: string): PFrameInternal.PFrameWasm {\n const frame = this.frames.get(handle);\n if (frame === undefined) throw new Error(`No such spec frame: ${handle}`);\n return frame;\n }\n}\n"],"mappings":";;;;;;;;;AAgBA,IAAa,aAAb,MAA+C;CAC7C,AAAiB,yBAAS,IAAI,KAAwC;CAEtE,gBAAgB,OAAqD;EACnE,MAAM,QAAQ,aAAa,MAAM;EACjC,MAAM,SAAS,YAAY;AAC3B,OAAK,OAAO,IAAI,QAAQ,MAAM;AAC9B,SAAO;;CAGT,yBACE,QACA,SACyB;AACzB,SAAO,KAAK,SAAS,OAAO,CAAC,gBAAgB,QAAQ;;CAGvD,iBAAiB,QAA+B;EAC9C,MAAM,QAAQ,KAAK,OAAO,IAAI,OAAO;AACrC,MAAI,OAAO;AACT,SAAM,OAAO,UAAU;AACvB,QAAK,OAAO,OAAO,OAAO;;;;CAK9B,aAAmB;AACjB,OAAK,MAAM,SAAS,KAAK,OAAO,QAAQ,CACtC,OAAM,OAAO,UAAU;AAEzB,OAAK,OAAO,OAAO;;CAGrB,AAAQ,SAAS,QAA2C;EAC1D,MAAM,QAAQ,KAAK,OAAO,IAAI,OAAO;AACrC,MAAI,UAAU,OAAW,OAAM,IAAI,MAAM,uBAAuB,SAAS;AACzE,SAAO"}