@milaboratories/pf-driver 1.7.13 → 1.7.14
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/_virtual/{_@oxc-project_runtime@0.123.0/helpers → _@oxc-project_runtime@0.137.0/helpers/esm}/usingCtx.cjs +2 -2
- package/dist/_virtual/{_@oxc-project_runtime@0.123.0/helpers → _@oxc-project_runtime@0.137.0/helpers/esm}/usingCtx.js +2 -2
- package/dist/csv_writer.cjs +2 -1
- package/dist/csv_writer.cjs.map +1 -1
- package/dist/csv_writer.js +1 -1
- package/dist/csv_writer.js.map +1 -1
- package/dist/data_info_helpers.cjs +0 -1
- package/dist/data_info_helpers.cjs.map +1 -1
- package/dist/data_info_helpers.js.map +1 -1
- package/dist/driver_double.cjs +5 -2
- package/dist/driver_double.cjs.map +1 -1
- package/dist/driver_double.d.ts.map +1 -1
- package/dist/driver_double.js +3 -0
- package/dist/driver_double.js.map +1 -1
- package/dist/driver_impl.cjs +10 -10
- package/dist/driver_impl.cjs.map +1 -1
- package/dist/driver_impl.d.ts.map +1 -1
- package/dist/driver_impl.js +1 -1
- package/dist/driver_impl.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/logging.cjs.map +1 -1
- package/dist/logging.js.map +1 -1
- package/dist/pframe_pool.cjs +8 -1
- package/dist/pframe_pool.cjs.map +1 -1
- package/dist/pframe_pool.js +8 -1
- package/dist/pframe_pool.js.map +1 -1
- package/dist/ptable_cache_per_frame.cjs +2 -1
- package/dist/ptable_cache_per_frame.cjs.map +1 -1
- package/dist/ptable_cache_per_frame.d.ts.map +1 -1
- package/dist/ptable_cache_per_frame.js +2 -0
- package/dist/ptable_cache_per_frame.js.map +1 -1
- package/dist/ptable_cache_plain.cjs +1 -1
- package/dist/ptable_cache_plain.cjs.map +1 -1
- package/dist/ptable_cache_plain.d.ts.map +1 -1
- package/dist/ptable_cache_plain.js +1 -0
- package/dist/ptable_cache_plain.js.map +1 -1
- package/dist/ptable_def_pool.cjs +5 -1
- package/dist/ptable_def_pool.cjs.map +1 -1
- package/dist/ptable_def_pool.js +5 -1
- package/dist/ptable_def_pool.js.map +1 -1
- package/dist/ptable_pool.cjs +7 -1
- package/dist/ptable_pool.cjs.map +1 -1
- package/dist/ptable_pool.js +7 -1
- package/dist/ptable_pool.js.map +1 -1
- package/dist/ptable_shared.cjs +1 -1
- package/dist/ptable_shared.cjs.map +1 -1
- package/dist/ptable_shared.js +1 -1
- package/dist/ptable_shared.js.map +1 -1
- package/package.json +4 -4
package/dist/driver_impl.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"driver_impl.js","names":["fs"],"sources":["../src/driver_impl.ts"],"sourcesContent":["import {\n mapPObjectData,\n mapPTableDef,\n extractAllColumns,\n uniqueBy,\n canonicalizeJson,\n bigintReplacer,\n ValueType,\n type CalculateTableDataRequest,\n type CalculateTableDataResponse,\n type FindColumnsRequest,\n type FindColumnsResponse,\n type PColumnIdAndSpec,\n type PColumnSpec,\n type PFrameHandle,\n type PObjectId,\n type PTableColumnSpec,\n type PTableHandle,\n type PTableShape,\n type PTableVector,\n type TableRange,\n type UniqueValuesRequest,\n type UniqueValuesResponse,\n type PColumn,\n type PFrameDef,\n type PTableDef,\n type PTableRecordSingleValueFilterV2,\n type PTableRecordFilter,\n type JsonSerializable,\n type PTableDefV2,\n mapSpecQueryColumns,\n collectSpecQueryColumns,\n sortSpecQuery,\n sortPTableDef,\n resolveAnnotationParents,\n PFrameDriverError,\n XLSX_MAX_ROWS_PER_SHEET,\n} from \"@milaboratories/pl-model-common\";\nimport type { PFrameInternal } from \"@milaboratories/pl-model-middle-layer\";\nimport {\n ConcurrencyLimitingExecutor,\n createPathAtomically,\n type MiLogger,\n} from \"@milaboratories/ts-helpers\";\nimport { isNil, PoolEntryGuard, type PoolEntry } from \"@milaboratories/helpers\";\nimport { PFrameFactory } from \"@milaboratories/pframes-rs-node\";\nimport { expandAxes, findTableColumn, rewriteLegacyFilters } from \"@milaboratories/pframes-rs-wasm\";\nimport { tmpdir } from \"node:os\";\nimport * as fs from \"node:fs\";\nimport { Readable } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport * as zlib from \"node:zlib\";\nimport { columnLabel, streamPTableRows } from \"./csv_writer\";\nimport type {\n AbstractInternalPFrameDriver,\n WritePTableToFsOptions,\n WritePTableToFsResult,\n ExportPTableOptions,\n} from \"./driver_decl\";\nimport { logPFrames } from \"./logging\";\nimport {\n PFramePool,\n type LocalBlobProvider as PoolLocalBlobProvider,\n type RemoteBlobProvider as PoolRemoteBlobProvider,\n} from \"./pframe_pool\";\nimport { PTableDefPool } from \"./ptable_def_pool\";\nimport { PTablePool } from \"./ptable_pool\";\nimport { embedInlineColumnTypeSpecs } from \"./ptable_shared\";\nimport {\n PTableCachePerFrame,\n PTableCachePerFrameOpsDefaults,\n type PTableCachePerFrameOps,\n} from \"./ptable_cache_per_frame\";\nimport {\n PTableCachePlain,\n PTableCachePlainOpsDefaults,\n type PTableCachePlainOps,\n} from \"./ptable_cache_plain\";\n\nexport interface LocalBlobProvider<TreeEntry extends JsonSerializable>\n extends PoolLocalBlobProvider<TreeEntry>, AsyncDisposable {}\n\nexport interface RemoteBlobProvider<TreeEntry extends JsonSerializable>\n extends PoolRemoteBlobProvider<TreeEntry>, AsyncDisposable {\n getCacheMetrics(): Promise<PFrameInternal.CacheMetrics | null>;\n resetCache(): Promise<void>;\n}\n\nexport type AbstractPFrameDriverOps = PTableCachePerFrameOps &\n PTableCachePlainOps & {\n /** Concurrency limits for `getUniqueValues` and `calculateTableData` requests */\n pFrameConcurrency: number;\n /** Concurrency limits for `getShape` and `getData` requests */\n pTableConcurrency: number;\n };\n\nexport const AbstractPFrameDriverOpsDefaults: AbstractPFrameDriverOps = {\n ...PTableCachePerFrameOpsDefaults,\n ...PTableCachePlainOpsDefaults,\n pFrameConcurrency: 1, // 1 join is executed in parallel and utilize all RAM and CPU cores\n pTableConcurrency: 1, // 1 joined table is read from disk at a time, which matches 1 table the user can view in the UI\n};\n\nexport type DataInfoResolver<PColumnData, TreeEntry extends JsonSerializable> = (\n spec: PColumnSpec,\n data: PColumnData,\n) => PFrameInternal.DataInfo<TreeEntry>;\n\nexport class AbstractPFrameDriver<\n PColumnData,\n TreeEntry extends JsonSerializable,\n> implements AbstractInternalPFrameDriver<PColumnData> {\n private readonly logger: PFrameInternal.Logger;\n\n private readonly localBlobProvider: LocalBlobProvider<TreeEntry>;\n private readonly remoteBlobProvider: RemoteBlobProvider<TreeEntry>;\n\n private readonly resolveDataInfo: DataInfoResolver<PColumnData, TreeEntry>;\n\n private readonly pFrames: PFramePool<TreeEntry>;\n private readonly pTableDefs: PTableDefPool;\n private readonly pTables: PTablePool<TreeEntry>;\n\n private readonly pTableCachePerFrame: PTableCachePerFrame;\n private readonly pTableCachePlain: PTableCachePlain;\n\n private readonly frameConcurrencyLimiter: ConcurrencyLimitingExecutor;\n private readonly tableConcurrencyLimiter: ConcurrencyLimitingExecutor;\n\n public async pprofDump(): Promise<Uint8Array> {\n return await PFrameFactory.pprofDump();\n }\n\n public async getCacheMetrics(): Promise<PFrameInternal.CacheMetrics | null> {\n return await this.remoteBlobProvider.getCacheMetrics();\n }\n\n public async resetCache(): Promise<void> {\n await this.remoteBlobProvider.resetCache();\n }\n\n public constructor({\n logger = () => {},\n localBlobProvider,\n remoteBlobProvider,\n spillPath = tmpdir(),\n options = AbstractPFrameDriverOpsDefaults,\n resolveDataInfo,\n }: {\n logger?: PFrameInternal.Logger;\n localBlobProvider: LocalBlobProvider<TreeEntry>;\n remoteBlobProvider: RemoteBlobProvider<TreeEntry>;\n spillPath?: string;\n options?: AbstractPFrameDriverOps;\n resolveDataInfo: DataInfoResolver<PColumnData, TreeEntry>;\n }) {\n this.logger = logger;\n\n this.localBlobProvider = localBlobProvider;\n this.remoteBlobProvider = remoteBlobProvider;\n\n this.resolveDataInfo = resolveDataInfo;\n\n this.frameConcurrencyLimiter = new ConcurrencyLimitingExecutor(options.pFrameConcurrency);\n this.tableConcurrencyLimiter = new ConcurrencyLimitingExecutor(options.pTableConcurrency);\n\n this.pFrames = new PFramePool(\n this.localBlobProvider,\n this.remoteBlobProvider,\n this.logger,\n spillPath,\n );\n this.pTableDefs = new PTableDefPool(this.logger);\n this.pTables = new PTablePool(this.pFrames, this.pTableDefs, this.logger);\n\n this.pTableCachePerFrame = new PTableCachePerFrame(this.logger, options);\n this.pTableCachePlain = new PTableCachePlain(this.logger, options);\n }\n\n async dispose(): Promise<void> {\n void (await Promise.allSettled([\n this.pTables[Symbol.asyncDispose](),\n this.pTableDefs[Symbol.asyncDispose](),\n this.pFrames[Symbol.asyncDispose](),\n this.localBlobProvider[Symbol.asyncDispose](),\n this.remoteBlobProvider[Symbol.asyncDispose](),\n ]));\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n return await this.dispose();\n }\n\n //\n // Internal / Config API Methods\n //\n\n public createPFrame(def: PFrameDef<PColumn<PColumnData>>): PoolEntry<PFrameHandle> {\n const ValueTypes = new Set(Object.values(ValueType));\n const supportedColumns = def\n .filter((column) => ValueTypes.has(column.spec.valueType))\n .map((c) => ({ ...c, spec: resolveAnnotationParents(c.spec) }));\n const uniqueColumns = uniqueBy(supportedColumns, (column) => column.id);\n const columns = uniqueColumns.map((c) =>\n mapPObjectData(c, (d) => this.resolveDataInfo(c.spec, d)),\n );\n\n return this.pFrames.acquire(columns);\n }\n\n public createPTable(rawDef: PTableDef<PColumn<PColumnData>>): PoolEntry<PTableHandle> {\n const columns = uniqueBy(extractAllColumns(rawDef.src), (c) => c.id);\n using pFrameGuard = new PoolEntryGuard(this.createPFrame(columns));\n const sortedDef = sortPTableDef(\n migrateTableFilter(\n mapPTableDef(rawDef, (c) => c.id),\n this.logger,\n ),\n );\n const pFrameSpec = this.pFrames.getByKey(pFrameGuard.key).pFrameSpec;\n using pTableGuard = new PoolEntryGuard(\n this.pTableDefs.acquireFromLegacy({\n pFrameHandle: pFrameGuard.key,\n def: sortedDef,\n pFrameSpec,\n }).entry,\n );\n if (logPFrames()) {\n this.logger(\n \"info\",\n `Create PTable call (pFrameHandle = ${pFrameGuard.key}; pTableHandle = ${pTableGuard.key})`,\n );\n }\n\n const pFrameEntry = pFrameGuard.keep();\n const pTableEntry = pTableGuard.keep();\n const unref = () => {\n pTableEntry.unref();\n pFrameEntry.unref();\n };\n return {\n key: pTableEntry.key,\n resource: pTableEntry.resource,\n unref,\n [Symbol.dispose]: unref,\n };\n }\n\n public createPTableV2(def: PTableDefV2<PColumn<PColumnData>>): PoolEntry<PTableHandle> {\n const columns = uniqueBy(collectSpecQueryColumns(def.query), (c) => c.id);\n using pFrameGuard = new PoolEntryGuard(this.createPFrame(columns));\n const pFrameSpec = this.pFrames.getByKey(pFrameGuard.key).pFrameSpec;\n const sortedQuery = sortSpecQuery(mapSpecQueryColumns(def.query, (c) => c.id));\n const { tableSpec, dataQuery } = pFrameSpec.evaluateQuery(\n embedInlineColumnTypeSpecs(sortedQuery),\n );\n\n using pTableGuard = new PoolEntryGuard(\n this.pTableDefs.acquire({\n pFrameHandle: pFrameGuard.key,\n tableSpec,\n dataQuery,\n }),\n );\n if (logPFrames()) {\n this.logger(\n \"info\",\n `Create PTable call (pFrameHandle = ${pFrameGuard.key}; pTableHandle = ${pTableGuard.key})`,\n );\n }\n\n const pFrameEntry = pFrameGuard.keep();\n const pTableEntry = pTableGuard.keep();\n const unref = () => {\n pTableEntry.unref();\n pFrameEntry.unref();\n };\n return {\n key: pTableEntry.key,\n resource: pTableEntry.resource,\n unref,\n [Symbol.dispose]: unref,\n };\n }\n\n public async writePTableToFs(\n handle: PTableHandle,\n options: WritePTableToFsOptions,\n ): Promise<WritePTableToFsResult> {\n this.logger(\n \"info\",\n `[WritePTableToFs] ENTER (handle = ${handle}, path = ${options.path}, format = ${options.format}, compression = ${options.compression ?? \"auto\"}, columns = ${options.columnIndices.length})`,\n );\n const startTime = performance.now();\n const { def, disposeSignal: defDisposeSignal } = this.pTableDefs.getByKey(handle);\n using tableGuard = new PoolEntryGuard(this.pTables.acquire(def));\n const { pTablePromise, disposeSignal } = tableGuard.resource;\n const pTable = await pTablePromise;\n\n const combinedSignal = AbortSignal.any(\n [options.signal, disposeSignal].filter((s): s is AbortSignal => !isNil(s)),\n );\n\n // `combinedSignal` is passed twice on purpose: into the native calls for cooperative\n // cancellation, and into `run` so the concurrency slot is released on abort even if a\n // native call fails to unwind. Dropping the `run` signal reintroduces the queue wedge.\n // keep()/cache live outside the limiter task: on abort `run` rejects and they are\n // skipped, so an abandoned (detached) operation never caches its result nor touches\n // `tableGuard` after the `using` block has already unref'd it.\n const { result, overallSize } = await this.tableConcurrencyLimiter.run(async () => {\n const shape = await pTable.getShape({ signal: combinedSignal });\n const clippedRange = clipRange(options.range, shape);\n const specs = def.tableSpec;\n const separator = options.format === \"tsv\" ? \"\\t\" : \",\";\n\n const iterable = streamPTableRows({\n pTable,\n specs,\n columnIndices: options.columnIndices,\n range: clippedRange,\n chunkSize: options.chunkSize ?? 50_000,\n separator,\n includeHeader: options.includeHeader ?? true,\n bom: options.bom ?? true,\n signal: combinedSignal,\n });\n\n const miLogger: MiLogger = {\n info: (msg) => this.logger(\"info\", String(msg)),\n warn: (msg) => this.logger(\"warn\", String(msg)),\n error: (msg) => this.logger(\"error\", String(msg)),\n };\n\n let bytesWritten = 0;\n await createPathAtomically(miLogger, options.path, async (tempPath) => {\n const writeStream = fs.createWriteStream(tempPath, { flags: \"wx\" });\n const source = Readable.from(iterable, { objectMode: false });\n if (options.compression?.type === \"gzip\") {\n const gzip = zlib.createGzip({ level: options.compression.level ?? 6 });\n await pipeline(source, gzip, writeStream, { signal: combinedSignal });\n } else {\n await pipeline(source, writeStream, { signal: combinedSignal });\n }\n bytesWritten = writeStream.bytesWritten;\n });\n\n const overallSize = await tableGuard.resource.cacheSize;\n\n // rowsWritten equals the clipped range length — the generator streams the\n // entire effective range without early termination, so this is accurate.\n const rowsWritten = clippedRange.length;\n\n if (logPFrames()) {\n const durationMs = Math.round(performance.now() - startTime);\n this.logger(\n \"info\",\n `[WritePTableToFs] complete (handle = ${handle}, columns = ${options.columnIndices.length}, rows = ${rowsWritten}, bytes = ${bytesWritten}, duration = ${durationMs}ms)`,\n );\n }\n\n return { result: { path: options.path, rowsWritten, bytesWritten }, overallSize };\n }, combinedSignal);\n\n this.pTableCachePlain.cache(tableGuard.keep(), overallSize, defDisposeSignal);\n return result;\n }\n\n public async exportPTable(\n handle: PTableHandle,\n options: ExportPTableOptions,\n signal?: AbortSignal,\n ): Promise<void> {\n const { path, columnIndices } = options;\n\n this.logger(\"info\", `[ExportPTable] ENTER (handle = ${handle}, path = ${path})`);\n const startTime = performance.now();\n\n const { def, disposeSignal: defDisposeSignal } = this.pTableDefs.getByKey(handle);\n using tableGuard = new PoolEntryGuard(this.pTables.acquire(def));\n const { pTablePromise, disposeSignal } = tableGuard.resource;\n const pTable = await pTablePromise;\n\n const combinedSignal = AbortSignal.any(\n [signal, disposeSignal].filter((s): s is AbortSignal => !isNil(s)),\n );\n\n const headers: [number, string][] = columnIndices.map((index): [number, string] => [\n index,\n columnLabel(def.tableSpec[index]),\n ]);\n\n // keep()/cache live outside the limiter task: on abort `run` rejects and they are\n // skipped, so an abandoned (detached) operation never caches its result nor touches\n // `tableGuard` after the `using` block has already unref'd it.\n const overallSize = await this.tableConcurrencyLimiter.run(async () => {\n // Cap data rows per xlsx sheet below Excel's hard limit of 1,048,576.\n if (path.toLowerCase().endsWith(\".xlsx\")) {\n const shape = await pTable.getShape({ signal: combinedSignal });\n if (shape.rows > XLSX_MAX_ROWS_PER_SHEET) {\n const error = new PFrameDriverError(`exportPTable failed`);\n error.cause = new Error(\n `xlsx export rejected: ${shape.rows} rows exceed the per-sheet ` +\n `limit of ${XLSX_MAX_ROWS_PER_SHEET} rows`,\n );\n throw error;\n }\n }\n\n await pTable.export(path, { headers, signal: combinedSignal });\n\n const overallSize = await tableGuard.resource.cacheSize;\n\n if (logPFrames()) {\n const durationMs = Math.round(performance.now() - startTime);\n this.logger(\n \"info\",\n `[ExportPTable] complete (handle = ${handle}, path = ${path}), ` +\n `duration = ${durationMs}ms`,\n );\n }\n\n return overallSize;\n }, combinedSignal);\n\n this.pTableCachePlain.cache(tableGuard.keep(), overallSize, defDisposeSignal);\n }\n\n //\n // PFrame instance methods\n //\n\n public async findColumns(\n handle: PFrameHandle,\n request: FindColumnsRequest,\n ): Promise<FindColumnsResponse> {\n const iRequest: PFrameInternal.FindColumnsRequest = {\n ...request,\n compatibleWith:\n request.compatibleWith.length !== 0\n ? [\n {\n axesSpec: [\n ...new Map(\n request.compatibleWith.map((item) => [canonicalizeJson(item), item] as const),\n ).values(),\n ],\n qualifications: [],\n },\n ]\n : [],\n };\n\n const { pFrameSpec } = this.pFrames.getByKey(handle);\n const response = pFrameSpec.findColumns(iRequest);\n return {\n hits: response.hits\n .filter(\n (h) =>\n // only exactly matching columns\n h.mappingVariants.length === 0 ||\n h.mappingVariants.some(\n (v) =>\n v.qualifications.forHit.length === 0 &&\n v.qualifications.forQueries.every((q) => q.length === 0),\n ),\n )\n .map((h) => h.hit),\n };\n }\n\n public async getColumnSpec(\n handle: PFrameHandle,\n columnId: PObjectId,\n ): Promise<PColumnSpec | null> {\n const { columnSpecs } = this.pFrames.getByKey(handle);\n return columnSpecs[columnId] ?? null;\n }\n\n public async listColumns(handle: PFrameHandle): Promise<PColumnIdAndSpec[]> {\n const { pFrameSpec } = this.pFrames.getByKey(handle);\n return pFrameSpec.listColumns().map(({ columnId, spec }) => ({ columnId, spec }));\n }\n\n public async calculateTableData(\n handle: PFrameHandle,\n request: CalculateTableDataRequest<PObjectId>,\n range: TableRange | undefined,\n signal?: AbortSignal,\n ): Promise<CalculateTableDataResponse> {\n if (logPFrames()) {\n this.logger(\n \"info\",\n `Call calculateTableData, handle = ${handle}, request = ${JSON.stringify(request, bigintReplacer)}`,\n );\n }\n\n const { pFrameSpec } = this.pFrames.getByKey(handle);\n const sortedDef = sortPTableDef(migrateTableFilter(request, this.logger));\n const { def, entry } = this.pTables.acquireFromLegacy({\n pFrameHandle: handle,\n def: sortedDef,\n pFrameSpec,\n });\n using tableGuard = new PoolEntryGuard(entry);\n const tableSpec = def.tableSpec;\n const { pTablePromise, disposeSignal } = tableGuard.resource;\n const pTable = await pTablePromise;\n\n const combinedSignal = AbortSignal.any([signal, disposeSignal].filter((s) => !!s));\n // keep()/cache live outside the limiter task: on abort `run` rejects and they are\n // skipped, so an abandoned (detached) operation never caches its result nor touches\n // `tableGuard` after the `using` block has already unref'd it.\n const { data, overallSize } = await this.frameConcurrencyLimiter.run(async () => {\n // TODO: throw error when more then 200k rows is requested\n // after pf-plots migration to stream API\n\n const data = await pTable.getData([...tableSpec.keys()], {\n range,\n signal: combinedSignal,\n });\n\n const overallSize = await tableGuard.resource.cacheSize;\n return { data, overallSize };\n }, combinedSignal);\n\n this.pTableCachePerFrame.cache(tableGuard.keep(), overallSize);\n return tableSpec.map((spec, i) => ({\n spec: spec,\n data: data[i],\n }));\n }\n\n public async getUniqueValues(\n handle: PFrameHandle,\n request: UniqueValuesRequest,\n signal?: AbortSignal,\n ): Promise<UniqueValuesResponse> {\n if (logPFrames()) {\n this.logger(\n \"info\",\n `Call getUniqueValues, handle = ${handle}, request = ${JSON.stringify(request, bigintReplacer)}`,\n );\n }\n\n const { pFrameDataPromise, columnSpecs, disposeSignal } = this.pFrames.getByKey(handle);\n const pFrameData = await pFrameDataPromise;\n\n const columnSpec = columnSpecs[request.columnId];\n if (!columnSpec) {\n const error = new PFrameDriverError(`getUniqueValues failed`);\n error.cause = new Error(`column ${request.columnId} is not registered in the PFrame`);\n throw error;\n }\n\n const axisIds = expandAxes(columnSpec.axesSpec);\n const tableSpec: PTableColumnSpec[] = [\n ...columnSpec.axesSpec.map(\n (axisSpec, i): PTableColumnSpec => ({\n type: \"axis\",\n id: axisIds[i],\n spec: axisSpec,\n }),\n ),\n { type: \"column\", id: request.columnId, spec: columnSpec },\n ];\n\n let axisIndex: number | undefined;\n if (request.axis !== undefined) {\n const index = findTableColumn(tableSpec, { type: \"axis\", id: request.axis });\n if (index < 0) {\n const error = new PFrameDriverError(`getUniqueValues failed`);\n error.cause = new Error(\n `axis ${JSON.stringify(request.axis)} not found among axes of column ${request.columnId}`,\n );\n throw error;\n }\n axisIndex = index;\n }\n\n const resolvedRequest: PFrameInternal.UniqueValuesRequestV2 = {\n columnId: request.columnId,\n axisIndex,\n filters: rewriteLegacyFilters({\n tableSpec,\n filters: migrateFilters(request.filters, this.logger),\n }),\n limit: request.limit,\n };\n\n const combinedSignal = AbortSignal.any([signal, disposeSignal].filter((s) => !!s));\n return await this.frameConcurrencyLimiter.run(async () => {\n return await pFrameData.getUniqueValues(resolvedRequest, { signal: combinedSignal });\n }, combinedSignal);\n }\n\n //\n // PTable instance methods\n //\n\n public async getSpec(handle: PTableHandle): Promise<PTableColumnSpec[]> {\n const { def } = this.pTableDefs.getByKey(handle);\n return def.tableSpec;\n }\n\n public async getShape(handle: PTableHandle, signal?: AbortSignal): Promise<PTableShape> {\n const { def, disposeSignal: defDisposeSignal } = this.pTableDefs.getByKey(handle);\n using tableGuard = new PoolEntryGuard(this.pTables.acquire(def));\n\n const { pTablePromise, disposeSignal } = tableGuard.resource;\n const pTable = await pTablePromise;\n\n const combinedSignal = AbortSignal.any([signal, disposeSignal].filter((s) => !!s));\n const { shape, overallSize } = await this.tableConcurrencyLimiter.run(async () => {\n const shape = await pTable.getShape({\n signal: combinedSignal,\n });\n\n const overallSize = await tableGuard.resource.cacheSize;\n\n return { shape, overallSize };\n }, combinedSignal);\n\n this.pTableCachePlain.cache(tableGuard.keep(), overallSize, defDisposeSignal);\n return shape;\n }\n\n public async getData(\n handle: PTableHandle,\n columnIndices: number[],\n range: TableRange | undefined,\n signal?: AbortSignal,\n ): Promise<PTableVector[]> {\n const { def, disposeSignal: defDisposeSignal } = this.pTableDefs.getByKey(handle);\n using tableGuard = new PoolEntryGuard(this.pTables.acquire(def));\n\n const { pTablePromise, disposeSignal } = tableGuard.resource;\n const pTable = await pTablePromise;\n\n const combinedSignal = AbortSignal.any([signal, disposeSignal].filter((s) => !!s));\n const { data, overallSize } = await this.tableConcurrencyLimiter.run(async () => {\n const data = await pTable.getData(columnIndices, {\n range,\n signal: combinedSignal,\n });\n\n const overallSize = await tableGuard.resource.cacheSize;\n\n return { data, overallSize };\n }, combinedSignal);\n\n this.pTableCachePlain.cache(tableGuard.keep(), overallSize, defDisposeSignal);\n return data;\n }\n}\n\n/** Clamp range to table shape. When range is undefined, returns full table range. */\nfunction clipRange(range: undefined | TableRange, shape: PTableShape): TableRange {\n if (isNil(range)) {\n return { offset: 0, length: shape.rows };\n }\n const clampedOffset = Math.min(range.offset, shape.rows);\n const clampedLength = Math.min(range.length, shape.rows - clampedOffset);\n return { offset: clampedOffset, length: clampedLength };\n}\n\nfunction migrateFilters(\n filters: PTableRecordFilter[],\n logger: PFrameInternal.Logger,\n): PTableRecordFilter[] {\n const filtersV1 = [];\n const filtersV2: PTableRecordSingleValueFilterV2[] = [];\n for (const filter of filters) {\n if ((filter.type as unknown) === \"bySingleColumn\") {\n filtersV1.push(filter);\n filtersV2.push({\n ...filter,\n type: \"bySingleColumnV2\",\n });\n } else {\n filtersV2.push(filter);\n }\n }\n if (filtersV1.length > 0) {\n const filtersV1Json = JSON.stringify(filtersV1);\n logger(\n \"warn\",\n `type overwritten from 'bySingleColumn' to 'bySingleColumnV2' for filters: ${filtersV1Json}`,\n );\n }\n return filtersV2;\n}\n\nfunction migrateTableFilter<T>(\n def: Omit<PTableDef<T>, \"partitionFilters\"> | PTableDef<T>,\n logger: PFrameInternal.Logger,\n): PTableDef<T> {\n if (!(\"partitionFilters\" in def)) {\n // For old blocks assume all axes filters to be partition filters\n return {\n ...def,\n partitionFilters: migrateFilters(\n def.filters.filter((f) => f.column.type === \"axis\"),\n logger,\n ),\n filters: migrateFilters(\n def.filters.filter((f) => f.column.type === \"column\"),\n logger,\n ),\n };\n }\n return {\n ...def,\n partitionFilters: migrateFilters(def.partitionFilters, logger),\n filters: migrateFilters(def.filters, logger),\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"driver_impl.js","names":["fs"],"sources":["../src/driver_impl.ts"],"sourcesContent":["import {\n mapPObjectData,\n mapPTableDef,\n extractAllColumns,\n uniqueBy,\n canonicalizeJson,\n bigintReplacer,\n ValueType,\n type CalculateTableDataRequest,\n type CalculateTableDataResponse,\n type FindColumnsRequest,\n type FindColumnsResponse,\n type PColumnIdAndSpec,\n type PColumnSpec,\n type PFrameHandle,\n type PObjectId,\n type PTableColumnSpec,\n type PTableHandle,\n type PTableShape,\n type PTableVector,\n type TableRange,\n type UniqueValuesRequest,\n type UniqueValuesResponse,\n type PColumn,\n type PFrameDef,\n type PTableDef,\n type PTableRecordSingleValueFilterV2,\n type PTableRecordFilter,\n type JsonSerializable,\n type PTableDefV2,\n mapSpecQueryColumns,\n collectSpecQueryColumns,\n sortSpecQuery,\n sortPTableDef,\n resolveAnnotationParents,\n PFrameDriverError,\n XLSX_MAX_ROWS_PER_SHEET,\n} from \"@milaboratories/pl-model-common\";\nimport type { PFrameInternal } from \"@milaboratories/pl-model-middle-layer\";\nimport {\n ConcurrencyLimitingExecutor,\n createPathAtomically,\n type MiLogger,\n} from \"@milaboratories/ts-helpers\";\nimport { isNil, PoolEntryGuard, type PoolEntry } from \"@milaboratories/helpers\";\nimport { PFrameFactory } from \"@milaboratories/pframes-rs-node\";\nimport { expandAxes, findTableColumn, rewriteLegacyFilters } from \"@milaboratories/pframes-rs-wasm\";\nimport { tmpdir } from \"node:os\";\nimport * as fs from \"node:fs\";\nimport { Readable } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport * as zlib from \"node:zlib\";\nimport { columnLabel, streamPTableRows } from \"./csv_writer\";\nimport type {\n AbstractInternalPFrameDriver,\n WritePTableToFsOptions,\n WritePTableToFsResult,\n ExportPTableOptions,\n} from \"./driver_decl\";\nimport { logPFrames } from \"./logging\";\nimport {\n PFramePool,\n type LocalBlobProvider as PoolLocalBlobProvider,\n type RemoteBlobProvider as PoolRemoteBlobProvider,\n} from \"./pframe_pool\";\nimport { PTableDefPool } from \"./ptable_def_pool\";\nimport { PTablePool } from \"./ptable_pool\";\nimport { embedInlineColumnTypeSpecs } from \"./ptable_shared\";\nimport {\n PTableCachePerFrame,\n PTableCachePerFrameOpsDefaults,\n type PTableCachePerFrameOps,\n} from \"./ptable_cache_per_frame\";\nimport {\n PTableCachePlain,\n PTableCachePlainOpsDefaults,\n type PTableCachePlainOps,\n} from \"./ptable_cache_plain\";\n\nexport interface LocalBlobProvider<TreeEntry extends JsonSerializable>\n extends PoolLocalBlobProvider<TreeEntry>, AsyncDisposable {}\n\nexport interface RemoteBlobProvider<TreeEntry extends JsonSerializable>\n extends PoolRemoteBlobProvider<TreeEntry>, AsyncDisposable {\n getCacheMetrics(): Promise<PFrameInternal.CacheMetrics | null>;\n resetCache(): Promise<void>;\n}\n\nexport type AbstractPFrameDriverOps = PTableCachePerFrameOps &\n PTableCachePlainOps & {\n /** Concurrency limits for `getUniqueValues` and `calculateTableData` requests */\n pFrameConcurrency: number;\n /** Concurrency limits for `getShape` and `getData` requests */\n pTableConcurrency: number;\n };\n\nexport const AbstractPFrameDriverOpsDefaults: AbstractPFrameDriverOps = {\n ...PTableCachePerFrameOpsDefaults,\n ...PTableCachePlainOpsDefaults,\n pFrameConcurrency: 1, // 1 join is executed in parallel and utilize all RAM and CPU cores\n pTableConcurrency: 1, // 1 joined table is read from disk at a time, which matches 1 table the user can view in the UI\n};\n\nexport type DataInfoResolver<PColumnData, TreeEntry extends JsonSerializable> = (\n spec: PColumnSpec,\n data: PColumnData,\n) => PFrameInternal.DataInfo<TreeEntry>;\n\nexport class AbstractPFrameDriver<\n PColumnData,\n TreeEntry extends JsonSerializable,\n> implements AbstractInternalPFrameDriver<PColumnData> {\n private readonly logger: PFrameInternal.Logger;\n\n private readonly localBlobProvider: LocalBlobProvider<TreeEntry>;\n private readonly remoteBlobProvider: RemoteBlobProvider<TreeEntry>;\n\n private readonly resolveDataInfo: DataInfoResolver<PColumnData, TreeEntry>;\n\n private readonly pFrames: PFramePool<TreeEntry>;\n private readonly pTableDefs: PTableDefPool;\n private readonly pTables: PTablePool<TreeEntry>;\n\n private readonly pTableCachePerFrame: PTableCachePerFrame;\n private readonly pTableCachePlain: PTableCachePlain;\n\n private readonly frameConcurrencyLimiter: ConcurrencyLimitingExecutor;\n private readonly tableConcurrencyLimiter: ConcurrencyLimitingExecutor;\n\n public async pprofDump(): Promise<Uint8Array> {\n return await PFrameFactory.pprofDump();\n }\n\n public async getCacheMetrics(): Promise<PFrameInternal.CacheMetrics | null> {\n return await this.remoteBlobProvider.getCacheMetrics();\n }\n\n public async resetCache(): Promise<void> {\n await this.remoteBlobProvider.resetCache();\n }\n\n public constructor({\n logger = () => {},\n localBlobProvider,\n remoteBlobProvider,\n spillPath = tmpdir(),\n options = AbstractPFrameDriverOpsDefaults,\n resolveDataInfo,\n }: {\n logger?: PFrameInternal.Logger;\n localBlobProvider: LocalBlobProvider<TreeEntry>;\n remoteBlobProvider: RemoteBlobProvider<TreeEntry>;\n spillPath?: string;\n options?: AbstractPFrameDriverOps;\n resolveDataInfo: DataInfoResolver<PColumnData, TreeEntry>;\n }) {\n this.logger = logger;\n\n this.localBlobProvider = localBlobProvider;\n this.remoteBlobProvider = remoteBlobProvider;\n\n this.resolveDataInfo = resolveDataInfo;\n\n this.frameConcurrencyLimiter = new ConcurrencyLimitingExecutor(options.pFrameConcurrency);\n this.tableConcurrencyLimiter = new ConcurrencyLimitingExecutor(options.pTableConcurrency);\n\n this.pFrames = new PFramePool(\n this.localBlobProvider,\n this.remoteBlobProvider,\n this.logger,\n spillPath,\n );\n this.pTableDefs = new PTableDefPool(this.logger);\n this.pTables = new PTablePool(this.pFrames, this.pTableDefs, this.logger);\n\n this.pTableCachePerFrame = new PTableCachePerFrame(this.logger, options);\n this.pTableCachePlain = new PTableCachePlain(this.logger, options);\n }\n\n async dispose(): Promise<void> {\n void (await Promise.allSettled([\n this.pTables[Symbol.asyncDispose](),\n this.pTableDefs[Symbol.asyncDispose](),\n this.pFrames[Symbol.asyncDispose](),\n this.localBlobProvider[Symbol.asyncDispose](),\n this.remoteBlobProvider[Symbol.asyncDispose](),\n ]));\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n return await this.dispose();\n }\n\n //\n // Internal / Config API Methods\n //\n\n public createPFrame(def: PFrameDef<PColumn<PColumnData>>): PoolEntry<PFrameHandle> {\n const ValueTypes = new Set(Object.values(ValueType));\n const supportedColumns = def\n .filter((column) => ValueTypes.has(column.spec.valueType))\n .map((c) => ({ ...c, spec: resolveAnnotationParents(c.spec) }));\n const uniqueColumns = uniqueBy(supportedColumns, (column) => column.id);\n const columns = uniqueColumns.map((c) =>\n mapPObjectData(c, (d) => this.resolveDataInfo(c.spec, d)),\n );\n\n return this.pFrames.acquire(columns);\n }\n\n public createPTable(rawDef: PTableDef<PColumn<PColumnData>>): PoolEntry<PTableHandle> {\n const columns = uniqueBy(extractAllColumns(rawDef.src), (c) => c.id);\n using pFrameGuard = new PoolEntryGuard(this.createPFrame(columns));\n const sortedDef = sortPTableDef(\n migrateTableFilter(\n mapPTableDef(rawDef, (c) => c.id),\n this.logger,\n ),\n );\n const pFrameSpec = this.pFrames.getByKey(pFrameGuard.key).pFrameSpec;\n using pTableGuard = new PoolEntryGuard(\n this.pTableDefs.acquireFromLegacy({\n pFrameHandle: pFrameGuard.key,\n def: sortedDef,\n pFrameSpec,\n }).entry,\n );\n if (logPFrames()) {\n this.logger(\n \"info\",\n `Create PTable call (pFrameHandle = ${pFrameGuard.key}; pTableHandle = ${pTableGuard.key})`,\n );\n }\n\n const pFrameEntry = pFrameGuard.keep();\n const pTableEntry = pTableGuard.keep();\n const unref = () => {\n pTableEntry.unref();\n pFrameEntry.unref();\n };\n return {\n key: pTableEntry.key,\n resource: pTableEntry.resource,\n unref,\n [Symbol.dispose]: unref,\n };\n }\n\n public createPTableV2(def: PTableDefV2<PColumn<PColumnData>>): PoolEntry<PTableHandle> {\n const columns = uniqueBy(collectSpecQueryColumns(def.query), (c) => c.id);\n using pFrameGuard = new PoolEntryGuard(this.createPFrame(columns));\n const pFrameSpec = this.pFrames.getByKey(pFrameGuard.key).pFrameSpec;\n const sortedQuery = sortSpecQuery(mapSpecQueryColumns(def.query, (c) => c.id));\n const { tableSpec, dataQuery } = pFrameSpec.evaluateQuery(\n embedInlineColumnTypeSpecs(sortedQuery),\n );\n\n using pTableGuard = new PoolEntryGuard(\n this.pTableDefs.acquire({\n pFrameHandle: pFrameGuard.key,\n tableSpec,\n dataQuery,\n }),\n );\n if (logPFrames()) {\n this.logger(\n \"info\",\n `Create PTable call (pFrameHandle = ${pFrameGuard.key}; pTableHandle = ${pTableGuard.key})`,\n );\n }\n\n const pFrameEntry = pFrameGuard.keep();\n const pTableEntry = pTableGuard.keep();\n const unref = () => {\n pTableEntry.unref();\n pFrameEntry.unref();\n };\n return {\n key: pTableEntry.key,\n resource: pTableEntry.resource,\n unref,\n [Symbol.dispose]: unref,\n };\n }\n\n public async writePTableToFs(\n handle: PTableHandle,\n options: WritePTableToFsOptions,\n ): Promise<WritePTableToFsResult> {\n this.logger(\n \"info\",\n `[WritePTableToFs] ENTER (handle = ${handle}, path = ${options.path}, format = ${options.format}, compression = ${options.compression ?? \"auto\"}, columns = ${options.columnIndices.length})`,\n );\n const startTime = performance.now();\n const { def, disposeSignal: defDisposeSignal } = this.pTableDefs.getByKey(handle);\n using tableGuard = new PoolEntryGuard(this.pTables.acquire(def));\n const { pTablePromise, disposeSignal } = tableGuard.resource;\n const pTable = await pTablePromise;\n\n const combinedSignal = AbortSignal.any(\n [options.signal, disposeSignal].filter((s): s is AbortSignal => !isNil(s)),\n );\n\n // `combinedSignal` is passed twice on purpose: into the native calls for cooperative\n // cancellation, and into `run` so the concurrency slot is released on abort even if a\n // native call fails to unwind. Dropping the `run` signal reintroduces the queue wedge.\n // keep()/cache live outside the limiter task: on abort `run` rejects and they are\n // skipped, so an abandoned (detached) operation never caches its result nor touches\n // `tableGuard` after the `using` block has already unref'd it.\n const { result, overallSize } = await this.tableConcurrencyLimiter.run(async () => {\n const shape = await pTable.getShape({ signal: combinedSignal });\n const clippedRange = clipRange(options.range, shape);\n const specs = def.tableSpec;\n const separator = options.format === \"tsv\" ? \"\\t\" : \",\";\n\n const iterable = streamPTableRows({\n pTable,\n specs,\n columnIndices: options.columnIndices,\n range: clippedRange,\n chunkSize: options.chunkSize ?? 50_000,\n separator,\n includeHeader: options.includeHeader ?? true,\n bom: options.bom ?? true,\n signal: combinedSignal,\n });\n\n const miLogger: MiLogger = {\n info: (msg) => this.logger(\"info\", String(msg)),\n warn: (msg) => this.logger(\"warn\", String(msg)),\n error: (msg) => this.logger(\"error\", String(msg)),\n };\n\n let bytesWritten = 0;\n await createPathAtomically(miLogger, options.path, async (tempPath) => {\n const writeStream = fs.createWriteStream(tempPath, { flags: \"wx\" });\n const source = Readable.from(iterable, { objectMode: false });\n if (options.compression?.type === \"gzip\") {\n const gzip = zlib.createGzip({ level: options.compression.level ?? 6 });\n await pipeline(source, gzip, writeStream, { signal: combinedSignal });\n } else {\n await pipeline(source, writeStream, { signal: combinedSignal });\n }\n bytesWritten = writeStream.bytesWritten;\n });\n\n const overallSize = await tableGuard.resource.cacheSize;\n\n // rowsWritten equals the clipped range length — the generator streams the\n // entire effective range without early termination, so this is accurate.\n const rowsWritten = clippedRange.length;\n\n if (logPFrames()) {\n const durationMs = Math.round(performance.now() - startTime);\n this.logger(\n \"info\",\n `[WritePTableToFs] complete (handle = ${handle}, columns = ${options.columnIndices.length}, rows = ${rowsWritten}, bytes = ${bytesWritten}, duration = ${durationMs}ms)`,\n );\n }\n\n return { result: { path: options.path, rowsWritten, bytesWritten }, overallSize };\n }, combinedSignal);\n\n this.pTableCachePlain.cache(tableGuard.keep(), overallSize, defDisposeSignal);\n return result;\n }\n\n public async exportPTable(\n handle: PTableHandle,\n options: ExportPTableOptions,\n signal?: AbortSignal,\n ): Promise<void> {\n const { path, columnIndices } = options;\n\n this.logger(\"info\", `[ExportPTable] ENTER (handle = ${handle}, path = ${path})`);\n const startTime = performance.now();\n\n const { def, disposeSignal: defDisposeSignal } = this.pTableDefs.getByKey(handle);\n using tableGuard = new PoolEntryGuard(this.pTables.acquire(def));\n const { pTablePromise, disposeSignal } = tableGuard.resource;\n const pTable = await pTablePromise;\n\n const combinedSignal = AbortSignal.any(\n [signal, disposeSignal].filter((s): s is AbortSignal => !isNil(s)),\n );\n\n const headers: [number, string][] = columnIndices.map((index): [number, string] => [\n index,\n columnLabel(def.tableSpec[index]),\n ]);\n\n // keep()/cache live outside the limiter task: on abort `run` rejects and they are\n // skipped, so an abandoned (detached) operation never caches its result nor touches\n // `tableGuard` after the `using` block has already unref'd it.\n const overallSize = await this.tableConcurrencyLimiter.run(async () => {\n // Cap data rows per xlsx sheet below Excel's hard limit of 1,048,576.\n if (path.toLowerCase().endsWith(\".xlsx\")) {\n const shape = await pTable.getShape({ signal: combinedSignal });\n if (shape.rows > XLSX_MAX_ROWS_PER_SHEET) {\n const error = new PFrameDriverError(`exportPTable failed`);\n error.cause = new Error(\n `xlsx export rejected: ${shape.rows} rows exceed the per-sheet ` +\n `limit of ${XLSX_MAX_ROWS_PER_SHEET} rows`,\n );\n throw error;\n }\n }\n\n await pTable.export(path, { headers, signal: combinedSignal });\n\n const overallSize = await tableGuard.resource.cacheSize;\n\n if (logPFrames()) {\n const durationMs = Math.round(performance.now() - startTime);\n this.logger(\n \"info\",\n `[ExportPTable] complete (handle = ${handle}, path = ${path}), ` +\n `duration = ${durationMs}ms`,\n );\n }\n\n return overallSize;\n }, combinedSignal);\n\n this.pTableCachePlain.cache(tableGuard.keep(), overallSize, defDisposeSignal);\n }\n\n //\n // PFrame instance methods\n //\n\n public async findColumns(\n handle: PFrameHandle,\n request: FindColumnsRequest,\n ): Promise<FindColumnsResponse> {\n const iRequest: PFrameInternal.FindColumnsRequest = {\n ...request,\n compatibleWith:\n request.compatibleWith.length !== 0\n ? [\n {\n axesSpec: [\n ...new Map(\n request.compatibleWith.map((item) => [canonicalizeJson(item), item] as const),\n ).values(),\n ],\n qualifications: [],\n },\n ]\n : [],\n };\n\n const { pFrameSpec } = this.pFrames.getByKey(handle);\n const response = pFrameSpec.findColumns(iRequest);\n return {\n hits: response.hits\n .filter(\n (h) =>\n // only exactly matching columns\n h.mappingVariants.length === 0 ||\n h.mappingVariants.some(\n (v) =>\n v.qualifications.forHit.length === 0 &&\n v.qualifications.forQueries.every((q) => q.length === 0),\n ),\n )\n .map((h) => h.hit),\n };\n }\n\n public async getColumnSpec(\n handle: PFrameHandle,\n columnId: PObjectId,\n ): Promise<PColumnSpec | null> {\n const { columnSpecs } = this.pFrames.getByKey(handle);\n return columnSpecs[columnId] ?? null;\n }\n\n public async listColumns(handle: PFrameHandle): Promise<PColumnIdAndSpec[]> {\n const { pFrameSpec } = this.pFrames.getByKey(handle);\n return pFrameSpec.listColumns().map(({ columnId, spec }) => ({ columnId, spec }));\n }\n\n public async calculateTableData(\n handle: PFrameHandle,\n request: CalculateTableDataRequest<PObjectId>,\n range: TableRange | undefined,\n signal?: AbortSignal,\n ): Promise<CalculateTableDataResponse> {\n if (logPFrames()) {\n this.logger(\n \"info\",\n `Call calculateTableData, handle = ${handle}, request = ${JSON.stringify(request, bigintReplacer)}`,\n );\n }\n\n const { pFrameSpec } = this.pFrames.getByKey(handle);\n const sortedDef = sortPTableDef(migrateTableFilter(request, this.logger));\n const { def, entry } = this.pTables.acquireFromLegacy({\n pFrameHandle: handle,\n def: sortedDef,\n pFrameSpec,\n });\n using tableGuard = new PoolEntryGuard(entry);\n const tableSpec = def.tableSpec;\n const { pTablePromise, disposeSignal } = tableGuard.resource;\n const pTable = await pTablePromise;\n\n const combinedSignal = AbortSignal.any([signal, disposeSignal].filter((s) => !!s));\n // keep()/cache live outside the limiter task: on abort `run` rejects and they are\n // skipped, so an abandoned (detached) operation never caches its result nor touches\n // `tableGuard` after the `using` block has already unref'd it.\n const { data, overallSize } = await this.frameConcurrencyLimiter.run(async () => {\n // TODO: throw error when more then 200k rows is requested\n // after pf-plots migration to stream API\n\n const data = await pTable.getData([...tableSpec.keys()], {\n range,\n signal: combinedSignal,\n });\n\n const overallSize = await tableGuard.resource.cacheSize;\n return { data, overallSize };\n }, combinedSignal);\n\n this.pTableCachePerFrame.cache(tableGuard.keep(), overallSize);\n return tableSpec.map((spec, i) => ({\n spec: spec,\n data: data[i],\n }));\n }\n\n public async getUniqueValues(\n handle: PFrameHandle,\n request: UniqueValuesRequest,\n signal?: AbortSignal,\n ): Promise<UniqueValuesResponse> {\n if (logPFrames()) {\n this.logger(\n \"info\",\n `Call getUniqueValues, handle = ${handle}, request = ${JSON.stringify(request, bigintReplacer)}`,\n );\n }\n\n const { pFrameDataPromise, columnSpecs, disposeSignal } = this.pFrames.getByKey(handle);\n const pFrameData = await pFrameDataPromise;\n\n const columnSpec = columnSpecs[request.columnId];\n if (!columnSpec) {\n const error = new PFrameDriverError(`getUniqueValues failed`);\n error.cause = new Error(`column ${request.columnId} is not registered in the PFrame`);\n throw error;\n }\n\n const axisIds = expandAxes(columnSpec.axesSpec);\n const tableSpec: PTableColumnSpec[] = [\n ...columnSpec.axesSpec.map(\n (axisSpec, i): PTableColumnSpec => ({\n type: \"axis\",\n id: axisIds[i],\n spec: axisSpec,\n }),\n ),\n { type: \"column\", id: request.columnId, spec: columnSpec },\n ];\n\n let axisIndex: number | undefined;\n if (request.axis !== undefined) {\n const index = findTableColumn(tableSpec, { type: \"axis\", id: request.axis });\n if (index < 0) {\n const error = new PFrameDriverError(`getUniqueValues failed`);\n error.cause = new Error(\n `axis ${JSON.stringify(request.axis)} not found among axes of column ${request.columnId}`,\n );\n throw error;\n }\n axisIndex = index;\n }\n\n const resolvedRequest: PFrameInternal.UniqueValuesRequestV2 = {\n columnId: request.columnId,\n axisIndex,\n filters: rewriteLegacyFilters({\n tableSpec,\n filters: migrateFilters(request.filters, this.logger),\n }),\n limit: request.limit,\n };\n\n const combinedSignal = AbortSignal.any([signal, disposeSignal].filter((s) => !!s));\n return await this.frameConcurrencyLimiter.run(async () => {\n return await pFrameData.getUniqueValues(resolvedRequest, { signal: combinedSignal });\n }, combinedSignal);\n }\n\n //\n // PTable instance methods\n //\n\n public async getSpec(handle: PTableHandle): Promise<PTableColumnSpec[]> {\n const { def } = this.pTableDefs.getByKey(handle);\n return def.tableSpec;\n }\n\n public async getShape(handle: PTableHandle, signal?: AbortSignal): Promise<PTableShape> {\n const { def, disposeSignal: defDisposeSignal } = this.pTableDefs.getByKey(handle);\n using tableGuard = new PoolEntryGuard(this.pTables.acquire(def));\n\n const { pTablePromise, disposeSignal } = tableGuard.resource;\n const pTable = await pTablePromise;\n\n const combinedSignal = AbortSignal.any([signal, disposeSignal].filter((s) => !!s));\n const { shape, overallSize } = await this.tableConcurrencyLimiter.run(async () => {\n const shape = await pTable.getShape({\n signal: combinedSignal,\n });\n\n const overallSize = await tableGuard.resource.cacheSize;\n\n return { shape, overallSize };\n }, combinedSignal);\n\n this.pTableCachePlain.cache(tableGuard.keep(), overallSize, defDisposeSignal);\n return shape;\n }\n\n public async getData(\n handle: PTableHandle,\n columnIndices: number[],\n range: TableRange | undefined,\n signal?: AbortSignal,\n ): Promise<PTableVector[]> {\n const { def, disposeSignal: defDisposeSignal } = this.pTableDefs.getByKey(handle);\n using tableGuard = new PoolEntryGuard(this.pTables.acquire(def));\n\n const { pTablePromise, disposeSignal } = tableGuard.resource;\n const pTable = await pTablePromise;\n\n const combinedSignal = AbortSignal.any([signal, disposeSignal].filter((s) => !!s));\n const { data, overallSize } = await this.tableConcurrencyLimiter.run(async () => {\n const data = await pTable.getData(columnIndices, {\n range,\n signal: combinedSignal,\n });\n\n const overallSize = await tableGuard.resource.cacheSize;\n\n return { data, overallSize };\n }, combinedSignal);\n\n this.pTableCachePlain.cache(tableGuard.keep(), overallSize, defDisposeSignal);\n return data;\n }\n}\n\n/** Clamp range to table shape. When range is undefined, returns full table range. */\nfunction clipRange(range: undefined | TableRange, shape: PTableShape): TableRange {\n if (isNil(range)) {\n return { offset: 0, length: shape.rows };\n }\n const clampedOffset = Math.min(range.offset, shape.rows);\n const clampedLength = Math.min(range.length, shape.rows - clampedOffset);\n return { offset: clampedOffset, length: clampedLength };\n}\n\nfunction migrateFilters(\n filters: PTableRecordFilter[],\n logger: PFrameInternal.Logger,\n): PTableRecordFilter[] {\n const filtersV1 = [];\n const filtersV2: PTableRecordSingleValueFilterV2[] = [];\n for (const filter of filters) {\n if ((filter.type as unknown) === \"bySingleColumn\") {\n filtersV1.push(filter);\n filtersV2.push({\n ...filter,\n type: \"bySingleColumnV2\",\n });\n } else {\n filtersV2.push(filter);\n }\n }\n if (filtersV1.length > 0) {\n const filtersV1Json = JSON.stringify(filtersV1);\n logger(\n \"warn\",\n `type overwritten from 'bySingleColumn' to 'bySingleColumnV2' for filters: ${filtersV1Json}`,\n );\n }\n return filtersV2;\n}\n\nfunction migrateTableFilter<T>(\n def: Omit<PTableDef<T>, \"partitionFilters\"> | PTableDef<T>,\n logger: PFrameInternal.Logger,\n): PTableDef<T> {\n if (!(\"partitionFilters\" in def)) {\n // For old blocks assume all axes filters to be partition filters\n return {\n ...def,\n partitionFilters: migrateFilters(\n def.filters.filter((f) => f.column.type === \"axis\"),\n logger,\n ),\n filters: migrateFilters(\n def.filters.filter((f) => f.column.type === \"column\"),\n logger,\n ),\n };\n }\n return {\n ...def,\n partitionFilters: migrateFilters(def.partitionFilters, logger),\n filters: migrateFilters(def.filters, logger),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAgGA,MAAa,kCAA2D;CACtE,GAAG;CACH,GAAG;CACH,mBAAmB;CACnB,mBAAmB;AACrB;AAOA,IAAa,uBAAb,MAGuD;CACrD;CAEA;CACA;CAEA;CAEA;CACA;CACA;CAEA;CACA;CAEA;CACA;CAEA,MAAa,YAAiC;EAC5C,OAAO,MAAM,cAAc,UAAU;CACvC;CAEA,MAAa,kBAA+D;EAC1E,OAAO,MAAM,KAAK,mBAAmB,gBAAgB;CACvD;CAEA,MAAa,aAA4B;EACvC,MAAM,KAAK,mBAAmB,WAAW;CAC3C;CAEA,YAAmB,EACjB,eAAe,CAAC,GAChB,mBACA,oBACA,YAAY,OAAO,GACnB,UAAU,iCACV,mBAQC;EACD,KAAK,SAAS;EAEd,KAAK,oBAAoB;EACzB,KAAK,qBAAqB;EAE1B,KAAK,kBAAkB;EAEvB,KAAK,0BAA0B,IAAI,4BAA4B,QAAQ,iBAAiB;EACxF,KAAK,0BAA0B,IAAI,4BAA4B,QAAQ,iBAAiB;EAExF,KAAK,UAAU,IAAI,WACjB,KAAK,mBACL,KAAK,oBACL,KAAK,QACL,SACF;EACA,KAAK,aAAa,IAAI,cAAc,KAAK,MAAM;EAC/C,KAAK,UAAU,IAAI,WAAW,KAAK,SAAS,KAAK,YAAY,KAAK,MAAM;EAExE,KAAK,sBAAsB,IAAI,oBAAoB,KAAK,QAAQ,OAAO;EACvE,KAAK,mBAAmB,IAAI,iBAAiB,KAAK,QAAQ,OAAO;CACnE;CAEA,MAAM,UAAyB;EAC7B,MAAY,QAAQ,WAAW;GAC7B,KAAK,QAAQ,OAAO,aAAa,CAAC;GAClC,KAAK,WAAW,OAAO,aAAa,CAAC;GACrC,KAAK,QAAQ,OAAO,aAAa,CAAC;GAClC,KAAK,kBAAkB,OAAO,aAAa,CAAC;GAC5C,KAAK,mBAAmB,OAAO,aAAa,CAAC;EAC/C,CAAC;CACH;CAEA,OAAO,OAAO,gBAA+B;EAC3C,OAAO,MAAM,KAAK,QAAQ;CAC5B;CAMA,aAAoB,KAA+D;EACjF,MAAM,aAAa,IAAI,IAAI,OAAO,OAAO,SAAS,CAAC;EAKnD,MAAM,UADgB,SAHG,IACtB,QAAQ,WAAW,WAAW,IAAI,OAAO,KAAK,SAAS,CAAC,CAAC,CACzD,KAAK,OAAO;GAAE,GAAG;GAAG,MAAM,yBAAyB,EAAE,IAAI;EAAE,EAChB,IAAI,WAAW,OAAO,EACxC,CAAC,CAAC,KAAK,MACjC,eAAe,IAAI,MAAM,KAAK,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAC1D;EAEA,OAAO,KAAK,QAAQ,QAAQ,OAAO;CACrC;CAEA,aAAoB,QAAkE;;;GACpF,MAAM,UAAU,SAAS,kBAAkB,OAAO,GAAG,IAAI,MAAM,EAAE,EAAE;GACnE,MAAM,cAAA,YAAA,EAAc,IAAI,eAAe,KAAK,aAAa,OAAO,CAAC,CAAA;GACjE,MAAM,YAAY,cAChB,mBACE,aAAa,SAAS,MAAM,EAAE,EAAE,GAChC,KAAK,MACP,CACF;GACA,MAAM,aAAa,KAAK,QAAQ,SAAS,YAAY,GAAG,CAAC,CAAC;GAC1D,MAAM,cAAA,YAAA,EAAc,IAAI,eACtB,KAAK,WAAW,kBAAkB;IAChC,cAAc,YAAY;IAC1B,KAAK;IACL;GACF,CAAC,CAAC,CAAC,KACL,CAAA;GACA,IAAI,WAAW,GACb,KAAK,OACH,QACA,sCAAsC,YAAY,IAAI,mBAAmB,YAAY,IAAI,EAC3F;GAGF,MAAM,cAAc,YAAY,KAAK;GACrC,MAAM,cAAc,YAAY,KAAK;GACrC,MAAM,cAAc;IAClB,YAAY,MAAM;IAClB,YAAY,MAAM;GACpB;GACA,OAAO;IACL,KAAK,YAAY;IACjB,UAAU,YAAY;IACtB;KACC,OAAO,UAAU;GACpB;;;;;;CACF;CAEA,eAAsB,KAAiE;;;GACrF,MAAM,UAAU,SAAS,wBAAwB,IAAI,KAAK,IAAI,MAAM,EAAE,EAAE;GACxE,MAAM,cAAA,WAAA,EAAc,IAAI,eAAe,KAAK,aAAa,OAAO,CAAC,CAAA;GACjE,MAAM,aAAa,KAAK,QAAQ,SAAS,YAAY,GAAG,CAAC,CAAC;GAC1D,MAAM,cAAc,cAAc,oBAAoB,IAAI,QAAQ,MAAM,EAAE,EAAE,CAAC;GAC7E,MAAM,EAAE,WAAW,cAAc,WAAW,cAC1C,2BAA2B,WAAW,CACxC;GAEA,MAAM,cAAA,WAAA,EAAc,IAAI,eACtB,KAAK,WAAW,QAAQ;IACtB,cAAc,YAAY;IAC1B;IACA;GACF,CAAC,CACH,CAAA;GACA,IAAI,WAAW,GACb,KAAK,OACH,QACA,sCAAsC,YAAY,IAAI,mBAAmB,YAAY,IAAI,EAC3F;GAGF,MAAM,cAAc,YAAY,KAAK;GACrC,MAAM,cAAc,YAAY,KAAK;GACrC,MAAM,cAAc;IAClB,YAAY,MAAM;IAClB,YAAY,MAAM;GACpB;GACA,OAAO;IACL,KAAK,YAAY;IACjB,UAAU,YAAY;IACtB;KACC,OAAO,UAAU;GACpB;;;;;;CACF;CAEA,MAAa,gBACX,QACA,SACgC;;;GAChC,KAAK,OACH,QACA,qCAAqC,OAAO,WAAW,QAAQ,KAAK,aAAa,QAAQ,OAAO,kBAAkB,QAAQ,eAAe,OAAO,cAAc,QAAQ,cAAc,OAAO,EAC7L;GACA,MAAM,YAAY,YAAY,IAAI;GAClC,MAAM,EAAE,KAAK,eAAe,qBAAqB,KAAK,WAAW,SAAS,MAAM;GAChF,MAAM,aAAA,WAAA,EAAa,IAAI,eAAe,KAAK,QAAQ,QAAQ,GAAG,CAAC,CAAA;GAC/D,MAAM,EAAE,eAAe,kBAAkB,WAAW;GACpD,MAAM,SAAS,MAAM;GAErB,MAAM,iBAAiB,YAAY,IACjC,CAAC,QAAQ,QAAQ,aAAa,CAAC,CAAC,QAAQ,MAAwB,CAAC,MAAM,CAAC,CAAC,CAC3E;GAQA,MAAM,EAAE,QAAQ,gBAAgB,MAAM,KAAK,wBAAwB,IAAI,YAAY;IACjF,MAAM,QAAQ,MAAM,OAAO,SAAS,EAAE,QAAQ,eAAe,CAAC;IAC9D,MAAM,eAAe,UAAU,QAAQ,OAAO,KAAK;IACnD,MAAM,QAAQ,IAAI;IAClB,MAAM,YAAY,QAAQ,WAAW,QAAQ,MAAO;IAEpD,MAAM,WAAW,iBAAiB;KAChC;KACA;KACA,eAAe,QAAQ;KACvB,OAAO;KACP,WAAW,QAAQ,aAAa;KAChC;KACA,eAAe,QAAQ,iBAAiB;KACxC,KAAK,QAAQ,OAAO;KACpB,QAAQ;IACV,CAAC;IAED,MAAM,WAAqB;KACzB,OAAO,QAAQ,KAAK,OAAO,QAAQ,OAAO,GAAG,CAAC;KAC9C,OAAO,QAAQ,KAAK,OAAO,QAAQ,OAAO,GAAG,CAAC;KAC9C,QAAQ,QAAQ,KAAK,OAAO,SAAS,OAAO,GAAG,CAAC;IAClD;IAEA,IAAI,eAAe;IACnB,MAAM,qBAAqB,UAAU,QAAQ,MAAM,OAAO,aAAa;KACrE,MAAM,cAAcA,KAAG,kBAAkB,UAAU,EAAE,OAAO,KAAK,CAAC;KAClE,MAAM,SAAS,SAAS,KAAK,UAAU,EAAE,YAAY,MAAM,CAAC;KAC5D,IAAI,QAAQ,aAAa,SAAS,QAEhC,MAAM,SAAS,QADF,KAAK,WAAW,EAAE,OAAO,QAAQ,YAAY,SAAS,EAAE,CAC3C,GAAG,aAAa,EAAE,QAAQ,eAAe,CAAC;UAEpE,MAAM,SAAS,QAAQ,aAAa,EAAE,QAAQ,eAAe,CAAC;KAEhE,eAAe,YAAY;IAC7B,CAAC;IAED,MAAM,cAAc,MAAM,WAAW,SAAS;IAI9C,MAAM,cAAc,aAAa;IAEjC,IAAI,WAAW,GAAG;KAChB,MAAM,aAAa,KAAK,MAAM,YAAY,IAAI,IAAI,SAAS;KAC3D,KAAK,OACH,QACA,wCAAwC,OAAO,cAAc,QAAQ,cAAc,OAAO,WAAW,YAAY,YAAY,aAAa,eAAe,WAAW,IACtK;IACF;IAEA,OAAO;KAAE,QAAQ;MAAE,MAAM,QAAQ;MAAM;MAAa;KAAa;KAAG;IAAY;GAClF,GAAG,cAAc;GAEjB,KAAK,iBAAiB,MAAM,WAAW,KAAK,GAAG,aAAa,gBAAgB;GAC5E,OAAO;;;;;;CACT;CAEA,MAAa,aACX,QACA,SACA,QACe;;;GACf,MAAM,EAAE,MAAM,kBAAkB;GAEhC,KAAK,OAAO,QAAQ,kCAAkC,OAAO,WAAW,KAAK,EAAE;GAC/E,MAAM,YAAY,YAAY,IAAI;GAElC,MAAM,EAAE,KAAK,eAAe,qBAAqB,KAAK,WAAW,SAAS,MAAM;GAChF,MAAM,aAAA,WAAA,EAAa,IAAI,eAAe,KAAK,QAAQ,QAAQ,GAAG,CAAC,CAAA;GAC/D,MAAM,EAAE,eAAe,kBAAkB,WAAW;GACpD,MAAM,SAAS,MAAM;GAErB,MAAM,iBAAiB,YAAY,IACjC,CAAC,QAAQ,aAAa,CAAC,CAAC,QAAQ,MAAwB,CAAC,MAAM,CAAC,CAAC,CACnE;GAEA,MAAM,UAA8B,cAAc,KAAK,UAA4B,CACjF,OACA,YAAY,IAAI,UAAU,MAAM,CAClC,CAAC;GAKD,MAAM,cAAc,MAAM,KAAK,wBAAwB,IAAI,YAAY;IAErE,IAAI,KAAK,YAAY,CAAC,CAAC,SAAS,OAAO,GAAG;KACxC,MAAM,QAAQ,MAAM,OAAO,SAAS,EAAE,QAAQ,eAAe,CAAC;KAC9D,IAAI,MAAM,OAAO,yBAAyB;MACxC,MAAM,QAAQ,IAAI,kBAAkB,qBAAqB;MACzD,MAAM,wBAAQ,IAAI,MAChB,yBAAyB,MAAM,KAAK,sCACtB,wBAAwB,MACxC;MACA,MAAM;KACR;IACF;IAEA,MAAM,OAAO,OAAO,MAAM;KAAE;KAAS,QAAQ;IAAe,CAAC;IAE7D,MAAM,cAAc,MAAM,WAAW,SAAS;IAE9C,IAAI,WAAW,GAAG;KAChB,MAAM,aAAa,KAAK,MAAM,YAAY,IAAI,IAAI,SAAS;KAC3D,KAAK,OACH,QACA,qCAAqC,OAAO,WAAW,KAAK,gBAC5C,WAAW,GAC7B;IACF;IAEA,OAAO;GACT,GAAG,cAAc;GAEjB,KAAK,iBAAiB,MAAM,WAAW,KAAK,GAAG,aAAa,gBAAgB;;;;;;CAC9E;CAMA,MAAa,YACX,QACA,SAC8B;EAC9B,MAAM,WAA8C;GAClD,GAAG;GACH,gBACE,QAAQ,eAAe,WAAW,IAC9B,CACE;IACE,UAAU,CACR,GAAG,IAAI,IACL,QAAQ,eAAe,KAAK,SAAS,CAAC,iBAAiB,IAAI,GAAG,IAAI,CAAU,CAC9E,CAAC,CAAC,OAAO,CACX;IACA,gBAAgB,CAAC;GACnB,CACF,IACA,CAAC;EACT;EAEA,MAAM,EAAE,eAAe,KAAK,QAAQ,SAAS,MAAM;EAEnD,OAAO,EACL,MAFe,WAAW,YAAY,QAEzB,CAAC,CAAC,KACZ,QACE,MAEC,EAAE,gBAAgB,WAAW,KAC7B,EAAE,gBAAgB,MACf,MACC,EAAE,eAAe,OAAO,WAAW,KACnC,EAAE,eAAe,WAAW,OAAO,MAAM,EAAE,WAAW,CAAC,CAC3D,CACJ,CAAC,CACA,KAAK,MAAM,EAAE,GAAG,EACrB;CACF;CAEA,MAAa,cACX,QACA,UAC6B;EAC7B,MAAM,EAAE,gBAAgB,KAAK,QAAQ,SAAS,MAAM;EACpD,OAAO,YAAY,aAAa;CAClC;CAEA,MAAa,YAAY,QAAmD;EAC1E,MAAM,EAAE,eAAe,KAAK,QAAQ,SAAS,MAAM;EACnD,OAAO,WAAW,YAAY,CAAC,CAAC,KAAK,EAAE,UAAU,YAAY;GAAE;GAAU;EAAK,EAAE;CAClF;CAEA,MAAa,mBACX,QACA,SACA,OACA,QACqC;;;GACrC,IAAI,WAAW,GACb,KAAK,OACH,QACA,qCAAqC,OAAO,cAAc,KAAK,UAAU,SAAS,cAAc,GAClG;GAGF,MAAM,EAAE,eAAe,KAAK,QAAQ,SAAS,MAAM;GACnD,MAAM,YAAY,cAAc,mBAAmB,SAAS,KAAK,MAAM,CAAC;GACxE,MAAM,EAAE,KAAK,UAAU,KAAK,QAAQ,kBAAkB;IACpD,cAAc;IACd,KAAK;IACL;GACF,CAAC;GACD,MAAM,aAAA,WAAA,EAAa,IAAI,eAAe,KAAK,CAAA;GAC3C,MAAM,YAAY,IAAI;GACtB,MAAM,EAAE,eAAe,kBAAkB,WAAW;GACpD,MAAM,SAAS,MAAM;GAErB,MAAM,iBAAiB,YAAY,IAAI,CAAC,QAAQ,aAAa,CAAC,CAAC,QAAQ,MAAM,CAAC,CAAC,CAAC,CAAC;GAIjF,MAAM,EAAE,MAAM,gBAAgB,MAAM,KAAK,wBAAwB,IAAI,YAAY;IAU/E,OAAO;KAAE,MAAA,MANU,OAAO,QAAQ,CAAC,GAAG,UAAU,KAAK,CAAC,GAAG;MACvD;MACA,QAAQ;KACV,CAAC;KAGc,aAAA,MADW,WAAW,SAAS;IACnB;GAC7B,GAAG,cAAc;GAEjB,KAAK,oBAAoB,MAAM,WAAW,KAAK,GAAG,WAAW;GAC7D,OAAO,UAAU,KAAK,MAAM,OAAO;IAC3B;IACN,MAAM,KAAK;GACb,EAAE;;;;;;CACJ;CAEA,MAAa,gBACX,QACA,SACA,QAC+B;EAC/B,IAAI,WAAW,GACb,KAAK,OACH,QACA,kCAAkC,OAAO,cAAc,KAAK,UAAU,SAAS,cAAc,GAC/F;EAGF,MAAM,EAAE,mBAAmB,aAAa,kBAAkB,KAAK,QAAQ,SAAS,MAAM;EACtF,MAAM,aAAa,MAAM;EAEzB,MAAM,aAAa,YAAY,QAAQ;EACvC,IAAI,CAAC,YAAY;GACf,MAAM,QAAQ,IAAI,kBAAkB,wBAAwB;GAC5D,MAAM,wBAAQ,IAAI,MAAM,UAAU,QAAQ,SAAS,iCAAiC;GACpF,MAAM;EACR;EAEA,MAAM,UAAU,WAAW,WAAW,QAAQ;EAC9C,MAAM,YAAgC,CACpC,GAAG,WAAW,SAAS,KACpB,UAAU,OAAyB;GAClC,MAAM;GACN,IAAI,QAAQ;GACZ,MAAM;EACR,EACF,GACA;GAAE,MAAM;GAAU,IAAI,QAAQ;GAAU,MAAM;EAAW,CAC3D;EAEA,IAAI;EACJ,IAAI,QAAQ,SAAS,KAAA,GAAW;GAC9B,MAAM,QAAQ,gBAAgB,WAAW;IAAE,MAAM;IAAQ,IAAI,QAAQ;GAAK,CAAC;GAC3E,IAAI,QAAQ,GAAG;IACb,MAAM,QAAQ,IAAI,kBAAkB,wBAAwB;IAC5D,MAAM,wBAAQ,IAAI,MAChB,QAAQ,KAAK,UAAU,QAAQ,IAAI,EAAE,kCAAkC,QAAQ,UACjF;IACA,MAAM;GACR;GACA,YAAY;EACd;EAEA,MAAM,kBAAwD;GAC5D,UAAU,QAAQ;GAClB;GACA,SAAS,qBAAqB;IAC5B;IACA,SAAS,eAAe,QAAQ,SAAS,KAAK,MAAM;GACtD,CAAC;GACD,OAAO,QAAQ;EACjB;EAEA,MAAM,iBAAiB,YAAY,IAAI,CAAC,QAAQ,aAAa,CAAC,CAAC,QAAQ,MAAM,CAAC,CAAC,CAAC,CAAC;EACjF,OAAO,MAAM,KAAK,wBAAwB,IAAI,YAAY;GACxD,OAAO,MAAM,WAAW,gBAAgB,iBAAiB,EAAE,QAAQ,eAAe,CAAC;EACrF,GAAG,cAAc;CACnB;CAMA,MAAa,QAAQ,QAAmD;EACtE,MAAM,EAAE,QAAQ,KAAK,WAAW,SAAS,MAAM;EAC/C,OAAO,IAAI;CACb;CAEA,MAAa,SAAS,QAAsB,QAA4C;;;GACtF,MAAM,EAAE,KAAK,eAAe,qBAAqB,KAAK,WAAW,SAAS,MAAM;GAChF,MAAM,aAAA,WAAA,EAAa,IAAI,eAAe,KAAK,QAAQ,QAAQ,GAAG,CAAC,CAAA;GAE/D,MAAM,EAAE,eAAe,kBAAkB,WAAW;GACpD,MAAM,SAAS,MAAM;GAErB,MAAM,iBAAiB,YAAY,IAAI,CAAC,QAAQ,aAAa,CAAC,CAAC,QAAQ,MAAM,CAAC,CAAC,CAAC,CAAC;GACjF,MAAM,EAAE,OAAO,gBAAgB,MAAM,KAAK,wBAAwB,IAAI,YAAY;IAOhF,OAAO;KAAE,OAAA,MANW,OAAO,SAAS,EAClC,QAAQ,eACV,CAAC;KAIe,aAAA,MAFU,WAAW,SAAS;IAElB;GAC9B,GAAG,cAAc;GAEjB,KAAK,iBAAiB,MAAM,WAAW,KAAK,GAAG,aAAa,gBAAgB;GAC5E,OAAO;;;;;;CACT;CAEA,MAAa,QACX,QACA,eACA,OACA,QACyB;;;GACzB,MAAM,EAAE,KAAK,eAAe,qBAAqB,KAAK,WAAW,SAAS,MAAM;GAChF,MAAM,aAAA,WAAA,EAAa,IAAI,eAAe,KAAK,QAAQ,QAAQ,GAAG,CAAC,CAAA;GAE/D,MAAM,EAAE,eAAe,kBAAkB,WAAW;GACpD,MAAM,SAAS,MAAM;GAErB,MAAM,iBAAiB,YAAY,IAAI,CAAC,QAAQ,aAAa,CAAC,CAAC,QAAQ,MAAM,CAAC,CAAC,CAAC,CAAC;GACjF,MAAM,EAAE,MAAM,gBAAgB,MAAM,KAAK,wBAAwB,IAAI,YAAY;IAQ/E,OAAO;KAAE,MAAA,MAPU,OAAO,QAAQ,eAAe;MAC/C;MACA,QAAQ;KACV,CAAC;KAIc,aAAA,MAFW,WAAW,SAAS;IAEnB;GAC7B,GAAG,cAAc;GAEjB,KAAK,iBAAiB,MAAM,WAAW,KAAK,GAAG,aAAa,gBAAgB;GAC5E,OAAO;;;;;;CACT;AACF;;AAGA,SAAS,UAAU,OAA+B,OAAgC;CAChF,IAAI,MAAM,KAAK,GACb,OAAO;EAAE,QAAQ;EAAG,QAAQ,MAAM;CAAK;CAEzC,MAAM,gBAAgB,KAAK,IAAI,MAAM,QAAQ,MAAM,IAAI;CAEvD,OAAO;EAAE,QAAQ;EAAe,QADV,KAAK,IAAI,MAAM,QAAQ,MAAM,OAAO,aACN;CAAE;AACxD;AAEA,SAAS,eACP,SACA,QACsB;CACtB,MAAM,YAAY,CAAC;CACnB,MAAM,YAA+C,CAAC;CACtD,KAAK,MAAM,UAAU,SACnB,IAAK,OAAO,SAAqB,kBAAkB;EACjD,UAAU,KAAK,MAAM;EACrB,UAAU,KAAK;GACb,GAAG;GACH,MAAM;EACR,CAAC;CACH,OACE,UAAU,KAAK,MAAM;CAGzB,IAAI,UAAU,SAAS,GAErB,OACE,QACA,6EAHoB,KAAK,UAAU,SAGsD,GAC3F;CAEF,OAAO;AACT;AAEA,SAAS,mBACP,KACA,QACc;CACd,IAAI,EAAE,sBAAsB,MAE1B,OAAO;EACL,GAAG;EACH,kBAAkB,eAChB,IAAI,QAAQ,QAAQ,MAAM,EAAE,OAAO,SAAS,MAAM,GAClD,MACF;EACA,SAAS,eACP,IAAI,QAAQ,QAAQ,MAAM,EAAE,OAAO,SAAS,QAAQ,GACpD,MACF;CACF;CAEF,OAAO;EACL,GAAG;EACH,kBAAkB,eAAe,IAAI,kBAAkB,MAAM;EAC7D,SAAS,eAAe,IAAI,SAAS,MAAM;CAC7C;AACF"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,4 +2,4 @@ import { AbstractInternalPFrameDriver, ExportPTableOptions, PTableDownloadFormat
|
|
|
2
2
|
import { AbstractPFrameDriver, AbstractPFrameDriverOps, AbstractPFrameDriverOpsDefaults, DataInfoResolver, LocalBlobProvider, RemoteBlobProvider } from "./driver_impl.js";
|
|
3
3
|
import { makeJsonDataInfo } from "./data_info_helpers.js";
|
|
4
4
|
import { FileName, FilePath, FolderPath, InternalPFrameDriverDouble, createPFrameDriverDouble, makeFolderPath } from "./driver_double.js";
|
|
5
|
-
export { AbstractInternalPFrameDriver, AbstractPFrameDriver, AbstractPFrameDriverOps, AbstractPFrameDriverOpsDefaults, DataInfoResolver, ExportPTableOptions, FileName, FilePath, FolderPath, InternalPFrameDriverDouble, LocalBlobProvider, PTableDownloadFormat, RemoteBlobProvider, WritePTableToFsOptions, WritePTableToFsResult, createPFrameDriverDouble, makeFolderPath, makeJsonDataInfo };
|
|
5
|
+
export { AbstractInternalPFrameDriver, AbstractPFrameDriver, AbstractPFrameDriverOps, AbstractPFrameDriverOpsDefaults, DataInfoResolver, type ExportPTableOptions, FileName, FilePath, FolderPath, InternalPFrameDriverDouble, LocalBlobProvider, type PTableDownloadFormat, RemoteBlobProvider, type WritePTableToFsOptions, type WritePTableToFsResult, createPFrameDriverDouble, makeFolderPath, makeJsonDataInfo };
|
package/dist/logging.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logging.cjs","names":[],"sources":["../src/logging.ts"],"sourcesContent":["const LogPFrames = Boolean(process.env.MI_LOG_PFRAMES);\n\nexport function logPFrames(): boolean {\n return LogPFrames;\n}\n"],"mappings":";AAAA,MAAM,aAAa,QAAQ,QAAQ,IAAI,
|
|
1
|
+
{"version":3,"file":"logging.cjs","names":[],"sources":["../src/logging.ts"],"sourcesContent":["const LogPFrames = Boolean(process.env.MI_LOG_PFRAMES);\n\nexport function logPFrames(): boolean {\n return LogPFrames;\n}\n"],"mappings":";AAAA,MAAM,aAAa,QAAQ,QAAQ,IAAI,cAAc;AAErD,SAAgB,aAAsB;CACpC,OAAO;AACT"}
|
package/dist/logging.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logging.js","names":[],"sources":["../src/logging.ts"],"sourcesContent":["const LogPFrames = Boolean(process.env.MI_LOG_PFRAMES);\n\nexport function logPFrames(): boolean {\n return LogPFrames;\n}\n"],"mappings":";AAAA,MAAM,aAAa,QAAQ,QAAQ,IAAI,
|
|
1
|
+
{"version":3,"file":"logging.js","names":[],"sources":["../src/logging.ts"],"sourcesContent":["const LogPFrames = Boolean(process.env.MI_LOG_PFRAMES);\n\nexport function logPFrames(): boolean {\n return LogPFrames;\n}\n"],"mappings":";AAAA,MAAM,aAAa,QAAQ,QAAQ,IAAI,cAAc;AAErD,SAAgB,aAAsB;CACpC,OAAO;AACT"}
|
package/dist/pframe_pool.cjs
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
require("./_virtual/_rolldown/runtime.cjs");
|
|
2
1
|
const require_logging = require("./logging.cjs");
|
|
3
2
|
let _milaboratories_pl_model_common = require("@milaboratories/pl-model-common");
|
|
4
3
|
let _milaboratories_helpers = require("@milaboratories/helpers");
|
|
@@ -8,6 +7,9 @@ let _milaboratories_pl_model_middle_layer = require("@milaboratories/pl-model-mi
|
|
|
8
7
|
let es_toolkit = require("es-toolkit");
|
|
9
8
|
//#region src/pframe_pool.ts
|
|
10
9
|
var PFrameHolder = class {
|
|
10
|
+
localBlobProvider;
|
|
11
|
+
remoteBlobProvider;
|
|
12
|
+
spillPath;
|
|
11
13
|
pFrameDataPromise;
|
|
12
14
|
/**
|
|
13
15
|
* WASM-spec frame built from this PFrame's columns. Source of truth
|
|
@@ -122,6 +124,10 @@ var PFrameHolder = class {
|
|
|
122
124
|
}
|
|
123
125
|
};
|
|
124
126
|
var PFramePool = class extends _milaboratories_helpers.RefCountPoolBase {
|
|
127
|
+
localBlobProvider;
|
|
128
|
+
remoteBlobProvider;
|
|
129
|
+
logger;
|
|
130
|
+
spillPath;
|
|
125
131
|
constructor(localBlobProvider, remoteBlobProvider, logger, spillPath) {
|
|
126
132
|
super();
|
|
127
133
|
this.localBlobProvider = localBlobProvider;
|
|
@@ -203,6 +209,7 @@ function stableKeyFromPFrameData(data) {
|
|
|
203
209
|
return (0, _milaboratories_pl_model_middle_layer.hashJson)(orderedData);
|
|
204
210
|
}
|
|
205
211
|
//#endregion
|
|
212
|
+
exports.PFrameHolder = PFrameHolder;
|
|
206
213
|
exports.PFramePool = PFramePool;
|
|
207
214
|
|
|
208
215
|
//# sourceMappingURL=pframe_pool.cjs.map
|
package/dist/pframe_pool.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pframe_pool.cjs","names":["ValueType","PFrameInternal","PFrameFactory","PFrameDriverError","RefCountPoolBase","logPFrames","bigintReplacer"],"sources":["../src/pframe_pool.ts"],"sourcesContent":["import {\n assertNever,\n bigintReplacer,\n canonicalizeJson,\n ensureError,\n mapPObjectData,\n PFrameDriverError,\n ValueType,\n resolveAnnotationParents,\n type JsonSerializable,\n type PColumn,\n type PColumnSpec,\n type PFrameHandle,\n type PObjectId,\n} from \"@milaboratories/pl-model-common\";\nimport { hashJson, PFrameInternal } from \"@milaboratories/pl-model-middle-layer\";\nimport { RefCountPoolBase, type PoolEntry } from \"@milaboratories/helpers\";\nimport { PFrameFactory } from \"@milaboratories/pframes-rs-node\";\nimport { createPFrame as createPFrameSpec } from \"@milaboratories/pframes-rs-wasm\";\nimport { mapValues } from \"es-toolkit\";\nimport { logPFrames } from \"./logging\";\n\nexport interface LocalBlobProvider<TreeEntry extends JsonSerializable> {\n acquire(params: TreeEntry): PoolEntry<PFrameInternal.PFrameBlobId>;\n makeDataSource(signal: AbortSignal): Omit<PFrameInternal.PFrameDataSourceV2, \"parquetServer\">;\n}\n\nexport interface RemoteBlobProvider<TreeEntry extends JsonSerializable> {\n acquire(params: TreeEntry): PoolEntry<PFrameInternal.PFrameBlobId>;\n httpServerInfo(): PFrameInternal.HttpServerInfo;\n}\n\nexport class PFrameHolder<TreeEntry extends JsonSerializable> implements Disposable {\n public readonly pFrameDataPromise: Promise<PFrameInternal.PFrameV18>;\n /**\n * WASM-spec frame built from this PFrame's columns. Source of truth\n * for spec-side operations: column discovery, selector resolution,\n * legacy-query lowering.\n */\n public readonly pFrameSpec: PFrameInternal.PFrameWasmV3;\n public readonly columnSpecs: Readonly<Record<PObjectId, PColumnSpec>>;\n private readonly abortController = new AbortController();\n\n private readonly localBlobs: PoolEntry<PFrameInternal.PFrameBlobId>[] = [];\n private readonly remoteBlobs: PoolEntry<PFrameInternal.PFrameBlobId>[] = [];\n\n constructor(\n frameId: PFrameInternal.PFrameId,\n private readonly localBlobProvider: LocalBlobProvider<TreeEntry>,\n private readonly remoteBlobProvider: RemoteBlobProvider<TreeEntry>,\n logger: PFrameInternal.Logger,\n private readonly spillPath: string,\n columns: PColumn<PFrameInternal.DataInfo<TreeEntry>>[],\n ) {\n const ValueTypes = new Set(Object.values(ValueType));\n const specColumnsMap: Record<PObjectId, PColumnSpec> = Object.create(null);\n for (const c of columns) {\n if (ValueTypes.has(c.spec.valueType)) {\n specColumnsMap[c.id] = resolveAnnotationParents(c.spec);\n }\n }\n this.pFrameSpec = createPFrameSpec(specColumnsMap);\n this.columnSpecs = specColumnsMap;\n\n try {\n const makeLocalBlobId = (blob: TreeEntry): PFrameInternal.PFrameBlobId => {\n const localBlob = this.localBlobProvider.acquire(blob);\n this.localBlobs.push(localBlob);\n return localBlob.key;\n };\n\n const makeRemoteBlobId = (blob: TreeEntry): PFrameInternal.PFrameBlobId => {\n const remoteBlob = this.remoteBlobProvider.acquire(blob);\n this.remoteBlobs.push(remoteBlob);\n return `${remoteBlob.key}${PFrameInternal.ParquetExtension}` as PFrameInternal.PFrameBlobId;\n };\n\n const mapColumnData = (\n data: PFrameInternal.DataInfo<TreeEntry>,\n ): PFrameInternal.DataInfo<PFrameInternal.PFrameBlobId> => {\n switch (data.type) {\n case \"Json\":\n return { ...data };\n case \"JsonPartitioned\":\n return {\n ...data,\n parts: mapValues(data.parts, makeLocalBlobId),\n };\n case \"BinaryPartitioned\":\n return {\n ...data,\n parts: mapValues(data.parts, (v) => ({\n index: makeLocalBlobId(v.index),\n values: makeLocalBlobId(v.values),\n })),\n };\n case \"ParquetPartitioned\":\n return {\n ...data,\n parts: mapValues(data.parts, (v) => ({\n ...v,\n data: makeRemoteBlobId(v.data),\n })),\n };\n default:\n assertNever(data);\n }\n };\n\n const jsonifiedColumns = columns.map((column) => ({\n ...column,\n data: mapColumnData(column.data),\n }));\n\n const pFrameData = PFrameFactory.createPFrame({ frameId, spillPath: this.spillPath, logger });\n try {\n pFrameData.setDataSource({\n ...this.localBlobProvider.makeDataSource(this.disposeSignal),\n parquetServer: this.remoteBlobProvider.httpServerInfo(),\n });\n\n this.pFrameDataPromise = pFrameData\n .addColumns(\n jsonifiedColumns.map((c) => ({\n id: c.id,\n data: {\n ...c.data,\n typeSpec: {\n axes: c.spec.axesSpec.map((a) => a.type),\n column: c.spec.valueType,\n },\n },\n })),\n { signal: this.disposeSignal },\n )\n .then(() => pFrameData)\n .catch((err: unknown) => {\n this.dispose();\n pFrameData.dispose();\n const error = new PFrameDriverError(\"PFrame creation failed asynchronously\");\n error.cause = new Error(\n `PFrame cannot be created from columns: ${JSON.stringify(jsonifiedColumns)}`,\n { cause: ensureError(err) },\n );\n throw error;\n });\n } catch (err: unknown) {\n // setDataSource / addColumns threw synchronously before\n // pFrameDataPromise was assigned — dispose the addon's pFrameData\n // explicitly (the dispose() path can't reach it yet).\n pFrameData.dispose();\n throw err;\n }\n } catch (err: unknown) {\n // Release everything allocated so far in this constructor:\n // acquired blobs, the WASM spec frame, and the abort signal.\n this.abortController.abort();\n this.localBlobs.forEach((entry) => entry.unref());\n this.remoteBlobs.forEach((entry) => entry.unref());\n this.pFrameSpec[Symbol.dispose]();\n const error = new PFrameDriverError(\"PFrame creation failed synchronously\");\n error.cause = new Error(`PFrame cannot be created from columns: ${JSON.stringify(columns)}`, {\n cause: ensureError(err),\n });\n throw error;\n }\n }\n\n public get disposeSignal(): AbortSignal {\n return this.abortController.signal;\n }\n\n private dispose(): void {\n this.abortController.abort();\n this.localBlobs.forEach((entry) => entry.unref());\n this.remoteBlobs.forEach((entry) => entry.unref());\n this.pFrameSpec[Symbol.dispose]();\n void this.pFrameDataPromise\n .then((pFrameData) => pFrameData.dispose())\n .catch(() => {\n /* mute error */\n });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n}\n\nexport class PFramePool<TreeEntry extends JsonSerializable> extends RefCountPoolBase<\n PColumn<PFrameInternal.DataInfo<TreeEntry>>[],\n PFrameHandle,\n PFrameHolder<TreeEntry>\n> {\n constructor(\n private readonly localBlobProvider: LocalBlobProvider<TreeEntry>,\n private readonly remoteBlobProvider: RemoteBlobProvider<TreeEntry>,\n private readonly logger: PFrameInternal.Logger,\n private readonly spillPath: string,\n ) {\n super();\n }\n\n protected calculateParamsKey(\n params: PColumn<PFrameInternal.DataInfo<TreeEntry>>[],\n ): PFrameHandle {\n return stableKeyFromPFrameData(params);\n }\n\n protected createNewResource(\n params: PColumn<PFrameInternal.DataInfo<TreeEntry>>[],\n key: PFrameHandle,\n ): PFrameHolder<TreeEntry> {\n if (logPFrames()) {\n this.logger(\n \"info\",\n `PFrame creation (pFrameHandle = ${key}): ` + `${JSON.stringify(params, bigintReplacer)}`,\n );\n }\n return new PFrameHolder(\n key,\n this.localBlobProvider,\n this.remoteBlobProvider,\n this.logger,\n this.spillPath,\n params,\n );\n }\n\n public getByKey(key: PFrameHandle): PFrameHolder<TreeEntry> {\n const resource = super.tryGetByKey(key);\n if (!resource) {\n const error = new PFrameDriverError(`Invalid PFrame handle`);\n error.cause = new Error(`PFrame with handle ${key} not found`);\n throw error;\n }\n return resource;\n }\n}\n\nfunction stableKeyFromPFrameData<TreeEntry extends JsonSerializable>(\n data: PColumn<PFrameInternal.DataInfo<TreeEntry>>[],\n): PFrameHandle {\n const orderedData = [...data].map((column) =>\n mapPObjectData(column, (r) => {\n let result: {\n type: string;\n keyLength: number;\n payload: {\n key: string;\n value: null | number | string | [string, string];\n }[];\n };\n const type = r.type;\n switch (type) {\n case \"Json\":\n result = {\n type: r.type,\n keyLength: r.keyLength,\n payload: Object.entries(r.data).map(([part, value]) => ({\n key: part,\n value,\n })),\n };\n break;\n case \"JsonPartitioned\":\n result = {\n type: r.type,\n keyLength: r.partitionKeyLength,\n payload: Object.entries(r.parts).map(([part, info]) => ({\n key: part,\n value: canonicalizeJson(info),\n })),\n };\n break;\n case \"BinaryPartitioned\":\n result = {\n type: r.type,\n keyLength: r.partitionKeyLength,\n payload: Object.entries(r.parts).map(([part, info]) => ({\n key: part,\n value: [canonicalizeJson(info.index), canonicalizeJson(info.values)] as const,\n })),\n };\n break;\n case \"ParquetPartitioned\":\n result = {\n type: r.type,\n keyLength: r.partitionKeyLength,\n payload: Object.entries(r.parts).map(([part, info]) => ({\n key: part,\n value:\n info.dataDigest ||\n ([\n canonicalizeJson(info.data),\n JSON.stringify({ axes: info.axes, column: info.column }),\n ] as const),\n })),\n };\n break;\n default:\n throw new PFrameDriverError(\n `unsupported resource type: ${JSON.stringify(type satisfies never)}`,\n );\n }\n result.payload.sort((lhs, rhs) => (lhs.key < rhs.key ? -1 : 1));\n return result;\n }),\n );\n orderedData.sort((lhs, rhs) => (lhs.id < rhs.id ? -1 : 1));\n return hashJson(orderedData) as string as PFrameHandle;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pframe_pool.cjs","names":["ValueType","PFrameInternal","PFrameFactory","PFrameDriverError","RefCountPoolBase","logPFrames","bigintReplacer"],"sources":["../src/pframe_pool.ts"],"sourcesContent":["import {\n assertNever,\n bigintReplacer,\n canonicalizeJson,\n ensureError,\n mapPObjectData,\n PFrameDriverError,\n ValueType,\n resolveAnnotationParents,\n type JsonSerializable,\n type PColumn,\n type PColumnSpec,\n type PFrameHandle,\n type PObjectId,\n} from \"@milaboratories/pl-model-common\";\nimport { hashJson, PFrameInternal } from \"@milaboratories/pl-model-middle-layer\";\nimport { RefCountPoolBase, type PoolEntry } from \"@milaboratories/helpers\";\nimport { PFrameFactory } from \"@milaboratories/pframes-rs-node\";\nimport { createPFrame as createPFrameSpec } from \"@milaboratories/pframes-rs-wasm\";\nimport { mapValues } from \"es-toolkit\";\nimport { logPFrames } from \"./logging\";\n\nexport interface LocalBlobProvider<TreeEntry extends JsonSerializable> {\n acquire(params: TreeEntry): PoolEntry<PFrameInternal.PFrameBlobId>;\n makeDataSource(signal: AbortSignal): Omit<PFrameInternal.PFrameDataSourceV2, \"parquetServer\">;\n}\n\nexport interface RemoteBlobProvider<TreeEntry extends JsonSerializable> {\n acquire(params: TreeEntry): PoolEntry<PFrameInternal.PFrameBlobId>;\n httpServerInfo(): PFrameInternal.HttpServerInfo;\n}\n\nexport class PFrameHolder<TreeEntry extends JsonSerializable> implements Disposable {\n public readonly pFrameDataPromise: Promise<PFrameInternal.PFrameV18>;\n /**\n * WASM-spec frame built from this PFrame's columns. Source of truth\n * for spec-side operations: column discovery, selector resolution,\n * legacy-query lowering.\n */\n public readonly pFrameSpec: PFrameInternal.PFrameWasmV3;\n public readonly columnSpecs: Readonly<Record<PObjectId, PColumnSpec>>;\n private readonly abortController = new AbortController();\n\n private readonly localBlobs: PoolEntry<PFrameInternal.PFrameBlobId>[] = [];\n private readonly remoteBlobs: PoolEntry<PFrameInternal.PFrameBlobId>[] = [];\n\n constructor(\n frameId: PFrameInternal.PFrameId,\n private readonly localBlobProvider: LocalBlobProvider<TreeEntry>,\n private readonly remoteBlobProvider: RemoteBlobProvider<TreeEntry>,\n logger: PFrameInternal.Logger,\n private readonly spillPath: string,\n columns: PColumn<PFrameInternal.DataInfo<TreeEntry>>[],\n ) {\n const ValueTypes = new Set(Object.values(ValueType));\n const specColumnsMap: Record<PObjectId, PColumnSpec> = Object.create(null);\n for (const c of columns) {\n if (ValueTypes.has(c.spec.valueType)) {\n specColumnsMap[c.id] = resolveAnnotationParents(c.spec);\n }\n }\n this.pFrameSpec = createPFrameSpec(specColumnsMap);\n this.columnSpecs = specColumnsMap;\n\n try {\n const makeLocalBlobId = (blob: TreeEntry): PFrameInternal.PFrameBlobId => {\n const localBlob = this.localBlobProvider.acquire(blob);\n this.localBlobs.push(localBlob);\n return localBlob.key;\n };\n\n const makeRemoteBlobId = (blob: TreeEntry): PFrameInternal.PFrameBlobId => {\n const remoteBlob = this.remoteBlobProvider.acquire(blob);\n this.remoteBlobs.push(remoteBlob);\n return `${remoteBlob.key}${PFrameInternal.ParquetExtension}` as PFrameInternal.PFrameBlobId;\n };\n\n const mapColumnData = (\n data: PFrameInternal.DataInfo<TreeEntry>,\n ): PFrameInternal.DataInfo<PFrameInternal.PFrameBlobId> => {\n switch (data.type) {\n case \"Json\":\n return { ...data };\n case \"JsonPartitioned\":\n return {\n ...data,\n parts: mapValues(data.parts, makeLocalBlobId),\n };\n case \"BinaryPartitioned\":\n return {\n ...data,\n parts: mapValues(data.parts, (v) => ({\n index: makeLocalBlobId(v.index),\n values: makeLocalBlobId(v.values),\n })),\n };\n case \"ParquetPartitioned\":\n return {\n ...data,\n parts: mapValues(data.parts, (v) => ({\n ...v,\n data: makeRemoteBlobId(v.data),\n })),\n };\n default:\n assertNever(data);\n }\n };\n\n const jsonifiedColumns = columns.map((column) => ({\n ...column,\n data: mapColumnData(column.data),\n }));\n\n const pFrameData = PFrameFactory.createPFrame({ frameId, spillPath: this.spillPath, logger });\n try {\n pFrameData.setDataSource({\n ...this.localBlobProvider.makeDataSource(this.disposeSignal),\n parquetServer: this.remoteBlobProvider.httpServerInfo(),\n });\n\n this.pFrameDataPromise = pFrameData\n .addColumns(\n jsonifiedColumns.map((c) => ({\n id: c.id,\n data: {\n ...c.data,\n typeSpec: {\n axes: c.spec.axesSpec.map((a) => a.type),\n column: c.spec.valueType,\n },\n },\n })),\n { signal: this.disposeSignal },\n )\n .then(() => pFrameData)\n .catch((err: unknown) => {\n this.dispose();\n pFrameData.dispose();\n const error = new PFrameDriverError(\"PFrame creation failed asynchronously\");\n error.cause = new Error(\n `PFrame cannot be created from columns: ${JSON.stringify(jsonifiedColumns)}`,\n { cause: ensureError(err) },\n );\n throw error;\n });\n } catch (err: unknown) {\n // setDataSource / addColumns threw synchronously before\n // pFrameDataPromise was assigned — dispose the addon's pFrameData\n // explicitly (the dispose() path can't reach it yet).\n pFrameData.dispose();\n throw err;\n }\n } catch (err: unknown) {\n // Release everything allocated so far in this constructor:\n // acquired blobs, the WASM spec frame, and the abort signal.\n this.abortController.abort();\n this.localBlobs.forEach((entry) => entry.unref());\n this.remoteBlobs.forEach((entry) => entry.unref());\n this.pFrameSpec[Symbol.dispose]();\n const error = new PFrameDriverError(\"PFrame creation failed synchronously\");\n error.cause = new Error(`PFrame cannot be created from columns: ${JSON.stringify(columns)}`, {\n cause: ensureError(err),\n });\n throw error;\n }\n }\n\n public get disposeSignal(): AbortSignal {\n return this.abortController.signal;\n }\n\n private dispose(): void {\n this.abortController.abort();\n this.localBlobs.forEach((entry) => entry.unref());\n this.remoteBlobs.forEach((entry) => entry.unref());\n this.pFrameSpec[Symbol.dispose]();\n void this.pFrameDataPromise\n .then((pFrameData) => pFrameData.dispose())\n .catch(() => {\n /* mute error */\n });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n}\n\nexport class PFramePool<TreeEntry extends JsonSerializable> extends RefCountPoolBase<\n PColumn<PFrameInternal.DataInfo<TreeEntry>>[],\n PFrameHandle,\n PFrameHolder<TreeEntry>\n> {\n constructor(\n private readonly localBlobProvider: LocalBlobProvider<TreeEntry>,\n private readonly remoteBlobProvider: RemoteBlobProvider<TreeEntry>,\n private readonly logger: PFrameInternal.Logger,\n private readonly spillPath: string,\n ) {\n super();\n }\n\n protected calculateParamsKey(\n params: PColumn<PFrameInternal.DataInfo<TreeEntry>>[],\n ): PFrameHandle {\n return stableKeyFromPFrameData(params);\n }\n\n protected createNewResource(\n params: PColumn<PFrameInternal.DataInfo<TreeEntry>>[],\n key: PFrameHandle,\n ): PFrameHolder<TreeEntry> {\n if (logPFrames()) {\n this.logger(\n \"info\",\n `PFrame creation (pFrameHandle = ${key}): ` + `${JSON.stringify(params, bigintReplacer)}`,\n );\n }\n return new PFrameHolder(\n key,\n this.localBlobProvider,\n this.remoteBlobProvider,\n this.logger,\n this.spillPath,\n params,\n );\n }\n\n public getByKey(key: PFrameHandle): PFrameHolder<TreeEntry> {\n const resource = super.tryGetByKey(key);\n if (!resource) {\n const error = new PFrameDriverError(`Invalid PFrame handle`);\n error.cause = new Error(`PFrame with handle ${key} not found`);\n throw error;\n }\n return resource;\n }\n}\n\nfunction stableKeyFromPFrameData<TreeEntry extends JsonSerializable>(\n data: PColumn<PFrameInternal.DataInfo<TreeEntry>>[],\n): PFrameHandle {\n const orderedData = [...data].map((column) =>\n mapPObjectData(column, (r) => {\n let result: {\n type: string;\n keyLength: number;\n payload: {\n key: string;\n value: null | number | string | [string, string];\n }[];\n };\n const type = r.type;\n switch (type) {\n case \"Json\":\n result = {\n type: r.type,\n keyLength: r.keyLength,\n payload: Object.entries(r.data).map(([part, value]) => ({\n key: part,\n value,\n })),\n };\n break;\n case \"JsonPartitioned\":\n result = {\n type: r.type,\n keyLength: r.partitionKeyLength,\n payload: Object.entries(r.parts).map(([part, info]) => ({\n key: part,\n value: canonicalizeJson(info),\n })),\n };\n break;\n case \"BinaryPartitioned\":\n result = {\n type: r.type,\n keyLength: r.partitionKeyLength,\n payload: Object.entries(r.parts).map(([part, info]) => ({\n key: part,\n value: [canonicalizeJson(info.index), canonicalizeJson(info.values)] as const,\n })),\n };\n break;\n case \"ParquetPartitioned\":\n result = {\n type: r.type,\n keyLength: r.partitionKeyLength,\n payload: Object.entries(r.parts).map(([part, info]) => ({\n key: part,\n value:\n info.dataDigest ||\n ([\n canonicalizeJson(info.data),\n JSON.stringify({ axes: info.axes, column: info.column }),\n ] as const),\n })),\n };\n break;\n default:\n throw new PFrameDriverError(\n `unsupported resource type: ${JSON.stringify(type satisfies never)}`,\n );\n }\n result.payload.sort((lhs, rhs) => (lhs.key < rhs.key ? -1 : 1));\n return result;\n }),\n );\n orderedData.sort((lhs, rhs) => (lhs.id < rhs.id ? -1 : 1));\n return hashJson(orderedData) as string as PFrameHandle;\n}\n"],"mappings":";;;;;;;;AAgCA,IAAa,eAAb,MAAoF;CAgB/D;CACA;CAEA;CAlBnB;;;;;;CAMA;CACA;CACA,kBAAmC,IAAI,gBAAgB;CAEvD,aAAwE,CAAC;CACzE,cAAyE,CAAC;CAE1E,YACE,SACA,mBACA,oBACA,QACA,WACA,SACA;EALiB,KAAA,oBAAA;EACA,KAAA,qBAAA;EAEA,KAAA,YAAA;EAGjB,MAAM,aAAa,IAAI,IAAI,OAAO,OAAOA,gCAAAA,SAAS,CAAC;EACnD,MAAM,iBAAiD,OAAO,OAAO,IAAI;EACzE,KAAK,MAAM,KAAK,SACd,IAAI,WAAW,IAAI,EAAE,KAAK,SAAS,GACjC,eAAe,EAAE,OAAA,GAAA,gCAAA,yBAAA,CAA+B,EAAE,IAAI;EAG1D,KAAK,cAAA,GAAA,gCAAA,aAAA,CAA8B,cAAc;EACjD,KAAK,cAAc;EAEnB,IAAI;GACF,MAAM,mBAAmB,SAAiD;IACxE,MAAM,YAAY,KAAK,kBAAkB,QAAQ,IAAI;IACrD,KAAK,WAAW,KAAK,SAAS;IAC9B,OAAO,UAAU;GACnB;GAEA,MAAM,oBAAoB,SAAiD;IACzE,MAAM,aAAa,KAAK,mBAAmB,QAAQ,IAAI;IACvD,KAAK,YAAY,KAAK,UAAU;IAChC,OAAO,GAAG,WAAW,MAAMC,sCAAAA,eAAe;GAC5C;GAEA,MAAM,iBACJ,SACyD;IACzD,QAAQ,KAAK,MAAb;KACE,KAAK,QACH,OAAO,EAAE,GAAG,KAAK;KACnB,KAAK,mBACH,OAAO;MACL,GAAG;MACH,QAAA,GAAA,WAAA,UAAA,CAAiB,KAAK,OAAO,eAAe;KAC9C;KACF,KAAK,qBACH,OAAO;MACL,GAAG;MACH,QAAA,GAAA,WAAA,UAAA,CAAiB,KAAK,QAAQ,OAAO;OACnC,OAAO,gBAAgB,EAAE,KAAK;OAC9B,QAAQ,gBAAgB,EAAE,MAAM;MAClC,EAAE;KACJ;KACF,KAAK,sBACH,OAAO;MACL,GAAG;MACH,QAAA,GAAA,WAAA,UAAA,CAAiB,KAAK,QAAQ,OAAO;OACnC,GAAG;OACH,MAAM,iBAAiB,EAAE,IAAI;MAC/B,EAAE;KACJ;KACF,SACE,CAAA,GAAA,gCAAA,YAAA,CAAY,IAAI;IACpB;GACF;GAEA,MAAM,mBAAmB,QAAQ,KAAK,YAAY;IAChD,GAAG;IACH,MAAM,cAAc,OAAO,IAAI;GACjC,EAAE;GAEF,MAAM,aAAaC,gCAAAA,cAAc,aAAa;IAAE;IAAS,WAAW,KAAK;IAAW;GAAO,CAAC;GAC5F,IAAI;IACF,WAAW,cAAc;KACvB,GAAG,KAAK,kBAAkB,eAAe,KAAK,aAAa;KAC3D,eAAe,KAAK,mBAAmB,eAAe;IACxD,CAAC;IAED,KAAK,oBAAoB,WACtB,WACC,iBAAiB,KAAK,OAAO;KAC3B,IAAI,EAAE;KACN,MAAM;MACJ,GAAG,EAAE;MACL,UAAU;OACR,MAAM,EAAE,KAAK,SAAS,KAAK,MAAM,EAAE,IAAI;OACvC,QAAQ,EAAE,KAAK;MACjB;KACF;IACF,EAAE,GACF,EAAE,QAAQ,KAAK,cAAc,CAC/B,CAAC,CACA,WAAW,UAAU,CAAC,CACtB,OAAO,QAAiB;KACvB,KAAK,QAAQ;KACb,WAAW,QAAQ;KACnB,MAAM,QAAQ,IAAIC,gCAAAA,kBAAkB,uCAAuC;KAC3E,MAAM,QAAQ,IAAI,MAChB,0CAA0C,KAAK,UAAU,gBAAgB,KACzE,EAAE,QAAA,GAAA,gCAAA,YAAA,CAAmB,GAAG,EAAE,CAC5B;KACA,MAAM;IACR,CAAC;GACL,SAAS,KAAc;IAIrB,WAAW,QAAQ;IACnB,MAAM;GACR;EACF,SAAS,KAAc;GAGrB,KAAK,gBAAgB,MAAM;GAC3B,KAAK,WAAW,SAAS,UAAU,MAAM,MAAM,CAAC;GAChD,KAAK,YAAY,SAAS,UAAU,MAAM,MAAM,CAAC;GACjD,KAAK,WAAW,OAAO,QAAQ,CAAC;GAChC,MAAM,QAAQ,IAAIA,gCAAAA,kBAAkB,sCAAsC;GAC1E,MAAM,QAAQ,IAAI,MAAM,0CAA0C,KAAK,UAAU,OAAO,KAAK,EAC3F,QAAA,GAAA,gCAAA,YAAA,CAAmB,GAAG,EACxB,CAAC;GACD,MAAM;EACR;CACF;CAEA,IAAW,gBAA6B;EACtC,OAAO,KAAK,gBAAgB;CAC9B;CAEA,UAAwB;EACtB,KAAK,gBAAgB,MAAM;EAC3B,KAAK,WAAW,SAAS,UAAU,MAAM,MAAM,CAAC;EAChD,KAAK,YAAY,SAAS,UAAU,MAAM,MAAM,CAAC;EACjD,KAAK,WAAW,OAAO,QAAQ,CAAC;EAChC,KAAU,kBACP,MAAM,eAAe,WAAW,QAAQ,CAAC,CAAC,CAC1C,YAAY,CAEb,CAAC;CACL;CAEA,CAAC,OAAO,WAAiB;EACvB,KAAK,QAAQ;CACf;AACF;AAEA,IAAa,aAAb,cAAoEC,wBAAAA,iBAIlE;CAEmB;CACA;CACA;CACA;CAJnB,YACE,mBACA,oBACA,QACA,WACA;EACA,MAAM;EALW,KAAA,oBAAA;EACA,KAAA,qBAAA;EACA,KAAA,SAAA;EACA,KAAA,YAAA;CAGnB;CAEA,mBACE,QACc;EACd,OAAO,wBAAwB,MAAM;CACvC;CAEA,kBACE,QACA,KACyB;EACzB,IAAIC,gBAAAA,WAAW,GACb,KAAK,OACH,QACA,mCAAmC,IAAI,KAAU,KAAK,UAAU,QAAQC,gCAAAA,cAAc,GACxF;EAEF,OAAO,IAAI,aACT,KACA,KAAK,mBACL,KAAK,oBACL,KAAK,QACL,KAAK,WACL,MACF;CACF;CAEA,SAAgB,KAA4C;EAC1D,MAAM,WAAW,MAAM,YAAY,GAAG;EACtC,IAAI,CAAC,UAAU;GACb,MAAM,QAAQ,IAAIH,gCAAAA,kBAAkB,uBAAuB;GAC3D,MAAM,wBAAQ,IAAI,MAAM,sBAAsB,IAAI,WAAW;GAC7D,MAAM;EACR;EACA,OAAO;CACT;AACF;AAEA,SAAS,wBACP,MACc;CACd,MAAM,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC,KAAK,YAAA,GAAA,gCAAA,eAAA,CAClB,SAAS,MAAM;EAC5B,IAAI;EAQJ,MAAM,OAAO,EAAE;EACf,QAAQ,MAAR;GACE,KAAK;IACH,SAAS;KACP,MAAM,EAAE;KACR,WAAW,EAAE;KACb,SAAS,OAAO,QAAQ,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,YAAY;MACtD,KAAK;MACL;KACF,EAAE;IACJ;IACA;GACF,KAAK;IACH,SAAS;KACP,MAAM,EAAE;KACR,WAAW,EAAE;KACb,SAAS,OAAO,QAAQ,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM,WAAW;MACtD,KAAK;MACL,QAAA,GAAA,gCAAA,iBAAA,CAAwB,IAAI;KAC9B,EAAE;IACJ;IACA;GACF,KAAK;IACH,SAAS;KACP,MAAM,EAAE;KACR,WAAW,EAAE;KACb,SAAS,OAAO,QAAQ,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM,WAAW;MACtD,KAAK;MACL,OAAO,EAAA,GAAA,gCAAA,iBAAA,CAAkB,KAAK,KAAK,IAAA,GAAA,gCAAA,iBAAA,CAAoB,KAAK,MAAM,CAAC;KACrE,EAAE;IACJ;IACA;GACF,KAAK;IACH,SAAS;KACP,MAAM,EAAE;KACR,WAAW,EAAE;KACb,SAAS,OAAO,QAAQ,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM,WAAW;MACtD,KAAK;MACL,OACE,KAAK,cACJ,EAAA,GAAA,gCAAA,iBAAA,CACkB,KAAK,IAAI,GAC1B,KAAK,UAAU;OAAE,MAAM,KAAK;OAAM,QAAQ,KAAK;MAAO,CAAC,CACzD;KACJ,EAAE;IACJ;IACA;GACF,SACE,MAAM,IAAIA,gCAAAA,kBACR,8BAA8B,KAAK,UAAU,IAAoB,GACnE;EACJ;EACA,OAAO,QAAQ,MAAM,KAAK,QAAS,IAAI,MAAM,IAAI,MAAM,KAAK,CAAE;EAC9D,OAAO;CACT,CAAC,CACH;CACA,YAAY,MAAM,KAAK,QAAS,IAAI,KAAK,IAAI,KAAK,KAAK,CAAE;CACzD,QAAA,GAAA,sCAAA,SAAA,CAAgB,WAAW;AAC7B"}
|
package/dist/pframe_pool.js
CHANGED
|
@@ -7,6 +7,9 @@ import { PFrameInternal, hashJson } from "@milaboratories/pl-model-middle-layer"
|
|
|
7
7
|
import { mapValues } from "es-toolkit";
|
|
8
8
|
//#region src/pframe_pool.ts
|
|
9
9
|
var PFrameHolder = class {
|
|
10
|
+
localBlobProvider;
|
|
11
|
+
remoteBlobProvider;
|
|
12
|
+
spillPath;
|
|
10
13
|
pFrameDataPromise;
|
|
11
14
|
/**
|
|
12
15
|
* WASM-spec frame built from this PFrame's columns. Source of truth
|
|
@@ -121,6 +124,10 @@ var PFrameHolder = class {
|
|
|
121
124
|
}
|
|
122
125
|
};
|
|
123
126
|
var PFramePool = class extends RefCountPoolBase {
|
|
127
|
+
localBlobProvider;
|
|
128
|
+
remoteBlobProvider;
|
|
129
|
+
logger;
|
|
130
|
+
spillPath;
|
|
124
131
|
constructor(localBlobProvider, remoteBlobProvider, logger, spillPath) {
|
|
125
132
|
super();
|
|
126
133
|
this.localBlobProvider = localBlobProvider;
|
|
@@ -202,6 +209,6 @@ function stableKeyFromPFrameData(data) {
|
|
|
202
209
|
return hashJson(orderedData);
|
|
203
210
|
}
|
|
204
211
|
//#endregion
|
|
205
|
-
export { PFramePool };
|
|
212
|
+
export { PFrameHolder, PFramePool };
|
|
206
213
|
|
|
207
214
|
//# sourceMappingURL=pframe_pool.js.map
|
package/dist/pframe_pool.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pframe_pool.js","names":["createPFrameSpec"],"sources":["../src/pframe_pool.ts"],"sourcesContent":["import {\n assertNever,\n bigintReplacer,\n canonicalizeJson,\n ensureError,\n mapPObjectData,\n PFrameDriverError,\n ValueType,\n resolveAnnotationParents,\n type JsonSerializable,\n type PColumn,\n type PColumnSpec,\n type PFrameHandle,\n type PObjectId,\n} from \"@milaboratories/pl-model-common\";\nimport { hashJson, PFrameInternal } from \"@milaboratories/pl-model-middle-layer\";\nimport { RefCountPoolBase, type PoolEntry } from \"@milaboratories/helpers\";\nimport { PFrameFactory } from \"@milaboratories/pframes-rs-node\";\nimport { createPFrame as createPFrameSpec } from \"@milaboratories/pframes-rs-wasm\";\nimport { mapValues } from \"es-toolkit\";\nimport { logPFrames } from \"./logging\";\n\nexport interface LocalBlobProvider<TreeEntry extends JsonSerializable> {\n acquire(params: TreeEntry): PoolEntry<PFrameInternal.PFrameBlobId>;\n makeDataSource(signal: AbortSignal): Omit<PFrameInternal.PFrameDataSourceV2, \"parquetServer\">;\n}\n\nexport interface RemoteBlobProvider<TreeEntry extends JsonSerializable> {\n acquire(params: TreeEntry): PoolEntry<PFrameInternal.PFrameBlobId>;\n httpServerInfo(): PFrameInternal.HttpServerInfo;\n}\n\nexport class PFrameHolder<TreeEntry extends JsonSerializable> implements Disposable {\n public readonly pFrameDataPromise: Promise<PFrameInternal.PFrameV18>;\n /**\n * WASM-spec frame built from this PFrame's columns. Source of truth\n * for spec-side operations: column discovery, selector resolution,\n * legacy-query lowering.\n */\n public readonly pFrameSpec: PFrameInternal.PFrameWasmV3;\n public readonly columnSpecs: Readonly<Record<PObjectId, PColumnSpec>>;\n private readonly abortController = new AbortController();\n\n private readonly localBlobs: PoolEntry<PFrameInternal.PFrameBlobId>[] = [];\n private readonly remoteBlobs: PoolEntry<PFrameInternal.PFrameBlobId>[] = [];\n\n constructor(\n frameId: PFrameInternal.PFrameId,\n private readonly localBlobProvider: LocalBlobProvider<TreeEntry>,\n private readonly remoteBlobProvider: RemoteBlobProvider<TreeEntry>,\n logger: PFrameInternal.Logger,\n private readonly spillPath: string,\n columns: PColumn<PFrameInternal.DataInfo<TreeEntry>>[],\n ) {\n const ValueTypes = new Set(Object.values(ValueType));\n const specColumnsMap: Record<PObjectId, PColumnSpec> = Object.create(null);\n for (const c of columns) {\n if (ValueTypes.has(c.spec.valueType)) {\n specColumnsMap[c.id] = resolveAnnotationParents(c.spec);\n }\n }\n this.pFrameSpec = createPFrameSpec(specColumnsMap);\n this.columnSpecs = specColumnsMap;\n\n try {\n const makeLocalBlobId = (blob: TreeEntry): PFrameInternal.PFrameBlobId => {\n const localBlob = this.localBlobProvider.acquire(blob);\n this.localBlobs.push(localBlob);\n return localBlob.key;\n };\n\n const makeRemoteBlobId = (blob: TreeEntry): PFrameInternal.PFrameBlobId => {\n const remoteBlob = this.remoteBlobProvider.acquire(blob);\n this.remoteBlobs.push(remoteBlob);\n return `${remoteBlob.key}${PFrameInternal.ParquetExtension}` as PFrameInternal.PFrameBlobId;\n };\n\n const mapColumnData = (\n data: PFrameInternal.DataInfo<TreeEntry>,\n ): PFrameInternal.DataInfo<PFrameInternal.PFrameBlobId> => {\n switch (data.type) {\n case \"Json\":\n return { ...data };\n case \"JsonPartitioned\":\n return {\n ...data,\n parts: mapValues(data.parts, makeLocalBlobId),\n };\n case \"BinaryPartitioned\":\n return {\n ...data,\n parts: mapValues(data.parts, (v) => ({\n index: makeLocalBlobId(v.index),\n values: makeLocalBlobId(v.values),\n })),\n };\n case \"ParquetPartitioned\":\n return {\n ...data,\n parts: mapValues(data.parts, (v) => ({\n ...v,\n data: makeRemoteBlobId(v.data),\n })),\n };\n default:\n assertNever(data);\n }\n };\n\n const jsonifiedColumns = columns.map((column) => ({\n ...column,\n data: mapColumnData(column.data),\n }));\n\n const pFrameData = PFrameFactory.createPFrame({ frameId, spillPath: this.spillPath, logger });\n try {\n pFrameData.setDataSource({\n ...this.localBlobProvider.makeDataSource(this.disposeSignal),\n parquetServer: this.remoteBlobProvider.httpServerInfo(),\n });\n\n this.pFrameDataPromise = pFrameData\n .addColumns(\n jsonifiedColumns.map((c) => ({\n id: c.id,\n data: {\n ...c.data,\n typeSpec: {\n axes: c.spec.axesSpec.map((a) => a.type),\n column: c.spec.valueType,\n },\n },\n })),\n { signal: this.disposeSignal },\n )\n .then(() => pFrameData)\n .catch((err: unknown) => {\n this.dispose();\n pFrameData.dispose();\n const error = new PFrameDriverError(\"PFrame creation failed asynchronously\");\n error.cause = new Error(\n `PFrame cannot be created from columns: ${JSON.stringify(jsonifiedColumns)}`,\n { cause: ensureError(err) },\n );\n throw error;\n });\n } catch (err: unknown) {\n // setDataSource / addColumns threw synchronously before\n // pFrameDataPromise was assigned — dispose the addon's pFrameData\n // explicitly (the dispose() path can't reach it yet).\n pFrameData.dispose();\n throw err;\n }\n } catch (err: unknown) {\n // Release everything allocated so far in this constructor:\n // acquired blobs, the WASM spec frame, and the abort signal.\n this.abortController.abort();\n this.localBlobs.forEach((entry) => entry.unref());\n this.remoteBlobs.forEach((entry) => entry.unref());\n this.pFrameSpec[Symbol.dispose]();\n const error = new PFrameDriverError(\"PFrame creation failed synchronously\");\n error.cause = new Error(`PFrame cannot be created from columns: ${JSON.stringify(columns)}`, {\n cause: ensureError(err),\n });\n throw error;\n }\n }\n\n public get disposeSignal(): AbortSignal {\n return this.abortController.signal;\n }\n\n private dispose(): void {\n this.abortController.abort();\n this.localBlobs.forEach((entry) => entry.unref());\n this.remoteBlobs.forEach((entry) => entry.unref());\n this.pFrameSpec[Symbol.dispose]();\n void this.pFrameDataPromise\n .then((pFrameData) => pFrameData.dispose())\n .catch(() => {\n /* mute error */\n });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n}\n\nexport class PFramePool<TreeEntry extends JsonSerializable> extends RefCountPoolBase<\n PColumn<PFrameInternal.DataInfo<TreeEntry>>[],\n PFrameHandle,\n PFrameHolder<TreeEntry>\n> {\n constructor(\n private readonly localBlobProvider: LocalBlobProvider<TreeEntry>,\n private readonly remoteBlobProvider: RemoteBlobProvider<TreeEntry>,\n private readonly logger: PFrameInternal.Logger,\n private readonly spillPath: string,\n ) {\n super();\n }\n\n protected calculateParamsKey(\n params: PColumn<PFrameInternal.DataInfo<TreeEntry>>[],\n ): PFrameHandle {\n return stableKeyFromPFrameData(params);\n }\n\n protected createNewResource(\n params: PColumn<PFrameInternal.DataInfo<TreeEntry>>[],\n key: PFrameHandle,\n ): PFrameHolder<TreeEntry> {\n if (logPFrames()) {\n this.logger(\n \"info\",\n `PFrame creation (pFrameHandle = ${key}): ` + `${JSON.stringify(params, bigintReplacer)}`,\n );\n }\n return new PFrameHolder(\n key,\n this.localBlobProvider,\n this.remoteBlobProvider,\n this.logger,\n this.spillPath,\n params,\n );\n }\n\n public getByKey(key: PFrameHandle): PFrameHolder<TreeEntry> {\n const resource = super.tryGetByKey(key);\n if (!resource) {\n const error = new PFrameDriverError(`Invalid PFrame handle`);\n error.cause = new Error(`PFrame with handle ${key} not found`);\n throw error;\n }\n return resource;\n }\n}\n\nfunction stableKeyFromPFrameData<TreeEntry extends JsonSerializable>(\n data: PColumn<PFrameInternal.DataInfo<TreeEntry>>[],\n): PFrameHandle {\n const orderedData = [...data].map((column) =>\n mapPObjectData(column, (r) => {\n let result: {\n type: string;\n keyLength: number;\n payload: {\n key: string;\n value: null | number | string | [string, string];\n }[];\n };\n const type = r.type;\n switch (type) {\n case \"Json\":\n result = {\n type: r.type,\n keyLength: r.keyLength,\n payload: Object.entries(r.data).map(([part, value]) => ({\n key: part,\n value,\n })),\n };\n break;\n case \"JsonPartitioned\":\n result = {\n type: r.type,\n keyLength: r.partitionKeyLength,\n payload: Object.entries(r.parts).map(([part, info]) => ({\n key: part,\n value: canonicalizeJson(info),\n })),\n };\n break;\n case \"BinaryPartitioned\":\n result = {\n type: r.type,\n keyLength: r.partitionKeyLength,\n payload: Object.entries(r.parts).map(([part, info]) => ({\n key: part,\n value: [canonicalizeJson(info.index), canonicalizeJson(info.values)] as const,\n })),\n };\n break;\n case \"ParquetPartitioned\":\n result = {\n type: r.type,\n keyLength: r.partitionKeyLength,\n payload: Object.entries(r.parts).map(([part, info]) => ({\n key: part,\n value:\n info.dataDigest ||\n ([\n canonicalizeJson(info.data),\n JSON.stringify({ axes: info.axes, column: info.column }),\n ] as const),\n })),\n };\n break;\n default:\n throw new PFrameDriverError(\n `unsupported resource type: ${JSON.stringify(type satisfies never)}`,\n );\n }\n result.payload.sort((lhs, rhs) => (lhs.key < rhs.key ? -1 : 1));\n return result;\n }),\n );\n orderedData.sort((lhs, rhs) => (lhs.id < rhs.id ? -1 : 1));\n return hashJson(orderedData) as string as PFrameHandle;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pframe_pool.js","names":["createPFrameSpec"],"sources":["../src/pframe_pool.ts"],"sourcesContent":["import {\n assertNever,\n bigintReplacer,\n canonicalizeJson,\n ensureError,\n mapPObjectData,\n PFrameDriverError,\n ValueType,\n resolveAnnotationParents,\n type JsonSerializable,\n type PColumn,\n type PColumnSpec,\n type PFrameHandle,\n type PObjectId,\n} from \"@milaboratories/pl-model-common\";\nimport { hashJson, PFrameInternal } from \"@milaboratories/pl-model-middle-layer\";\nimport { RefCountPoolBase, type PoolEntry } from \"@milaboratories/helpers\";\nimport { PFrameFactory } from \"@milaboratories/pframes-rs-node\";\nimport { createPFrame as createPFrameSpec } from \"@milaboratories/pframes-rs-wasm\";\nimport { mapValues } from \"es-toolkit\";\nimport { logPFrames } from \"./logging\";\n\nexport interface LocalBlobProvider<TreeEntry extends JsonSerializable> {\n acquire(params: TreeEntry): PoolEntry<PFrameInternal.PFrameBlobId>;\n makeDataSource(signal: AbortSignal): Omit<PFrameInternal.PFrameDataSourceV2, \"parquetServer\">;\n}\n\nexport interface RemoteBlobProvider<TreeEntry extends JsonSerializable> {\n acquire(params: TreeEntry): PoolEntry<PFrameInternal.PFrameBlobId>;\n httpServerInfo(): PFrameInternal.HttpServerInfo;\n}\n\nexport class PFrameHolder<TreeEntry extends JsonSerializable> implements Disposable {\n public readonly pFrameDataPromise: Promise<PFrameInternal.PFrameV18>;\n /**\n * WASM-spec frame built from this PFrame's columns. Source of truth\n * for spec-side operations: column discovery, selector resolution,\n * legacy-query lowering.\n */\n public readonly pFrameSpec: PFrameInternal.PFrameWasmV3;\n public readonly columnSpecs: Readonly<Record<PObjectId, PColumnSpec>>;\n private readonly abortController = new AbortController();\n\n private readonly localBlobs: PoolEntry<PFrameInternal.PFrameBlobId>[] = [];\n private readonly remoteBlobs: PoolEntry<PFrameInternal.PFrameBlobId>[] = [];\n\n constructor(\n frameId: PFrameInternal.PFrameId,\n private readonly localBlobProvider: LocalBlobProvider<TreeEntry>,\n private readonly remoteBlobProvider: RemoteBlobProvider<TreeEntry>,\n logger: PFrameInternal.Logger,\n private readonly spillPath: string,\n columns: PColumn<PFrameInternal.DataInfo<TreeEntry>>[],\n ) {\n const ValueTypes = new Set(Object.values(ValueType));\n const specColumnsMap: Record<PObjectId, PColumnSpec> = Object.create(null);\n for (const c of columns) {\n if (ValueTypes.has(c.spec.valueType)) {\n specColumnsMap[c.id] = resolveAnnotationParents(c.spec);\n }\n }\n this.pFrameSpec = createPFrameSpec(specColumnsMap);\n this.columnSpecs = specColumnsMap;\n\n try {\n const makeLocalBlobId = (blob: TreeEntry): PFrameInternal.PFrameBlobId => {\n const localBlob = this.localBlobProvider.acquire(blob);\n this.localBlobs.push(localBlob);\n return localBlob.key;\n };\n\n const makeRemoteBlobId = (blob: TreeEntry): PFrameInternal.PFrameBlobId => {\n const remoteBlob = this.remoteBlobProvider.acquire(blob);\n this.remoteBlobs.push(remoteBlob);\n return `${remoteBlob.key}${PFrameInternal.ParquetExtension}` as PFrameInternal.PFrameBlobId;\n };\n\n const mapColumnData = (\n data: PFrameInternal.DataInfo<TreeEntry>,\n ): PFrameInternal.DataInfo<PFrameInternal.PFrameBlobId> => {\n switch (data.type) {\n case \"Json\":\n return { ...data };\n case \"JsonPartitioned\":\n return {\n ...data,\n parts: mapValues(data.parts, makeLocalBlobId),\n };\n case \"BinaryPartitioned\":\n return {\n ...data,\n parts: mapValues(data.parts, (v) => ({\n index: makeLocalBlobId(v.index),\n values: makeLocalBlobId(v.values),\n })),\n };\n case \"ParquetPartitioned\":\n return {\n ...data,\n parts: mapValues(data.parts, (v) => ({\n ...v,\n data: makeRemoteBlobId(v.data),\n })),\n };\n default:\n assertNever(data);\n }\n };\n\n const jsonifiedColumns = columns.map((column) => ({\n ...column,\n data: mapColumnData(column.data),\n }));\n\n const pFrameData = PFrameFactory.createPFrame({ frameId, spillPath: this.spillPath, logger });\n try {\n pFrameData.setDataSource({\n ...this.localBlobProvider.makeDataSource(this.disposeSignal),\n parquetServer: this.remoteBlobProvider.httpServerInfo(),\n });\n\n this.pFrameDataPromise = pFrameData\n .addColumns(\n jsonifiedColumns.map((c) => ({\n id: c.id,\n data: {\n ...c.data,\n typeSpec: {\n axes: c.spec.axesSpec.map((a) => a.type),\n column: c.spec.valueType,\n },\n },\n })),\n { signal: this.disposeSignal },\n )\n .then(() => pFrameData)\n .catch((err: unknown) => {\n this.dispose();\n pFrameData.dispose();\n const error = new PFrameDriverError(\"PFrame creation failed asynchronously\");\n error.cause = new Error(\n `PFrame cannot be created from columns: ${JSON.stringify(jsonifiedColumns)}`,\n { cause: ensureError(err) },\n );\n throw error;\n });\n } catch (err: unknown) {\n // setDataSource / addColumns threw synchronously before\n // pFrameDataPromise was assigned — dispose the addon's pFrameData\n // explicitly (the dispose() path can't reach it yet).\n pFrameData.dispose();\n throw err;\n }\n } catch (err: unknown) {\n // Release everything allocated so far in this constructor:\n // acquired blobs, the WASM spec frame, and the abort signal.\n this.abortController.abort();\n this.localBlobs.forEach((entry) => entry.unref());\n this.remoteBlobs.forEach((entry) => entry.unref());\n this.pFrameSpec[Symbol.dispose]();\n const error = new PFrameDriverError(\"PFrame creation failed synchronously\");\n error.cause = new Error(`PFrame cannot be created from columns: ${JSON.stringify(columns)}`, {\n cause: ensureError(err),\n });\n throw error;\n }\n }\n\n public get disposeSignal(): AbortSignal {\n return this.abortController.signal;\n }\n\n private dispose(): void {\n this.abortController.abort();\n this.localBlobs.forEach((entry) => entry.unref());\n this.remoteBlobs.forEach((entry) => entry.unref());\n this.pFrameSpec[Symbol.dispose]();\n void this.pFrameDataPromise\n .then((pFrameData) => pFrameData.dispose())\n .catch(() => {\n /* mute error */\n });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n}\n\nexport class PFramePool<TreeEntry extends JsonSerializable> extends RefCountPoolBase<\n PColumn<PFrameInternal.DataInfo<TreeEntry>>[],\n PFrameHandle,\n PFrameHolder<TreeEntry>\n> {\n constructor(\n private readonly localBlobProvider: LocalBlobProvider<TreeEntry>,\n private readonly remoteBlobProvider: RemoteBlobProvider<TreeEntry>,\n private readonly logger: PFrameInternal.Logger,\n private readonly spillPath: string,\n ) {\n super();\n }\n\n protected calculateParamsKey(\n params: PColumn<PFrameInternal.DataInfo<TreeEntry>>[],\n ): PFrameHandle {\n return stableKeyFromPFrameData(params);\n }\n\n protected createNewResource(\n params: PColumn<PFrameInternal.DataInfo<TreeEntry>>[],\n key: PFrameHandle,\n ): PFrameHolder<TreeEntry> {\n if (logPFrames()) {\n this.logger(\n \"info\",\n `PFrame creation (pFrameHandle = ${key}): ` + `${JSON.stringify(params, bigintReplacer)}`,\n );\n }\n return new PFrameHolder(\n key,\n this.localBlobProvider,\n this.remoteBlobProvider,\n this.logger,\n this.spillPath,\n params,\n );\n }\n\n public getByKey(key: PFrameHandle): PFrameHolder<TreeEntry> {\n const resource = super.tryGetByKey(key);\n if (!resource) {\n const error = new PFrameDriverError(`Invalid PFrame handle`);\n error.cause = new Error(`PFrame with handle ${key} not found`);\n throw error;\n }\n return resource;\n }\n}\n\nfunction stableKeyFromPFrameData<TreeEntry extends JsonSerializable>(\n data: PColumn<PFrameInternal.DataInfo<TreeEntry>>[],\n): PFrameHandle {\n const orderedData = [...data].map((column) =>\n mapPObjectData(column, (r) => {\n let result: {\n type: string;\n keyLength: number;\n payload: {\n key: string;\n value: null | number | string | [string, string];\n }[];\n };\n const type = r.type;\n switch (type) {\n case \"Json\":\n result = {\n type: r.type,\n keyLength: r.keyLength,\n payload: Object.entries(r.data).map(([part, value]) => ({\n key: part,\n value,\n })),\n };\n break;\n case \"JsonPartitioned\":\n result = {\n type: r.type,\n keyLength: r.partitionKeyLength,\n payload: Object.entries(r.parts).map(([part, info]) => ({\n key: part,\n value: canonicalizeJson(info),\n })),\n };\n break;\n case \"BinaryPartitioned\":\n result = {\n type: r.type,\n keyLength: r.partitionKeyLength,\n payload: Object.entries(r.parts).map(([part, info]) => ({\n key: part,\n value: [canonicalizeJson(info.index), canonicalizeJson(info.values)] as const,\n })),\n };\n break;\n case \"ParquetPartitioned\":\n result = {\n type: r.type,\n keyLength: r.partitionKeyLength,\n payload: Object.entries(r.parts).map(([part, info]) => ({\n key: part,\n value:\n info.dataDigest ||\n ([\n canonicalizeJson(info.data),\n JSON.stringify({ axes: info.axes, column: info.column }),\n ] as const),\n })),\n };\n break;\n default:\n throw new PFrameDriverError(\n `unsupported resource type: ${JSON.stringify(type satisfies never)}`,\n );\n }\n result.payload.sort((lhs, rhs) => (lhs.key < rhs.key ? -1 : 1));\n return result;\n }),\n );\n orderedData.sort((lhs, rhs) => (lhs.id < rhs.id ? -1 : 1));\n return hashJson(orderedData) as string as PFrameHandle;\n}\n"],"mappings":";;;;;;;;AAgCA,IAAa,eAAb,MAAoF;CAgB/D;CACA;CAEA;CAlBnB;;;;;;CAMA;CACA;CACA,kBAAmC,IAAI,gBAAgB;CAEvD,aAAwE,CAAC;CACzE,cAAyE,CAAC;CAE1E,YACE,SACA,mBACA,oBACA,QACA,WACA,SACA;EALiB,KAAA,oBAAA;EACA,KAAA,qBAAA;EAEA,KAAA,YAAA;EAGjB,MAAM,aAAa,IAAI,IAAI,OAAO,OAAO,SAAS,CAAC;EACnD,MAAM,iBAAiD,OAAO,OAAO,IAAI;EACzE,KAAK,MAAM,KAAK,SACd,IAAI,WAAW,IAAI,EAAE,KAAK,SAAS,GACjC,eAAe,EAAE,MAAM,yBAAyB,EAAE,IAAI;EAG1D,KAAK,aAAaA,aAAiB,cAAc;EACjD,KAAK,cAAc;EAEnB,IAAI;GACF,MAAM,mBAAmB,SAAiD;IACxE,MAAM,YAAY,KAAK,kBAAkB,QAAQ,IAAI;IACrD,KAAK,WAAW,KAAK,SAAS;IAC9B,OAAO,UAAU;GACnB;GAEA,MAAM,oBAAoB,SAAiD;IACzE,MAAM,aAAa,KAAK,mBAAmB,QAAQ,IAAI;IACvD,KAAK,YAAY,KAAK,UAAU;IAChC,OAAO,GAAG,WAAW,MAAM,eAAe;GAC5C;GAEA,MAAM,iBACJ,SACyD;IACzD,QAAQ,KAAK,MAAb;KACE,KAAK,QACH,OAAO,EAAE,GAAG,KAAK;KACnB,KAAK,mBACH,OAAO;MACL,GAAG;MACH,OAAO,UAAU,KAAK,OAAO,eAAe;KAC9C;KACF,KAAK,qBACH,OAAO;MACL,GAAG;MACH,OAAO,UAAU,KAAK,QAAQ,OAAO;OACnC,OAAO,gBAAgB,EAAE,KAAK;OAC9B,QAAQ,gBAAgB,EAAE,MAAM;MAClC,EAAE;KACJ;KACF,KAAK,sBACH,OAAO;MACL,GAAG;MACH,OAAO,UAAU,KAAK,QAAQ,OAAO;OACnC,GAAG;OACH,MAAM,iBAAiB,EAAE,IAAI;MAC/B,EAAE;KACJ;KACF,SACE,YAAY,IAAI;IACpB;GACF;GAEA,MAAM,mBAAmB,QAAQ,KAAK,YAAY;IAChD,GAAG;IACH,MAAM,cAAc,OAAO,IAAI;GACjC,EAAE;GAEF,MAAM,aAAa,cAAc,aAAa;IAAE;IAAS,WAAW,KAAK;IAAW;GAAO,CAAC;GAC5F,IAAI;IACF,WAAW,cAAc;KACvB,GAAG,KAAK,kBAAkB,eAAe,KAAK,aAAa;KAC3D,eAAe,KAAK,mBAAmB,eAAe;IACxD,CAAC;IAED,KAAK,oBAAoB,WACtB,WACC,iBAAiB,KAAK,OAAO;KAC3B,IAAI,EAAE;KACN,MAAM;MACJ,GAAG,EAAE;MACL,UAAU;OACR,MAAM,EAAE,KAAK,SAAS,KAAK,MAAM,EAAE,IAAI;OACvC,QAAQ,EAAE,KAAK;MACjB;KACF;IACF,EAAE,GACF,EAAE,QAAQ,KAAK,cAAc,CAC/B,CAAC,CACA,WAAW,UAAU,CAAC,CACtB,OAAO,QAAiB;KACvB,KAAK,QAAQ;KACb,WAAW,QAAQ;KACnB,MAAM,QAAQ,IAAI,kBAAkB,uCAAuC;KAC3E,MAAM,QAAQ,IAAI,MAChB,0CAA0C,KAAK,UAAU,gBAAgB,KACzE,EAAE,OAAO,YAAY,GAAG,EAAE,CAC5B;KACA,MAAM;IACR,CAAC;GACL,SAAS,KAAc;IAIrB,WAAW,QAAQ;IACnB,MAAM;GACR;EACF,SAAS,KAAc;GAGrB,KAAK,gBAAgB,MAAM;GAC3B,KAAK,WAAW,SAAS,UAAU,MAAM,MAAM,CAAC;GAChD,KAAK,YAAY,SAAS,UAAU,MAAM,MAAM,CAAC;GACjD,KAAK,WAAW,OAAO,QAAQ,CAAC;GAChC,MAAM,QAAQ,IAAI,kBAAkB,sCAAsC;GAC1E,MAAM,QAAQ,IAAI,MAAM,0CAA0C,KAAK,UAAU,OAAO,KAAK,EAC3F,OAAO,YAAY,GAAG,EACxB,CAAC;GACD,MAAM;EACR;CACF;CAEA,IAAW,gBAA6B;EACtC,OAAO,KAAK,gBAAgB;CAC9B;CAEA,UAAwB;EACtB,KAAK,gBAAgB,MAAM;EAC3B,KAAK,WAAW,SAAS,UAAU,MAAM,MAAM,CAAC;EAChD,KAAK,YAAY,SAAS,UAAU,MAAM,MAAM,CAAC;EACjD,KAAK,WAAW,OAAO,QAAQ,CAAC;EAChC,KAAU,kBACP,MAAM,eAAe,WAAW,QAAQ,CAAC,CAAC,CAC1C,YAAY,CAEb,CAAC;CACL;CAEA,CAAC,OAAO,WAAiB;EACvB,KAAK,QAAQ;CACf;AACF;AAEA,IAAa,aAAb,cAAoE,iBAIlE;CAEmB;CACA;CACA;CACA;CAJnB,YACE,mBACA,oBACA,QACA,WACA;EACA,MAAM;EALW,KAAA,oBAAA;EACA,KAAA,qBAAA;EACA,KAAA,SAAA;EACA,KAAA,YAAA;CAGnB;CAEA,mBACE,QACc;EACd,OAAO,wBAAwB,MAAM;CACvC;CAEA,kBACE,QACA,KACyB;EACzB,IAAI,WAAW,GACb,KAAK,OACH,QACA,mCAAmC,IAAI,KAAU,KAAK,UAAU,QAAQ,cAAc,GACxF;EAEF,OAAO,IAAI,aACT,KACA,KAAK,mBACL,KAAK,oBACL,KAAK,QACL,KAAK,WACL,MACF;CACF;CAEA,SAAgB,KAA4C;EAC1D,MAAM,WAAW,MAAM,YAAY,GAAG;EACtC,IAAI,CAAC,UAAU;GACb,MAAM,QAAQ,IAAI,kBAAkB,uBAAuB;GAC3D,MAAM,wBAAQ,IAAI,MAAM,sBAAsB,IAAI,WAAW;GAC7D,MAAM;EACR;EACA,OAAO;CACT;AACF;AAEA,SAAS,wBACP,MACc;CACd,MAAM,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC,KAAK,WACjC,eAAe,SAAS,MAAM;EAC5B,IAAI;EAQJ,MAAM,OAAO,EAAE;EACf,QAAQ,MAAR;GACE,KAAK;IACH,SAAS;KACP,MAAM,EAAE;KACR,WAAW,EAAE;KACb,SAAS,OAAO,QAAQ,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,YAAY;MACtD,KAAK;MACL;KACF,EAAE;IACJ;IACA;GACF,KAAK;IACH,SAAS;KACP,MAAM,EAAE;KACR,WAAW,EAAE;KACb,SAAS,OAAO,QAAQ,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM,WAAW;MACtD,KAAK;MACL,OAAO,iBAAiB,IAAI;KAC9B,EAAE;IACJ;IACA;GACF,KAAK;IACH,SAAS;KACP,MAAM,EAAE;KACR,WAAW,EAAE;KACb,SAAS,OAAO,QAAQ,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM,WAAW;MACtD,KAAK;MACL,OAAO,CAAC,iBAAiB,KAAK,KAAK,GAAG,iBAAiB,KAAK,MAAM,CAAC;KACrE,EAAE;IACJ;IACA;GACF,KAAK;IACH,SAAS;KACP,MAAM,EAAE;KACR,WAAW,EAAE;KACb,SAAS,OAAO,QAAQ,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM,WAAW;MACtD,KAAK;MACL,OACE,KAAK,cACJ,CACC,iBAAiB,KAAK,IAAI,GAC1B,KAAK,UAAU;OAAE,MAAM,KAAK;OAAM,QAAQ,KAAK;MAAO,CAAC,CACzD;KACJ,EAAE;IACJ;IACA;GACF,SACE,MAAM,IAAI,kBACR,8BAA8B,KAAK,UAAU,IAAoB,GACnE;EACJ;EACA,OAAO,QAAQ,MAAM,KAAK,QAAS,IAAI,MAAM,IAAI,MAAM,KAAK,CAAE;EAC9D,OAAO;CACT,CAAC,CACH;CACA,YAAY,MAAM,KAAK,QAAS,IAAI,KAAK,IAAI,KAAK,KAAK,CAAE;CACzD,OAAO,SAAS,WAAW;AAC7B"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
require("./_virtual/_rolldown/runtime.cjs");
|
|
2
1
|
const require_logging = require("./logging.cjs");
|
|
3
2
|
let lru_cache = require("lru-cache");
|
|
4
3
|
//#region src/ptable_cache_per_frame.ts
|
|
@@ -7,6 +6,8 @@ const PTableCachePerFrameOpsDefaults = {
|
|
|
7
6
|
pFramesCacheMaxSize: 8 * 1024 * 1024 * 1024
|
|
8
7
|
};
|
|
9
8
|
var PTableCachePerFrame = class {
|
|
9
|
+
logger;
|
|
10
|
+
ops;
|
|
10
11
|
perFrame = /* @__PURE__ */ new Map();
|
|
11
12
|
global;
|
|
12
13
|
disposeListeners = /* @__PURE__ */ new Set();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ptable_cache_per_frame.cjs","names":["LRUCache","logPFrames"],"sources":["../src/ptable_cache_per_frame.ts"],"sourcesContent":["import type { PFrameHandle, PTableHandle } from \"@milaboratories/pl-model-common\";\nimport type { PFrameInternal } from \"@milaboratories/pl-model-middle-layer\";\nimport type { PoolEntry } from \"@milaboratories/helpers\";\nimport { LRUCache } from \"lru-cache\";\nimport { logPFrames } from \"./logging\";\nimport type { PTableHolder } from \"./ptable_pool\";\n\nexport type PTableCachePerFrameOps = {\n /** Maximum number of `calculateTableData` results cached for each PFrame */\n pFrameCacheMaxCount: number;\n /**\n * Maximum size of `calculateTableData` results cached for PFrames overall.\n * The limit is soft, as the same table could be materialized with other requests and will not be deleted in such case.\n * Also each table has predecessors, overlapping predecessors will be counted twice, so the effective limit is smaller.\n */\n pFramesCacheMaxSize: number;\n};\n\nexport const PTableCachePerFrameOpsDefaults: PTableCachePerFrameOps = {\n pFrameCacheMaxCount: 18, // SHM trees create 3 PTables per graphic, we want to cache 6 graphics per PFrame\n pFramesCacheMaxSize: 8 * 1024 * 1024 * 1024, // 8 GB, same as blob driver cache (must be at least 2GB)\n};\n\nexport class PTableCachePerFrame {\n private readonly perFrame = new Map<\n PFrameHandle,\n LRUCache<PTableHandle, PoolEntry<PTableHandle, PTableHolder>>\n >();\n private readonly global: LRUCache<PTableHandle, PoolEntry<PTableHandle, PTableHolder>>;\n private readonly disposeListeners = new Set<PTableHandle>();\n\n constructor(\n private readonly logger: PFrameInternal.Logger,\n private readonly ops: PTableCachePerFrameOps,\n ) {\n this.global = new LRUCache<PTableHandle, PoolEntry<PTableHandle, PTableHolder>>({\n maxSize: this.ops.pFramesCacheMaxSize,\n dispose: (resource, key, reason) => {\n if (reason === \"evict\") {\n this.perFrame.get(resource.resource.pFrame)?.delete(key);\n }\n\n if (this.perFrame.get(resource.resource.pFrame)?.size === 0) {\n this.perFrame.delete(resource.resource.pFrame);\n }\n\n resource.unref();\n if (logPFrames()) {\n logger(\"info\", `calculateTableData cache - removed PTable ${key} (reason: ${reason})`);\n }\n },\n });\n }\n\n public cache(resource: PoolEntry<PTableHandle, PTableHolder>, size: number): void {\n const key = resource.key;\n if (logPFrames()) {\n this.logger(\"info\", `calculateTableData cache - added PTable ${key} with size ${size}`);\n }\n\n this.global.set(key, resource, { size: Math.max(size, 1) }); // 1 is minimum size to avoid cache evictions\n\n let perFrame = this.perFrame.get(resource.resource.pFrame);\n if (!perFrame) {\n perFrame = new LRUCache<PTableHandle, PoolEntry<PTableHandle, PTableHolder>>({\n max: this.ops.pFrameCacheMaxCount,\n dispose: (_resource, key, reason) => {\n if (reason === \"evict\") {\n this.global.delete(key);\n }\n },\n });\n this.perFrame.set(resource.resource.pFrame, perFrame);\n }\n perFrame.set(key, resource);\n\n if (!this.disposeListeners.has(key)) {\n const disposeListener = () => {\n this.perFrame.get(resource.resource.pFrame)?.delete(key);\n this.global.delete(key);\n\n this.disposeListeners.delete(key);\n resource.resource.disposeSignal.removeEventListener(\"abort\", disposeListener);\n };\n this.disposeListeners.add(key);\n resource.resource.disposeSignal.addEventListener(\"abort\", disposeListener);\n }\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"ptable_cache_per_frame.cjs","names":["LRUCache","logPFrames"],"sources":["../src/ptable_cache_per_frame.ts"],"sourcesContent":["import type { PFrameHandle, PTableHandle } from \"@milaboratories/pl-model-common\";\nimport type { PFrameInternal } from \"@milaboratories/pl-model-middle-layer\";\nimport type { PoolEntry } from \"@milaboratories/helpers\";\nimport { LRUCache } from \"lru-cache\";\nimport { logPFrames } from \"./logging\";\nimport type { PTableHolder } from \"./ptable_pool\";\n\nexport type PTableCachePerFrameOps = {\n /** Maximum number of `calculateTableData` results cached for each PFrame */\n pFrameCacheMaxCount: number;\n /**\n * Maximum size of `calculateTableData` results cached for PFrames overall.\n * The limit is soft, as the same table could be materialized with other requests and will not be deleted in such case.\n * Also each table has predecessors, overlapping predecessors will be counted twice, so the effective limit is smaller.\n */\n pFramesCacheMaxSize: number;\n};\n\nexport const PTableCachePerFrameOpsDefaults: PTableCachePerFrameOps = {\n pFrameCacheMaxCount: 18, // SHM trees create 3 PTables per graphic, we want to cache 6 graphics per PFrame\n pFramesCacheMaxSize: 8 * 1024 * 1024 * 1024, // 8 GB, same as blob driver cache (must be at least 2GB)\n};\n\nexport class PTableCachePerFrame {\n private readonly perFrame = new Map<\n PFrameHandle,\n LRUCache<PTableHandle, PoolEntry<PTableHandle, PTableHolder>>\n >();\n private readonly global: LRUCache<PTableHandle, PoolEntry<PTableHandle, PTableHolder>>;\n private readonly disposeListeners = new Set<PTableHandle>();\n\n constructor(\n private readonly logger: PFrameInternal.Logger,\n private readonly ops: PTableCachePerFrameOps,\n ) {\n this.global = new LRUCache<PTableHandle, PoolEntry<PTableHandle, PTableHolder>>({\n maxSize: this.ops.pFramesCacheMaxSize,\n dispose: (resource, key, reason) => {\n if (reason === \"evict\") {\n this.perFrame.get(resource.resource.pFrame)?.delete(key);\n }\n\n if (this.perFrame.get(resource.resource.pFrame)?.size === 0) {\n this.perFrame.delete(resource.resource.pFrame);\n }\n\n resource.unref();\n if (logPFrames()) {\n logger(\"info\", `calculateTableData cache - removed PTable ${key} (reason: ${reason})`);\n }\n },\n });\n }\n\n public cache(resource: PoolEntry<PTableHandle, PTableHolder>, size: number): void {\n const key = resource.key;\n if (logPFrames()) {\n this.logger(\"info\", `calculateTableData cache - added PTable ${key} with size ${size}`);\n }\n\n this.global.set(key, resource, { size: Math.max(size, 1) }); // 1 is minimum size to avoid cache evictions\n\n let perFrame = this.perFrame.get(resource.resource.pFrame);\n if (!perFrame) {\n perFrame = new LRUCache<PTableHandle, PoolEntry<PTableHandle, PTableHolder>>({\n max: this.ops.pFrameCacheMaxCount,\n dispose: (_resource, key, reason) => {\n if (reason === \"evict\") {\n this.global.delete(key);\n }\n },\n });\n this.perFrame.set(resource.resource.pFrame, perFrame);\n }\n perFrame.set(key, resource);\n\n if (!this.disposeListeners.has(key)) {\n const disposeListener = () => {\n this.perFrame.get(resource.resource.pFrame)?.delete(key);\n this.global.delete(key);\n\n this.disposeListeners.delete(key);\n resource.resource.disposeSignal.removeEventListener(\"abort\", disposeListener);\n };\n this.disposeListeners.add(key);\n resource.resource.disposeSignal.addEventListener(\"abort\", disposeListener);\n }\n }\n}\n"],"mappings":";;;AAkBA,MAAa,iCAAyD;CACpE,qBAAqB;CACrB,qBAAqB,IAAI,OAAO,OAAO;AACzC;AAEA,IAAa,sBAAb,MAAiC;CASZ;CACA;CATnB,2BAA4B,IAAI,IAG9B;CACF;CACA,mCAAoC,IAAI,IAAkB;CAE1D,YACE,QACA,KACA;EAFiB,KAAA,SAAA;EACA,KAAA,MAAA;EAEjB,KAAK,SAAS,IAAIA,UAAAA,SAA8D;GAC9E,SAAS,KAAK,IAAI;GAClB,UAAU,UAAU,KAAK,WAAW;IAClC,IAAI,WAAW,SACb,KAAK,SAAS,IAAI,SAAS,SAAS,MAAM,CAAC,EAAE,OAAO,GAAG;IAGzD,IAAI,KAAK,SAAS,IAAI,SAAS,SAAS,MAAM,CAAC,EAAE,SAAS,GACxD,KAAK,SAAS,OAAO,SAAS,SAAS,MAAM;IAG/C,SAAS,MAAM;IACf,IAAIC,gBAAAA,WAAW,GACb,OAAO,QAAQ,6CAA6C,IAAI,YAAY,OAAO,EAAE;GAEzF;EACF,CAAC;CACH;CAEA,MAAa,UAAiD,MAAoB;EAChF,MAAM,MAAM,SAAS;EACrB,IAAIA,gBAAAA,WAAW,GACb,KAAK,OAAO,QAAQ,2CAA2C,IAAI,aAAa,MAAM;EAGxF,KAAK,OAAO,IAAI,KAAK,UAAU,EAAE,MAAM,KAAK,IAAI,MAAM,CAAC,EAAE,CAAC;EAE1D,IAAI,WAAW,KAAK,SAAS,IAAI,SAAS,SAAS,MAAM;EACzD,IAAI,CAAC,UAAU;GACb,WAAW,IAAID,UAAAA,SAA8D;IAC3E,KAAK,KAAK,IAAI;IACd,UAAU,WAAW,KAAK,WAAW;KACnC,IAAI,WAAW,SACb,KAAK,OAAO,OAAO,GAAG;IAE1B;GACF,CAAC;GACD,KAAK,SAAS,IAAI,SAAS,SAAS,QAAQ,QAAQ;EACtD;EACA,SAAS,IAAI,KAAK,QAAQ;EAE1B,IAAI,CAAC,KAAK,iBAAiB,IAAI,GAAG,GAAG;GACnC,MAAM,wBAAwB;IAC5B,KAAK,SAAS,IAAI,SAAS,SAAS,MAAM,CAAC,EAAE,OAAO,GAAG;IACvD,KAAK,OAAO,OAAO,GAAG;IAEtB,KAAK,iBAAiB,OAAO,GAAG;IAChC,SAAS,SAAS,cAAc,oBAAoB,SAAS,eAAe;GAC9E;GACA,KAAK,iBAAiB,IAAI,GAAG;GAC7B,SAAS,SAAS,cAAc,iBAAiB,SAAS,eAAe;EAC3E;CACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ptable_cache_per_frame.d.ts","names":[],"sources":["../src/ptable_cache_per_frame.ts"],"mappings":";;;;;KAOY,sBAAA;8EAEV,mBAAA;EAFgC
|
|
1
|
+
{"version":3,"file":"ptable_cache_per_frame.d.ts","names":[],"sources":["../src/ptable_cache_per_frame.ts"],"mappings":";;;;;KAOY,sBAAA;8EAEV,mBAAA;EAFgC;;;AAQb;;EAAnB,mBAAmB;AAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ptable_cache_per_frame.js","names":[],"sources":["../src/ptable_cache_per_frame.ts"],"sourcesContent":["import type { PFrameHandle, PTableHandle } from \"@milaboratories/pl-model-common\";\nimport type { PFrameInternal } from \"@milaboratories/pl-model-middle-layer\";\nimport type { PoolEntry } from \"@milaboratories/helpers\";\nimport { LRUCache } from \"lru-cache\";\nimport { logPFrames } from \"./logging\";\nimport type { PTableHolder } from \"./ptable_pool\";\n\nexport type PTableCachePerFrameOps = {\n /** Maximum number of `calculateTableData` results cached for each PFrame */\n pFrameCacheMaxCount: number;\n /**\n * Maximum size of `calculateTableData` results cached for PFrames overall.\n * The limit is soft, as the same table could be materialized with other requests and will not be deleted in such case.\n * Also each table has predecessors, overlapping predecessors will be counted twice, so the effective limit is smaller.\n */\n pFramesCacheMaxSize: number;\n};\n\nexport const PTableCachePerFrameOpsDefaults: PTableCachePerFrameOps = {\n pFrameCacheMaxCount: 18, // SHM trees create 3 PTables per graphic, we want to cache 6 graphics per PFrame\n pFramesCacheMaxSize: 8 * 1024 * 1024 * 1024, // 8 GB, same as blob driver cache (must be at least 2GB)\n};\n\nexport class PTableCachePerFrame {\n private readonly perFrame = new Map<\n PFrameHandle,\n LRUCache<PTableHandle, PoolEntry<PTableHandle, PTableHolder>>\n >();\n private readonly global: LRUCache<PTableHandle, PoolEntry<PTableHandle, PTableHolder>>;\n private readonly disposeListeners = new Set<PTableHandle>();\n\n constructor(\n private readonly logger: PFrameInternal.Logger,\n private readonly ops: PTableCachePerFrameOps,\n ) {\n this.global = new LRUCache<PTableHandle, PoolEntry<PTableHandle, PTableHolder>>({\n maxSize: this.ops.pFramesCacheMaxSize,\n dispose: (resource, key, reason) => {\n if (reason === \"evict\") {\n this.perFrame.get(resource.resource.pFrame)?.delete(key);\n }\n\n if (this.perFrame.get(resource.resource.pFrame)?.size === 0) {\n this.perFrame.delete(resource.resource.pFrame);\n }\n\n resource.unref();\n if (logPFrames()) {\n logger(\"info\", `calculateTableData cache - removed PTable ${key} (reason: ${reason})`);\n }\n },\n });\n }\n\n public cache(resource: PoolEntry<PTableHandle, PTableHolder>, size: number): void {\n const key = resource.key;\n if (logPFrames()) {\n this.logger(\"info\", `calculateTableData cache - added PTable ${key} with size ${size}`);\n }\n\n this.global.set(key, resource, { size: Math.max(size, 1) }); // 1 is minimum size to avoid cache evictions\n\n let perFrame = this.perFrame.get(resource.resource.pFrame);\n if (!perFrame) {\n perFrame = new LRUCache<PTableHandle, PoolEntry<PTableHandle, PTableHolder>>({\n max: this.ops.pFrameCacheMaxCount,\n dispose: (_resource, key, reason) => {\n if (reason === \"evict\") {\n this.global.delete(key);\n }\n },\n });\n this.perFrame.set(resource.resource.pFrame, perFrame);\n }\n perFrame.set(key, resource);\n\n if (!this.disposeListeners.has(key)) {\n const disposeListener = () => {\n this.perFrame.get(resource.resource.pFrame)?.delete(key);\n this.global.delete(key);\n\n this.disposeListeners.delete(key);\n resource.resource.disposeSignal.removeEventListener(\"abort\", disposeListener);\n };\n this.disposeListeners.add(key);\n resource.resource.disposeSignal.addEventListener(\"abort\", disposeListener);\n }\n }\n}\n"],"mappings":";;;AAkBA,MAAa,iCAAyD;CACpE,qBAAqB;CACrB,qBAAqB,IAAI,OAAO,OAAO;
|
|
1
|
+
{"version":3,"file":"ptable_cache_per_frame.js","names":[],"sources":["../src/ptable_cache_per_frame.ts"],"sourcesContent":["import type { PFrameHandle, PTableHandle } from \"@milaboratories/pl-model-common\";\nimport type { PFrameInternal } from \"@milaboratories/pl-model-middle-layer\";\nimport type { PoolEntry } from \"@milaboratories/helpers\";\nimport { LRUCache } from \"lru-cache\";\nimport { logPFrames } from \"./logging\";\nimport type { PTableHolder } from \"./ptable_pool\";\n\nexport type PTableCachePerFrameOps = {\n /** Maximum number of `calculateTableData` results cached for each PFrame */\n pFrameCacheMaxCount: number;\n /**\n * Maximum size of `calculateTableData` results cached for PFrames overall.\n * The limit is soft, as the same table could be materialized with other requests and will not be deleted in such case.\n * Also each table has predecessors, overlapping predecessors will be counted twice, so the effective limit is smaller.\n */\n pFramesCacheMaxSize: number;\n};\n\nexport const PTableCachePerFrameOpsDefaults: PTableCachePerFrameOps = {\n pFrameCacheMaxCount: 18, // SHM trees create 3 PTables per graphic, we want to cache 6 graphics per PFrame\n pFramesCacheMaxSize: 8 * 1024 * 1024 * 1024, // 8 GB, same as blob driver cache (must be at least 2GB)\n};\n\nexport class PTableCachePerFrame {\n private readonly perFrame = new Map<\n PFrameHandle,\n LRUCache<PTableHandle, PoolEntry<PTableHandle, PTableHolder>>\n >();\n private readonly global: LRUCache<PTableHandle, PoolEntry<PTableHandle, PTableHolder>>;\n private readonly disposeListeners = new Set<PTableHandle>();\n\n constructor(\n private readonly logger: PFrameInternal.Logger,\n private readonly ops: PTableCachePerFrameOps,\n ) {\n this.global = new LRUCache<PTableHandle, PoolEntry<PTableHandle, PTableHolder>>({\n maxSize: this.ops.pFramesCacheMaxSize,\n dispose: (resource, key, reason) => {\n if (reason === \"evict\") {\n this.perFrame.get(resource.resource.pFrame)?.delete(key);\n }\n\n if (this.perFrame.get(resource.resource.pFrame)?.size === 0) {\n this.perFrame.delete(resource.resource.pFrame);\n }\n\n resource.unref();\n if (logPFrames()) {\n logger(\"info\", `calculateTableData cache - removed PTable ${key} (reason: ${reason})`);\n }\n },\n });\n }\n\n public cache(resource: PoolEntry<PTableHandle, PTableHolder>, size: number): void {\n const key = resource.key;\n if (logPFrames()) {\n this.logger(\"info\", `calculateTableData cache - added PTable ${key} with size ${size}`);\n }\n\n this.global.set(key, resource, { size: Math.max(size, 1) }); // 1 is minimum size to avoid cache evictions\n\n let perFrame = this.perFrame.get(resource.resource.pFrame);\n if (!perFrame) {\n perFrame = new LRUCache<PTableHandle, PoolEntry<PTableHandle, PTableHolder>>({\n max: this.ops.pFrameCacheMaxCount,\n dispose: (_resource, key, reason) => {\n if (reason === \"evict\") {\n this.global.delete(key);\n }\n },\n });\n this.perFrame.set(resource.resource.pFrame, perFrame);\n }\n perFrame.set(key, resource);\n\n if (!this.disposeListeners.has(key)) {\n const disposeListener = () => {\n this.perFrame.get(resource.resource.pFrame)?.delete(key);\n this.global.delete(key);\n\n this.disposeListeners.delete(key);\n resource.resource.disposeSignal.removeEventListener(\"abort\", disposeListener);\n };\n this.disposeListeners.add(key);\n resource.resource.disposeSignal.addEventListener(\"abort\", disposeListener);\n }\n }\n}\n"],"mappings":";;;AAkBA,MAAa,iCAAyD;CACpE,qBAAqB;CACrB,qBAAqB,IAAI,OAAO,OAAO;AACzC;AAEA,IAAa,sBAAb,MAAiC;CASZ;CACA;CATnB,2BAA4B,IAAI,IAG9B;CACF;CACA,mCAAoC,IAAI,IAAkB;CAE1D,YACE,QACA,KACA;EAFiB,KAAA,SAAA;EACA,KAAA,MAAA;EAEjB,KAAK,SAAS,IAAI,SAA8D;GAC9E,SAAS,KAAK,IAAI;GAClB,UAAU,UAAU,KAAK,WAAW;IAClC,IAAI,WAAW,SACb,KAAK,SAAS,IAAI,SAAS,SAAS,MAAM,CAAC,EAAE,OAAO,GAAG;IAGzD,IAAI,KAAK,SAAS,IAAI,SAAS,SAAS,MAAM,CAAC,EAAE,SAAS,GACxD,KAAK,SAAS,OAAO,SAAS,SAAS,MAAM;IAG/C,SAAS,MAAM;IACf,IAAI,WAAW,GACb,OAAO,QAAQ,6CAA6C,IAAI,YAAY,OAAO,EAAE;GAEzF;EACF,CAAC;CACH;CAEA,MAAa,UAAiD,MAAoB;EAChF,MAAM,MAAM,SAAS;EACrB,IAAI,WAAW,GACb,KAAK,OAAO,QAAQ,2CAA2C,IAAI,aAAa,MAAM;EAGxF,KAAK,OAAO,IAAI,KAAK,UAAU,EAAE,MAAM,KAAK,IAAI,MAAM,CAAC,EAAE,CAAC;EAE1D,IAAI,WAAW,KAAK,SAAS,IAAI,SAAS,SAAS,MAAM;EACzD,IAAI,CAAC,UAAU;GACb,WAAW,IAAI,SAA8D;IAC3E,KAAK,KAAK,IAAI;IACd,UAAU,WAAW,KAAK,WAAW;KACnC,IAAI,WAAW,SACb,KAAK,OAAO,OAAO,GAAG;IAE1B;GACF,CAAC;GACD,KAAK,SAAS,IAAI,SAAS,SAAS,QAAQ,QAAQ;EACtD;EACA,SAAS,IAAI,KAAK,QAAQ;EAE1B,IAAI,CAAC,KAAK,iBAAiB,IAAI,GAAG,GAAG;GACnC,MAAM,wBAAwB;IAC5B,KAAK,SAAS,IAAI,SAAS,SAAS,MAAM,CAAC,EAAE,OAAO,GAAG;IACvD,KAAK,OAAO,OAAO,GAAG;IAEtB,KAAK,iBAAiB,OAAO,GAAG;IAChC,SAAS,SAAS,cAAc,oBAAoB,SAAS,eAAe;GAC9E;GACA,KAAK,iBAAiB,IAAI,GAAG;GAC7B,SAAS,SAAS,cAAc,iBAAiB,SAAS,eAAe;EAC3E;CACF;AACF"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
require("./_virtual/_rolldown/runtime.cjs");
|
|
2
1
|
const require_logging = require("./logging.cjs");
|
|
3
2
|
let lru_cache = require("lru-cache");
|
|
4
3
|
//#region src/ptable_cache_plain.ts
|
|
5
4
|
const PTableCachePlainOpsDefaults = { pTablesCacheMaxSize: 32 * 1024 * 1024 * 1024 };
|
|
6
5
|
var PTableCachePlain = class {
|
|
6
|
+
logger;
|
|
7
7
|
global;
|
|
8
8
|
disposeListeners = /* @__PURE__ */ new Set();
|
|
9
9
|
constructor(logger, ops) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ptable_cache_plain.cjs","names":["LRUCache","logPFrames"],"sources":["../src/ptable_cache_plain.ts"],"sourcesContent":["import type { PTableHandle } from \"@milaboratories/pl-model-common\";\nimport type { PFrameInternal } from \"@milaboratories/pl-model-middle-layer\";\nimport type { PoolEntry } from \"@milaboratories/helpers\";\nimport { LRUCache } from \"lru-cache\";\nimport { logPFrames } from \"./logging\";\nimport type { PTableHolder } from \"./ptable_pool\";\n\nexport type PTableCachePlainOps = {\n /**\n * Maximum size of `createPTable` results cached on disk.\n * The limit is soft, as the same table could be materialized with other requests and will not be deleted in such case.\n * Also each table has predecessors, overlapping predecessors will be counted twice, so the effective limit is smaller.\n */\n pTablesCacheMaxSize: number;\n};\n\nexport const PTableCachePlainOpsDefaults: PTableCachePlainOps = {\n pTablesCacheMaxSize: 32 * 1024 * 1024 * 1024, // 32 GB (must be at least 8GB)\n};\n\nexport class PTableCachePlain {\n private readonly global: LRUCache<PTableHandle, PoolEntry<PTableHandle, PTableHolder>>;\n private readonly disposeListeners = new Set<PTableHandle>();\n\n constructor(\n private readonly logger: PFrameInternal.Logger,\n ops: PTableCachePlainOps,\n ) {\n this.global = new LRUCache<PTableHandle, PoolEntry<PTableHandle, PTableHolder>>({\n maxSize: ops.pTablesCacheMaxSize,\n dispose: (resource, key, reason) => {\n resource.unref();\n if (logPFrames()) {\n logger(\"info\", `createPTable cache - removed PTable ${key} (reason: ${reason})`);\n }\n },\n });\n }\n\n public cache(\n resource: PoolEntry<PTableHandle, PTableHolder>,\n size: number,\n defDisposeSignal: AbortSignal,\n ): void {\n const key = resource.key;\n if (logPFrames()) {\n this.logger(\"info\", `createPTable cache - added PTable ${key} with size ${size}`);\n }\n\n const status: LRUCache.Status<PoolEntry<PTableHandle, PTableHolder>> = {};\n this.global.set(key, resource, { size: Math.max(size, 1), status }); // 1 is minimum size to avoid cache evictions\n\n if (status.maxEntrySizeExceeded) {\n resource.unref();\n if (logPFrames()) {\n this.logger(\"info\", `createPTable cache - removed PTable ${key} (maxEntrySizeExceeded)`);\n }\n } else {\n if (!this.disposeListeners.has(key)) {\n const disposeListener = () => {\n this.global.delete(key);\n\n this.disposeListeners.delete(key);\n defDisposeSignal.removeEventListener(\"abort\", disposeListener);\n };\n this.disposeListeners.add(key);\n defDisposeSignal.addEventListener(\"abort\", disposeListener);\n }\n }\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"ptable_cache_plain.cjs","names":["LRUCache","logPFrames"],"sources":["../src/ptable_cache_plain.ts"],"sourcesContent":["import type { PTableHandle } from \"@milaboratories/pl-model-common\";\nimport type { PFrameInternal } from \"@milaboratories/pl-model-middle-layer\";\nimport type { PoolEntry } from \"@milaboratories/helpers\";\nimport { LRUCache } from \"lru-cache\";\nimport { logPFrames } from \"./logging\";\nimport type { PTableHolder } from \"./ptable_pool\";\n\nexport type PTableCachePlainOps = {\n /**\n * Maximum size of `createPTable` results cached on disk.\n * The limit is soft, as the same table could be materialized with other requests and will not be deleted in such case.\n * Also each table has predecessors, overlapping predecessors will be counted twice, so the effective limit is smaller.\n */\n pTablesCacheMaxSize: number;\n};\n\nexport const PTableCachePlainOpsDefaults: PTableCachePlainOps = {\n pTablesCacheMaxSize: 32 * 1024 * 1024 * 1024, // 32 GB (must be at least 8GB)\n};\n\nexport class PTableCachePlain {\n private readonly global: LRUCache<PTableHandle, PoolEntry<PTableHandle, PTableHolder>>;\n private readonly disposeListeners = new Set<PTableHandle>();\n\n constructor(\n private readonly logger: PFrameInternal.Logger,\n ops: PTableCachePlainOps,\n ) {\n this.global = new LRUCache<PTableHandle, PoolEntry<PTableHandle, PTableHolder>>({\n maxSize: ops.pTablesCacheMaxSize,\n dispose: (resource, key, reason) => {\n resource.unref();\n if (logPFrames()) {\n logger(\"info\", `createPTable cache - removed PTable ${key} (reason: ${reason})`);\n }\n },\n });\n }\n\n public cache(\n resource: PoolEntry<PTableHandle, PTableHolder>,\n size: number,\n defDisposeSignal: AbortSignal,\n ): void {\n const key = resource.key;\n if (logPFrames()) {\n this.logger(\"info\", `createPTable cache - added PTable ${key} with size ${size}`);\n }\n\n const status: LRUCache.Status<PoolEntry<PTableHandle, PTableHolder>> = {};\n this.global.set(key, resource, { size: Math.max(size, 1), status }); // 1 is minimum size to avoid cache evictions\n\n if (status.maxEntrySizeExceeded) {\n resource.unref();\n if (logPFrames()) {\n this.logger(\"info\", `createPTable cache - removed PTable ${key} (maxEntrySizeExceeded)`);\n }\n } else {\n if (!this.disposeListeners.has(key)) {\n const disposeListener = () => {\n this.global.delete(key);\n\n this.disposeListeners.delete(key);\n defDisposeSignal.removeEventListener(\"abort\", disposeListener);\n };\n this.disposeListeners.add(key);\n defDisposeSignal.addEventListener(\"abort\", disposeListener);\n }\n }\n }\n}\n"],"mappings":";;;AAgBA,MAAa,8BAAmD,EAC9D,qBAAqB,KAAK,OAAO,OAAO,KAC1C;AAEA,IAAa,mBAAb,MAA8B;CAKT;CAJnB;CACA,mCAAoC,IAAI,IAAkB;CAE1D,YACE,QACA,KACA;EAFiB,KAAA,SAAA;EAGjB,KAAK,SAAS,IAAIA,UAAAA,SAA8D;GAC9E,SAAS,IAAI;GACb,UAAU,UAAU,KAAK,WAAW;IAClC,SAAS,MAAM;IACf,IAAIC,gBAAAA,WAAW,GACb,OAAO,QAAQ,uCAAuC,IAAI,YAAY,OAAO,EAAE;GAEnF;EACF,CAAC;CACH;CAEA,MACE,UACA,MACA,kBACM;EACN,MAAM,MAAM,SAAS;EACrB,IAAIA,gBAAAA,WAAW,GACb,KAAK,OAAO,QAAQ,qCAAqC,IAAI,aAAa,MAAM;EAGlF,MAAM,SAAiE,CAAC;EACxE,KAAK,OAAO,IAAI,KAAK,UAAU;GAAE,MAAM,KAAK,IAAI,MAAM,CAAC;GAAG;EAAO,CAAC;EAElE,IAAI,OAAO,sBAAsB;GAC/B,SAAS,MAAM;GACf,IAAIA,gBAAAA,WAAW,GACb,KAAK,OAAO,QAAQ,uCAAuC,IAAI,wBAAwB;EAE3F,OACE,IAAI,CAAC,KAAK,iBAAiB,IAAI,GAAG,GAAG;GACnC,MAAM,wBAAwB;IAC5B,KAAK,OAAO,OAAO,GAAG;IAEtB,KAAK,iBAAiB,OAAO,GAAG;IAChC,iBAAiB,oBAAoB,SAAS,eAAe;GAC/D;GACA,KAAK,iBAAiB,IAAI,GAAG;GAC7B,iBAAiB,iBAAiB,SAAS,eAAe;EAC5D;CAEJ;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ptable_cache_plain.d.ts","names":[],"sources":["../src/ptable_cache_plain.ts"],"mappings":";;;;;KAOY,mBAAA;;AAAZ;;;;EAME,
|
|
1
|
+
{"version":3,"file":"ptable_cache_plain.d.ts","names":[],"sources":["../src/ptable_cache_plain.ts"],"mappings":";;;;;KAOY,mBAAA;;AAAZ;;;;EAME,mBAAmB;AAAA"}
|
|
@@ -3,6 +3,7 @@ import { LRUCache } from "lru-cache";
|
|
|
3
3
|
//#region src/ptable_cache_plain.ts
|
|
4
4
|
const PTableCachePlainOpsDefaults = { pTablesCacheMaxSize: 32 * 1024 * 1024 * 1024 };
|
|
5
5
|
var PTableCachePlain = class {
|
|
6
|
+
logger;
|
|
6
7
|
global;
|
|
7
8
|
disposeListeners = /* @__PURE__ */ new Set();
|
|
8
9
|
constructor(logger, ops) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ptable_cache_plain.js","names":[],"sources":["../src/ptable_cache_plain.ts"],"sourcesContent":["import type { PTableHandle } from \"@milaboratories/pl-model-common\";\nimport type { PFrameInternal } from \"@milaboratories/pl-model-middle-layer\";\nimport type { PoolEntry } from \"@milaboratories/helpers\";\nimport { LRUCache } from \"lru-cache\";\nimport { logPFrames } from \"./logging\";\nimport type { PTableHolder } from \"./ptable_pool\";\n\nexport type PTableCachePlainOps = {\n /**\n * Maximum size of `createPTable` results cached on disk.\n * The limit is soft, as the same table could be materialized with other requests and will not be deleted in such case.\n * Also each table has predecessors, overlapping predecessors will be counted twice, so the effective limit is smaller.\n */\n pTablesCacheMaxSize: number;\n};\n\nexport const PTableCachePlainOpsDefaults: PTableCachePlainOps = {\n pTablesCacheMaxSize: 32 * 1024 * 1024 * 1024, // 32 GB (must be at least 8GB)\n};\n\nexport class PTableCachePlain {\n private readonly global: LRUCache<PTableHandle, PoolEntry<PTableHandle, PTableHolder>>;\n private readonly disposeListeners = new Set<PTableHandle>();\n\n constructor(\n private readonly logger: PFrameInternal.Logger,\n ops: PTableCachePlainOps,\n ) {\n this.global = new LRUCache<PTableHandle, PoolEntry<PTableHandle, PTableHolder>>({\n maxSize: ops.pTablesCacheMaxSize,\n dispose: (resource, key, reason) => {\n resource.unref();\n if (logPFrames()) {\n logger(\"info\", `createPTable cache - removed PTable ${key} (reason: ${reason})`);\n }\n },\n });\n }\n\n public cache(\n resource: PoolEntry<PTableHandle, PTableHolder>,\n size: number,\n defDisposeSignal: AbortSignal,\n ): void {\n const key = resource.key;\n if (logPFrames()) {\n this.logger(\"info\", `createPTable cache - added PTable ${key} with size ${size}`);\n }\n\n const status: LRUCache.Status<PoolEntry<PTableHandle, PTableHolder>> = {};\n this.global.set(key, resource, { size: Math.max(size, 1), status }); // 1 is minimum size to avoid cache evictions\n\n if (status.maxEntrySizeExceeded) {\n resource.unref();\n if (logPFrames()) {\n this.logger(\"info\", `createPTable cache - removed PTable ${key} (maxEntrySizeExceeded)`);\n }\n } else {\n if (!this.disposeListeners.has(key)) {\n const disposeListener = () => {\n this.global.delete(key);\n\n this.disposeListeners.delete(key);\n defDisposeSignal.removeEventListener(\"abort\", disposeListener);\n };\n this.disposeListeners.add(key);\n defDisposeSignal.addEventListener(\"abort\", disposeListener);\n }\n }\n }\n}\n"],"mappings":";;;AAgBA,MAAa,8BAAmD,EAC9D,qBAAqB,KAAK,OAAO,OAAO,
|
|
1
|
+
{"version":3,"file":"ptable_cache_plain.js","names":[],"sources":["../src/ptable_cache_plain.ts"],"sourcesContent":["import type { PTableHandle } from \"@milaboratories/pl-model-common\";\nimport type { PFrameInternal } from \"@milaboratories/pl-model-middle-layer\";\nimport type { PoolEntry } from \"@milaboratories/helpers\";\nimport { LRUCache } from \"lru-cache\";\nimport { logPFrames } from \"./logging\";\nimport type { PTableHolder } from \"./ptable_pool\";\n\nexport type PTableCachePlainOps = {\n /**\n * Maximum size of `createPTable` results cached on disk.\n * The limit is soft, as the same table could be materialized with other requests and will not be deleted in such case.\n * Also each table has predecessors, overlapping predecessors will be counted twice, so the effective limit is smaller.\n */\n pTablesCacheMaxSize: number;\n};\n\nexport const PTableCachePlainOpsDefaults: PTableCachePlainOps = {\n pTablesCacheMaxSize: 32 * 1024 * 1024 * 1024, // 32 GB (must be at least 8GB)\n};\n\nexport class PTableCachePlain {\n private readonly global: LRUCache<PTableHandle, PoolEntry<PTableHandle, PTableHolder>>;\n private readonly disposeListeners = new Set<PTableHandle>();\n\n constructor(\n private readonly logger: PFrameInternal.Logger,\n ops: PTableCachePlainOps,\n ) {\n this.global = new LRUCache<PTableHandle, PoolEntry<PTableHandle, PTableHolder>>({\n maxSize: ops.pTablesCacheMaxSize,\n dispose: (resource, key, reason) => {\n resource.unref();\n if (logPFrames()) {\n logger(\"info\", `createPTable cache - removed PTable ${key} (reason: ${reason})`);\n }\n },\n });\n }\n\n public cache(\n resource: PoolEntry<PTableHandle, PTableHolder>,\n size: number,\n defDisposeSignal: AbortSignal,\n ): void {\n const key = resource.key;\n if (logPFrames()) {\n this.logger(\"info\", `createPTable cache - added PTable ${key} with size ${size}`);\n }\n\n const status: LRUCache.Status<PoolEntry<PTableHandle, PTableHolder>> = {};\n this.global.set(key, resource, { size: Math.max(size, 1), status }); // 1 is minimum size to avoid cache evictions\n\n if (status.maxEntrySizeExceeded) {\n resource.unref();\n if (logPFrames()) {\n this.logger(\"info\", `createPTable cache - removed PTable ${key} (maxEntrySizeExceeded)`);\n }\n } else {\n if (!this.disposeListeners.has(key)) {\n const disposeListener = () => {\n this.global.delete(key);\n\n this.disposeListeners.delete(key);\n defDisposeSignal.removeEventListener(\"abort\", disposeListener);\n };\n this.disposeListeners.add(key);\n defDisposeSignal.addEventListener(\"abort\", disposeListener);\n }\n }\n }\n}\n"],"mappings":";;;AAgBA,MAAa,8BAAmD,EAC9D,qBAAqB,KAAK,OAAO,OAAO,KAC1C;AAEA,IAAa,mBAAb,MAA8B;CAKT;CAJnB;CACA,mCAAoC,IAAI,IAAkB;CAE1D,YACE,QACA,KACA;EAFiB,KAAA,SAAA;EAGjB,KAAK,SAAS,IAAI,SAA8D;GAC9E,SAAS,IAAI;GACb,UAAU,UAAU,KAAK,WAAW;IAClC,SAAS,MAAM;IACf,IAAI,WAAW,GACb,OAAO,QAAQ,uCAAuC,IAAI,YAAY,OAAO,EAAE;GAEnF;EACF,CAAC;CACH;CAEA,MACE,UACA,MACA,kBACM;EACN,MAAM,MAAM,SAAS;EACrB,IAAI,WAAW,GACb,KAAK,OAAO,QAAQ,qCAAqC,IAAI,aAAa,MAAM;EAGlF,MAAM,SAAiE,CAAC;EACxE,KAAK,OAAO,IAAI,KAAK,UAAU;GAAE,MAAM,KAAK,IAAI,MAAM,CAAC;GAAG;EAAO,CAAC;EAElE,IAAI,OAAO,sBAAsB;GAC/B,SAAS,MAAM;GACf,IAAI,WAAW,GACb,KAAK,OAAO,QAAQ,uCAAuC,IAAI,wBAAwB;EAE3F,OACE,IAAI,CAAC,KAAK,iBAAiB,IAAI,GAAG,GAAG;GACnC,MAAM,wBAAwB;IAC5B,KAAK,OAAO,OAAO,GAAG;IAEtB,KAAK,iBAAiB,OAAO,GAAG;IAChC,iBAAiB,oBAAoB,SAAS,eAAe;GAC/D;GACA,KAAK,iBAAiB,IAAI,GAAG;GAC7B,iBAAiB,iBAAiB,SAAS,eAAe;EAC5D;CAEJ;AACF"}
|