@milaboratories/pl-middle-layer 1.43.60 → 1.43.63

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.
@@ -9,7 +9,9 @@ const workerApi = {
9
9
  const t1 = performance.now();
10
10
  const result = parseTemplate(payload);
11
11
  const t2 = performance.now();
12
- console.info(`>>>> parseTemplate in worker took ${t2 - t1}ms`);
12
+ const dt = t2 - t1;
13
+ if (dt > 100)
14
+ console.warn(`parseTemplate in worker took ${dt}ms`);
13
15
  return result;
14
16
  },
15
17
  };
@@ -1 +1 @@
1
- {"version":3,"file":"workerApi.js","sources":["../../src/worker/workerApi.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/require-await */\nimport { parseTemplate } from '@milaboratories/pl-model-backend';\n\n/**\n * Add there all heavy synchronous operations that can be moved to the worker thread.\n */\nexport const workerApi = {\n parseTemplate: async (payload: Uint8Array) => {\n const t1 = performance.now();\n const result = parseTemplate(payload);\n const t2 = performance.now();\n console.info(`>>>> parseTemplate in worker took ${t2 - t1}ms`);\n return result;\n },\n} satisfies Record<string, (...args: any[]) => Promise<unknown>>;\n\ntype ToScheme<T extends Record<string, (...args: any[]) => any>> = {\n [K in keyof T]: {\n args: Parameters<T[K]>;\n response: Awaited<ReturnType<T[K]>>;\n };\n};\n\nexport type Scheme = ToScheme<typeof workerApi>;\n"],"names":[],"mappings":";;AAAA;AAGA;;AAEG;AACI,MAAM,SAAS,GAAG;AACvB,IAAA,aAAa,EAAE,OAAO,OAAmB,KAAI;AAC3C,QAAA,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE;AAC5B,QAAA,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC;AACrC,QAAA,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE;QAC5B,OAAO,CAAC,IAAI,CAAC,CAAA,kCAAA,EAAqC,EAAE,GAAG,EAAE,CAAA,EAAA,CAAI,CAAC;AAC9D,QAAA,OAAO,MAAM;IACf,CAAC;;;;;"}
1
+ {"version":3,"file":"workerApi.js","sources":["../../src/worker/workerApi.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/require-await */\nimport { parseTemplate } from '@milaboratories/pl-model-backend';\n\n/**\n * Add there all heavy synchronous operations that can be moved to the worker thread.\n */\nexport const workerApi = {\n parseTemplate: async (payload: Uint8Array) => {\n const t1 = performance.now();\n const result = parseTemplate(payload);\n const t2 = performance.now();\n const dt = t2 - t1;\n if (dt > 100) console.warn(`parseTemplate in worker took ${dt}ms`);\n return result;\n },\n} satisfies Record<string, (...args: any[]) => Promise<unknown>>;\n\ntype ToScheme<T extends Record<string, (...args: any[]) => any>> = {\n [K in keyof T]: {\n args: Parameters<T[K]>;\n response: Awaited<ReturnType<T[K]>>;\n };\n};\n\nexport type Scheme = ToScheme<typeof workerApi>;\n"],"names":[],"mappings":";;AAAA;AAGA;;AAEG;AACI,MAAM,SAAS,GAAG;AACvB,IAAA,aAAa,EAAE,OAAO,OAAmB,KAAI;AAC3C,QAAA,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE;AAC5B,QAAA,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC;AACrC,QAAA,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE;AAC5B,QAAA,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE;QAClB,IAAI,EAAE,GAAG,GAAG;AAAE,YAAA,OAAO,CAAC,IAAI,CAAC,gCAAgC,EAAE,CAAA,EAAA,CAAI,CAAC;AAClE,QAAA,OAAO,MAAM;IACf,CAAC;;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@milaboratories/pl-middle-layer",
3
- "version": "1.43.60",
3
+ "version": "1.43.63",
4
4
  "description": "Pl Middle Layer",
5
5
  "engines": {
6
6
  "node": ">=22.19.0"
@@ -28,21 +28,21 @@
28
28
  "remeda": "^2.28.0",
29
29
  "@milaboratories/pl-http": "1.2.0",
30
30
  "@milaboratories/resolve-helper": "1.1.1",
31
- "@milaboratories/computable": "2.7.2",
32
- "@milaboratories/pl-client": "2.16.3",
33
- "@milaboratories/pl-drivers": "1.11.14",
34
- "@platforma-sdk/block-tools": "2.6.17",
31
+ "@milaboratories/computable": "2.7.4",
32
+ "@milaboratories/pl-client": "2.16.6",
33
+ "@platforma-sdk/block-tools": "2.6.20",
35
34
  "@milaboratories/pl-model-common": "1.21.5",
36
- "@milaboratories/pl-model-middle-layer": "1.8.36",
37
- "@milaboratories/pl-model-backend": "1.1.20",
38
- "@milaboratories/pl-tree": "1.8.10",
39
- "@platforma-sdk/workflow-tengo": "5.5.17",
40
- "@milaboratories/ts-helpers": "1.5.2",
35
+ "@milaboratories/pl-drivers": "1.11.17",
36
+ "@milaboratories/pl-model-middle-layer": "1.8.39",
37
+ "@milaboratories/pl-tree": "1.8.13",
38
+ "@milaboratories/pl-model-backend": "1.1.23",
39
+ "@milaboratories/ts-helpers": "1.5.4",
41
40
  "@platforma-sdk/model": "1.45.26",
42
- "@milaboratories/pl-config": "1.7.7",
43
- "@milaboratories/pl-deployments": "2.12.1",
44
- "@milaboratories/pl-errors": "1.1.35",
45
- "@milaboratories/pf-driver": "1.0.0"
41
+ "@milaboratories/pl-deployments": "2.12.3",
42
+ "@platforma-sdk/workflow-tengo": "5.5.17",
43
+ "@milaboratories/pl-errors": "1.1.38",
44
+ "@milaboratories/pf-driver": "1.0.3",
45
+ "@milaboratories/pl-config": "1.7.9"
46
46
  },
47
47
  "devDependencies": {
48
48
  "semver": "^7.7.2",
@@ -51,10 +51,10 @@
51
51
  "vitest": "^4.0.7",
52
52
  "@types/node": "~24.5.2",
53
53
  "tslib": "~2.7.0",
54
- "@milaboratories/build-configs": "1.0.8",
55
54
  "@milaboratories/ts-builder": "1.0.5",
56
55
  "@milaboratories/ts-configs": "1.0.6",
57
- "@milaboratories/eslint-config": "1.0.4"
56
+ "@milaboratories/build-configs": "1.0.8",
57
+ "@milaboratories/eslint-config": "1.0.5"
58
58
  },
59
59
  "scripts": {
60
60
  "type-check": "ts-builder types --target node",
@@ -93,7 +93,10 @@ export class Project {
93
93
  private readonly refreshLoopResult: Promise<void>;
94
94
 
95
95
  private readonly abortController = new AbortController();
96
- private destroyed = false;
96
+
97
+ private get destroyed() {
98
+ return this.abortController.signal.aborted;
99
+ }
97
100
 
98
101
  constructor(
99
102
  private readonly env: MiddleLayerEnvironment,
@@ -110,7 +113,7 @@ export class Project {
110
113
  this.rid = rid;
111
114
  this.refreshLoopResult = this.refreshLoop();
112
115
  this.refreshLoopResult.catch((err) => {
113
- env.logger.error(err); // TODO (safe voiding for now)
116
+ env.logger.warn(new Error('Error during refresh loop', { cause: err })); // TODO (safe voiding for now)
114
117
  });
115
118
  this.activeConfigs = activeConfigs(projectTree.entry(), env);
116
119
  }
@@ -140,13 +143,25 @@ export class Project {
140
143
  }
141
144
  }
142
145
  } catch (e: unknown) {
146
+ // If we're destroyed, exit gracefully regardless of error type
147
+ if (this.destroyed) {
148
+ // Log just in case, to help with debugging if something unexpected happens during shutdown
149
+ this.env.logger.warn(new Error('Error during refresh loop shutdown', { cause: e }));
150
+ break;
151
+ }
152
+
143
153
  if (isNotFoundError(e)) {
144
154
  console.warn(
145
155
  'project refresh routine terminated, because project was externally deleted',
146
156
  );
147
157
  break;
148
- } else if (!isTimeoutOrCancelError(e))
158
+ } else if (isTimeoutOrCancelError(e)) {
159
+ // Timeout during normal operation, continue the loop
160
+ } else {
161
+ // TODO: This stops the refresh loop permanently, leaving the project broken.
162
+ // Need to decide how to handle this case.
149
163
  throw new Error('Unexpected exception', { cause: e });
164
+ }
150
165
  }
151
166
  }
