@milaboratories/pl-middle-layer 1.11.6 → 1.12.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.
@@ -7,6 +7,8 @@ export declare class PFrameDriver implements SdkPFrameDriver {
7
7
  private readonly pFrames;
8
8
  private readonly pTables;
9
9
  private readonly blobContentCache;
10
+ /** Limits concurrent requests to PFrame API to prevent deadlock with Node's IO threads */
11
+ private readonly concurrencyLimiter;
10
12
  constructor(blobDriver: DownloadDriver);
11
13
  createPFrame(def: PFrameDef<PlTreeNodeAccessor>, ctx: ComputableCtx): PFrameHandle;
12
14
  createPTable(def: PTableDef<PColumn<PlTreeNodeAccessor>>, ctx: ComputableCtx): PTableHandle;
@@ -1 +1 @@
1
- {"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../src/pool/driver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAE5D,OAAO,EAAE,kBAAkB,EAAgB,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,aAAa,EAA2B,MAAM,4BAA4B,CAAC;AACpF,OAAO,EACL,yBAAyB,EACzB,0BAA0B,EAC1B,kBAAkB,EAClB,mBAAmB,EAEnB,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,UAAU,EACV,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,IAAI,eAAe,EAC/B,OAAO,EAEP,SAAS,EACT,SAAS,EACT,SAAS,EAEV,MAAM,sBAAsB,CAAC;AAuF9B,qBAAa,YAAa,YAAW,eAAe;IAKtC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAJvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyD;IACjF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsE;IAC9F,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA+B;gBAEnC,UAAU,EAAE,cAAc;IA8ChD,YAAY,CAAC,GAAG,EAAE,SAAS,CAAC,kBAAkB,CAAC,EAAE,GAAG,EAAE,aAAa,GAAG,YAAY;IAOlF,YAAY,CACjB,GAAG,EAAE,SAAS,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC,EAC3C,GAAG,EAAE,aAAa,GACjB,YAAY;IAYF,WAAW,CACtB,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,mBAAmB,CAAC;IAelB,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IAI9E,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAI9D,kBAAkB,CAC7B,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,yBAAyB,CAAC,SAAS,CAAC,GAC5C,OAAO,CAAC,0BAA0B,CAAC;IAsBzB,eAAe,CAC1B,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,oBAAoB,CAAC;IAQnB,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;IAKpD,OAAO,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAK1D,OAAO,CAClB,MAAM,EAAE,YAAY,EACpB,aAAa,EAAE,MAAM,EAAE,EACvB,KAAK,CAAC,EAAE,UAAU,GACjB,OAAO,CAAC,YAAY,EAAE,CAAC;CAI3B;AA+CD,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAI/E"}
1
+ {"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../src/pool/driver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAE5D,OAAO,EAAE,kBAAkB,EAAgB,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,aAAa,EAA2B,MAAM,4BAA4B,CAAC;AACpF,OAAO,EACL,yBAAyB,EACzB,0BAA0B,EAC1B,kBAAkB,EAClB,mBAAmB,EAEnB,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,UAAU,EACV,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,IAAI,eAAe,EAC/B,OAAO,EAEP,SAAS,EACT,SAAS,EACT,SAAS,EAEV,MAAM,sBAAsB,CAAC;AAwF9B,qBAAa,YAAa,YAAW,eAAe;IAOtC,OAAO,CAAC,QAAQ,CAAC,UAAU;IANvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyD;IACjF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsE;IAC9F,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA+B;IAChE,0FAA0F;IAC1F,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA8B;gBAEpC,UAAU,EAAE,cAAc;IAmDhD,YAAY,CAAC,GAAG,EAAE,SAAS,CAAC,kBAAkB,CAAC,EAAE,GAAG,EAAE,aAAa,GAAG,YAAY;IAOlF,YAAY,CACjB,GAAG,EAAE,SAAS,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC,EAC3C,GAAG,EAAE,aAAa,GACjB,YAAY;IAYF,WAAW,CACtB,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,mBAAmB,CAAC;IAiBlB,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IAM9E,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAM9D,kBAAkB,CAC7B,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,yBAAyB,CAAC,SAAS,CAAC,GAC5C,OAAO,CAAC,0BAA0B,CAAC;IA6BzB,eAAe,CAC1B,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,oBAAoB,CAAC;IAUnB,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;IAKpD,OAAO,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAK1D,OAAO,CAClB,MAAM,EAAE,YAAY,EACpB,aAAa,EAAE,MAAM,EAAE,EACvB,KAAK,CAAC,EAAE,UAAU,GACjB,OAAO,CAAC,YAAY,EAAE,CAAC;CAM3B;AA+CD,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAI/E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@milaboratories/pl-middle-layer",
3
- "version": "1.11.6",
3
+ "version": "1.12.0",
4
4
  "description": "Pl Middle Layer",
5
5
  "types": "./dist/index.d.ts",
6
6
  "main": "./dist/index.js",
@@ -19,7 +19,7 @@
19
19
  "keywords": [],
20
20
  "license": "UNLICENSED",
21
21
  "dependencies": {
22
- "@milaboratories/pframes-node": "^1.5.10",
22
+ "@milaboratories/pframes-node": "^1.6.0",
23
23
  "canonicalize": "^2.0.0",
24
24
  "denque": "^2.1.0",
25
25
  "lru-cache": "^11.0.1",
@@ -28,19 +28,19 @@
28
28
  "utility-types": "^3.11.0",
29
29
  "yaml": "^2.5.1",
30
30
  "zod": "^3.23.8",
31
- "@milaboratories/computable": "^2.1.12",
32
31
  "@milaboratories/resolve-helper": "^1.0.1",
33
- "@platforma-sdk/block-tools": "^2.3.13",
34
- "@milaboratories/pl-client": "^2.5.0",
32
+ "@platforma-sdk/block-tools": "^2.3.14",
33
+ "@milaboratories/computable": "^2.1.13",
34
+ "@milaboratories/pl-client": "^2.5.1",
35
+ "@milaboratories/pl-drivers": "^1.2.33",
35
36
  "@milaboratories/pl-model-common": "^1.3.14",
36
- "@milaboratories/pl-drivers": "^1.2.32",
37
- "@milaboratories/pl-model-middle-layer": "^1.4.5",
37
+ "@milaboratories/pl-model-middle-layer": "^1.5.0",
38
+ "@milaboratories/pl-tree": "^1.4.2",
38
39
  "@platforma-sdk/model": "^1.5.40",
39
- "@milaboratories/ts-helpers": "^1.0.30",
40
- "@milaboratories/pl-tree": "^1.4.1",
41
- "@platforma-sdk/workflow-tengo": "1.4.2",
42
- "@milaboratories/pl-config": "^1.2.6",
43
- "@milaboratories/pl-local": "^1.2.5"
40
+ "@milaboratories/ts-helpers": "^1.1.0",
41
+ "@milaboratories/pl-config": "^1.2.7",
42
+ "@milaboratories/pl-local": "^1.2.6",
43
+ "@platforma-sdk/workflow-tengo": "1.4.2"
44
44
  },
45
45
  "devDependencies": {
46
46
  "typescript": "~5.5.4",
@@ -35,6 +35,7 @@ import canonicalize from 'canonicalize';
35
35
  import { PFrame } from '@milaboratories/pframes-node';
36
36
  import * as fsp from 'node:fs/promises';
37
37
  import { LRUCache } from 'lru-cache';
38
+ import { ConcurrencyLimitingExecutor } from '@milaboratories/ts-helpers';
38
39
 
39
40
  function blobKey(res: ResourceInfo): string {
40
41
  return String(res.id);
@@ -117,6 +118,8 @@ export class PFrameDriver implements SdkPFrameDriver {
117
118
  private readonly pFrames: RefCountResourcePool<InternalPFrameData, PFrameHolder>;
118
119
  private readonly pTables: RefCountResourcePool<FullPTableDef, Promise<PFrameInternal.PTable>>;
119
120
  private readonly blobContentCache: LRUCache<string, Uint8Array>;
121
+ /** Limits concurrent requests to PFrame API to prevent deadlock with Node's IO threads */
122
+ private readonly concurrencyLimiter: ConcurrencyLimitingExecutor;
120
123
 
121
124
  constructor(private readonly blobDriver: DownloadDriver) {
122
125
  const blobContentCache = new LRUCache<string, Uint8Array>({
@@ -124,7 +127,9 @@ export class PFrameDriver implements SdkPFrameDriver {
124
127
  fetchMethod: async (key) => await fsp.readFile(key),
125
128
  sizeCalculation: (v) => v.length
126
129
  });
130
+ const concurrencyLimiter = new ConcurrencyLimitingExecutor(2);
127
131
  this.blobContentCache = blobContentCache;
132
+ this.concurrencyLimiter = concurrencyLimiter;
128
133
  this.pFrames = new (class extends RefCountResourcePool<InternalPFrameData, PFrameHolder> {
129
134
  constructor(private readonly blobDriver: DownloadDriver) {
130
135
  super();
@@ -148,10 +153,13 @@ export class PFrameDriver implements SdkPFrameDriver {
148
153
  }
149
154
  protected async createNewResource(params: FullPTableDef): Promise<PFrameInternal.PTable> {
150
155
  const pFrame = this.pFrames.getByKey(params.pFrameHandle);
151
- const rawPTable = await pFrame.pFrame.createTable({
152
- src: joinEntryToInternal(params.def.src),
153
- filters: params.def.filters
154
- });
156
+ const rawPTable = await concurrencyLimiter.run(
157
+ async () =>
158
+ await pFrame.pFrame.createTable({
159
+ src: joinEntryToInternal(params.def.src),
160
+ filters: params.def.filters
161
+ })
162
+ );
155
163
  return params.def.sorting.length !== 0 ? rawPTable.sort(params.def.sorting) : rawPTable;
156
164
  }
157
165
  protected calculateParamsKey(params: FullPTableDef): string {
@@ -198,37 +206,50 @@ export class PFrameDriver implements SdkPFrameDriver {
198
206
  : []
199
207
  };
200
208
  return {
201
- hits: (await this.pFrames.getByKey(handle).pFrame.findColumns(iRequest)).hits.map(
202
- (h) => h.hit
203
- )
209
+ hits: (
210
+ await this.concurrencyLimiter.run(
211
+ async () => await this.pFrames.getByKey(handle).pFrame.findColumns(iRequest)
212
+ )
213
+ ).hits.map((h) => h.hit)
204
214
  };
205
215
  }
206
216
 
207
217
  public async getColumnSpec(handle: PFrameHandle, columnId: PObjectId): Promise<PColumnSpec> {
208
- return this.pFrames.getByKey(handle).pFrame.getColumnSpec(columnId);
218
+ return await this.concurrencyLimiter.run(
219
+ async () => await this.pFrames.getByKey(handle).pFrame.getColumnSpec(columnId)
220
+ );
209
221
  }
210
222
 
211
223
  public async listColumns(handle: PFrameHandle): Promise<PColumnIdAndSpec[]> {
212
- return this.pFrames.getByKey(handle).pFrame.listColumns();
224
+ return await this.concurrencyLimiter.run(
225
+ async () => await this.pFrames.getByKey(handle).pFrame.listColumns()
226
+ );
213
227
  }
214
228
 
215
229
  public async calculateTableData(
216
230
  handle: PFrameHandle,
217
231
  request: CalculateTableDataRequest<PObjectId>
218
232
  ): Promise<CalculateTableDataResponse> {
219
- let table = await this.pFrames.getByKey(handle).pFrame.createTable({
220
- src: joinEntryToInternal(request.src),
221
- filters: request.filters
222
- });
233
+ let table = await this.concurrencyLimiter.run(
234
+ async () =>
235
+ await this.pFrames.getByKey(handle).pFrame.createTable({
236
+ src: joinEntryToInternal(request.src),
237
+ filters: request.filters
238
+ })
239
+ );
223
240
 
224
241
  if (request.sorting.length > 0) {
225
- const sortedTable = await table.sort(request.sorting);
242
+ const sortedTable = await this.concurrencyLimiter.run(
243
+ async () => await table.sort(request.sorting)
244
+ );
226
245
  table.dispose();
227
246
  table = sortedTable;
228
247
  }
229
248
 
230
249
  const spec = table.getSpec();
231
- const data = await table.getData([...spec.keys()]);
250
+ const data = await this.concurrencyLimiter.run(
251
+ async () => await table.getData([...spec.keys()])
252
+ );
232
253
  table.dispose();
233
254
 
234
255
  return spec.map((spec, i) => ({
@@ -241,7 +262,9 @@ export class PFrameDriver implements SdkPFrameDriver {
241
262
  handle: PFrameHandle,
242
263
  request: UniqueValuesRequest
243
264
  ): Promise<UniqueValuesResponse> {
244
- return await this.pFrames.getByKey(handle).pFrame.getUniqueValues(request);
265
+ return await this.concurrencyLimiter.run(
266
+ async () => await this.pFrames.getByKey(handle).pFrame.getUniqueValues(request)
267
+ );
245
268
  }
246
269
 
247
270
  //
@@ -249,13 +272,13 @@ export class PFrameDriver implements SdkPFrameDriver {
249
272
  //
250
273
 
251
274
  public async getShape(handle: PTableHandle): Promise<PTableShape> {
252
- const pTable = await this.pTables.getByKey(handle);
275
+ const pTable = await this.pTables.getByKey(handle); // internally concurrency limited
253
276
  return pTable.getShape();
254
277
  }
255
278
 
256
279
  public async getSpec(handle: PTableHandle): Promise<PTableColumnSpec[]> {
257
- const pTable = await this.pTables.getByKey(handle);
258
- return pTable.getSpec();
280
+ const pTable = await this.pTables.getByKey(handle); // internally concurrency limited
281
+ return pTable.getSpec(); // sync operation
259
282
  }
260
283
 
261
284
  public async getData(
@@ -263,8 +286,10 @@ export class PFrameDriver implements SdkPFrameDriver {
263
286
  columnIndices: number[],
264
287
  range?: TableRange
265
288
  ): Promise<PTableVector[]> {
266
- const pTable = await this.pTables.getByKey(handle);
267
- return pTable.getData(columnIndices, range);
289
+ const pTable = await this.pTables.getByKey(handle); // internally concurrency limited
290
+ return await this.concurrencyLimiter.run(
291
+ async () => await pTable.getData(columnIndices, range)
292
+ );
268
293
  }
269
294
  }
270
295