@milaboratories/pl-client 2.10.2 → 2.11.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.
- package/dist/core/final.d.ts.map +1 -1
- package/dist/core/stat.d.ts +3 -0
- package/dist/core/stat.d.ts.map +1 -1
- package/dist/core/transaction.d.ts +5 -1
- package/dist/core/transaction.d.ts.map +1 -1
- package/dist/helpers/pl.d.ts +1 -0
- package/dist/helpers/pl.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1072 -1045
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -10
- package/src/core/final.ts +4 -0
- package/src/core/stat.ts +11 -1
- package/src/core/transaction.ts +52 -34
- package/src/helpers/pl.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@milaboratories/pl-client",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.11.0",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">=20.3.0"
|
|
6
6
|
},
|
|
@@ -20,26 +20,26 @@
|
|
|
20
20
|
"./src/**/*"
|
|
21
21
|
],
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@grpc/grpc-js": "~1.13.
|
|
24
|
-
"@protobuf-ts/grpc-transport": "2.
|
|
25
|
-
"@protobuf-ts/runtime": "2.
|
|
26
|
-
"@protobuf-ts/runtime-rpc": "2.
|
|
23
|
+
"@grpc/grpc-js": "~1.13.4",
|
|
24
|
+
"@protobuf-ts/grpc-transport": "2.11.0",
|
|
25
|
+
"@protobuf-ts/runtime": "2.11.0",
|
|
26
|
+
"@protobuf-ts/runtime-rpc": "2.11.0",
|
|
27
27
|
"canonicalize": "~2.1.0",
|
|
28
28
|
"denque": "^2.1.0",
|
|
29
29
|
"lru-cache": "^11.1.0",
|
|
30
30
|
"https-proxy-agent": "^7.0.6",
|
|
31
|
-
"long": "^5.3.
|
|
32
|
-
"undici": "~7.
|
|
31
|
+
"long": "^5.3.2",
|
|
32
|
+
"undici": "~7.10.0",
|
|
33
33
|
"utility-types": "^3.11.0",
|
|
34
34
|
"yaml": "^2.7.0",
|
|
35
|
-
"@milaboratories/
|
|
36
|
-
"@milaboratories/
|
|
35
|
+
"@milaboratories/pl-http": "^1.1.3",
|
|
36
|
+
"@milaboratories/ts-helpers": "^1.4.0"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"typescript": "~5.5.4",
|
|
40
40
|
"vite": "^6.3.5",
|
|
41
41
|
"@types/node": "~20.16.15",
|
|
42
|
-
"@protobuf-ts/plugin": "2.
|
|
42
|
+
"@protobuf-ts/plugin": "2.11.0",
|
|
43
43
|
"@types/http-proxy": "^1.17.16",
|
|
44
44
|
"@types/jest": "^29.5.14",
|
|
45
45
|
"jest": "^29.7.0",
|
package/src/core/final.ts
CHANGED
|
@@ -71,6 +71,7 @@ export const DefaultFinalResourceDataPredicate: FinalResourceDataPredicate = (r)
|
|
|
71
71
|
case 'json/resourceError':
|
|
72
72
|
return r.type.version === '1';
|
|
73
73
|
case 'json/object':
|
|
74
|
+
case 'json-gz/object':
|
|
74
75
|
case 'json/string':
|
|
75
76
|
case 'json/array':
|
|
76
77
|
case 'json/number':
|
|
@@ -79,6 +80,7 @@ export const DefaultFinalResourceDataPredicate: FinalResourceDataPredicate = (r)
|
|
|
79
80
|
case 'Frontend/FromFolder':
|
|
80
81
|
case 'BObjectSpec':
|
|
81
82
|
case 'Blob':
|
|
83
|
+
case 'Null':
|
|
82
84
|
case 'binary':
|
|
83
85
|
case 'LSProvider':
|
|
84
86
|
return true;
|
|
@@ -92,6 +94,8 @@ export const DefaultFinalResourceDataPredicate: FinalResourceDataPredicate = (r)
|
|
|
92
94
|
return readyAndHasAllOutputsFilled(r);
|
|
93
95
|
} else if (r.type.name.startsWith('PColumnData/')) {
|
|
94
96
|
return readyOrDuplicateOrError(r);
|
|
97
|
+
} else if (r.type.name.startsWith('StreamWorkdir/')) {
|
|
98
|
+
return readyOrDuplicateOrError(r);
|
|
95
99
|
} else {
|
|
96
100
|
// Unknonw resource type detected
|
|
97
101
|
// Set used to log this message only once
|
package/src/core/stat.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export type TxStat = {
|
|
2
2
|
txCount: number;
|
|
3
|
+
timeMs: number;
|
|
3
4
|
|
|
4
5
|
rootsCreated: number;
|
|
5
6
|
structsCreated: number;
|
|
@@ -33,7 +34,9 @@ export type TxStat = {
|
|
|
33
34
|
kvGetBytes: number;
|
|
34
35
|
};
|
|
35
36
|
|
|
36
|
-
export
|
|
37
|
+
export type TxStatWithoutTime = Omit<TxStat, 'timeMs'>;
|
|
38
|
+
|
|
39
|
+
export function initialTxStatWithoutTime(): TxStatWithoutTime {
|
|
37
40
|
return {
|
|
38
41
|
txCount: 0,
|
|
39
42
|
rootsCreated: 0,
|
|
@@ -63,10 +66,17 @@ export function initialTxStat(): TxStat {
|
|
|
63
66
|
kvGetBytes: 0,
|
|
64
67
|
};
|
|
65
68
|
}
|
|
69
|
+
export function initialTxStat(): TxStat {
|
|
70
|
+
return {
|
|
71
|
+
...initialTxStatWithoutTime(),
|
|
72
|
+
timeMs: 0,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
66
75
|
|
|
67
76
|
export function addStat(a: TxStat, b: TxStat): TxStat {
|
|
68
77
|
return {
|
|
69
78
|
txCount: a.txCount + b.txCount,
|
|
79
|
+
timeMs: a.timeMs + b.timeMs,
|
|
70
80
|
rootsCreated: a.rootsCreated + b.rootsCreated,
|
|
71
81
|
structsCreated: a.structsCreated + b.structsCreated,
|
|
72
82
|
structsCreatedDataBytes: a.structsCreatedDataBytes + b.structsCreatedDataBytes,
|
package/src/core/transaction.ts
CHANGED
|
@@ -29,15 +29,16 @@ import { TxAPI_Open_Request_WritableTx } from '../proto/github.com/milaboratory/
|
|
|
29
29
|
import type { NonUndefined } from 'utility-types';
|
|
30
30
|
import { toBytes } from '../util/util';
|
|
31
31
|
import { fieldTypeToProto, protoToField, protoToResource } from './type_conversion';
|
|
32
|
-
import { deepFreeze, notEmpty } from '@milaboratories/ts-helpers';
|
|
32
|
+
import { canonicalJsonBytes, canonicalJsonGzBytes, deepFreeze, notEmpty } from '@milaboratories/ts-helpers';
|
|
33
33
|
import { isNotFoundError } from './errors';
|
|
34
34
|
import type { FinalResourceDataPredicate } from './final';
|
|
35
35
|
import type { LRUCache } from 'lru-cache';
|
|
36
36
|
import type { ResourceDataCacheRecord } from './cache';
|
|
37
37
|
import type { TxStat } from './stat';
|
|
38
|
-
import {
|
|
38
|
+
import { initialTxStatWithoutTime } from './stat';
|
|
39
39
|
import type { ErrorResourceData } from './error_resource';
|
|
40
40
|
import { ErrorResourceType } from './error_resource';
|
|
41
|
+
import { JsonGzObject, JsonObject } from '../helpers/pl';
|
|
41
42
|
|
|
42
43
|
/** Reference to resource, used only within transaction */
|
|
43
44
|
export interface ResourceRef {
|
|
@@ -168,7 +169,14 @@ export class PlTransaction {
|
|
|
168
169
|
|
|
169
170
|
private globalTxIdWasAwaited: boolean = false;
|
|
170
171
|
|
|
171
|
-
|
|
172
|
+
private readonly _startTime = Date.now();
|
|
173
|
+
private readonly _stat = initialTxStatWithoutTime();
|
|
174
|
+
public get stat(): TxStat {
|
|
175
|
+
return {
|
|
176
|
+
...this._stat,
|
|
177
|
+
timeMs: Date.now() - this._startTime,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
172
180
|
|
|
173
181
|
constructor(
|
|
174
182
|
private readonly ll: LLPlTransaction,
|
|
@@ -200,7 +208,7 @@ export class PlTransaction {
|
|
|
200
208
|
});
|
|
201
209
|
|
|
202
210
|
// Adding stats
|
|
203
|
-
this.
|
|
211
|
+
this._stat.txCount++;
|
|
204
212
|
}
|
|
205
213
|
|
|
206
214
|
private async drainAndAwaitPendingOps(): Promise<void> {
|
|
@@ -380,7 +388,7 @@ export class PlTransaction {
|
|
|
380
388
|
}
|
|
381
389
|
|
|
382
390
|
public createRoot(type: ResourceType): ResourceRef {
|
|
383
|
-
this.
|
|
391
|
+
this._stat.rootsCreated++;
|
|
384
392
|
return this.createResource(
|
|
385
393
|
true,
|
|
386
394
|
(localId) => ({ oneofKind: 'resourceCreateRoot', resourceCreateRoot: { type, id: localId } }),
|
|
@@ -389,8 +397,8 @@ export class PlTransaction {
|
|
|
389
397
|
}
|
|
390
398
|
|
|
391
399
|
public createStruct(type: ResourceType, data?: Uint8Array | string): ResourceRef {
|
|
392
|
-
this.
|
|
393
|
-
this.
|
|
400
|
+
this._stat.structsCreated++;
|
|
401
|
+
this._stat.structsCreatedDataBytes += data?.length ?? 0;
|
|
394
402
|
return this.createResource(
|
|
395
403
|
false,
|
|
396
404
|
(localId) => ({
|
|
@@ -406,8 +414,8 @@ export class PlTransaction {
|
|
|
406
414
|
}
|
|
407
415
|
|
|
408
416
|
public createEphemeral(type: ResourceType, data?: Uint8Array | string): ResourceRef {
|
|
409
|
-
this.
|
|
410
|
-
this.
|
|
417
|
+
this._stat.ephemeralsCreated++;
|
|
418
|
+
this._stat.ephemeralsCreatedDataBytes += data?.length ?? 0;
|
|
411
419
|
return this.createResource(
|
|
412
420
|
false,
|
|
413
421
|
(localId) => ({
|
|
@@ -427,8 +435,8 @@ export class PlTransaction {
|
|
|
427
435
|
data: Uint8Array | string,
|
|
428
436
|
errorIfExists: boolean = false,
|
|
429
437
|
): ResourceRef {
|
|
430
|
-
this.
|
|
431
|
-
this.
|
|
438
|
+
this._stat.valuesCreated++;
|
|
439
|
+
this._stat.valuesCreatedDataBytes += data?.length ?? 0;
|
|
432
440
|
return this.createResource(
|
|
433
441
|
false,
|
|
434
442
|
(localId) => ({
|
|
@@ -444,6 +452,16 @@ export class PlTransaction {
|
|
|
444
452
|
);
|
|
445
453
|
}
|
|
446
454
|
|
|
455
|
+
public createJsonValue(data: unknown): ResourceRef {
|
|
456
|
+
const jsonData = canonicalJsonBytes(data);
|
|
457
|
+
return this.createValue(JsonObject, jsonData, false);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
public createJsonGzValue(data: unknown, minSizeToGzip: number | undefined = 16_384): ResourceRef {
|
|
461
|
+
const { data: jsonData, isGzipped } = canonicalJsonGzBytes(data, minSizeToGzip);
|
|
462
|
+
return this.createValue(isGzipped ? JsonGzObject : JsonObject, jsonData, false);
|
|
463
|
+
}
|
|
464
|
+
|
|
447
465
|
public createError(message: string): ResourceRef {
|
|
448
466
|
return this.createValue(ErrorResourceType, JSON.stringify({ message } satisfies ErrorResourceData));
|
|
449
467
|
}
|
|
@@ -521,13 +539,13 @@ export class PlTransaction {
|
|
|
521
539
|
const fromCache = this.sharedResourceDataCache.get(rId);
|
|
522
540
|
if (fromCache && fromCache.cacheTxOpenTimestamp < this.txOpenTimestamp) {
|
|
523
541
|
if (!loadFields) {
|
|
524
|
-
this.
|
|
525
|
-
this.
|
|
542
|
+
this._stat.rGetDataCacheHits++;
|
|
543
|
+
this._stat.rGetDataCacheBytes += fromCache.basicData.data?.length ?? 0;
|
|
526
544
|
return fromCache.basicData;
|
|
527
545
|
} else if (fromCache.data) {
|
|
528
|
-
this.
|
|
529
|
-
this.
|
|
530
|
-
this.
|
|
546
|
+
this._stat.rGetDataCacheHits++;
|
|
547
|
+
this._stat.rGetDataCacheBytes += fromCache.basicData.data?.length ?? 0;
|
|
548
|
+
this._stat.rGetDataCacheFields += fromCache.data.fields.length;
|
|
531
549
|
return fromCache.data;
|
|
532
550
|
}
|
|
533
551
|
}
|
|
@@ -541,9 +559,9 @@ export class PlTransaction {
|
|
|
541
559
|
(r) => protoToResource(notEmpty(r.resourceGet.resource)),
|
|
542
560
|
);
|
|
543
561
|
|
|
544
|
-
this.
|
|
545
|
-
this.
|
|
546
|
-
this.
|
|
562
|
+
this._stat.rGetDataNetRequests++;
|
|
563
|
+
this._stat.rGetDataNetBytes += result.data?.length ?? 0;
|
|
564
|
+
this._stat.rGetDataNetFields += result.fields.length;
|
|
547
565
|
|
|
548
566
|
// we will cache only final resource data states
|
|
549
567
|
// caching result even if we were ignore the cache
|
|
@@ -614,7 +632,7 @@ export class PlTransaction {
|
|
|
614
632
|
* have their values, if inputs list is not locked.
|
|
615
633
|
*/
|
|
616
634
|
public lockInputs(rId: AnyResourceRef): void {
|
|
617
|
-
this.
|
|
635
|
+
this._stat.inputsLocked++;
|
|
618
636
|
this.sendVoidAsync({
|
|
619
637
|
oneofKind: 'resourceLockInputs',
|
|
620
638
|
resourceLockInputs: { resourceId: toResourceId(rId) },
|
|
@@ -626,7 +644,7 @@ export class PlTransaction {
|
|
|
626
644
|
* This is required for resource to pass deduplication.
|
|
627
645
|
*/
|
|
628
646
|
public lockOutputs(rId: AnyResourceRef): void {
|
|
629
|
-
this.
|
|
647
|
+
this._stat.outputsLocked++;
|
|
630
648
|
this.sendVoidAsync({
|
|
631
649
|
oneofKind: 'resourceLockOutputs',
|
|
632
650
|
resourceLockOutputs: { resourceId: toResourceId(rId) },
|
|
@@ -650,7 +668,7 @@ export class PlTransaction {
|
|
|
650
668
|
//
|
|
651
669
|
|
|
652
670
|
public createField(fId: AnyFieldRef, fieldType: FieldType, value?: AnyRef): void {
|
|
653
|
-
this.
|
|
671
|
+
this._stat.fieldsCreated++;
|
|
654
672
|
this.sendVoidAsync({
|
|
655
673
|
oneofKind: 'fieldCreate',
|
|
656
674
|
fieldCreate: { type: fieldTypeToProto(fieldType), id: toFieldId(fId) },
|
|
@@ -669,7 +687,7 @@ export class PlTransaction {
|
|
|
669
687
|
}
|
|
670
688
|
|
|
671
689
|
public setField(fId: AnyFieldRef, ref: AnyRef): void {
|
|
672
|
-
this.
|
|
690
|
+
this._stat.fieldsSet++;
|
|
673
691
|
if (isResource(ref))
|
|
674
692
|
this.sendVoidAsync({
|
|
675
693
|
oneofKind: 'fieldSet',
|
|
@@ -692,7 +710,7 @@ export class PlTransaction {
|
|
|
692
710
|
}
|
|
693
711
|
|
|
694
712
|
public setFieldError(fId: AnyFieldRef, ref: AnyResourceRef): void {
|
|
695
|
-
this.
|
|
713
|
+
this._stat.fieldsSet++;
|
|
696
714
|
this.sendVoidAsync({
|
|
697
715
|
oneofKind: 'fieldSetError',
|
|
698
716
|
fieldSetError: { field: toFieldId(fId), errResourceId: toResourceId(ref) },
|
|
@@ -700,7 +718,7 @@ export class PlTransaction {
|
|
|
700
718
|
}
|
|
701
719
|
|
|
702
720
|
public async getField(fId: AnyFieldRef): Promise<FieldData> {
|
|
703
|
-
this.
|
|
721
|
+
this._stat.fieldsGet++;
|
|
704
722
|
return await this.sendSingleAndParse(
|
|
705
723
|
{ oneofKind: 'fieldGet', fieldGet: { field: toFieldId(fId) } },
|
|
706
724
|
(r) => protoToField(notEmpty(r.fieldGet.field)),
|
|
@@ -732,9 +750,9 @@ export class PlTransaction {
|
|
|
732
750
|
(r) => r.map((e) => e.resourceKeyValueList.record!),
|
|
733
751
|
);
|
|
734
752
|
|
|
735
|
-
this.
|
|
736
|
-
this.
|
|
737
|
-
for (const kv of result) this.
|
|
753
|
+
this._stat.kvListRequests++;
|
|
754
|
+
this._stat.kvListEntries += result.length;
|
|
755
|
+
for (const kv of result) this._stat.kvListBytes += kv.key.length + kv.value.length;
|
|
738
756
|
|
|
739
757
|
return result;
|
|
740
758
|
}
|
|
@@ -757,8 +775,8 @@ export class PlTransaction {
|
|
|
757
775
|
}
|
|
758
776
|
|
|
759
777
|
public setKValue(rId: AnyResourceRef, key: string, value: Uint8Array | string): void {
|
|
760
|
-
this.
|
|
761
|
-
this.
|
|
778
|
+
this._stat.kvSetRequests++;
|
|
779
|
+
this._stat.kvSetBytes++;
|
|
762
780
|
this.sendVoidAsync({
|
|
763
781
|
oneofKind: 'resourceKeyValueSet',
|
|
764
782
|
resourceKeyValueSet: {
|
|
@@ -788,8 +806,8 @@ export class PlTransaction {
|
|
|
788
806
|
(r) => r.resourceKeyValueGet.value,
|
|
789
807
|
);
|
|
790
808
|
|
|
791
|
-
this.
|
|
792
|
-
this.
|
|
809
|
+
this._stat.kvGetRequests++;
|
|
810
|
+
this._stat.kvGetBytes += result.length;
|
|
793
811
|
|
|
794
812
|
return result;
|
|
795
813
|
}
|
|
@@ -815,8 +833,8 @@ export class PlTransaction {
|
|
|
815
833
|
r.resourceKeyValueGetIfExists.exists ? r.resourceKeyValueGetIfExists.value : undefined,
|
|
816
834
|
);
|
|
817
835
|
|
|
818
|
-
this.
|
|
819
|
-
this.
|
|
836
|
+
this._stat.kvGetRequests++;
|
|
837
|
+
this._stat.kvGetBytes += result?.length ?? 0;
|
|
820
838
|
|
|
821
839
|
return result;
|
|
822
840
|
}
|
package/src/helpers/pl.ts
CHANGED
|
@@ -23,6 +23,7 @@ export const ValueTestResource = rt('ValueTest', '1');
|
|
|
23
23
|
export const JsonString = rt('json/string', '1');
|
|
24
24
|
export const JsonBool = rt('json/bool', '1');
|
|
25
25
|
export const JsonObject = rt('json/object', '1');
|
|
26
|
+
export const JsonGzObject = rt('json-gz/object', '1');
|
|
26
27
|
export const JsonArray = rt('json/array', '1');
|
|
27
28
|
export const JsonNumber = rt('json/number', '1');
|
|
28
29
|
export const JsonNull = rt('json/null', '1');
|