152
167
  }
@@ -471,12 +486,22 @@ export class Project {
471
486
  /** Called by middle layer on close */
472
487
  public async destroy(): Promise<void> {
473
488
  // terminating the project service loop
474
- this.destroyed = true;
475
489
  this.abortController.abort();
476
- await this.refreshLoopResult;
490
+ try {
491
+ await this.refreshLoopResult;
492
+ } catch (e: unknown) {
493
+ // Error was already logged in the constructor's catch handler, but log again for context
494
+ this.env.logger.warn(new Error('Refresh loop had terminated with error before destroy', { cause: e }));
495
+ }
477
496
 
478
497
  // terminating the synchronized project tree
479
- await this.projectTree.terminate();
498
+ try {
499
+ await this.projectTree.terminate();
500
+ } catch (e: unknown) {
501
+ // TODO: SynchronizedTreeState.terminate() can throw if mainLoop had an error before termination
502
+ // Log error but continue cleanup - we must clean up remaining resources
503
+ this.env.logger.warn(new Error('Project tree termination failed', { cause: e }));
504
+ }
480
505
 
481
506
  // the following will deregister all external resource holders, like
482
507
  // downloaded files, running uploads and alike
@@ -536,7 +536,7 @@ export class ProjectMutator {
536
536
  gzipped = isGzipped;
537
537
  }
538
538
  if (Buffer.compare(info.fields[fieldName]!.value!, data) === 0) continue;
539
- console.log('setting', fieldName, gzipped, data.length);
539
+ // console.log('setting', fieldName, gzipped, data.length);
540
540
  const statePartRef = this.tx.createValue(gzipped ? Pl.JsonGzObject : Pl.JsonObject, data);
541
541
  this.setBlockField(req.blockId, fieldName, statePartRef, 'Ready', data);
542
542
 
@@ -46,7 +46,7 @@ import {
46
46
  } from './data';
47
47
 
48
48
  function makeBlobId(res: PlTreeEntry): PFrameInternal.PFrameBlobId {
49
- return String(res.rid);
49
+ return String(res.rid) as PFrameInternal.PFrameBlobId;
50
50
  }
51
51
 
52
52
  type LocalBlob = ComputableStableDefined<LocalBlobHandleAndSize>;
@@ -156,7 +156,7 @@ class BlobStore extends PFrameInternal.BaseObjectStore {
156
156
  callback: (response: PFrameInternal.ObjectStoreResponse) => Promise<void>;
157
157
  },
158
158
  ): Promise<void> {
159
- const blobId = filename.slice(0, -PFrameInternal.ParquetExtension.length);
159
+ const blobId = filename.slice(0, -PFrameInternal.ParquetExtension.length) as PFrameInternal.PFrameBlobId;
160
160
  const respond = async (response: PFrameInternal.ObjectStoreResponse): Promise<void> => {
161
161
  try {
162
162
  await params.callback(response);
@@ -247,7 +247,7 @@ class RemoteBlobProviderImpl implements RemoteBlobProvider<PlTreeEntry> {
247
247
  return new RemoteBlobProviderImpl(pool, server);
248
248
  }
249
249
 
250
- public acquire(params: PlTreeEntry): PoolEntry {
250
+ public acquire(params: PlTreeEntry): PoolEntry<PFrameInternal.PFrameBlobId> {
251
251
  return this.pool.acquire(params);
252
252
  }
253
253
 
@@ -9,7 +9,8 @@ export const workerApi = {
9
9
  const t1 = performance.now();
10
10
  const result = parseTemplate(payload);
11
11
  const t2 = performance.now();
12
- console.info(`>>>> parseTemplate in worker took ${t2 - t1}ms`);
12
+ const dt = t2 - t1;
13
+ if (dt > 100) console.warn(`parseTemplate in worker took ${dt}ms`);
13
14
  return result;
14
15
  },
15
16
  } satisfies Record<string, (...args: any[]) => Promise<unknown>>;