@milaboratories/pf-driver 1.4.11 → 1.4.13
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/driver_impl.cjs +50 -54
- package/dist/driver_impl.cjs.map +1 -1
- package/dist/driver_impl.d.ts.map +1 -1
- package/dist/driver_impl.js +50 -54
- package/dist/driver_impl.js.map +1 -1
- package/dist/pframe_pool.cjs +78 -56
- package/dist/pframe_pool.cjs.map +1 -1
- package/dist/pframe_pool.d.ts.map +1 -1
- package/dist/pframe_pool.js +79 -57
- package/dist/pframe_pool.js.map +1 -1
- package/dist/ptable_def_pool.cjs +15 -0
- package/dist/ptable_def_pool.cjs.map +1 -1
- package/dist/ptable_def_pool.d.ts +2 -2
- package/dist/ptable_def_pool.js +16 -1
- package/dist/ptable_def_pool.js.map +1 -1
- package/dist/ptable_pool.cjs +18 -96
- package/dist/ptable_pool.cjs.map +1 -1
- package/dist/ptable_pool.d.ts +1 -1
- package/dist/ptable_pool.js +20 -98
- package/dist/ptable_pool.js.map +1 -1
- package/dist/ptable_shared.cjs +26 -0
- package/dist/ptable_shared.cjs.map +1 -1
- package/dist/ptable_shared.d.ts +2 -1
- package/dist/ptable_shared.js +26 -1
- package/dist/ptable_shared.js.map +1 -1
- package/package.json +5 -5
- package/src/driver_impl.ts +44 -58
- package/src/pframe_pool.ts +115 -76
- package/src/ptable_def_pool.ts +26 -3
- package/src/ptable_pool.ts +19 -140
- package/src/ptable_shared.ts +47 -18
package/src/driver_impl.ts
CHANGED
|
@@ -71,7 +71,6 @@ import {
|
|
|
71
71
|
PTableCachePlainOpsDefaults,
|
|
72
72
|
type PTableCachePlainOps,
|
|
73
73
|
} from "./ptable_cache_plain";
|
|
74
|
-
import { createPFrame as createSpecFrame } from "@milaboratories/pframes-rs-wasm";
|
|
75
74
|
|
|
76
75
|
export interface LocalBlobProvider<TreeEntry extends JsonSerializable>
|
|
77
76
|
extends PoolLocalBlobProvider<TreeEntry>, AsyncDisposable {}
|
|
@@ -194,26 +193,31 @@ export class AbstractPFrameDriver<
|
|
|
194
193
|
}
|
|
195
194
|
|
|
196
195
|
public createPTable(rawDef: PTableDef<PColumn<PColumnData>>): PoolEntry<PTableHandle> {
|
|
197
|
-
|
|
196
|
+
const columns = uniqueBy(extractAllColumns(rawDef.src), (c) => c.id);
|
|
197
|
+
using pFrameGuard = new PoolEntryGuard(this.createPFrame(columns));
|
|
198
198
|
const sortedDef = sortPTableDef(
|
|
199
199
|
migrateTableFilter(
|
|
200
200
|
mapPTableDef(rawDef, (c) => c.id),
|
|
201
201
|
this.logger,
|
|
202
202
|
),
|
|
203
203
|
);
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
204
|
+
const pFrameSpec = this.pFrames.getByKey(pFrameGuard.key).pFrameSpec;
|
|
205
|
+
using pTableGuard = new PoolEntryGuard(
|
|
206
|
+
this.pTableDefs.acquireFromLegacy({
|
|
207
|
+
pFrameHandle: pFrameGuard.key,
|
|
208
|
+
def: sortedDef,
|
|
209
|
+
pFrameSpec,
|
|
210
|
+
}).entry,
|
|
211
|
+
);
|
|
209
212
|
if (logPFrames()) {
|
|
210
213
|
this.logger(
|
|
211
214
|
"info",
|
|
212
|
-
`Create PTable call (pFrameHandle = ${pFrameGuard.key}; pTableHandle = ${
|
|
215
|
+
`Create PTable call (pFrameHandle = ${pFrameGuard.key}; pTableHandle = ${pTableGuard.key})`,
|
|
213
216
|
);
|
|
214
217
|
}
|
|
215
218
|
|
|
216
219
|
const pFrameEntry = pFrameGuard.keep();
|
|
220
|
+
const pTableEntry = pTableGuard.keep();
|
|
217
221
|
const unref = () => {
|
|
218
222
|
pTableEntry.unref();
|
|
219
223
|
pFrameEntry.unref();
|
|
@@ -228,38 +232,27 @@ export class AbstractPFrameDriver<
|
|
|
228
232
|
|
|
229
233
|
public createPTableV2(def: PTableDefV2<PColumn<PColumnData>>): PoolEntry<PTableHandle> {
|
|
230
234
|
const columns = uniqueBy(collectSpecQueryColumns(def.query), (c) => c.id);
|
|
231
|
-
const columnsMap = columns.reduce(
|
|
232
|
-
(acc, col) => ((acc[col.id] = col.spec), acc),
|
|
233
|
-
{} as Record<string, PColumnSpec>,
|
|
234
|
-
);
|
|
235
|
-
|
|
236
235
|
using pFrameGuard = new PoolEntryGuard(this.createPFrame(columns));
|
|
237
|
-
const
|
|
238
|
-
const specColumnsMap = Object.fromEntries(
|
|
239
|
-
Object.entries(columnsMap)
|
|
240
|
-
.filter(([, spec]) => ValueTypes.has(spec.valueType))
|
|
241
|
-
.map(([id, spec]) => [id, resolveAnnotationParents(spec)]),
|
|
242
|
-
);
|
|
243
|
-
const specFrame = createSpecFrame(specColumnsMap);
|
|
236
|
+
const pFrameSpec = this.pFrames.getByKey(pFrameGuard.key).pFrameSpec;
|
|
244
237
|
const sortedQuery = sortSpecQuery(mapSpecQueryColumns(def.query, (c) => c.id));
|
|
245
|
-
const { tableSpec, dataQuery } =
|
|
238
|
+
const { tableSpec, dataQuery } = pFrameSpec.evaluateQuery(sortedQuery);
|
|
246
239
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
def: {
|
|
240
|
+
using pTableGuard = new PoolEntryGuard(
|
|
241
|
+
this.pTableDefs.acquire({
|
|
242
|
+
pFrameHandle: pFrameGuard.key,
|
|
251
243
|
tableSpec,
|
|
252
244
|
dataQuery,
|
|
253
|
-
},
|
|
254
|
-
|
|
245
|
+
}),
|
|
246
|
+
);
|
|
255
247
|
if (logPFrames()) {
|
|
256
248
|
this.logger(
|
|
257
249
|
"info",
|
|
258
|
-
`Create PTable call (pFrameHandle = ${pFrameGuard.key}; pTableHandle = ${
|
|
250
|
+
`Create PTable call (pFrameHandle = ${pFrameGuard.key}; pTableHandle = ${pTableGuard.key})`,
|
|
259
251
|
);
|
|
260
252
|
}
|
|
261
253
|
|
|
262
254
|
const pFrameEntry = pFrameGuard.keep();
|
|
255
|
+
const pTableEntry = pTableGuard.keep();
|
|
263
256
|
const unref = () => {
|
|
264
257
|
pTableEntry.unref();
|
|
265
258
|
pFrameEntry.unref();
|
|
@@ -293,7 +286,7 @@ export class AbstractPFrameDriver<
|
|
|
293
286
|
return await this.tableConcurrencyLimiter.run(async () => {
|
|
294
287
|
const shape = await pTable.getShape({ signal: combinedSignal });
|
|
295
288
|
const clippedRange = clipRange(options.range, shape);
|
|
296
|
-
const specs =
|
|
289
|
+
const specs = def.tableSpec;
|
|
297
290
|
const separator = options.format === "tsv" ? "\t" : ",";
|
|
298
291
|
|
|
299
292
|
const iterable = streamPTableRows({
|
|
@@ -371,10 +364,8 @@ export class AbstractPFrameDriver<
|
|
|
371
364
|
: [],
|
|
372
365
|
};
|
|
373
366
|
|
|
374
|
-
const {
|
|
375
|
-
const
|
|
376
|
-
|
|
377
|
-
const response = await pFrame.findColumns(iRequest);
|
|
367
|
+
const { pFrameSpec } = this.pFrames.getByKey(handle);
|
|
368
|
+
const response = pFrameSpec.findColumns(iRequest);
|
|
378
369
|
return {
|
|
379
370
|
hits: response.hits
|
|
380
371
|
.filter(
|
|
@@ -395,15 +386,14 @@ export class AbstractPFrameDriver<
|
|
|
395
386
|
handle: PFrameHandle,
|
|
396
387
|
columnId: PObjectId,
|
|
397
388
|
): Promise<PColumnSpec | null> {
|
|
398
|
-
const {
|
|
399
|
-
const
|
|
400
|
-
return
|
|
389
|
+
const { pFrameSpec } = this.pFrames.getByKey(handle);
|
|
390
|
+
const info = pFrameSpec.listColumns().find((c) => c.columnId === columnId);
|
|
391
|
+
return info?.spec ?? null;
|
|
401
392
|
}
|
|
402
393
|
|
|
403
394
|
public async listColumns(handle: PFrameHandle): Promise<PColumnIdAndSpec[]> {
|
|
404
|
-
const {
|
|
405
|
-
|
|
406
|
-
return await pFrame.listColumns();
|
|
395
|
+
const { pFrameSpec } = this.pFrames.getByKey(handle);
|
|
396
|
+
return pFrameSpec.listColumns().map(({ columnId, spec }) => ({ columnId, spec }));
|
|
407
397
|
}
|
|
408
398
|
|
|
409
399
|
public async calculateTableData(
|
|
@@ -419,13 +409,15 @@ export class AbstractPFrameDriver<
|
|
|
419
409
|
);
|
|
420
410
|
}
|
|
421
411
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
);
|
|
412
|
+
const { pFrameSpec } = this.pFrames.getByKey(handle);
|
|
413
|
+
const sortedDef = sortPTableDef(migrateTableFilter(request, this.logger));
|
|
414
|
+
const { def, entry } = this.pTables.acquireFromLegacy({
|
|
415
|
+
pFrameHandle: handle,
|
|
416
|
+
def: sortedDef,
|
|
417
|
+
pFrameSpec,
|
|
418
|
+
});
|
|
419
|
+
using tableGuard = new PoolEntryGuard(entry);
|
|
420
|
+
const tableSpec = def.tableSpec;
|
|
429
421
|
const { pTablePromise, disposeSignal } = tableGuard.resource;
|
|
430
422
|
const pTable = await pTablePromise;
|
|
431
423
|
|
|
@@ -434,8 +426,7 @@ export class AbstractPFrameDriver<
|
|
|
434
426
|
// TODO: throw error when more then 150k rows is requested
|
|
435
427
|
// after pf-plots migration to stream API
|
|
436
428
|
|
|
437
|
-
const
|
|
438
|
-
const data = await pTable.getData([...spec.keys()], {
|
|
429
|
+
const data = await pTable.getData([...tableSpec.keys()], {
|
|
439
430
|
range,
|
|
440
431
|
signal: combinedSignal,
|
|
441
432
|
});
|
|
@@ -445,7 +436,7 @@ export class AbstractPFrameDriver<
|
|
|
445
436
|
});
|
|
446
437
|
this.pTableCachePerFrame.cache(tableGuard.keep(), overallSize);
|
|
447
438
|
|
|
448
|
-
return
|
|
439
|
+
return tableSpec.map((spec, i) => ({
|
|
449
440
|
spec: spec,
|
|
450
441
|
data: data[i],
|
|
451
442
|
}));
|
|
@@ -464,12 +455,12 @@ export class AbstractPFrameDriver<
|
|
|
464
455
|
);
|
|
465
456
|
}
|
|
466
457
|
|
|
467
|
-
const {
|
|
468
|
-
const
|
|
458
|
+
const { pFrameDataPromise, disposeSignal } = this.pFrames.getByKey(handle);
|
|
459
|
+
const pFrameData = await pFrameDataPromise;
|
|
469
460
|
|
|
470
461
|
const combinedSignal = AbortSignal.any([signal, disposeSignal].filter((s) => !!s));
|
|
471
462
|
return await this.frameConcurrencyLimiter.run(async () => {
|
|
472
|
-
return await
|
|
463
|
+
return await pFrameData.getUniqueValues(
|
|
473
464
|
{
|
|
474
465
|
...request,
|
|
475
466
|
filters: migrateFilters(request.filters, this.logger),
|
|
@@ -487,12 +478,7 @@ export class AbstractPFrameDriver<
|
|
|
487
478
|
|
|
488
479
|
public async getSpec(handle: PTableHandle): Promise<PTableColumnSpec[]> {
|
|
489
480
|
const { def } = this.pTableDefs.getByKey(handle);
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
const { pTablePromise } = table.resource;
|
|
493
|
-
const pTable = await pTablePromise;
|
|
494
|
-
|
|
495
|
-
return pTable.getSpec();
|
|
481
|
+
return def.tableSpec;
|
|
496
482
|
}
|
|
497
483
|
|
|
498
484
|
public async getShape(handle: PTableHandle, signal?: AbortSignal): Promise<PTableShape> {
|
package/src/pframe_pool.ts
CHANGED
|
@@ -5,13 +5,17 @@ import {
|
|
|
5
5
|
ensureError,
|
|
6
6
|
mapPObjectData,
|
|
7
7
|
PFrameDriverError,
|
|
8
|
+
ValueType,
|
|
9
|
+
resolveAnnotationParents,
|
|
8
10
|
type JsonSerializable,
|
|
9
11
|
type PColumn,
|
|
12
|
+
type PColumnSpec,
|
|
10
13
|
type PFrameHandle,
|
|
11
14
|
} from "@milaboratories/pl-model-common";
|
|
12
15
|
import { hashJson, PFrameInternal } from "@milaboratories/pl-model-middle-layer";
|
|
13
16
|
import { RefCountPoolBase, type PoolEntry } from "@milaboratories/helpers";
|
|
14
17
|
import { PFrameFactory } from "@milaboratories/pframes-rs-node";
|
|
18
|
+
import { createPFrame as createPFrameSpec } from "@milaboratories/pframes-rs-wasm";
|
|
15
19
|
import { mapValues } from "es-toolkit";
|
|
16
20
|
import { logPFrames } from "./logging";
|
|
17
21
|
|
|
@@ -26,7 +30,13 @@ export interface RemoteBlobProvider<TreeEntry extends JsonSerializable> {
|
|
|
26
30
|
}
|
|
27
31
|
|
|
28
32
|
export class PFrameHolder<TreeEntry extends JsonSerializable> implements Disposable {
|
|
29
|
-
public readonly
|
|
33
|
+
public readonly pFrameDataPromise: Promise<PFrameInternal.PFrameV13>;
|
|
34
|
+
/**
|
|
35
|
+
* WASM-spec frame built from this PFrame's columns. Source of truth
|
|
36
|
+
* for spec-side operations: column discovery, selector resolution,
|
|
37
|
+
* legacy-query lowering.
|
|
38
|
+
*/
|
|
39
|
+
public readonly pFrameSpec: PFrameInternal.PFrameWasmV3;
|
|
30
40
|
private readonly abortController = new AbortController();
|
|
31
41
|
|
|
32
42
|
private readonly localBlobs: PoolEntry<PFrameInternal.PFrameBlobId>[] = [];
|
|
@@ -40,86 +50,114 @@ export class PFrameHolder<TreeEntry extends JsonSerializable> implements Disposa
|
|
|
40
50
|
private readonly spillPath: string,
|
|
41
51
|
columns: PColumn<PFrameInternal.DataInfo<TreeEntry>>[],
|
|
42
52
|
) {
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
53
|
+
const ValueTypes = new Set(Object.values(ValueType));
|
|
54
|
+
const specColumnsMap: Record<string, PColumnSpec> = {};
|
|
55
|
+
for (const c of columns) {
|
|
56
|
+
if (ValueTypes.has(c.spec.valueType)) {
|
|
57
|
+
specColumnsMap[c.id] = resolveAnnotationParents(c.spec);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
this.pFrameSpec = createPFrameSpec(specColumnsMap);
|
|
48
61
|
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
62
|
+
try {
|
|
63
|
+
const makeLocalBlobId = (blob: TreeEntry): PFrameInternal.PFrameBlobId => {
|
|
64
|
+
const localBlob = this.localBlobProvider.acquire(blob);
|
|
65
|
+
this.localBlobs.push(localBlob);
|
|
66
|
+
return localBlob.key;
|
|
67
|
+
};
|
|
54
68
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
return { ...data };
|
|
61
|
-
case "JsonPartitioned":
|
|
62
|
-
return {
|
|
63
|
-
...data,
|
|
64
|
-
parts: mapValues(data.parts, makeLocalBlobId),
|
|
65
|
-
};
|
|
66
|
-
case "BinaryPartitioned":
|
|
67
|
-
return {
|
|
68
|
-
...data,
|
|
69
|
-
parts: mapValues(data.parts, (v) => ({
|
|
70
|
-
index: makeLocalBlobId(v.index),
|
|
71
|
-
values: makeLocalBlobId(v.values),
|
|
72
|
-
})),
|
|
73
|
-
};
|
|
74
|
-
case "ParquetPartitioned":
|
|
75
|
-
return {
|
|
76
|
-
...data,
|
|
77
|
-
parts: mapValues(data.parts, (v) => ({
|
|
78
|
-
...v,
|
|
79
|
-
data: makeRemoteBlobId(v.data),
|
|
80
|
-
})),
|
|
81
|
-
};
|
|
82
|
-
default:
|
|
83
|
-
assertNever(data);
|
|
84
|
-
}
|
|
85
|
-
};
|
|
69
|
+
const makeRemoteBlobId = (blob: TreeEntry): PFrameInternal.PFrameBlobId => {
|
|
70
|
+
const remoteBlob = this.remoteBlobProvider.acquire(blob);
|
|
71
|
+
this.remoteBlobs.push(remoteBlob);
|
|
72
|
+
return `${remoteBlob.key}${PFrameInternal.ParquetExtension}` as PFrameInternal.PFrameBlobId;
|
|
73
|
+
};
|
|
86
74
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
75
|
+
const mapColumnData = (
|
|
76
|
+
data: PFrameInternal.DataInfo<TreeEntry>,
|
|
77
|
+
): PFrameInternal.DataInfo<PFrameInternal.PFrameBlobId> => {
|
|
78
|
+
switch (data.type) {
|
|
79
|
+
case "Json":
|
|
80
|
+
return { ...data };
|
|
81
|
+
case "JsonPartitioned":
|
|
82
|
+
return {
|
|
83
|
+
...data,
|
|
84
|
+
parts: mapValues(data.parts, makeLocalBlobId),
|
|
85
|
+
};
|
|
86
|
+
case "BinaryPartitioned":
|
|
87
|
+
return {
|
|
88
|
+
...data,
|
|
89
|
+
parts: mapValues(data.parts, (v) => ({
|
|
90
|
+
index: makeLocalBlobId(v.index),
|
|
91
|
+
values: makeLocalBlobId(v.values),
|
|
92
|
+
})),
|
|
93
|
+
};
|
|
94
|
+
case "ParquetPartitioned":
|
|
95
|
+
return {
|
|
96
|
+
...data,
|
|
97
|
+
parts: mapValues(data.parts, (v) => ({
|
|
98
|
+
...v,
|
|
99
|
+
data: makeRemoteBlobId(v.data),
|
|
100
|
+
})),
|
|
101
|
+
};
|
|
102
|
+
default:
|
|
103
|
+
assertNever(data);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
91
106
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
parquetServer: this.remoteBlobProvider.httpServerInfo(),
|
|
97
|
-
});
|
|
107
|
+
const jsonifiedColumns = columns.map((column) => ({
|
|
108
|
+
...column,
|
|
109
|
+
data: mapColumnData(column.data),
|
|
110
|
+
}));
|
|
98
111
|
|
|
112
|
+
const pFrameData = PFrameFactory.createPFrame({ frameId, spillPath: this.spillPath, logger });
|
|
99
113
|
const promises: Promise<void>[] = [];
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
114
|
+
try {
|
|
115
|
+
pFrameData.setDataSource({
|
|
116
|
+
...this.localBlobProvider.makeDataSource(this.disposeSignal),
|
|
117
|
+
parquetServer: this.remoteBlobProvider.httpServerInfo(),
|
|
118
|
+
});
|
|
104
119
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
pFrame.dispose();
|
|
110
|
-
const error = new PFrameDriverError("PFrame creation failed asynchronously");
|
|
111
|
-
error.cause = new Error(
|
|
112
|
-
`PFrame cannot be created from columns: ${JSON.stringify(jsonifiedColumns)}`,
|
|
113
|
-
{ cause: ensureError(err) },
|
|
120
|
+
for (const column of jsonifiedColumns) {
|
|
121
|
+
pFrameData.addColumnSpec(column.id, column.spec);
|
|
122
|
+
promises.push(
|
|
123
|
+
pFrameData.setColumnData(column.id, column.data, { signal: this.disposeSignal }),
|
|
114
124
|
);
|
|
115
|
-
|
|
116
|
-
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
this.pFrameDataPromise = Promise.all(promises)
|
|
128
|
+
.then(() => pFrameData)
|
|
129
|
+
.catch((err) => {
|
|
130
|
+
this.dispose();
|
|
131
|
+
pFrameData.dispose();
|
|
132
|
+
const error = new PFrameDriverError("PFrame creation failed asynchronously");
|
|
133
|
+
error.cause = new Error(
|
|
134
|
+
`PFrame cannot be created from columns: ${JSON.stringify(jsonifiedColumns)}`,
|
|
135
|
+
{ cause: ensureError(err) },
|
|
136
|
+
);
|
|
137
|
+
throw error;
|
|
138
|
+
});
|
|
139
|
+
} catch (err: unknown) {
|
|
140
|
+
// setDataSource / addColumnSpec / setColumnData threw synchronously
|
|
141
|
+
// before pFrameDataPromise was assigned — dispose the addon's
|
|
142
|
+
// pFrameData explicitly (the dispose() path can't reach it yet).
|
|
143
|
+
// `allSettled` attaches handlers to any in-flight setColumnData
|
|
144
|
+
// promises so they don't trigger unhandled-rejection warnings
|
|
145
|
+
// when the dispose below rejects them.
|
|
146
|
+
void Promise.allSettled(promises);
|
|
147
|
+
pFrameData.dispose();
|
|
148
|
+
throw err;
|
|
149
|
+
}
|
|
117
150
|
} catch (err: unknown) {
|
|
151
|
+
// Release everything allocated so far in this constructor:
|
|
152
|
+
// acquired blobs, the WASM spec frame, and the abort signal.
|
|
153
|
+
this.abortController.abort();
|
|
154
|
+
this.localBlobs.forEach((entry) => entry.unref());
|
|
155
|
+
this.remoteBlobs.forEach((entry) => entry.unref());
|
|
156
|
+
this.pFrameSpec[Symbol.dispose]();
|
|
118
157
|
const error = new PFrameDriverError("PFrame creation failed synchronously");
|
|
119
|
-
error.cause = new Error(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
);
|
|
158
|
+
error.cause = new Error(`PFrame cannot be created from columns: ${JSON.stringify(columns)}`, {
|
|
159
|
+
cause: ensureError(err),
|
|
160
|
+
});
|
|
123
161
|
throw error;
|
|
124
162
|
}
|
|
125
163
|
}
|
|
@@ -132,15 +170,16 @@ export class PFrameHolder<TreeEntry extends JsonSerializable> implements Disposa
|
|
|
132
170
|
this.abortController.abort();
|
|
133
171
|
this.localBlobs.forEach((entry) => entry.unref());
|
|
134
172
|
this.remoteBlobs.forEach((entry) => entry.unref());
|
|
173
|
+
this.pFrameSpec[Symbol.dispose]();
|
|
174
|
+
void this.pFrameDataPromise
|
|
175
|
+
.then((pFrameData) => pFrameData.dispose())
|
|
176
|
+
.catch(() => {
|
|
177
|
+
/* mute error */
|
|
178
|
+
});
|
|
135
179
|
}
|
|
136
180
|
|
|
137
181
|
[Symbol.dispose](): void {
|
|
138
182
|
this.dispose();
|
|
139
|
-
void this.pFramePromise
|
|
140
|
-
.then((pFrame) => pFrame.dispose())
|
|
141
|
-
.catch(() => {
|
|
142
|
-
/* mute error */
|
|
143
|
-
});
|
|
144
183
|
}
|
|
145
184
|
}
|
|
146
185
|
|
package/src/ptable_def_pool.ts
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
PFrameDriverError,
|
|
3
|
+
type PFrameHandle,
|
|
4
|
+
type PObjectId,
|
|
5
|
+
type PTableDef,
|
|
6
|
+
type PTableHandle,
|
|
7
|
+
} from "@milaboratories/pl-model-common";
|
|
2
8
|
import type { PFrameInternal } from "@milaboratories/pl-model-middle-layer";
|
|
3
|
-
import { RefCountPoolBase } from "@milaboratories/helpers";
|
|
9
|
+
import { RefCountPoolBase, type PoolEntry } from "@milaboratories/helpers";
|
|
4
10
|
import { logPFrames } from "./logging";
|
|
5
11
|
import type { FullPTableDef } from "./ptable_shared";
|
|
6
|
-
import { stableKeyFromFullPTableDef } from "./ptable_shared";
|
|
12
|
+
import { buildFullPTableDefFromLegacy, stableKeyFromFullPTableDef } from "./ptable_shared";
|
|
7
13
|
|
|
8
14
|
export class PTableDefHolder implements Disposable {
|
|
9
15
|
private readonly abortController = new AbortController();
|
|
@@ -52,4 +58,21 @@ export class PTableDefPool extends RefCountPoolBase<FullPTableDef, PTableHandle,
|
|
|
52
58
|
}
|
|
53
59
|
return resource;
|
|
54
60
|
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Acquire a def from a legacy `PTableDef` + column specs map.
|
|
64
|
+
* Lowers the input via WASM-spec and stores the resulting
|
|
65
|
+
* `{ tableSpec, dataQuery }` shape. Returns the lowered def
|
|
66
|
+
* alongside the pool entry — callers that need `tableSpec`
|
|
67
|
+
* (e.g. `calculateTableData`) read it from `def.tableSpec`
|
|
68
|
+
* without re-deriving.
|
|
69
|
+
*/
|
|
70
|
+
public acquireFromLegacy(opts: {
|
|
71
|
+
pFrameHandle: PFrameHandle;
|
|
72
|
+
def: PTableDef<PObjectId>;
|
|
73
|
+
pFrameSpec: PFrameInternal.PFrameWasmV3;
|
|
74
|
+
}): { def: FullPTableDef; entry: PoolEntry<PTableHandle> } {
|
|
75
|
+
const def = buildFullPTableDefFromLegacy(opts);
|
|
76
|
+
return { def, entry: this.acquire(def) };
|
|
77
|
+
}
|
|
55
78
|
}
|