@milaboratories/pl-tree 1.4.34 → 1.5.1
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/dump.d.ts +59 -0
- package/dist/dump.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +292 -225
- package/dist/index.mjs.map +1 -1
- package/dist/state.d.ts +4 -1
- package/dist/state.d.ts.map +1 -1
- package/dist/synchronized_tree.d.ts +6 -0
- package/dist/synchronized_tree.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/dump.ts +115 -0
- package/src/index.ts +1 -0
- package/src/state.ts +26 -3
- package/src/synchronized_tree.ts +9 -1
package/dist/dump.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { ExtendedResourceData } from './state';
|
|
2
|
+
export type ResourceStats = {
|
|
3
|
+
/** Number of resources of this type */
|
|
4
|
+
count: number;
|
|
5
|
+
/** Total number of bytes in the field names of all resources of this type */
|
|
6
|
+
fieldNameBytes: number;
|
|
7
|
+
/** Total number of fields in all resources of this type */
|
|
8
|
+
fieldsCount: number;
|
|
9
|
+
/** Total number of bytes in the data of all resources of this type */
|
|
10
|
+
dataBytes: number;
|
|
11
|
+
/** Total number of key-value records in all resources of this type */
|
|
12
|
+
kvCount: number;
|
|
13
|
+
/** Total number of bytes in the key-value records of all resources of this type */
|
|
14
|
+
kvBytes: number;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* A map of resource type statistics, keyed by the resource type name and version.
|
|
18
|
+
*
|
|
19
|
+
* @type {Record<string, ResourceStats>}
|
|
20
|
+
*/
|
|
21
|
+
export type TreeDumpStats = {
|
|
22
|
+
total: ResourceStats;
|
|
23
|
+
byResourceType: Record<`${string}/${string}`, ResourceStats>;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Analyzes a collection of resources and generates statistics grouped by resource type.
|
|
27
|
+
*
|
|
28
|
+
* This function processes an array of ExtendedResourceData and calculates various metrics
|
|
29
|
+
* for each unique resource type, including:
|
|
30
|
+
* - Count of resources
|
|
31
|
+
* - Total bytes in field names
|
|
32
|
+
* - Total number of fields
|
|
33
|
+
* - Total bytes in resource data
|
|
34
|
+
* - Total number of key-value records
|
|
35
|
+
* - Total bytes in key-value records
|
|
36
|
+
*
|
|
37
|
+
* The statistics are organized by resource type using a key in the format "typeName/version".
|
|
38
|
+
*
|
|
39
|
+
* @param dumpStats - Array of ExtendedResourceData objects to analyze
|
|
40
|
+
* @returns A DumpStats object containing statistics for each resource type
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* const resources = [...]; // Array of ExtendedResourceData
|
|
44
|
+
* const stats = treeDumpStats(resources);
|
|
45
|
+
* // stats = {
|
|
46
|
+
* // "MyResource/1": {
|
|
47
|
+
* // count: 5,
|
|
48
|
+
* // fieldNameBytes: 150,
|
|
49
|
+
* // fieldsCount: 10,
|
|
50
|
+
* // dataBytes: 1024,
|
|
51
|
+
* // kvCount: 3,
|
|
52
|
+
* // kvBytes: 256
|
|
53
|
+
* // },
|
|
54
|
+
* // ...
|
|
55
|
+
* // }
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare function treeDumpStats(dumpStats: ExtendedResourceData[]): TreeDumpStats;
|
|
59
|
+
//# sourceMappingURL=dump.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dump.d.ts","sourceRoot":"","sources":["../src/dump.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAE9C,MAAM,MAAM,aAAa,GAAG;IACxB,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,cAAc,EAAE,MAAM,CAAC;IACvB,2DAA2D;IAC3D,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,mFAAmF;IACnF,OAAO,EAAE,MAAM,CAAC;CACnB,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG;IACxB,KAAK,EAAE,aAAa,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC,GAAG,MAAM,IAAI,MAAM,EAAE,EAAE,aAAa,CAAC,CAAA;CAC/D,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,oBAAoB,EAAE,GAAG,aAAa,CAsD9E"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,QAAQ,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var K=Object.defineProperty;var M=(o,e,t)=>e in o?K(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var c=(o,e,t)=>M(o,typeof e!="symbol"?e+"":e,t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const g=require("@milaboratories/pl-client"),m=require("@milaboratories/computable"),O=require("@milaboratories/pl-errors"),p=require("@milaboratories/ts-helpers"),q=require("denque"),U=require("node:timers/promises");function J(o){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(o){for(const t in o)if(t!=="default"){const r=Object.getOwnPropertyDescriptor(o,t);Object.defineProperty(e,t,r.get?r:{enumerable:!0,get:()=>o[t]})}}return e.default=o,Object.freeze(e)}const B=J(U);function z(o,e){if(o!==void 0)return F(o,e)}function F(o,e){const t={};return o.value!==void 0&&(t.value=e(o.value)),o.error!==void 0&&(t.error=e(o.error)),t}function j(o){return typeof o=="object"&&o!==null&&o.__pl_tree_type_marker__==="PlTreeEntry"}function H(o){return typeof o=="object"&&o!==null&&o.__pl_tree_type_marker__==="PlTreeEntryAccessor"}function Y(o){return typeof o=="object"&&o!==null&&o.__pl_tree_type_marker__==="PlTreeNodeAccessor"}class S{constructor(e,t){c(this,"__pl_tree_type_marker__","PlTreeEntry");this.accessorData=e,this.rid=t}createAccessor(e,t){return new T(this.accessorData,this.accessorData.treeProvider(),this.rid,{ctx:e,guard:t})}toJSON(){return this.toString()}toString(){return`[ENTRY:${g.resourceIdToString(this.rid)}]`}}function P(o,e,t,r,s){const n=new $(o,e,e.get(t.ctx.watcher,r),t);if(!s.ignoreError){const a=n.getError();if(a!==void 0)throw O.parsePlError(p.notEmpty(a.getDataAsString()),n.id,n.resourceType)}if(s.assertResourceType!==void 0&&(Array.isArray(s.assertResourceType)?s.assertResourceType.findIndex(a=>g.resourceTypesEqual(a,n.resourceType))===-1:!g.resourceTypesEqual(s.assertResourceType,n.resourceType)))throw new Error(`wrong resource type ${g.resourceTypeToString(n.resourceType)} but expected ${s.assertResourceType}`);return n}class T{constructor(e,t,r,s){c(this,"__pl_tree_type_marker__","PlTreeEntryAccessor");this.accessorData=e,this.tree=t,this.rid=r,this.instanceData=s}node(e={}){return this.instanceData.guard(),this.accessorData.hooks!==void 0&&this.instanceData.ctx.attacheHooks(this.accessorData.hooks),P(this.accessorData,this.tree,this.instanceData,this.rid,e)}}function G(o,e){return o instanceof S?e.accessor(o).node().resourceInfo:o}class ${constructor(e,t,r,s){c(this,"__pl_tree_type_marker__","PlTreeNodeAccessor");c(this,"onUnstableLambda",e=>{this.instanceData.ctx.markUnstable(e)});this.accessorData=e,this.tree=t,this.resource=r,this.instanceData=s}get id(){return this.instanceData.guard(),this.resource.id}get originalId(){return this.instanceData.guard(),this.resource.originalResourceId}get resourceType(){return this.instanceData.guard(),this.resource.type}get resourceInfo(){return{id:this.id,type:this.resourceType}}getResourceFromTree(e,t){return P(this.accessorData,this.tree,this.instanceData,e,t)}traverse(...e){return this.traverseWithCommon({},...e)}traverseOrError(...e){return this.traverseOrErrorWithCommon({},...e)}traverseWithCommon(e,...t){const r=this.traverseOrErrorWithCommon(e,...t);if(r!==void 0){if(!r.ok)throw r.error;return r.value}}traverseOrErrorWithCommon(e,...t){let r=this;for(const s of t){const n=typeof s=="string"?{...e,field:s}:{...e,...s},a=r.getField(s);if(a===void 0||n.pureFieldErrorToUndefined&&a.value===void 0&&a.error!==void 0)return;if((!n.ignoreError||a.value===void 0)&&a.error!==void 0)return{ok:!1,error:O.parsePlError(p.notEmpty(a.error.getDataAsString()),r.id,r.resourceType,n.field)};if(a.value===void 0){if(n.errorIfFieldNotSet)return{ok:!1,error:`field have no assigned value ${n.field} of ${g.resourceIdToString(r.id)}`};this.onUnstableLambda("unpopulated_field:"+n.field);return}r=a.value}return{ok:!0,value:r}}getField(e){this.instanceData.guard();const t=typeof e=="string"?{field:e}:e,r=this.resource.getField(this.instanceData.ctx.watcher,t,this.onUnstableLambda);if(r!==void 0)return F(r,s=>this.getResourceFromTree(s,{ignoreError:!0}))}getInputsLocked(){this.instanceData.guard();const e=this.resource.getInputsLocked(this.instanceData.ctx.watcher);return e||this.instanceData.ctx.markUnstable("inputs_unlocked:"+this.resourceType.name),e}getOutputsLocked(){this.instanceData.guard();const e=this.resource.getOutputsLocked(this.instanceData.ctx.watcher);return e||this.instanceData.ctx.markUnstable("outputs_unlocked:"+this.resourceType.name),e}getIsReadyOrError(){this.instanceData.guard();const e=this.resource.getIsReadyOrError(this.instanceData.ctx.watcher);return e||this.instanceData.ctx.markUnstable("not_ready:"+this.resourceType.name),e}getIsFinal(){return this.instanceData.guard(),this.resource.getIsFinal(this.instanceData.ctx.watcher)}getError(){this.instanceData.guard();const e=this.resource.getError(this.instanceData.ctx.watcher);if(e!==void 0)return this.getResourceFromTree(e,{})}getData(){return this.resource.data}getDataAsString(){return this.resource.getDataAsString()}getDataAsJson(){return this.resource.getDataAsJson()}listInputFields(){return this.instanceData.guard(),this.getInputsLocked(),this.resource.listInputFields(this.instanceData.ctx.watcher)}listOutputFields(){return this.instanceData.guard(),this.getOutputsLocked(),this.resource.listOutputFields(this.instanceData.ctx.watcher)}listDynamicFields(){return this.instanceData.guard(),this.resource.listDynamicFields(this.instanceData.ctx.watcher)}getKeyValue(e,t=!1){this.instanceData.guard();const r=this.resource.getKeyValue(this.instanceData.ctx.watcher,e);return r===void 0&&t&&this.instanceData.ctx.markUnstable("key_not_found_b:"+e),r}getKeyValueString(e){return this.getKeyValueAsString(e)}getKeyValueAsString(e,t=!1){this.instanceData.guard();const r=this.resource.getKeyValueString(this.instanceData.ctx.watcher,e);return r===void 0&&t&&this.instanceData.ctx.markUnstable("key_not_found_s:"+e),r}getKeyValueAsJson(e,t=!1){const r=this.resource.getKeyValueString(this.instanceData.ctx.watcher,e);if(r===void 0){t&&this.instanceData.ctx.markUnstable("key_not_found_j:"+e);return}return JSON.parse(r)}toEntryAccessor(){return new T(this.accessorData,this.tree,this.id,this.instanceData)}persist(){return new S(this.accessorData,this.resource.id)}}class w extends Error{constructor(e){super(e)}}class _{constructor(e,t,r,s,n,a,i){c(this,"change",new m.ChangeSource);this.name=e,this.type=t,this.value=r,this.error=s,this.status=n,this.valueIsFinal=a,this.resourceVersion=i}}const E=0,A=new TextDecoder;class b{constructor(e,t){c(this,"refCount",0);c(this,"version",E);c(this,"dataVersion",E);c(this,"fieldsMap",new Map);c(this,"kv",new Map);c(this,"resourceRemoved",new m.ChangeSource);c(this,"finalChanged",new m.ChangeSource);c(this,"resourceStateChange",new m.ChangeSource);c(this,"lockedChange",new m.ChangeSource);c(this,"inputAndServiceFieldListChanged",new m.ChangeSource);c(this,"outputFieldListChanged",new m.ChangeSource);c(this,"dynamicFieldListChanged",new m.ChangeSource);c(this,"kvChanged",new m.ChangeSource);c(this,"id");c(this,"originalResourceId");c(this,"kind");c(this,"type");c(this,"data");c(this,"dataAsString");c(this,"dataAsJson");c(this,"error");c(this,"inputsLocked");c(this,"outputsLocked");c(this,"resourceReady");c(this,"finalFlag");c(this,"_finalState",!1);c(this,"logger");this.id=e.id,this.originalResourceId=e.originalResourceId,this.kind=e.kind,this.type=e.type,this.data=e.data,this.error=e.error,this.inputsLocked=e.inputsLocked,this.outputsLocked=e.outputsLocked,this.resourceReady=e.resourceReady,this.finalFlag=e.final,this.logger=t}info(e){this.logger!==void 0&&this.logger.info(e)}warn(e){this.logger!==void 0&&this.logger.warn(e)}get final(){return this.finalFlag}get finalState(){return this._finalState}get fields(){return[...this.fieldsMap.values()]}getField(e,t,r=()=>{}){var a,i,f;const s=typeof t=="string"?{field:t}:t,n=this.fieldsMap.get(s.field);if(n===void 0){if(s.errorIfFieldNotFound||s.errorIfFieldNotSet)throw new Error(`Field "${s.field}" not found in resource ${g.resourceIdToString(this.id)}`);if(!this.inputsLocked)(a=this.inputAndServiceFieldListChanged)==null||a.attachWatcher(e);else if(s.assertFieldType==="Service"||s.assertFieldType==="Input"){if(s.allowPermanentAbsence)return;throw new Error(`Service or input field not found ${s.field}.`)}if(!this.outputsLocked)(i=this.outputFieldListChanged)==null||i.attachWatcher(e);else if(s.assertFieldType==="Output"){if(s.allowPermanentAbsence)return;throw new Error(`Output field not found ${s.field}.`)}(f=this.dynamicFieldListChanged)==null||f.attachWatcher(e),!this._finalState&&!s.stableIfNotFound&&r("field_not_found:"+s.field);return}else{if(s.assertFieldType!==void 0&&n.type!==s.assertFieldType)throw new Error(`Unexpected field type: expected ${s.assertFieldType} but got ${n.type} for the field name ${s.field}`);const l={};return g.isNotNullResourceId(n.value)&&(l.value=n.value),g.isNotNullResourceId(n.error)&&(l.error=n.error),l.value===void 0&&l.error===void 0&&r("field_not_resolved:"+s.field),n.change.attachWatcher(e),l}}getInputsLocked(e){var t;return this.inputsLocked||(t=this.resourceStateChange)==null||t.attachWatcher(e),this.inputsLocked}getOutputsLocked(e){var t;return this.outputsLocked||(t=this.resourceStateChange)==null||t.attachWatcher(e),this.outputsLocked}get isReadyOrError(){return this.error!==g.NullResourceId||this.resourceReady||this.originalResourceId!==g.NullResourceId}getIsFinal(e){var t;return(t=this.finalChanged)==null||t.attachWatcher(e),this._finalState}getIsReadyOrError(e){var t;return this.isReadyOrError||(t=this.resourceStateChange)==null||t.attachWatcher(e),this.isReadyOrError}getError(e){var t;if(g.isNullResourceId(this.error)){(t=this.resourceStateChange)==null||t.attachWatcher(e);return}else return this.error}listInputFields(e){var r;const t=[];return this.fieldsMap.forEach((s,n)=>{(s.type==="Input"||s.type==="Service")&&t.push(n)}),this.inputsLocked||(r=this.inputAndServiceFieldListChanged)==null||r.attachWatcher(e),t}listOutputFields(e){var r;const t=[];return this.fieldsMap.forEach((s,n)=>{s.type==="Output"&&t.push(n)}),this.outputsLocked||(r=this.outputFieldListChanged)==null||r.attachWatcher(e),t}listDynamicFields(e){var r;const t=[];return this.fieldsMap.forEach((s,n)=>{s.type!=="Input"&&s.type!=="Output"&&t.push(n)}),(r=this.dynamicFieldListChanged)==null||r.attachWatcher(e),t}getKeyValue(e,t){var r;return(r=this.kvChanged)==null||r.attachWatcher(e),this.kv.get(t)}getKeyValueString(e,t){const r=this.getKeyValue(e,t);if(r!==void 0)return A.decode(r)}getDataAsString(){if(this.data!==void 0)return this.dataAsString===void 0&&(this.dataAsString=A.decode(this.data)),this.dataAsString}getDataAsJson(){if(this.data!==void 0)return this.dataAsJson===void 0&&(this.dataAsJson=JSON.parse(this.getDataAsString())),this.dataAsJson}verifyReadyState(){if(this.resourceReady&&!this.inputsLocked)throw new Error(`ready without input or output lock: ${g.stringifyWithResourceId(this.state)}`)}get state(){return{id:this.id,kind:this.kind,type:this.type,data:this.data,resourceReady:this.resourceReady,inputsLocked:this.inputsLocked,outputsLocked:this.outputsLocked,error:this.error,originalResourceId:this.originalResourceId,final:this.finalFlag}}markFinal(){this._finalState||(this._finalState=!0,p.notEmpty(this.finalChanged).markChanged(),this.finalChanged=void 0,this.resourceStateChange=void 0,this.dynamicFieldListChanged=void 0,this.inputAndServiceFieldListChanged=void 0,this.outputFieldListChanged=void 0,this.lockedChange=void 0)}markAllChanged(){var e,t,r,s,n,a,i;this.fieldsMap.forEach(f=>f.change.markChanged()),(e=this.finalChanged)==null||e.markChanged(),(t=this.resourceStateChange)==null||t.markChanged(),(r=this.lockedChange)==null||r.markChanged(),(s=this.inputAndServiceFieldListChanged)==null||s.markChanged(),(n=this.outputFieldListChanged)==null||n.markChanged(),(a=this.dynamicFieldListChanged)==null||a.markChanged(),(i=this.kvChanged)==null||i.markChanged(),this.resourceRemoved.markChanged()}}class I{constructor(e,t){c(this,"resources",new Map);c(this,"resourcesAdded",new m.ChangeSource);c(this,"_isValid",!0);c(this,"invalidationMessage");this.root=e,this.isFinalPredicate=t}forEachResource(e){this.resources.forEach(t=>e(t))}checkValid(){if(!this._isValid)throw new Error(this.invalidationMessage??"tree is in invalid state")}get(e,t){this.checkValid();const r=this.resources.get(t);if(r===void 0)throw this.resourcesAdded.attachWatcher(e),new Error(`resource ${g.resourceIdToString(t)} not found in the tree`);return r.resourceRemoved.attachWatcher(e),r}updateFromResourceData(e,t=!1){this.checkValid();const r=[],s=[];for(const a of e){let i=this.resources.get(a.id);const f=i==null?void 0:i.state,l=h=>{const{fields:k,...u}=a;throw this.invalidateTree(),new w(`Unexpected resource state transition (${h}): ${g.stringifyWithResourceId(u)} -> ${g.stringifyWithResourceId(f)}`)};if(i!==void 0){i.finalState&&l("resource state can be updated after it is marked as final");let h=!1;i.version+=1,i.originalResourceId!==a.originalResourceId&&(i.originalResourceId!==g.NullResourceId&&l("originalResourceId can't change after it is set"),i.originalResourceId=a.originalResourceId,p.notEmpty(i.resourceStateChange).markChanged(),h=!0),i.error!==a.error&&(g.isNotNullResourceId(i.error)&&l("resource can't change attached error after it is set"),i.error=a.error,r.push(i.error),p.notEmpty(i.resourceStateChange).markChanged(),h=!0);for(const u of a.fields){let d=i.fieldsMap.get(u.name);d?(d.type!==u.type&&(d.type!=="Dynamic"&&l(`field changed type ${d.type} -> ${u.type}`),p.notEmpty(i.dynamicFieldListChanged).markChanged(),(d.type==="Input"||d.type==="Service")&&(i.inputsLocked&&l(`adding input field "${u.name}", while corresponding list is locked`),p.notEmpty(i.inputAndServiceFieldListChanged).markChanged()),d.type==="Output"&&(i.outputsLocked&&l(`adding output field "${u.name}", while corresponding list is locked`),p.notEmpty(i.outputFieldListChanged).markChanged()),d.type=u.type,d.change.markChanged(),h=!0),d.value!==u.value&&(g.isNotNullResourceId(d.value)&&s.push(d.value),d.value=u.value,g.isNotNullResourceId(u.value)&&r.push(u.value),d.change.markChanged(),h=!0),d.error!==u.error&&(g.isNotNullResourceId(d.error)&&s.push(d.error),d.error=u.error,g.isNotNullResourceId(u.error)&&r.push(u.error),d.change.markChanged(),h=!0),d.status!==u.status&&(d.status=u.status,d.change.markChanged(),h=!0),d.valueIsFinal!==u.valueIsFinal&&(d.valueIsFinal=u.valueIsFinal,d.change.markChanged(),h=!0),d.resourceVersion=i.version):(d=new _(u.name,u.type,u.value,u.error,u.status,u.valueIsFinal,i.version),g.isNotNullResourceId(u.value)&&r.push(u.value),g.isNotNullResourceId(u.error)&&r.push(u.error),u.type==="Input"||u.type==="Service"?(i.inputsLocked&&l(`adding ${u.type} (${u.name}) field while inputs locked`),p.notEmpty(i.inputAndServiceFieldListChanged).markChanged()):u.type==="Output"?(i.outputsLocked&&l(`adding ${u.type} (${u.name}) field while outputs locked`),p.notEmpty(i.outputFieldListChanged).markChanged()):p.notEmpty(i.dynamicFieldListChanged).markChanged(),i.fieldsMap.set(u.name,d),h=!0)}if(i.fieldsMap.forEach((u,d,y)=>{u.resourceVersion!==i.version&&((u.type==="Input"||u.type==="Service"||u.type==="Output")&&l(`removal of ${u.type} field ${d}`),u.change.markChanged(),y.delete(d),g.isNotNullResourceId(u.value)&&s.push(u.value),g.isNotNullResourceId(u.error)&&s.push(u.error),p.notEmpty(i.dynamicFieldListChanged).markChanged())}),i.inputsLocked!==a.inputsLocked&&(i.inputsLocked&&l("inputs unlocking is not permitted"),i.inputsLocked=a.inputsLocked,p.notEmpty(i.lockedChange).markChanged(),h=!0),i.outputsLocked!==a.outputsLocked&&(i.outputsLocked&&l("outputs unlocking is not permitted"),i.outputsLocked=a.outputsLocked,p.notEmpty(i.lockedChange).markChanged(),h=!0),i.resourceReady!==a.resourceReady){const u=i.resourceReady;i.resourceReady=a.resourceReady,i.verifyReadyState(),i.isReadyOrError||l(`resource can't lose it's ready or error state (ready state before ${u})`),p.notEmpty(i.resourceStateChange).markChanged(),h=!0}let k=!1;for(const u of a.kv){const d=i.kv.get(u.key);(d===void 0||Buffer.compare(d,u.value)!==0)&&(i.kv.set(u.key,u.value),k=!0)}if(i.kv.size>a.kv.length){const u=new Set(a.kv.map(d=>d.key));i.kv.forEach((d,y,v)=>{u.has(y)||v.delete(y)}),k=!0}k&&p.notEmpty(i.kvChanged).markChanged(),h&&(i.dataVersion=i.version,this.isFinalPredicate(i)&&i.markFinal())}else{i=new b(a),i.verifyReadyState(),g.isNotNullResourceId(i.error)&&r.push(i.error);for(const h of a.fields){const k=new _(h.name,h.type,h.value,h.error,h.status,h.valueIsFinal,E);g.isNotNullResourceId(h.value)&&r.push(h.value),g.isNotNullResourceId(h.error)&&r.push(h.error),i.fieldsMap.set(h.name,k)}for(const h of a.kv)i.kv.set(h.key,h.value);this.isFinalPredicate(i)&&i.markFinal(),this.resources.set(i.id,i),this.resourcesAdded.markChanged()}}for(const a of r){const i=this.resources.get(a);if(!i)throw this.invalidateTree(),new w(`orphan resource ${a}`);i.refCount++}let n=s;for(;n.length>0;){const a=[];for(const i of n){const f=this.resources.get(i);if(!f)throw this.invalidateTree(),new w(`orphan resource ${i}`);f.refCount--,f.refCount===0&&f.id!==this.root&&(f.fieldsMap.forEach(l=>{g.isNotNullResourceId(l.value)&&a.push(l.value),g.isNotNullResourceId(l.error)&&a.push(l.error),l.change.markChanged()}),g.isNotNullResourceId(f.error)&&a.push(f.error),f.resourceRemoved.markChanged(),this.resources.delete(i))}n=a}if(!t){for(const a of e)if(!this.resources.has(a.id))throw this.invalidateTree(),new w(`orphan input resource ${a.id}`)}}accessor(e=this.root){return this.checkValid(),this.entry(e)}entry(e=this.root){return this.checkValid(),new S({treeProvider:()=>this},e)}invalidateTree(e){this._isValid=!1,this.invalidationMessage=e,this.resources.forEach(t=>{t.markAllChanged()})}}function x(o,e){const t=[],r=new Set;return o.forEachResource(s=>{s.finalState?r.add(s.id):t.push(s.id)}),t.length===0&&r.size===0&&t.push(o.root),{seedResources:t,finalResources:r,pruningFunction:e}}function C(){return{requests:0,roundTrips:0,retrievedResources:0,retrievedFields:0,retrievedKeyValues:0,retrievedResourceDataBytes:0,retrievedKeyValueBytes:0,prunedFields:0,finalResourcesSkipped:0,millisSpent:0}}function Q(o){let e=`Requests: ${o.requests}
|
|
1
|
+
"use strict";var K=Object.defineProperty;var B=(o,e,t)=>e in o?K(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var c=(o,e,t)=>B(o,typeof e!="symbol"?e+"":e,t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const g=require("@milaboratories/pl-client"),m=require("@milaboratories/computable"),b=require("@milaboratories/pl-errors"),p=require("@milaboratories/ts-helpers"),M=require("denque"),q=require("node:timers/promises");function U(o){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(o){for(const t in o)if(t!=="default"){const r=Object.getOwnPropertyDescriptor(o,t);Object.defineProperty(e,t,r.get?r:{enumerable:!0,get:()=>o[t]})}}return e.default=o,Object.freeze(e)}const J=U(q);function z(o,e){if(o!==void 0)return F(o,e)}function F(o,e){const t={};return o.value!==void 0&&(t.value=e(o.value)),o.error!==void 0&&(t.error=e(o.error)),t}function j(o){return typeof o=="object"&&o!==null&&o.__pl_tree_type_marker__==="PlTreeEntry"}function H(o){return typeof o=="object"&&o!==null&&o.__pl_tree_type_marker__==="PlTreeEntryAccessor"}function Y(o){return typeof o=="object"&&o!==null&&o.__pl_tree_type_marker__==="PlTreeNodeAccessor"}class S{constructor(e,t){c(this,"__pl_tree_type_marker__","PlTreeEntry");this.accessorData=e,this.rid=t}createAccessor(e,t){return new T(this.accessorData,this.accessorData.treeProvider(),this.rid,{ctx:e,guard:t})}toJSON(){return this.toString()}toString(){return`[ENTRY:${g.resourceIdToString(this.rid)}]`}}function O(o,e,t,r,i){const n=new P(o,e,e.get(t.ctx.watcher,r),t);if(!i.ignoreError){const a=n.getError();if(a!==void 0)throw b.parsePlError(p.notEmpty(a.getDataAsString()),n.id,n.resourceType)}if(i.assertResourceType!==void 0&&(Array.isArray(i.assertResourceType)?i.assertResourceType.findIndex(a=>g.resourceTypesEqual(a,n.resourceType))===-1:!g.resourceTypesEqual(i.assertResourceType,n.resourceType)))throw new Error(`wrong resource type ${g.resourceTypeToString(n.resourceType)} but expected ${i.assertResourceType}`);return n}class T{constructor(e,t,r,i){c(this,"__pl_tree_type_marker__","PlTreeEntryAccessor");this.accessorData=e,this.tree=t,this.rid=r,this.instanceData=i}node(e={}){return this.instanceData.guard(),this.accessorData.hooks!==void 0&&this.instanceData.ctx.attacheHooks(this.accessorData.hooks),O(this.accessorData,this.tree,this.instanceData,this.rid,e)}}function G(o,e){return o instanceof S?e.accessor(o).node().resourceInfo:o}class P{constructor(e,t,r,i){c(this,"__pl_tree_type_marker__","PlTreeNodeAccessor");c(this,"onUnstableLambda",e=>{this.instanceData.ctx.markUnstable(e)});this.accessorData=e,this.tree=t,this.resource=r,this.instanceData=i}get id(){return this.instanceData.guard(),this.resource.id}get originalId(){return this.instanceData.guard(),this.resource.originalResourceId}get resourceType(){return this.instanceData.guard(),this.resource.type}get resourceInfo(){return{id:this.id,type:this.resourceType}}getResourceFromTree(e,t){return O(this.accessorData,this.tree,this.instanceData,e,t)}traverse(...e){return this.traverseWithCommon({},...e)}traverseOrError(...e){return this.traverseOrErrorWithCommon({},...e)}traverseWithCommon(e,...t){const r=this.traverseOrErrorWithCommon(e,...t);if(r!==void 0){if(!r.ok)throw r.error;return r.value}}traverseOrErrorWithCommon(e,...t){let r=this;for(const i of t){const n=typeof i=="string"?{...e,field:i}:{...e,...i},a=r.getField(i);if(a===void 0||n.pureFieldErrorToUndefined&&a.value===void 0&&a.error!==void 0)return;if((!n.ignoreError||a.value===void 0)&&a.error!==void 0)return{ok:!1,error:b.parsePlError(p.notEmpty(a.error.getDataAsString()),r.id,r.resourceType,n.field)};if(a.value===void 0){if(n.errorIfFieldNotSet)return{ok:!1,error:`field have no assigned value ${n.field} of ${g.resourceIdToString(r.id)}`};this.onUnstableLambda("unpopulated_field:"+n.field);return}r=a.value}return{ok:!0,value:r}}getField(e){this.instanceData.guard();const t=typeof e=="string"?{field:e}:e,r=this.resource.getField(this.instanceData.ctx.watcher,t,this.onUnstableLambda);if(r!==void 0)return F(r,i=>this.getResourceFromTree(i,{ignoreError:!0}))}getInputsLocked(){this.instanceData.guard();const e=this.resource.getInputsLocked(this.instanceData.ctx.watcher);return e||this.instanceData.ctx.markUnstable("inputs_unlocked:"+this.resourceType.name),e}getOutputsLocked(){this.instanceData.guard();const e=this.resource.getOutputsLocked(this.instanceData.ctx.watcher);return e||this.instanceData.ctx.markUnstable("outputs_unlocked:"+this.resourceType.name),e}getIsReadyOrError(){this.instanceData.guard();const e=this.resource.getIsReadyOrError(this.instanceData.ctx.watcher);return e||this.instanceData.ctx.markUnstable("not_ready:"+this.resourceType.name),e}getIsFinal(){return this.instanceData.guard(),this.resource.getIsFinal(this.instanceData.ctx.watcher)}getError(){this.instanceData.guard();const e=this.resource.getError(this.instanceData.ctx.watcher);if(e!==void 0)return this.getResourceFromTree(e,{})}getData(){return this.resource.data}getDataAsString(){return this.resource.getDataAsString()}getDataAsJson(){return this.resource.getDataAsJson()}listInputFields(){return this.instanceData.guard(),this.getInputsLocked(),this.resource.listInputFields(this.instanceData.ctx.watcher)}listOutputFields(){return this.instanceData.guard(),this.getOutputsLocked(),this.resource.listOutputFields(this.instanceData.ctx.watcher)}listDynamicFields(){return this.instanceData.guard(),this.resource.listDynamicFields(this.instanceData.ctx.watcher)}getKeyValue(e,t=!1){this.instanceData.guard();const r=this.resource.getKeyValue(this.instanceData.ctx.watcher,e);return r===void 0&&t&&this.instanceData.ctx.markUnstable("key_not_found_b:"+e),r}getKeyValueString(e){return this.getKeyValueAsString(e)}getKeyValueAsString(e,t=!1){this.instanceData.guard();const r=this.resource.getKeyValueString(this.instanceData.ctx.watcher,e);return r===void 0&&t&&this.instanceData.ctx.markUnstable("key_not_found_s:"+e),r}getKeyValueAsJson(e,t=!1){const r=this.resource.getKeyValueString(this.instanceData.ctx.watcher,e);if(r===void 0){t&&this.instanceData.ctx.markUnstable("key_not_found_j:"+e);return}return JSON.parse(r)}toEntryAccessor(){return new T(this.accessorData,this.tree,this.id,this.instanceData)}persist(){return new S(this.accessorData,this.resource.id)}}class w extends Error{constructor(e){super(e)}}class _{constructor(e,t,r,i,n,a,s){c(this,"change",new m.ChangeSource);this.name=e,this.type=t,this.value=r,this.error=i,this.status=n,this.valueIsFinal=a,this.resourceVersion=s}get state(){return{name:this.name,type:this.type,status:this.status,value:this.value,error:this.error,valueIsFinal:this.valueIsFinal}}}const E=0,A=new TextDecoder;class ${constructor(e,t){c(this,"refCount",0);c(this,"version",E);c(this,"dataVersion",E);c(this,"fieldsMap",new Map);c(this,"kv",new Map);c(this,"resourceRemoved",new m.ChangeSource);c(this,"finalChanged",new m.ChangeSource);c(this,"resourceStateChange",new m.ChangeSource);c(this,"lockedChange",new m.ChangeSource);c(this,"inputAndServiceFieldListChanged",new m.ChangeSource);c(this,"outputFieldListChanged",new m.ChangeSource);c(this,"dynamicFieldListChanged",new m.ChangeSource);c(this,"kvChanged",new m.ChangeSource);c(this,"id");c(this,"originalResourceId");c(this,"kind");c(this,"type");c(this,"data");c(this,"dataAsString");c(this,"dataAsJson");c(this,"error");c(this,"inputsLocked");c(this,"outputsLocked");c(this,"resourceReady");c(this,"finalFlag");c(this,"_finalState",!1);c(this,"logger");this.id=e.id,this.originalResourceId=e.originalResourceId,this.kind=e.kind,this.type=e.type,this.data=e.data,this.error=e.error,this.inputsLocked=e.inputsLocked,this.outputsLocked=e.outputsLocked,this.resourceReady=e.resourceReady,this.finalFlag=e.final,this.logger=t}info(e){this.logger!==void 0&&this.logger.info(e)}warn(e){this.logger!==void 0&&this.logger.warn(e)}get final(){return this.finalFlag}get finalState(){return this._finalState}get fields(){return[...this.fieldsMap.values()]}getField(e,t,r=()=>{}){var a,s,f;const i=typeof t=="string"?{field:t}:t,n=this.fieldsMap.get(i.field);if(n===void 0){if(i.errorIfFieldNotFound||i.errorIfFieldNotSet)throw new Error(`Field "${i.field}" not found in resource ${g.resourceIdToString(this.id)}`);if(!this.inputsLocked)(a=this.inputAndServiceFieldListChanged)==null||a.attachWatcher(e);else if(i.assertFieldType==="Service"||i.assertFieldType==="Input"){if(i.allowPermanentAbsence)return;throw new Error(`Service or input field not found ${i.field}.`)}if(!this.outputsLocked)(s=this.outputFieldListChanged)==null||s.attachWatcher(e);else if(i.assertFieldType==="Output"){if(i.allowPermanentAbsence)return;throw new Error(`Output field not found ${i.field}.`)}(f=this.dynamicFieldListChanged)==null||f.attachWatcher(e),!this._finalState&&!i.stableIfNotFound&&r("field_not_found:"+i.field);return}else{if(i.assertFieldType!==void 0&&n.type!==i.assertFieldType)throw new Error(`Unexpected field type: expected ${i.assertFieldType} but got ${n.type} for the field name ${i.field}`);const h={};return g.isNotNullResourceId(n.value)&&(h.value=n.value),g.isNotNullResourceId(n.error)&&(h.error=n.error),h.value===void 0&&h.error===void 0&&r("field_not_resolved:"+i.field),n.change.attachWatcher(e),h}}getInputsLocked(e){var t;return this.inputsLocked||(t=this.resourceStateChange)==null||t.attachWatcher(e),this.inputsLocked}getOutputsLocked(e){var t;return this.outputsLocked||(t=this.resourceStateChange)==null||t.attachWatcher(e),this.outputsLocked}get isReadyOrError(){return this.error!==g.NullResourceId||this.resourceReady||this.originalResourceId!==g.NullResourceId}getIsFinal(e){var t;return(t=this.finalChanged)==null||t.attachWatcher(e),this._finalState}getIsReadyOrError(e){var t;return this.isReadyOrError||(t=this.resourceStateChange)==null||t.attachWatcher(e),this.isReadyOrError}getError(e){var t;if(g.isNullResourceId(this.error)){(t=this.resourceStateChange)==null||t.attachWatcher(e);return}else return this.error}listInputFields(e){var r;const t=[];return this.fieldsMap.forEach((i,n)=>{(i.type==="Input"||i.type==="Service")&&t.push(n)}),this.inputsLocked||(r=this.inputAndServiceFieldListChanged)==null||r.attachWatcher(e),t}listOutputFields(e){var r;const t=[];return this.fieldsMap.forEach((i,n)=>{i.type==="Output"&&t.push(n)}),this.outputsLocked||(r=this.outputFieldListChanged)==null||r.attachWatcher(e),t}listDynamicFields(e){var r;const t=[];return this.fieldsMap.forEach((i,n)=>{i.type!=="Input"&&i.type!=="Output"&&t.push(n)}),(r=this.dynamicFieldListChanged)==null||r.attachWatcher(e),t}getKeyValue(e,t){var r;return(r=this.kvChanged)==null||r.attachWatcher(e),this.kv.get(t)}getKeyValueString(e,t){const r=this.getKeyValue(e,t);if(r!==void 0)return A.decode(r)}getDataAsString(){if(this.data!==void 0)return this.dataAsString===void 0&&(this.dataAsString=A.decode(this.data)),this.dataAsString}getDataAsJson(){if(this.data!==void 0)return this.dataAsJson===void 0&&(this.dataAsJson=JSON.parse(this.getDataAsString())),this.dataAsJson}verifyReadyState(){if(this.resourceReady&&!this.inputsLocked)throw new Error(`ready without input or output lock: ${g.stringifyWithResourceId(this.basicState)}`)}get basicState(){return{id:this.id,kind:this.kind,type:this.type,data:this.data,resourceReady:this.resourceReady,inputsLocked:this.inputsLocked,outputsLocked:this.outputsLocked,error:this.error,originalResourceId:this.originalResourceId,final:this.finalFlag}}get extendedState(){return{...this.basicState,fields:this.fields,kv:Array.from(this.kv.entries()).map(([e,t])=>({key:e,value:t}))}}markFinal(){this._finalState||(this._finalState=!0,p.notEmpty(this.finalChanged).markChanged(),this.finalChanged=void 0,this.resourceStateChange=void 0,this.dynamicFieldListChanged=void 0,this.inputAndServiceFieldListChanged=void 0,this.outputFieldListChanged=void 0,this.lockedChange=void 0)}markAllChanged(){var e,t,r,i,n,a,s;this.fieldsMap.forEach(f=>f.change.markChanged()),(e=this.finalChanged)==null||e.markChanged(),(t=this.resourceStateChange)==null||t.markChanged(),(r=this.lockedChange)==null||r.markChanged(),(i=this.inputAndServiceFieldListChanged)==null||i.markChanged(),(n=this.outputFieldListChanged)==null||n.markChanged(),(a=this.dynamicFieldListChanged)==null||a.markChanged(),(s=this.kvChanged)==null||s.markChanged(),this.resourceRemoved.markChanged()}}class I{constructor(e,t){c(this,"resources",new Map);c(this,"resourcesAdded",new m.ChangeSource);c(this,"_isValid",!0);c(this,"invalidationMessage");this.root=e,this.isFinalPredicate=t}forEachResource(e){this.resources.forEach(t=>e(t))}checkValid(){if(!this._isValid)throw new Error(this.invalidationMessage??"tree is in invalid state")}get(e,t){this.checkValid();const r=this.resources.get(t);if(r===void 0)throw this.resourcesAdded.attachWatcher(e),new Error(`resource ${g.resourceIdToString(t)} not found in the tree`);return r.resourceRemoved.attachWatcher(e),r}updateFromResourceData(e,t=!1){this.checkValid();const r=[],i=[];for(const a of e){let s=this.resources.get(a.id);const f=s==null?void 0:s.basicState,h=l=>{const{fields:k,...u}=a;throw this.invalidateTree(),new w(`Unexpected resource state transition (${l}): ${g.stringifyWithResourceId(u)} -> ${g.stringifyWithResourceId(f)}`)};if(s!==void 0){s.finalState&&h("resource state can be updated after it is marked as final");let l=!1;s.version+=1,s.originalResourceId!==a.originalResourceId&&(s.originalResourceId!==g.NullResourceId&&h("originalResourceId can't change after it is set"),s.originalResourceId=a.originalResourceId,p.notEmpty(s.resourceStateChange).markChanged(),l=!0),s.error!==a.error&&(g.isNotNullResourceId(s.error)&&h("resource can't change attached error after it is set"),s.error=a.error,r.push(s.error),p.notEmpty(s.resourceStateChange).markChanged(),l=!0);for(const u of a.fields){let d=s.fieldsMap.get(u.name);d?(d.type!==u.type&&(d.type!=="Dynamic"&&h(`field changed type ${d.type} -> ${u.type}`),p.notEmpty(s.dynamicFieldListChanged).markChanged(),(d.type==="Input"||d.type==="Service")&&(s.inputsLocked&&h(`adding input field "${u.name}", while corresponding list is locked`),p.notEmpty(s.inputAndServiceFieldListChanged).markChanged()),d.type==="Output"&&(s.outputsLocked&&h(`adding output field "${u.name}", while corresponding list is locked`),p.notEmpty(s.outputFieldListChanged).markChanged()),d.type=u.type,d.change.markChanged(),l=!0),d.value!==u.value&&(g.isNotNullResourceId(d.value)&&i.push(d.value),d.value=u.value,g.isNotNullResourceId(u.value)&&r.push(u.value),d.change.markChanged(),l=!0),d.error!==u.error&&(g.isNotNullResourceId(d.error)&&i.push(d.error),d.error=u.error,g.isNotNullResourceId(u.error)&&r.push(u.error),d.change.markChanged(),l=!0),d.status!==u.status&&(d.status=u.status,d.change.markChanged(),l=!0),d.valueIsFinal!==u.valueIsFinal&&(d.valueIsFinal=u.valueIsFinal,d.change.markChanged(),l=!0),d.resourceVersion=s.version):(d=new _(u.name,u.type,u.value,u.error,u.status,u.valueIsFinal,s.version),g.isNotNullResourceId(u.value)&&r.push(u.value),g.isNotNullResourceId(u.error)&&r.push(u.error),u.type==="Input"||u.type==="Service"?(s.inputsLocked&&h(`adding ${u.type} (${u.name}) field while inputs locked`),p.notEmpty(s.inputAndServiceFieldListChanged).markChanged()):u.type==="Output"?(s.outputsLocked&&h(`adding ${u.type} (${u.name}) field while outputs locked`),p.notEmpty(s.outputFieldListChanged).markChanged()):p.notEmpty(s.dynamicFieldListChanged).markChanged(),s.fieldsMap.set(u.name,d),l=!0)}if(s.fieldsMap.forEach((u,d,y)=>{u.resourceVersion!==s.version&&((u.type==="Input"||u.type==="Service"||u.type==="Output")&&h(`removal of ${u.type} field ${d}`),u.change.markChanged(),y.delete(d),g.isNotNullResourceId(u.value)&&i.push(u.value),g.isNotNullResourceId(u.error)&&i.push(u.error),p.notEmpty(s.dynamicFieldListChanged).markChanged())}),s.inputsLocked!==a.inputsLocked&&(s.inputsLocked&&h("inputs unlocking is not permitted"),s.inputsLocked=a.inputsLocked,p.notEmpty(s.lockedChange).markChanged(),l=!0),s.outputsLocked!==a.outputsLocked&&(s.outputsLocked&&h("outputs unlocking is not permitted"),s.outputsLocked=a.outputsLocked,p.notEmpty(s.lockedChange).markChanged(),l=!0),s.resourceReady!==a.resourceReady){const u=s.resourceReady;s.resourceReady=a.resourceReady,s.verifyReadyState(),s.isReadyOrError||h(`resource can't lose it's ready or error state (ready state before ${u})`),p.notEmpty(s.resourceStateChange).markChanged(),l=!0}let k=!1;for(const u of a.kv){const d=s.kv.get(u.key);(d===void 0||Buffer.compare(d,u.value)!==0)&&(s.kv.set(u.key,u.value),k=!0)}if(s.kv.size>a.kv.length){const u=new Set(a.kv.map(d=>d.key));s.kv.forEach((d,y,v)=>{u.has(y)||v.delete(y)}),k=!0}k&&p.notEmpty(s.kvChanged).markChanged(),l&&(s.dataVersion=s.version,this.isFinalPredicate(s)&&s.markFinal())}else{s=new $(a),s.verifyReadyState(),g.isNotNullResourceId(s.error)&&r.push(s.error);for(const l of a.fields){const k=new _(l.name,l.type,l.value,l.error,l.status,l.valueIsFinal,E);g.isNotNullResourceId(l.value)&&r.push(l.value),g.isNotNullResourceId(l.error)&&r.push(l.error),s.fieldsMap.set(l.name,k)}for(const l of a.kv)s.kv.set(l.key,l.value);this.isFinalPredicate(s)&&s.markFinal(),this.resources.set(s.id,s),this.resourcesAdded.markChanged()}}for(const a of r){const s=this.resources.get(a);if(!s)throw this.invalidateTree(),new w(`orphan resource ${a}`);s.refCount++}let n=i;for(;n.length>0;){const a=[];for(const s of n){const f=this.resources.get(s);if(!f)throw this.invalidateTree(),new w(`orphan resource ${s}`);f.refCount--,f.refCount===0&&f.id!==this.root&&(f.fieldsMap.forEach(h=>{g.isNotNullResourceId(h.value)&&a.push(h.value),g.isNotNullResourceId(h.error)&&a.push(h.error),h.change.markChanged()}),g.isNotNullResourceId(f.error)&&a.push(f.error),f.resourceRemoved.markChanged(),this.resources.delete(s))}n=a}if(!t){for(const a of e)if(!this.resources.has(a.id))throw this.invalidateTree(),new w(`orphan input resource ${a.id}`)}}accessor(e=this.root){return this.checkValid(),this.entry(e)}entry(e=this.root){return this.checkValid(),new S({treeProvider:()=>this},e)}invalidateTree(e){this._isValid=!1,this.invalidationMessage=e,this.resources.forEach(t=>{t.markAllChanged()})}dumpState(){return Array.from(this.resources.values()).map(e=>e.extendedState)}}function x(o,e){const t=[],r=new Set;return o.forEachResource(i=>{i.finalState?r.add(i.id):t.push(i.id)}),t.length===0&&r.size===0&&t.push(o.root),{seedResources:t,finalResources:r,pruningFunction:e}}function C(){return{requests:0,roundTrips:0,retrievedResources:0,retrievedFields:0,retrievedKeyValues:0,retrievedResourceDataBytes:0,retrievedKeyValueBytes:0,prunedFields:0,finalResourcesSkipped:0,millisSpent:0}}function Q(o){let e=`Requests: ${o.requests}
|
|
2
2
|
`;return e+=`Total time: ${p.msToHumanReadable(o.millisSpent)}
|
|
3
3
|
`,e+=`Round-trips: ${o.roundTrips}
|
|
4
4
|
`,e+=`Resources: ${o.retrievedResources}
|
|
@@ -7,5 +7,5 @@
|
|
|
7
7
|
`,e+=`Data Bytes: ${o.retrievedResourceDataBytes}
|
|
8
8
|
`,e+=`KV Bytes: ${o.retrievedKeyValueBytes}
|
|
9
9
|
`,e+=`Pruned fields: ${o.prunedFields}
|
|
10
|
-
`,e+=`Final resources skipped: ${o.finalResourcesSkipped}`,e}async function V(o,e,t){var d;const r=Date.now();t&&t.requests++;const{seedResources:
|
|
10
|
+
`,e+=`Final resources skipped: ${o.finalResourcesSkipped}`,e}async function V(o,e,t){var d;const r=Date.now();t&&t.requests++;const{seedResources:i,finalResources:n,pruningFunction:a}=e,s=new M;let f=!0,h=0;const l=new Set,k=y=>{if(g.isNullResourceId(y)||l.has(y))return;if(n.has(y)){t&&t.finalResourcesSkipped++;return}l.add(y);const v=o.getResourceDataIfExists(y,!0),R=o.listKeyValuesIfResourceExists(y),W=f;f&&(f=!1),s.push((async()=>{const[L,N]=await Promise.all([v,R]);if(W&&(h++,f=!0),L!==void 0){if(N===void 0)throw new Error("Inconsistent replies");return{...L,kv:N}}})())};i.forEach(y=>k(y));const u=[];for(;;){const y=s.shift();if(y===void 0)break;let v=await y;if(v!==void 0){if(a!==void 0){const R=a(v);t&&(t.prunedFields+=v.fields.length-R.length),v={...v,fields:R}}k(v.error);for(const R of v.fields)k(R.value),k(R.error);if(t){t.retrievedResources++,t.retrievedFields+=v.fields.length,t.retrievedKeyValues+=v.kv.length,t.retrievedResourceDataBytes+=((d=v.data)==null?void 0:d.length)??0;for(const R of v.kv)t.retrievedKeyValueBytes+=R.value.length}u.push(v)}}return t&&(t.millisSpent+=Date.now()-r,t.roundTrips+=h),u}function X(o){return o}function Z(o,e,t){var a;const r=o instanceof S?p.notEmpty(t).accessor(o).node():o instanceof T?o.node():o,n={...r.resourceInfo};if(e.data!==void 0&&(e.data==="raw"?n.data=r.getData():n.data=e.data.parse(r.getDataAsJson())),e.fields!==void 0){const s={};for(const[f,h]of Object.entries(e.fields))s[f]=(a=r.traverse({field:f,errorIfFieldNotSet:h,stableIfNotFound:!h}))==null?void 0:a.id;n.fields=s}if(e.kv!==void 0){const s={};for(const[f,h]of Object.entries(e.kv)){const l=r.getKeyValue(f);if(l===void 0)throw new Error(`Key not found ${f}`);h==="raw"?s[f]=l:s[f]=h.parse(JSON.parse(Buffer.from(l).toString("utf-8")))}n.kv=s}return n}function ee(o,e,t){if(o instanceof S){const r=t.accessor(o).node(),i=r.resourceInfo,n=e.map(a=>{var s,f;return[a,(f=(s=r.getField(a))==null?void 0:s.value)==null?void 0:f.id]});return{...i,fields:new Map(n),data:r.getData()??new Uint8Array}}return o}function te(o,e,t){if(!(o instanceof S))return o;const r=t.accessor(o).node(),i=r.resourceInfo,n=e.map(a=>[a,r.getKeyValue(a)]);return{...i,metadata:Object.fromEntries(n)}}class D{constructor(e,t,r,i){c(this,"finalPredicate");c(this,"state");c(this,"pollingInterval");c(this,"pruning");c(this,"logStat");c(this,"hooks");c(this,"abortController",new AbortController);c(this,"scheduledOnNextState",[]);c(this,"keepRunning",!1);c(this,"currentLoop");c(this,"terminated",!1);this.pl=e,this.root=t,this.logger=i;const{finalPredicateOverride:n,pruning:a,pollingInterval:s,stopPollingDelay:f,logStat:h}=r;this.pruning=a,this.pollingInterval=s,this.finalPredicate=n??e.finalPredicate,this.logStat=h,this.state=new I(t,this.finalPredicate),this.hooks=new m.PollingComputableHooks(()=>this.startUpdating(),()=>this.stopUpdating(),{stopDebounce:f},(l,k)=>this.scheduleOnNextState(l,k))}accessor(e=this.root){if(this.terminated)throw new Error("tree synchronization is terminated");return this.entry(e)}entry(e=this.root){if(this.terminated)throw new Error("tree synchronization is terminated");return new S({treeProvider:()=>this.state,hooks:this.hooks},e)}async refreshState(){if(this.terminated)throw new Error("tree synchronization is terminated");await this.hooks.refreshState()}scheduleOnNextState(e,t){this.terminated?t(new Error("tree synchronization is terminated")):this.scheduledOnNextState.push({resolve:e,reject:t})}startUpdating(){this.terminated||(this.keepRunning=!0,this.currentLoop===void 0&&(this.currentLoop=this.mainLoop()))}stopUpdating(){this.keepRunning=!1}async refresh(e,t){if(this.terminated)throw new Error("tree synchronization is terminated");const r=x(this.state,this.pruning),i=await this.pl.withReadTx("ReadingTree",async n=>await V(n,r,e),t);this.state.updateFromResourceData(i,!0)}async mainLoop(){var t,r;let e=this.logStat?C():void 0;for(;this.keepRunning;){let i;this.scheduledOnNextState.length>0&&(i=this.scheduledOnNextState,this.scheduledOnNextState=[]);try{if(this.logStat==="per-request"&&(e=C()),await this.refresh(e),e&&this.logger&&this.logger.info(`Tree stat (success): ${JSON.stringify(e)}`),i!==void 0)for(const n of i)n.resolve()}catch(n){if(e&&this.logger&&this.logger.info(`Tree stat (error): ${JSON.stringify(e)}`),i!==void 0)for(const a of i)a.reject(n);if(n instanceof w){(t=this.logger)==null||t.error(n),this.state.invalidateTree("stat update error"),this.state=new I(this.root,this.finalPredicate);continue}else(r=this.logger)==null||r.warn(n)}if(!this.keepRunning||this.terminated)break;try{await J.setTimeout(this.pollingInterval,this.abortController.signal)}catch(n){if(!g.isTimeoutOrCancelError(n))throw new Error("Unexpected error",{cause:n});break}}this.currentLoop=void 0}dumpState(){return this.state.dumpState()}async terminate(){this.keepRunning=!1,this.terminated=!0,this.abortController.abort(),this.currentLoop!==void 0&&(await this.currentLoop,this.state.invalidateTree("synchronization terminated for the tree"))}async awaitSyncLoopTermination(){this.currentLoop!==void 0&&await this.currentLoop}static async init(e,t,r,i){const n=new D(e,t,r,i);let a=r.logStat?C():void 0,s=!1;try{await n.refresh(a,{timeout:r.initialTreeLoadingTimeout}),s=!0}finally{a&&i&&i.info(`Tree stat (initial load, ${s?"success":"failure"}): ${JSON.stringify(a)}`)}return n}}function re(o){var t;const e={total:{count:0,fieldNameBytes:0,fieldsCount:0,dataBytes:0,kvCount:0,kvBytes:0},byResourceType:{}};for(const r of o){const i=`${r.type.name}/${r.type.version}`;e.byResourceType[i]||(e.byResourceType[i]={count:0,fieldNameBytes:0,fieldsCount:0,dataBytes:0,kvCount:0,kvBytes:0});const n=e.byResourceType[i];n.count++,e.total.count++;for(const a of r.fields)n.fieldNameBytes+=a.name.length,n.fieldsCount++,e.total.fieldNameBytes+=a.name.length,e.total.fieldsCount++;if(r.data){const a=((t=r.data)==null?void 0:t.length)??0;n.dataBytes+=a,e.total.dataBytes+=a}n.kvCount+=r.kv.length,e.total.kvCount+=r.kv.length;for(const a of r.kv){const s=a.key.length+a.value.length;n.kvBytes+=s,e.total.kvBytes+=s}}return e}exports.PlTreeEntry=S;exports.PlTreeEntryAccessor=T;exports.PlTreeNodeAccessor=P;exports.PlTreeResource=$;exports.PlTreeState=I;exports.SynchronizedTreeState=D;exports.TreeStateUpdateError=w;exports.constructTreeLoadingRequest=x;exports.formatTreeLoadingStat=Q;exports.initialTreeLoadingStat=C;exports.isPlTreeEntry=j;exports.isPlTreeEntryAccessor=H;exports.isPlTreeNodeAccessor=Y;exports.loadTreeState=V;exports.makeResourceSnapshot=Z;exports.mapValueAndError=F;exports.mapValueAndErrorIfDefined=z;exports.rsSchema=X;exports.treeDumpStats=re;exports.treeEntryToResourceInfo=G;exports.treeEntryToResourceWithData=ee;exports.treeEntryToResourceWithMetadata=te;
|
|
11
11
|
//# sourceMappingURL=index.js.map
|