@milaboratories/pl-tree 1.6.12 → 1.7.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/index.js +10 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +395 -395
- package/dist/index.mjs.map +1 -1
- package/dist/state.d.ts +2 -2
- package/dist/state.d.ts.map +1 -1
- package/package.json +7 -7
- package/src/state.ts +44 -42
package/src/state.ts
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
stringifyWithResourceId,
|
|
18
18
|
} from '@milaboratories/pl-client';
|
|
19
19
|
import type { Watcher } from '@milaboratories/computable';
|
|
20
|
-
import { ChangeSource } from '@milaboratories/computable';
|
|
20
|
+
import { ChangeSource, KeyedChangeSource } from '@milaboratories/computable';
|
|
21
21
|
import { PlTreeEntry } from './accessors';
|
|
22
22
|
import type { ValueAndError } from './value_and_error';
|
|
23
23
|
import type { MiLogger } from '@milaboratories/ts-helpers';
|
|
@@ -94,7 +94,8 @@ export class PlTreeResource implements ResourceDataWithFinalState {
|
|
|
94
94
|
outputFieldListChanged? = new ChangeSource();
|
|
95
95
|
dynamicFieldListChanged? = new ChangeSource();
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
// kvChangedGlobal? = new ChangeSource();
|
|
98
|
+
kvChangedPerKey? = new KeyedChangeSource();
|
|
98
99
|
|
|
99
100
|
readonly id: ResourceId;
|
|
100
101
|
originalResourceId: OptionalResourceId;
|
|
@@ -294,7 +295,7 @@ export class PlTreeResource implements ResourceDataWithFinalState {
|
|
|
294
295
|
}
|
|
295
296
|
|
|
296
297
|
public getKeyValue(watcher: Watcher, key: string): Uint8Array | undefined {
|
|
297
|
-
this.
|
|
298
|
+
this.kvChangedPerKey?.attachWatcher(key, watcher);
|
|
298
299
|
return this.kv.get(key);
|
|
299
300
|
}
|
|
300
301
|
|
|
@@ -355,26 +356,29 @@ export class PlTreeResource implements ResourceDataWithFinalState {
|
|
|
355
356
|
if (this._finalState) return;
|
|
356
357
|
|
|
357
358
|
this._finalState = true;
|
|
358
|
-
notEmpty(this.finalChanged).markChanged();
|
|
359
|
+
notEmpty(this.finalChanged).markChanged('marked final');
|
|
359
360
|
this.finalChanged = undefined;
|
|
360
361
|
this.resourceStateChange = undefined;
|
|
361
362
|
this.dynamicFieldListChanged = undefined;
|
|
362
363
|
this.inputAndServiceFieldListChanged = undefined;
|
|
363
364
|
this.outputFieldListChanged = undefined;
|
|
364
365
|
this.lockedChange = undefined;
|
|
366
|
+
// this.kvChangedGlobal = undefined;
|
|
367
|
+
this.kvChangedPerKey = undefined;
|
|
365
368
|
}
|
|
366
369
|
|
|
367
370
|
/** Used for invalidation */
|
|
368
371
|
markAllChanged() {
|
|
369
|
-
this.fieldsMap.forEach((field) => field.change.markChanged());
|
|
370
|
-
this.finalChanged?.markChanged();
|
|
371
|
-
this.resourceStateChange?.markChanged();
|
|
372
|
-
this.lockedChange?.markChanged();
|
|
373
|
-
this.inputAndServiceFieldListChanged?.markChanged();
|
|
374
|
-
this.outputFieldListChanged?.markChanged();
|
|
375
|
-
this.dynamicFieldListChanged?.markChanged();
|
|
376
|
-
this.
|
|
377
|
-
this.
|
|
372
|
+
this.fieldsMap.forEach((field) => field.change.markChanged('marked all changed'));
|
|
373
|
+
this.finalChanged?.markChanged('marked all changed');
|
|
374
|
+
this.resourceStateChange?.markChanged('marked all changed');
|
|
375
|
+
this.lockedChange?.markChanged('marked all changed');
|
|
376
|
+
this.inputAndServiceFieldListChanged?.markChanged('marked all changed');
|
|
377
|
+
this.outputFieldListChanged?.markChanged('marked all changed');
|
|
378
|
+
this.dynamicFieldListChanged?.markChanged('marked all changed');
|
|
379
|
+
// this.kvChangedGlobal?.markChanged('marked all changed');
|
|
380
|
+
this.kvChangedPerKey?.markAllChanged('marked all changed');
|
|
381
|
+
this.resourceRemoved.markChanged('marked all changed');
|
|
378
382
|
}
|
|
379
383
|
}
|
|
380
384
|
|
|
@@ -453,7 +457,7 @@ export class PlTreeState {
|
|
|
453
457
|
unexpectedTransitionError('originalResourceId can\'t change after it is set');
|
|
454
458
|
resource.originalResourceId = rd.originalResourceId;
|
|
455
459
|
// duplicate status of the resource counts as ready for the external observer
|
|
456
|
-
notEmpty(resource.resourceStateChange).markChanged();
|
|
460
|
+
notEmpty(resource.resourceStateChange).markChanged(`originalResourceId changed for ${resourceIdToString(resource.id)}`);
|
|
457
461
|
changed = true;
|
|
458
462
|
}
|
|
459
463
|
|
|
@@ -463,7 +467,7 @@ export class PlTreeState {
|
|
|
463
467
|
unexpectedTransitionError('resource can\'t change attached error after it is set');
|
|
464
468
|
resource.error = rd.error;
|
|
465
469
|
incrementRefs.push(resource.error as ResourceId);
|
|
466
|
-
notEmpty(resource.resourceStateChange).markChanged();
|
|
470
|
+
notEmpty(resource.resourceStateChange).markChanged(`error changed for ${resourceIdToString(resource.id)}`);
|
|
467
471
|
changed = true;
|
|
468
472
|
}
|
|
469
473
|
|
|
@@ -491,15 +495,15 @@ export class PlTreeState {
|
|
|
491
495
|
unexpectedTransitionError(
|
|
492
496
|
`adding ${fd.type} (${fd.name}) field while inputs locked`,
|
|
493
497
|
);
|
|
494
|
-
notEmpty(resource.inputAndServiceFieldListChanged).markChanged();
|
|
498
|
+
notEmpty(resource.inputAndServiceFieldListChanged).markChanged(`new ${fd.type} field ${fd.name} added to ${resourceIdToString(resource.id)}`);
|
|
495
499
|
} else if (fd.type === 'Output') {
|
|
496
500
|
if (resource.outputsLocked)
|
|
497
501
|
unexpectedTransitionError(
|
|
498
502
|
`adding ${fd.type} (${fd.name}) field while outputs locked`,
|
|
499
503
|
);
|
|
500
|
-
notEmpty(resource.outputFieldListChanged).markChanged();
|
|
504
|
+
notEmpty(resource.outputFieldListChanged).markChanged(`new ${fd.type} field ${fd.name} added to ${resourceIdToString(resource.id)}`);
|
|
501
505
|
} else {
|
|
502
|
-
notEmpty(resource.dynamicFieldListChanged).markChanged();
|
|
506
|
+
notEmpty(resource.dynamicFieldListChanged).markChanged(`new ${fd.type} field ${fd.name} added to ${resourceIdToString(resource.id)}`);
|
|
503
507
|
}
|
|
504
508
|
|
|
505
509
|
resource.fieldsMap.set(fd.name, field);
|
|
@@ -512,23 +516,23 @@ export class PlTreeState {
|
|
|
512
516
|
if (field.type !== fd.type) {
|
|
513
517
|
if (field.type !== 'Dynamic')
|
|
514
518
|
unexpectedTransitionError(`field changed type ${field.type} -> ${fd.type}`);
|
|
515
|
-
notEmpty(resource.dynamicFieldListChanged).markChanged();
|
|
519
|
+
notEmpty(resource.dynamicFieldListChanged).markChanged(`field ${fd.name} changed type from Dynamic to ${fd.type} in ${resourceIdToString(resource.id)}`);
|
|
516
520
|
if (field.type === 'Input' || field.type === 'Service') {
|
|
517
521
|
if (resource.inputsLocked)
|
|
518
522
|
unexpectedTransitionError(
|
|
519
523
|
`adding input field "${fd.name}", while corresponding list is locked`,
|
|
520
524
|
);
|
|
521
|
-
notEmpty(resource.inputAndServiceFieldListChanged).markChanged();
|
|
525
|
+
notEmpty(resource.inputAndServiceFieldListChanged).markChanged(`field ${fd.name} changed to type ${fd.type} in ${resourceIdToString(resource.id)}`);
|
|
522
526
|
}
|
|
523
527
|
if (field.type === 'Output') {
|
|
524
528
|
if (resource.outputsLocked)
|
|
525
529
|
unexpectedTransitionError(
|
|
526
530
|
`adding output field "${fd.name}", while corresponding list is locked`,
|
|
527
531
|
);
|
|
528
|
-
notEmpty(resource.outputFieldListChanged).markChanged();
|
|
532
|
+
notEmpty(resource.outputFieldListChanged).markChanged(`field ${fd.name} changed to type ${fd.type} in ${resourceIdToString(resource.id)}`);
|
|
529
533
|
}
|
|
530
534
|
field.type = fd.type;
|
|
531
|
-
field.change.markChanged();
|
|
535
|
+
field.change.markChanged(`field ${fd.name} type changed to ${fd.type} in ${resourceIdToString(resource.id)}`);
|
|
532
536
|
changed = true;
|
|
533
537
|
}
|
|
534
538
|
|
|
@@ -537,7 +541,7 @@ export class PlTreeState {
|
|
|
537
541
|
if (isNotNullResourceId(field.value)) decrementRefs.push(field.value);
|
|
538
542
|
field.value = fd.value;
|
|
539
543
|
if (isNotNullResourceId(fd.value)) incrementRefs.push(fd.value);
|
|
540
|
-
field.change.markChanged();
|
|
544
|
+
field.change.markChanged(`field ${fd.name} value changed in ${resourceIdToString(resource.id)}`);
|
|
541
545
|
changed = true;
|
|
542
546
|
}
|
|
543
547
|
|
|
@@ -546,21 +550,21 @@ export class PlTreeState {
|
|
|
546
550
|
if (isNotNullResourceId(field.error)) decrementRefs.push(field.error);
|
|
547
551
|
field.error = fd.error;
|
|
548
552
|
if (isNotNullResourceId(fd.error)) incrementRefs.push(fd.error);
|
|
549
|
-
field.change.markChanged();
|
|
553
|
+
field.change.markChanged(`field ${fd.name} error changed in ${resourceIdToString(resource.id)}`);
|
|
550
554
|
changed = true;
|
|
551
555
|
}
|
|
552
556
|
|
|
553
557
|
// field status
|
|
554
558
|
if (field.status !== fd.status) {
|
|
555
559
|
field.status = fd.status;
|
|
556
|
-
field.change.markChanged();
|
|
560
|
+
field.change.markChanged(`field ${fd.name} status changed to ${fd.status} in ${resourceIdToString(resource.id)}`);
|
|
557
561
|
changed = true;
|
|
558
562
|
}
|
|
559
563
|
|
|
560
564
|
// field valueIsFinal flag
|
|
561
565
|
if (field.valueIsFinal !== fd.valueIsFinal) {
|
|
562
566
|
field.valueIsFinal = fd.valueIsFinal;
|
|
563
|
-
field.change.markChanged();
|
|
567
|
+
field.change.markChanged(`field ${fd.name} valueIsFinal changed to ${fd.valueIsFinal} in ${resourceIdToString(resource.id)}`);
|
|
564
568
|
changed = true;
|
|
565
569
|
}
|
|
566
570
|
|
|
@@ -573,13 +577,13 @@ export class PlTreeState {
|
|
|
573
577
|
if (field.resourceVersion !== resource!.version) {
|
|
574
578
|
if (field.type === 'Input' || field.type === 'Service' || field.type === 'Output')
|
|
575
579
|
unexpectedTransitionError(`removal of ${field.type} field ${fieldName}`);
|
|
576
|
-
field.change.markChanged();
|
|
580
|
+
field.change.markChanged(`dynamic field ${fieldName} removed from ${resourceIdToString(resource!.id)}`);
|
|
577
581
|
fields.delete(fieldName);
|
|
578
582
|
|
|
579
583
|
if (isNotNullResourceId(field.value)) decrementRefs.push(field.value);
|
|
580
584
|
if (isNotNullResourceId(field.error)) decrementRefs.push(field.error);
|
|
581
585
|
|
|
582
|
-
notEmpty(resource!.dynamicFieldListChanged).markChanged();
|
|
586
|
+
notEmpty(resource!.dynamicFieldListChanged).markChanged(`dynamic field ${fieldName} removed from ${resourceIdToString(resource!.id)}`);
|
|
583
587
|
}
|
|
584
588
|
});
|
|
585
589
|
|
|
@@ -587,7 +591,7 @@ export class PlTreeState {
|
|
|
587
591
|
if (resource.inputsLocked !== rd.inputsLocked) {
|
|
588
592
|
if (resource.inputsLocked) unexpectedTransitionError('inputs unlocking is not permitted');
|
|
589
593
|
resource.inputsLocked = rd.inputsLocked;
|
|
590
|
-
notEmpty(resource.lockedChange).markChanged();
|
|
594
|
+
notEmpty(resource.lockedChange).markChanged(`inputs locked for ${resourceIdToString(resource.id)}`);
|
|
591
595
|
changed = true;
|
|
592
596
|
}
|
|
593
597
|
|
|
@@ -596,7 +600,7 @@ export class PlTreeState {
|
|
|
596
600
|
if (resource.outputsLocked)
|
|
597
601
|
unexpectedTransitionError('outputs unlocking is not permitted');
|
|
598
602
|
resource.outputsLocked = rd.outputsLocked;
|
|
599
|
-
notEmpty(resource.lockedChange).markChanged();
|
|
603
|
+
notEmpty(resource.lockedChange).markChanged(`outputs locked for ${resourceIdToString(resource.id)}`);
|
|
600
604
|
changed = true;
|
|
601
605
|
}
|
|
602
606
|
|
|
@@ -609,20 +613,19 @@ export class PlTreeState {
|
|
|
609
613
|
unexpectedTransitionError(
|
|
610
614
|
`resource can't lose it's ready or error state (ready state before ${readyStateBefore})`,
|
|
611
615
|
);
|
|
612
|
-
notEmpty(resource.resourceStateChange).markChanged();
|
|
616
|
+
notEmpty(resource.resourceStateChange).markChanged(`ready flag changed to ${rd.resourceReady} for ${resourceIdToString(resource.id)}`);
|
|
613
617
|
changed = true;
|
|
614
618
|
}
|
|
615
619
|
|
|
616
620
|
// syncing kv
|
|
617
|
-
let kvChanged = false;
|
|
618
621
|
for (const kv of rd.kv) {
|
|
619
622
|
const current = resource.kv.get(kv.key);
|
|
620
623
|
if (current === undefined) {
|
|
621
624
|
resource.kv.set(kv.key, kv.value);
|
|
622
|
-
|
|
625
|
+
notEmpty(resource.kvChangedPerKey).markChanged(kv.key, `kv added for ${resourceIdToString(resource.id)}: ${kv.key}`);
|
|
623
626
|
} else if (Buffer.compare(current, kv.value) !== 0) {
|
|
624
627
|
resource.kv.set(kv.key, kv.value);
|
|
625
|
-
|
|
628
|
+
notEmpty(resource.kvChangedPerKey).markChanged(kv.key, `kv changed for ${resourceIdToString(resource.id)}: ${kv.key}`);
|
|
626
629
|
}
|
|
627
630
|
}
|
|
628
631
|
|
|
@@ -632,14 +635,13 @@ export class PlTreeState {
|
|
|
632
635
|
|
|
633
636
|
// deleting keys not present in resource anymore
|
|
634
637
|
resource.kv.forEach((_value, key, map) => {
|
|
635
|
-
if (!newStateKeys.has(key))
|
|
638
|
+
if (!newStateKeys.has(key)) {
|
|
639
|
+
map.delete(key);
|
|
640
|
+
notEmpty(resource!.kvChangedPerKey).markChanged(key, `kv deleted for ${resourceIdToString(resource!.id)}: ${key}`);
|
|
641
|
+
}
|
|
636
642
|
});
|
|
637
|
-
|
|
638
|
-
kvChanged = true;
|
|
639
643
|
}
|
|
640
644
|
|
|
641
|
-
if (kvChanged) notEmpty(resource.kvChanged).markChanged();
|
|
642
|
-
|
|
643
645
|
if (changed) {
|
|
644
646
|
// if resource was changed, updating resource data version
|
|
645
647
|
resource.dataVersion = resource.version;
|
|
@@ -674,7 +676,7 @@ export class PlTreeState {
|
|
|
674
676
|
|
|
675
677
|
// adding the resource to the heap
|
|
676
678
|
this.resources.set(resource.id, resource);
|
|
677
|
-
this.resourcesAdded.markChanged();
|
|
679
|
+
this.resourcesAdded.markChanged(`new resource ${resourceIdToString(resource.id)} added`);
|
|
678
680
|
}
|
|
679
681
|
}
|
|
680
682
|
|
|
@@ -706,10 +708,10 @@ export class PlTreeState {
|
|
|
706
708
|
res.fieldsMap.forEach((field) => {
|
|
707
709
|
if (isNotNullResourceId(field.value)) nextRefs.push(field.value);
|
|
708
710
|
if (isNotNullResourceId(field.error)) nextRefs.push(field.error);
|
|
709
|
-
field.change.markChanged();
|
|
711
|
+
field.change.markChanged(`field ${field.name} removed during garbage collection of ${resourceIdToString(res.id)}`);
|
|
710
712
|
});
|
|
711
713
|
if (isNotNullResourceId(res.error)) nextRefs.push(res.error);
|
|
712
|
-
res.resourceRemoved.markChanged();
|
|
714
|
+
res.resourceRemoved.markChanged(`resource removed during garbage collection: ${resourceIdToString(res.id)}`);
|
|
713
715
|
this.resources.delete(rid);
|
|
714
716
|
}
|
|
715
717
|
}
|