@milaboratories/pf-driver 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +1 -0
  2. package/dist/__external/.pnpm/@rollup_plugin-typescript@12.1.4_rollup@4.52.4_tslib@2.7.0_typescript@5.6.3/__external/tslib/tslib.es6.cjs +77 -0
  3. package/dist/__external/.pnpm/@rollup_plugin-typescript@12.1.4_rollup@4.52.4_tslib@2.7.0_typescript@5.6.3/__external/tslib/tslib.es6.cjs.map +1 -0
  4. package/dist/__external/.pnpm/@rollup_plugin-typescript@12.1.4_rollup@4.52.4_tslib@2.7.0_typescript@5.6.3/__external/tslib/tslib.es6.js +74 -0
  5. package/dist/__external/.pnpm/@rollup_plugin-typescript@12.1.4_rollup@4.52.4_tslib@2.7.0_typescript@5.6.3/__external/tslib/tslib.es6.js.map +1 -0
  6. package/dist/data_info_helpers.cjs +21 -0
  7. package/dist/data_info_helpers.cjs.map +1 -0
  8. package/dist/data_info_helpers.d.ts +3 -0
  9. package/dist/data_info_helpers.d.ts.map +1 -0
  10. package/dist/data_info_helpers.js +19 -0
  11. package/dist/data_info_helpers.js.map +1 -0
  12. package/dist/driver_decl.d.ts +38 -0
  13. package/dist/driver_decl.d.ts.map +1 -0
  14. package/dist/driver_double.cjs +98 -0
  15. package/dist/driver_double.cjs.map +1 -0
  16. package/dist/driver_double.d.ts +12 -0
  17. package/dist/driver_double.d.ts.map +1 -0
  18. package/dist/driver_double.js +95 -0
  19. package/dist/driver_double.js.map +1 -0
  20. package/dist/driver_impl.cjs +378 -0
  21. package/dist/driver_impl.cjs.map +1 -0
  22. package/dist/driver_impl.d.ts +54 -0
  23. package/dist/driver_impl.d.ts.map +1 -0
  24. package/dist/driver_impl.js +375 -0
  25. package/dist/driver_impl.js.map +1 -0
  26. package/dist/index.cjs +14 -0
  27. package/dist/index.cjs.map +1 -0
  28. package/dist/index.d.ts +5 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +4 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/logging.cjs +9 -0
  33. package/dist/logging.cjs.map +1 -0
  34. package/dist/logging.d.ts +2 -0
  35. package/dist/logging.d.ts.map +1 -0
  36. package/dist/logging.js +7 -0
  37. package/dist/logging.js.map +1 -0
  38. package/dist/pframe_pool.cjs +196 -0
  39. package/dist/pframe_pool.cjs.map +1 -0
  40. package/dist/pframe_pool.d.ts +35 -0
  41. package/dist/pframe_pool.d.ts.map +1 -0
  42. package/dist/pframe_pool.js +193 -0
  43. package/dist/pframe_pool.js.map +1 -0
  44. package/dist/ptable_cache_per_frame.cjs +69 -0
  45. package/dist/ptable_cache_per_frame.cjs.map +1 -0
  46. package/dist/ptable_cache_per_frame.d.ts +25 -0
  47. package/dist/ptable_cache_per_frame.d.ts.map +1 -0
  48. package/dist/ptable_cache_per_frame.js +66 -0
  49. package/dist/ptable_cache_per_frame.js.map +1 -0
  50. package/dist/ptable_cache_plain.cjs +54 -0
  51. package/dist/ptable_cache_plain.cjs.map +1 -0
  52. package/dist/ptable_cache_plain.d.ts +21 -0
  53. package/dist/ptable_cache_plain.d.ts.map +1 -0
  54. package/dist/ptable_cache_plain.js +51 -0
  55. package/dist/ptable_cache_plain.js.map +1 -0
  56. package/dist/ptable_def_pool.cjs +53 -0
  57. package/dist/ptable_def_pool.cjs.map +1 -0
  58. package/dist/ptable_def_pool.d.ts +21 -0
  59. package/dist/ptable_def_pool.d.ts.map +1 -0
  60. package/dist/ptable_def_pool.js +50 -0
  61. package/dist/ptable_def_pool.js.map +1 -0
  62. package/dist/ptable_pool.cjs +167 -0
  63. package/dist/ptable_pool.cjs.map +1 -0
  64. package/dist/ptable_pool.d.ts +26 -0
  65. package/dist/ptable_pool.d.ts.map +1 -0
  66. package/dist/ptable_pool.js +164 -0
  67. package/dist/ptable_pool.js.map +1 -0
  68. package/dist/ptable_shared.cjs +10 -0
  69. package/dist/ptable_shared.cjs.map +1 -0
  70. package/dist/ptable_shared.d.ts +7 -0
  71. package/dist/ptable_shared.d.ts.map +1 -0
  72. package/dist/ptable_shared.js +8 -0
  73. package/dist/ptable_shared.js.map +1 -0
  74. package/package.json +54 -0
  75. package/src/data_info_helpers.ts +26 -0
  76. package/src/driver_decl.ts +82 -0
  77. package/src/driver_double.test.ts +135 -0
  78. package/src/driver_double.ts +134 -0
  79. package/src/driver_impl.ts +535 -0
  80. package/src/index.ts +4 -0
  81. package/src/logging.ts +5 -0
  82. package/src/pframe_pool.ts +257 -0
  83. package/src/ptable_cache_per_frame.ts +86 -0
  84. package/src/ptable_cache_plain.ts +67 -0
  85. package/src/ptable_def_pool.ts +50 -0
  86. package/src/ptable_pool.ts +187 -0
  87. package/src/ptable_shared.ts +11 -0
@@ -0,0 +1,196 @@
1
+ 'use strict';
2
+
3
+ var model = require('@platforma-sdk/model');
4
+ var plModelMiddleLayer = require('@milaboratories/pl-model-middle-layer');
5
+ var tsHelpers = require('@milaboratories/ts-helpers');
6
+ var pframesRsNode = require('@milaboratories/pframes-rs-node');
7
+ var esToolkit = require('es-toolkit');
8
+ var logging = require('./logging.cjs');
9
+
10
+ class PFrameHolder {
11
+ localBlobProvider;
12
+ remoteBlobProvider;
13
+ spillPath;
14
+ pFramePromise;
15
+ abortController = new AbortController();
16
+ localBlobs = [];
17
+ remoteBlobs = [];
18
+ constructor(localBlobProvider, remoteBlobProvider, logger, spillPath, columns) {
19
+ this.localBlobProvider = localBlobProvider;
20
+ this.remoteBlobProvider = remoteBlobProvider;
21
+ this.spillPath = spillPath;
22
+ const makeLocalBlobId = (blob) => {
23
+ const localBlob = this.localBlobProvider.acquire(blob);
24
+ this.localBlobs.push(localBlob);
25
+ return localBlob.key;
26
+ };
27
+ const makeRemoteBlobId = (blob) => {
28
+ const remoteBlob = this.remoteBlobProvider.acquire(blob);
29
+ this.remoteBlobs.push(remoteBlob);
30
+ return `${remoteBlob.key}${plModelMiddleLayer.PFrameInternal.ParquetExtension}`;
31
+ };
32
+ const mapColumnData = (data) => {
33
+ switch (data.type) {
34
+ case 'Json':
35
+ return { ...data };
36
+ case 'JsonPartitioned':
37
+ return {
38
+ ...data,
39
+ parts: esToolkit.mapValues(data.parts, makeLocalBlobId),
40
+ };
41
+ case 'BinaryPartitioned':
42
+ return {
43
+ ...data,
44
+ parts: esToolkit.mapValues(data.parts, (v) => ({
45
+ index: makeLocalBlobId(v.index),
46
+ values: makeLocalBlobId(v.values),
47
+ })),
48
+ };
49
+ case 'ParquetPartitioned':
50
+ return {
51
+ ...data,
52
+ parts: esToolkit.mapValues(data.parts, (v) => ({
53
+ ...v,
54
+ data: makeRemoteBlobId(v.data),
55
+ })),
56
+ };
57
+ default:
58
+ model.assertNever(data);
59
+ }
60
+ };
61
+ const jsonifiedColumns = columns.map((column) => ({
62
+ ...column,
63
+ data: mapColumnData(column.data),
64
+ }));
65
+ try {
66
+ const pFrame = pframesRsNode.PFrameFactory.createPFrame({ spillPath: this.spillPath, logger });
67
+ pFrame.setDataSource({
68
+ ...this.localBlobProvider.makeDataSource(this.disposeSignal),
69
+ parquetServer: this.remoteBlobProvider.httpServerInfo(),
70
+ });
71
+ const promises = [];
72
+ for (const column of jsonifiedColumns) {
73
+ pFrame.addColumnSpec(column.id, column.spec);
74
+ promises.push(pFrame.setColumnData(column.id, column.data, { signal: this.disposeSignal }));
75
+ }
76
+ this.pFramePromise = Promise.all(promises)
77
+ .then(() => pFrame)
78
+ .catch((err) => {
79
+ this.dispose();
80
+ pFrame.dispose();
81
+ throw new model.PFrameDriverError(`PFrame creation failed asynchronously, `
82
+ + `columns: ${JSON.stringify(jsonifiedColumns)}, `
83
+ + `error: ${model.ensureError(err)}`);
84
+ });
85
+ }
86
+ catch (err) {
87
+ throw new model.PFrameDriverError(`PFrame creation failed synchronously, `
88
+ + `columns: ${JSON.stringify(jsonifiedColumns)}, `
89
+ + `error: ${model.ensureError(err)}`);
90
+ }
91
+ }
92
+ get disposeSignal() {
93
+ return this.abortController.signal;
94
+ }
95
+ dispose() {
96
+ this.abortController.abort();
97
+ this.localBlobs.forEach((entry) => entry.unref());
98
+ this.remoteBlobs.forEach((entry) => entry.unref());
99
+ }
100
+ [Symbol.dispose]() {
101
+ this.dispose();
102
+ void this.pFramePromise
103
+ .then((pFrame) => pFrame.dispose())
104
+ .catch(() => { });
105
+ }
106
+ }
107
+ class PFramePool extends tsHelpers.RefCountPoolBase {
108
+ localBlobProvider;
109
+ remoteBlobProvider;
110
+ logger;
111
+ spillPath;
112
+ constructor(localBlobProvider, remoteBlobProvider, logger, spillPath) {
113
+ super();
114
+ this.localBlobProvider = localBlobProvider;
115
+ this.remoteBlobProvider = remoteBlobProvider;
116
+ this.logger = logger;
117
+ this.spillPath = spillPath;
118
+ }
119
+ calculateParamsKey(params) {
120
+ return stableKeyFromPFrameData(params);
121
+ }
122
+ createNewResource(params, key) {
123
+ if (logging.logPFrames()) {
124
+ this.logger('info', `PFrame creation (pFrameHandle = ${key}): `
125
+ + `${JSON.stringify(params, model.bigintReplacer)}`);
126
+ }
127
+ return new PFrameHolder(this.localBlobProvider, this.remoteBlobProvider, this.logger, this.spillPath, params);
128
+ }
129
+ getByKey(key) {
130
+ const resource = super.tryGetByKey(key);
131
+ if (!resource)
132
+ throw new model.PFrameDriverError(`PFrame not found, handle = ${key}`);
133
+ return resource;
134
+ }
135
+ }
136
+ function stableKeyFromPFrameData(data) {
137
+ const orderedData = [...data].map((column) => model.mapPObjectData(column, (r) => {
138
+ let result;
139
+ const type = r.type;
140
+ switch (type) {
141
+ case 'Json':
142
+ result = {
143
+ type: r.type,
144
+ keyLength: r.keyLength,
145
+ payload: Object.entries(r.data).map(([part, value]) => ({
146
+ key: part,
147
+ value,
148
+ })),
149
+ };
150
+ break;
151
+ case 'JsonPartitioned':
152
+ result = {
153
+ type: r.type,
154
+ keyLength: r.partitionKeyLength,
155
+ payload: Object.entries(r.parts).map(([part, info]) => ({
156
+ key: part,
157
+ value: model.canonicalizeJson(info),
158
+ })),
159
+ };
160
+ break;
161
+ case 'BinaryPartitioned':
162
+ result = {
163
+ type: r.type,
164
+ keyLength: r.partitionKeyLength,
165
+ payload: Object.entries(r.parts).map(([part, info]) => ({
166
+ key: part,
167
+ value: [model.canonicalizeJson(info.index), model.canonicalizeJson(info.values)],
168
+ })),
169
+ };
170
+ break;
171
+ case 'ParquetPartitioned':
172
+ result = {
173
+ type: r.type,
174
+ keyLength: r.partitionKeyLength,
175
+ payload: Object.entries(r.parts).map(([part, info]) => ({
176
+ key: part,
177
+ value: info.dataDigest || [
178
+ model.canonicalizeJson(info.data),
179
+ JSON.stringify({ axes: info.axes, column: info.column }),
180
+ ],
181
+ })),
182
+ };
183
+ break;
184
+ default:
185
+ throw new model.PFrameDriverError(`unsupported resource type: ${JSON.stringify(type)}`);
186
+ }
187
+ result.payload.sort((lhs, rhs) => lhs.key < rhs.key ? -1 : 1);
188
+ return result;
189
+ }));
190
+ orderedData.sort((lhs, rhs) => lhs.id < rhs.id ? -1 : 1);
191
+ return tsHelpers.hashJson(orderedData);
192
+ }
193
+
194
+ exports.PFrameHolder = PFrameHolder;
195
+ exports.PFramePool = PFramePool;
196
+ //# sourceMappingURL=pframe_pool.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pframe_pool.cjs","sources":["../src/pframe_pool.ts"],"sourcesContent":["import {\n assertNever,\n bigintReplacer,\n canonicalizeJson,\n ensureError,\n mapPObjectData,\n PFrameDriverError,\n type JsonSerializable,\n type PColumn,\n type PFrameHandle,\n} from '@platforma-sdk/model';\nimport { PFrameInternal } from '@milaboratories/pl-model-middle-layer';\nimport {\n hashJson,\n RefCountPoolBase,\n type PoolEntry,\n} from '@milaboratories/ts-helpers';\nimport { PFrameFactory } from '@milaboratories/pframes-rs-node';\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 pFramePromise: Promise<PFrameInternal.PFrameV12>;\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 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 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}`;\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 try {\n const pFrame = PFrameFactory.createPFrame({ spillPath: this.spillPath, logger });\n pFrame.setDataSource({\n ...this.localBlobProvider.makeDataSource(this.disposeSignal),\n parquetServer: this.remoteBlobProvider.httpServerInfo(),\n });\n\n const promises: Promise<void>[] = [];\n for (const column of jsonifiedColumns) {\n pFrame.addColumnSpec(column.id, column.spec);\n promises.push(pFrame.setColumnData(column.id, column.data, { signal: this.disposeSignal }));\n }\n\n this.pFramePromise = Promise.all(promises)\n .then(() => pFrame)\n .catch((err) => {\n this.dispose();\n pFrame.dispose();\n throw new PFrameDriverError(\n `PFrame creation failed asynchronously, `\n + `columns: ${JSON.stringify(jsonifiedColumns)}, `\n + `error: ${ensureError(err)}`,\n );\n });\n } catch (err: unknown) {\n throw new PFrameDriverError(\n `PFrame creation failed synchronously, `\n + `columns: ${JSON.stringify(jsonifiedColumns)}, `\n + `error: ${ensureError(err)}`,\n );\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 }\n\n [Symbol.dispose](): void {\n this.dispose();\n void this.pFramePromise\n .then((pFrame) => pFrame.dispose())\n .catch(() => { /* mute error */ });\n }\n}\n\nexport class PFramePool<TreeEntry extends JsonSerializable>\n extends RefCountPoolBase<\n PColumn<PFrameInternal.DataInfo<TreeEntry>>[],\n PFrameHandle,\n PFrameHolder<TreeEntry>> {\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(params: PColumn<PFrameInternal.DataInfo<TreeEntry>>[]): 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('info',\n `PFrame creation (pFrameHandle = ${key}): `\n + `${JSON.stringify(params, bigintReplacer)}`,\n );\n }\n return new PFrameHolder(\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) throw new PFrameDriverError(`PFrame not found, handle = ${key}`);\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: info.dataDigest || [\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(`unsupported resource type: ${JSON.stringify(type satisfies never)}`);\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"],"names":["PFrameInternal","mapValues","assertNever","PFrameFactory","PFrameDriverError","ensureError","RefCountPoolBase","logPFrames","bigintReplacer","mapPObjectData","canonicalizeJson","hashJson"],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import { type JsonSerializable, type PColumn, type PFrameHandle } from '@platforma-sdk/model';
2
+ import { PFrameInternal } from '@milaboratories/pl-model-middle-layer';
3
+ import { RefCountPoolBase, type PoolEntry } from '@milaboratories/ts-helpers';
4
+ export interface LocalBlobProvider<TreeEntry extends JsonSerializable> {
5
+ acquire(params: TreeEntry): PoolEntry<PFrameInternal.PFrameBlobId>;
6
+ makeDataSource(signal: AbortSignal): Omit<PFrameInternal.PFrameDataSourceV2, 'parquetServer'>;
7
+ }
8
+ export interface RemoteBlobProvider<TreeEntry extends JsonSerializable> {
9
+ acquire(params: TreeEntry): PoolEntry<PFrameInternal.PFrameBlobId>;
10
+ httpServerInfo(): PFrameInternal.HttpServerInfo;
11
+ }
12
+ export declare class PFrameHolder<TreeEntry extends JsonSerializable> implements Disposable {
13
+ private readonly localBlobProvider;
14
+ private readonly remoteBlobProvider;
15
+ private readonly spillPath;
16
+ readonly pFramePromise: Promise<PFrameInternal.PFrameV12>;
17
+ private readonly abortController;
18
+ private readonly localBlobs;
19
+ private readonly remoteBlobs;
20
+ constructor(localBlobProvider: LocalBlobProvider<TreeEntry>, remoteBlobProvider: RemoteBlobProvider<TreeEntry>, logger: PFrameInternal.Logger, spillPath: string, columns: PColumn<PFrameInternal.DataInfo<TreeEntry>>[]);
21
+ get disposeSignal(): AbortSignal;
22
+ private dispose;
23
+ [Symbol.dispose](): void;
24
+ }
25
+ export declare class PFramePool<TreeEntry extends JsonSerializable> extends RefCountPoolBase<PColumn<PFrameInternal.DataInfo<TreeEntry>>[], PFrameHandle, PFrameHolder<TreeEntry>> {
26
+ private readonly localBlobProvider;
27
+ private readonly remoteBlobProvider;
28
+ private readonly logger;
29
+ private readonly spillPath;
30
+ constructor(localBlobProvider: LocalBlobProvider<TreeEntry>, remoteBlobProvider: RemoteBlobProvider<TreeEntry>, logger: PFrameInternal.Logger, spillPath: string);
31
+ protected calculateParamsKey(params: PColumn<PFrameInternal.DataInfo<TreeEntry>>[]): PFrameHandle;
32
+ protected createNewResource(params: PColumn<PFrameInternal.DataInfo<TreeEntry>>[], key: PFrameHandle): PFrameHolder<TreeEntry>;
33
+ getByKey(key: PFrameHandle): PFrameHolder<TreeEntry>;
34
+ }
35
+ //# sourceMappingURL=pframe_pool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pframe_pool.d.ts","sourceRoot":"","sources":["../src/pframe_pool.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,gBAAgB,EACrB,KAAK,OAAO,EACZ,KAAK,YAAY,EAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AACvE,OAAO,EAEL,gBAAgB,EAChB,KAAK,SAAS,EACf,MAAM,4BAA4B,CAAC;AAKpC,MAAM,WAAW,iBAAiB,CAAC,SAAS,SAAS,gBAAgB;IACnE,OAAO,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;IACnE,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC;CAC/F;AAED,MAAM,WAAW,kBAAkB,CAAC,SAAS,SAAS,gBAAgB;IACpE,OAAO,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;IACnE,cAAc,IAAI,cAAc,CAAC,cAAc,CAAC;CACjD;AAED,qBAAa,YAAY,CAAC,SAAS,SAAS,gBAAgB,CAAE,YAAW,UAAU;IAQ/E,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IAEnC,OAAO,CAAC,QAAQ,CAAC,SAAS;IAV5B,SAAgB,aAAa,EAAE,OAAO,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IACjE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAyB;IAEzD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgD;IAC3E,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAgD;gBAGzD,iBAAiB,EAAE,iBAAiB,CAAC,SAAS,CAAC,EAC/C,kBAAkB,EAAE,kBAAkB,CAAC,SAAS,CAAC,EAClE,MAAM,EAAE,cAAc,CAAC,MAAM,EACZ,SAAS,EAAE,MAAM,EAClC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE;IAoFxD,IAAW,aAAa,IAAI,WAAW,CAEtC;IAED,OAAO,CAAC,OAAO;IAMf,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI;CAMzB;AAED,qBAAa,UAAU,CAAC,SAAS,SAAS,gBAAgB,CACxD,SAAQ,gBAAgB,CACtB,OAAO,CAAC,cAAc,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,EAC7C,YAAY,EACZ,YAAY,CAAC,SAAS,CAAC,CAAC;IAExB,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAHT,iBAAiB,EAAE,iBAAiB,CAAC,SAAS,CAAC,EAC/C,kBAAkB,EAAE,kBAAkB,CAAC,SAAS,CAAC,EACjD,MAAM,EAAE,cAAc,CAAC,MAAM,EAC7B,SAAS,EAAE,MAAM;IAKpC,SAAS,CAAC,kBAAkB,CAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,YAAY;IAIjG,SAAS,CAAC,iBAAiB,CACzB,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,EACrD,GAAG,EAAE,YAAY,GAChB,YAAY,CAAC,SAAS,CAAC;IAgBnB,QAAQ,CAAC,GAAG,EAAE,YAAY,GAAG,YAAY,CAAC,SAAS,CAAC;CAK5D"}
@@ -0,0 +1,193 @@
1
+ import { bigintReplacer, PFrameDriverError, mapPObjectData, canonicalizeJson, ensureError, assertNever } from '@platforma-sdk/model';
2
+ import { PFrameInternal } from '@milaboratories/pl-model-middle-layer';
3
+ import { RefCountPoolBase, hashJson } from '@milaboratories/ts-helpers';
4
+ import { PFrameFactory } from '@milaboratories/pframes-rs-node';
5
+ import { mapValues } from 'es-toolkit';
6
+ import { logPFrames } from './logging.js';
7
+
8
+ class PFrameHolder {
9
+ localBlobProvider;
10
+ remoteBlobProvider;
11
+ spillPath;
12
+ pFramePromise;
13
+ abortController = new AbortController();
14
+ localBlobs = [];
15
+ remoteBlobs = [];
16
+ constructor(localBlobProvider, remoteBlobProvider, logger, spillPath, columns) {
17
+ this.localBlobProvider = localBlobProvider;
18
+ this.remoteBlobProvider = remoteBlobProvider;
19
+ this.spillPath = spillPath;
20
+ const makeLocalBlobId = (blob) => {
21
+ const localBlob = this.localBlobProvider.acquire(blob);
22
+ this.localBlobs.push(localBlob);
23
+ return localBlob.key;
24
+ };
25
+ const makeRemoteBlobId = (blob) => {
26
+ const remoteBlob = this.remoteBlobProvider.acquire(blob);
27
+ this.remoteBlobs.push(remoteBlob);
28
+ return `${remoteBlob.key}${PFrameInternal.ParquetExtension}`;
29
+ };
30
+ const mapColumnData = (data) => {
31
+ switch (data.type) {
32
+ case 'Json':
33
+ return { ...data };
34
+ case 'JsonPartitioned':
35
+ return {
36
+ ...data,
37
+ parts: mapValues(data.parts, makeLocalBlobId),
38
+ };
39
+ case 'BinaryPartitioned':
40
+ return {
41
+ ...data,
42
+ parts: mapValues(data.parts, (v) => ({
43
+ index: makeLocalBlobId(v.index),
44
+ values: makeLocalBlobId(v.values),
45
+ })),
46
+ };
47
+ case 'ParquetPartitioned':
48
+ return {
49
+ ...data,
50
+ parts: mapValues(data.parts, (v) => ({
51
+ ...v,
52
+ data: makeRemoteBlobId(v.data),
53
+ })),
54
+ };
55
+ default:
56
+ assertNever(data);
57
+ }
58
+ };
59
+ const jsonifiedColumns = columns.map((column) => ({
60
+ ...column,
61
+ data: mapColumnData(column.data),
62
+ }));
63
+ try {
64
+ const pFrame = PFrameFactory.createPFrame({ spillPath: this.spillPath, logger });
65
+ pFrame.setDataSource({
66
+ ...this.localBlobProvider.makeDataSource(this.disposeSignal),
67
+ parquetServer: this.remoteBlobProvider.httpServerInfo(),
68
+ });
69
+ const promises = [];
70
+ for (const column of jsonifiedColumns) {
71
+ pFrame.addColumnSpec(column.id, column.spec);
72
+ promises.push(pFrame.setColumnData(column.id, column.data, { signal: this.disposeSignal }));
73
+ }
74
+ this.pFramePromise = Promise.all(promises)
75
+ .then(() => pFrame)
76
+ .catch((err) => {
77
+ this.dispose();
78
+ pFrame.dispose();
79
+ throw new PFrameDriverError(`PFrame creation failed asynchronously, `
80
+ + `columns: ${JSON.stringify(jsonifiedColumns)}, `
81
+ + `error: ${ensureError(err)}`);
82
+ });
83
+ }
84
+ catch (err) {
85
+ throw new PFrameDriverError(`PFrame creation failed synchronously, `
86
+ + `columns: ${JSON.stringify(jsonifiedColumns)}, `
87
+ + `error: ${ensureError(err)}`);
88
+ }
89
+ }
90
+ get disposeSignal() {
91
+ return this.abortController.signal;
92
+ }
93
+ dispose() {
94
+ this.abortController.abort();
95
+ this.localBlobs.forEach((entry) => entry.unref());
96
+ this.remoteBlobs.forEach((entry) => entry.unref());
97
+ }
98
+ [Symbol.dispose]() {
99
+ this.dispose();
100
+ void this.pFramePromise
101
+ .then((pFrame) => pFrame.dispose())
102
+ .catch(() => { });
103
+ }
104
+ }
105
+ class PFramePool extends RefCountPoolBase {
106
+ localBlobProvider;
107
+ remoteBlobProvider;
108
+ logger;
109
+ spillPath;
110
+ constructor(localBlobProvider, remoteBlobProvider, logger, spillPath) {
111
+ super();
112
+ this.localBlobProvider = localBlobProvider;
113
+ this.remoteBlobProvider = remoteBlobProvider;
114
+ this.logger = logger;
115
+ this.spillPath = spillPath;
116
+ }
117
+ calculateParamsKey(params) {
118
+ return stableKeyFromPFrameData(params);
119
+ }
120
+ createNewResource(params, key) {
121
+ if (logPFrames()) {
122
+ this.logger('info', `PFrame creation (pFrameHandle = ${key}): `
123
+ + `${JSON.stringify(params, bigintReplacer)}`);
124
+ }
125
+ return new PFrameHolder(this.localBlobProvider, this.remoteBlobProvider, this.logger, this.spillPath, params);
126
+ }
127
+ getByKey(key) {
128
+ const resource = super.tryGetByKey(key);
129
+ if (!resource)
130
+ throw new PFrameDriverError(`PFrame not found, handle = ${key}`);
131
+ return resource;
132
+ }
133
+ }
134
+ function stableKeyFromPFrameData(data) {
135
+ const orderedData = [...data].map((column) => mapPObjectData(column, (r) => {
136
+ let result;
137
+ const type = r.type;
138
+ switch (type) {
139
+ case 'Json':
140
+ result = {
141
+ type: r.type,
142
+ keyLength: r.keyLength,
143
+ payload: Object.entries(r.data).map(([part, value]) => ({
144
+ key: part,
145
+ value,
146
+ })),
147
+ };
148
+ break;
149
+ case 'JsonPartitioned':
150
+ result = {
151
+ type: r.type,
152
+ keyLength: r.partitionKeyLength,
153
+ payload: Object.entries(r.parts).map(([part, info]) => ({
154
+ key: part,
155
+ value: canonicalizeJson(info),
156
+ })),
157
+ };
158
+ break;
159
+ case 'BinaryPartitioned':
160
+ result = {
161
+ type: r.type,
162
+ keyLength: r.partitionKeyLength,
163
+ payload: Object.entries(r.parts).map(([part, info]) => ({
164
+ key: part,
165
+ value: [canonicalizeJson(info.index), canonicalizeJson(info.values)],
166
+ })),
167
+ };
168
+ break;
169
+ case 'ParquetPartitioned':
170
+ result = {
171
+ type: r.type,
172
+ keyLength: r.partitionKeyLength,
173
+ payload: Object.entries(r.parts).map(([part, info]) => ({
174
+ key: part,
175
+ value: info.dataDigest || [
176
+ canonicalizeJson(info.data),
177
+ JSON.stringify({ axes: info.axes, column: info.column }),
178
+ ],
179
+ })),
180
+ };
181
+ break;
182
+ default:
183
+ throw new PFrameDriverError(`unsupported resource type: ${JSON.stringify(type)}`);
184
+ }
185
+ result.payload.sort((lhs, rhs) => lhs.key < rhs.key ? -1 : 1);
186
+ return result;
187
+ }));
188
+ orderedData.sort((lhs, rhs) => lhs.id < rhs.id ? -1 : 1);
189
+ return hashJson(orderedData);
190
+ }
191
+
192
+ export { PFrameHolder, PFramePool };
193
+ //# sourceMappingURL=pframe_pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pframe_pool.js","sources":["../src/pframe_pool.ts"],"sourcesContent":["import {\n assertNever,\n bigintReplacer,\n canonicalizeJson,\n ensureError,\n mapPObjectData,\n PFrameDriverError,\n type JsonSerializable,\n type PColumn,\n type PFrameHandle,\n} from '@platforma-sdk/model';\nimport { PFrameInternal } from '@milaboratories/pl-model-middle-layer';\nimport {\n hashJson,\n RefCountPoolBase,\n type PoolEntry,\n} from '@milaboratories/ts-helpers';\nimport { PFrameFactory } from '@milaboratories/pframes-rs-node';\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 pFramePromise: Promise<PFrameInternal.PFrameV12>;\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 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 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}`;\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 try {\n const pFrame = PFrameFactory.createPFrame({ spillPath: this.spillPath, logger });\n pFrame.setDataSource({\n ...this.localBlobProvider.makeDataSource(this.disposeSignal),\n parquetServer: this.remoteBlobProvider.httpServerInfo(),\n });\n\n const promises: Promise<void>[] = [];\n for (const column of jsonifiedColumns) {\n pFrame.addColumnSpec(column.id, column.spec);\n promises.push(pFrame.setColumnData(column.id, column.data, { signal: this.disposeSignal }));\n }\n\n this.pFramePromise = Promise.all(promises)\n .then(() => pFrame)\n .catch((err) => {\n this.dispose();\n pFrame.dispose();\n throw new PFrameDriverError(\n `PFrame creation failed asynchronously, `\n + `columns: ${JSON.stringify(jsonifiedColumns)}, `\n + `error: ${ensureError(err)}`,\n );\n });\n } catch (err: unknown) {\n throw new PFrameDriverError(\n `PFrame creation failed synchronously, `\n + `columns: ${JSON.stringify(jsonifiedColumns)}, `\n + `error: ${ensureError(err)}`,\n );\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 }\n\n [Symbol.dispose](): void {\n this.dispose();\n void this.pFramePromise\n .then((pFrame) => pFrame.dispose())\n .catch(() => { /* mute error */ });\n }\n}\n\nexport class PFramePool<TreeEntry extends JsonSerializable>\n extends RefCountPoolBase<\n PColumn<PFrameInternal.DataInfo<TreeEntry>>[],\n PFrameHandle,\n PFrameHolder<TreeEntry>> {\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(params: PColumn<PFrameInternal.DataInfo<TreeEntry>>[]): 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('info',\n `PFrame creation (pFrameHandle = ${key}): `\n + `${JSON.stringify(params, bigintReplacer)}`,\n );\n }\n return new PFrameHolder(\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) throw new PFrameDriverError(`PFrame not found, handle = ${key}`);\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: info.dataDigest || [\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(`unsupported resource type: ${JSON.stringify(type satisfies never)}`);\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"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ 'use strict';
2
+
3
+ var lruCache = require('lru-cache');
4
+ var logging = require('./logging.cjs');
5
+
6
+ const PTableCachePerFrameOpsDefaults = {
7
+ pFrameCacheMaxCount: 18, // SHM trees create 3 PTables per graphic, we want to cache 6 graphics per PFrame
8
+ pFramesCacheMaxSize: 8 * 1024 * 1024 * 1024, // 8 GB, same as blob driver cache (must be at least 2GB)
9
+ };
10
+ class PTableCachePerFrame {
11
+ logger;
12
+ ops;
13
+ perFrame = new Map();
14
+ global;
15
+ disposeListeners = new Set();
16
+ constructor(logger, ops) {
17
+ this.logger = logger;
18
+ this.ops = ops;
19
+ this.global = new lruCache.LRUCache({
20
+ maxSize: this.ops.pFramesCacheMaxSize,
21
+ dispose: (resource, key, reason) => {
22
+ if (reason === 'evict') {
23
+ this.perFrame.get(resource.resource.pFrame)?.delete(key);
24
+ }
25
+ if (this.perFrame.get(resource.resource.pFrame)?.size === 0) {
26
+ this.perFrame.delete(resource.resource.pFrame);
27
+ }
28
+ resource.unref();
29
+ if (logging.logPFrames()) {
30
+ logger('info', `calculateTableData cache - removed PTable ${key} (reason: ${reason})`);
31
+ }
32
+ },
33
+ });
34
+ }
35
+ cache(resource, size) {
36
+ const key = resource.key;
37
+ if (logging.logPFrames()) {
38
+ this.logger('info', `calculateTableData cache - added PTable ${key} with size ${size}`);
39
+ }
40
+ this.global.set(key, resource, { size: Math.max(size, 1) }); // 1 is minimum size to avoid cache evictions
41
+ let perFrame = this.perFrame.get(resource.resource.pFrame);
42
+ if (!perFrame) {
43
+ perFrame = new lruCache.LRUCache({
44
+ max: this.ops.pFrameCacheMaxCount,
45
+ dispose: (_resource, key, reason) => {
46
+ if (reason === 'evict') {
47
+ this.global.delete(key);
48
+ }
49
+ },
50
+ });
51
+ this.perFrame.set(resource.resource.pFrame, perFrame);
52
+ }
53
+ perFrame.set(key, resource);
54
+ if (!this.disposeListeners.has(key)) {
55
+ const disposeListener = () => {
56
+ this.perFrame.get(resource.resource.pFrame)?.delete(key);
57
+ this.global.delete(key);
58
+ this.disposeListeners.delete(key);
59
+ resource.resource.disposeSignal.removeEventListener('abort', disposeListener);
60
+ };
61
+ this.disposeListeners.add(key);
62
+ resource.resource.disposeSignal.addEventListener('abort', disposeListener);
63
+ }
64
+ }
65
+ }
66
+
67
+ exports.PTableCachePerFrame = PTableCachePerFrame;
68
+ exports.PTableCachePerFrameOpsDefaults = PTableCachePerFrameOpsDefaults;
69
+ //# sourceMappingURL=ptable_cache_per_frame.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ptable_cache_per_frame.cjs","sources":["../src/ptable_cache_per_frame.ts"],"sourcesContent":["import type { PFrameHandle, PTableHandle } from '@platforma-sdk/model';\nimport type { PFrameInternal } from '@milaboratories/pl-model-middle-layer';\nimport type { PoolEntry } from '@milaboratories/ts-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 predeccessors, 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<PFrameHandle, LRUCache<PTableHandle, PoolEntry<PTableHandle, PTableHolder>>>();\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"],"names":["LRUCache","logPFrames"],"mappings":";;;;;AAkBO,MAAM,8BAA8B,GAA2B;IACpE,mBAAmB,EAAE,EAAE;IACvB,mBAAmB,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI;;MAGhC,mBAAmB,CAAA;AAMX,IAAA,MAAA;AACA,IAAA,GAAA;AANF,IAAA,QAAQ,GAAG,IAAI,GAAG,EAA+E;AACjG,IAAA,MAAM;AACN,IAAA,gBAAgB,GAAG,IAAI,GAAG,EAAgB;IAE3D,WAAA,CACmB,MAA6B,EAC7B,GAA2B,EAAA;QAD3B,IAAA,CAAA,MAAM,GAAN,MAAM;QACN,IAAA,CAAA,GAAG,GAAH,GAAG;AAEpB,QAAA,IAAI,CAAC,MAAM,GAAG,IAAIA,iBAAQ,CAAsD;AAC9E,YAAA,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,mBAAmB;YACrC,OAAO,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,MAAM,KAAI;AACjC,gBAAA,IAAI,MAAM,KAAK,OAAO,EAAE;AACtB,oBAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC;gBAC1D;AAEA,gBAAA,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,KAAK,CAAC,EAAE;oBAC3D,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAChD;gBAEA,QAAQ,CAAC,KAAK,EAAE;gBAChB,IAAIC,kBAAU,EAAE,EAAE;oBAChB,MAAM,CAAC,MAAM,EAAE,CAAA,0CAAA,EAA6C,GAAG,CAAA,UAAA,EAAa,MAAM,CAAA,CAAA,CAAG,CAAC;gBACxF;YACF,CAAC;AACF,SAAA,CAAC;IACJ;IAEO,KAAK,CAAC,QAA+C,EAAE,IAAY,EAAA;AACxE,QAAA,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG;QACxB,IAAIA,kBAAU,EAAE,EAAE;YAChB,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAA,wCAAA,EAA2C,GAAG,CAAA,WAAA,EAAc,IAAI,CAAA,CAAE,CAAC;QACzF;QAEA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AAE5D,QAAA,IAAI,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC1D,IAAI,CAAC,QAAQ,EAAE;YACb,QAAQ,GAAG,IAAID,iBAAQ,CAAsD;AAC3E,gBAAA,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,mBAAmB;gBACjC,OAAO,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,MAAM,KAAI;AAClC,oBAAA,IAAI,MAAM,KAAK,OAAO,EAAE;AACtB,wBAAA,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC;oBACzB;gBACF,CAAC;AACF,aAAA,CAAC;AACF,YAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;QACvD;AACA,QAAA,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC;QAE3B,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;YACnC,MAAM,eAAe,GAAG,MAAK;AAC3B,gBAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC;AACxD,gBAAA,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC;AAEvB,gBAAA,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC;gBACjC,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,mBAAmB,CAAC,OAAO,EAAE,eAAe,CAAC;AAC/E,YAAA,CAAC;AACD,YAAA,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC;YAC9B,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,OAAO,EAAE,eAAe,CAAC;QAC5E;IACF;AACD;;;;;"}
@@ -0,0 +1,25 @@
1
+ import type { PTableHandle } from '@platforma-sdk/model';
2
+ import type { PFrameInternal } from '@milaboratories/pl-model-middle-layer';
3
+ import type { PoolEntry } from '@milaboratories/ts-helpers';
4
+ import type { PTableHolder } from './ptable_pool';
5
+ export type PTableCachePerFrameOps = {
6
+ /** Maximum number of `calculateTableData` results cached for each PFrame */
7
+ pFrameCacheMaxCount: number;
8
+ /**
9
+ * Maximum size of `calculateTableData` results cached for PFrames overall.
10
+ * The limit is soft, as the same table could be materialized with other requests and will not be deleted in such case.
11
+ * Also each table has predeccessors, overlapping predecessors will be counted twice, so the effective limit is smaller.
12
+ */
13
+ pFramesCacheMaxSize: number;
14
+ };
15
+ export declare const PTableCachePerFrameOpsDefaults: PTableCachePerFrameOps;
16
+ export declare class PTableCachePerFrame {
17
+ private readonly logger;
18
+ private readonly ops;
19
+ private readonly perFrame;
20
+ private readonly global;
21
+ private readonly disposeListeners;
22
+ constructor(logger: PFrameInternal.Logger, ops: PTableCachePerFrameOps);
23
+ cache(resource: PoolEntry<PTableHandle, PTableHolder>, size: number): void;
24
+ }
25
+ //# sourceMappingURL=ptable_cache_per_frame.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ptable_cache_per_frame.d.ts","sourceRoot":"","sources":["../src/ptable_cache_per_frame.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgB,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAG5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,MAAM,MAAM,sBAAsB,GAAG;IACnC,4EAA4E;IAC5E,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,eAAO,MAAM,8BAA8B,EAAE,sBAG5C,CAAC;AAEF,qBAAa,mBAAmB;IAM5B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,GAAG;IANtB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0F;IACnH,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgE;IACvF,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA2B;gBAGzC,MAAM,EAAE,cAAc,CAAC,MAAM,EAC7B,GAAG,EAAE,sBAAsB;IAqBvC,KAAK,CAAC,QAAQ,EAAE,SAAS,CAAC,YAAY,EAAE,YAAY,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;CAkClF"}