@fluidframework/runtime-utils 2.0.0-internal.3.3.1 → 2.0.0-internal.3.4.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/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/summarizerNode/summarizerNode.d.ts +3 -1
- package/dist/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/dist/summarizerNode/summarizerNode.js +4 -2
- package/dist/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summarizerNode/summarizerNodeWithGc.js +59 -15
- package/dist/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/summarizerNode/summarizerNode.d.ts +3 -1
- package/lib/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/lib/summarizerNode/summarizerNode.js +4 -2
- package/lib/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/lib/summarizerNode/summarizerNodeWithGc.js +60 -16
- package/lib/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/package.json +19 -20
- package/src/packageVersion.ts +1 -1
- package/src/summarizerNode/summarizerNode.ts +4 -2
- package/src/summarizerNode/summarizerNodeWithGc.ts +76 -17
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/runtime-utils",
|
|
3
|
-
"version": "2.0.0-internal.3.
|
|
3
|
+
"version": "2.0.0-internal.3.4.0",
|
|
4
4
|
"description": "Collection of utility functions for Fluid Runtime",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -37,35 +37,34 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@fluidframework/common-definitions": "^0.20.1",
|
|
39
39
|
"@fluidframework/common-utils": "^1.1.1",
|
|
40
|
-
"@fluidframework/container-definitions": "
|
|
41
|
-
"@fluidframework/container-runtime-definitions": "
|
|
42
|
-
"@fluidframework/core-interfaces": "
|
|
43
|
-
"@fluidframework/datastore-definitions": "
|
|
44
|
-
"@fluidframework/garbage-collector": "
|
|
45
|
-
"@fluidframework/protocol-base": "^0.1038.
|
|
40
|
+
"@fluidframework/container-definitions": "^2.0.0-internal.3.4.0",
|
|
41
|
+
"@fluidframework/container-runtime-definitions": "^2.0.0-internal.3.4.0",
|
|
42
|
+
"@fluidframework/core-interfaces": "^2.0.0-internal.3.4.0",
|
|
43
|
+
"@fluidframework/datastore-definitions": "^2.0.0-internal.3.4.0",
|
|
44
|
+
"@fluidframework/garbage-collector": "^2.0.0-internal.3.4.0",
|
|
45
|
+
"@fluidframework/protocol-base": "^0.1038.4000",
|
|
46
46
|
"@fluidframework/protocol-definitions": "^1.1.0",
|
|
47
|
-
"@fluidframework/runtime-definitions": "
|
|
48
|
-
"@fluidframework/telemetry-utils": "
|
|
47
|
+
"@fluidframework/runtime-definitions": "^2.0.0-internal.3.4.0",
|
|
48
|
+
"@fluidframework/telemetry-utils": "^2.0.0-internal.3.4.0"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@fluid-tools/build-cli": "^0.
|
|
51
|
+
"@fluid-tools/build-cli": "^0.13.0",
|
|
52
52
|
"@fluidframework/build-common": "^1.1.0",
|
|
53
|
-
"@fluidframework/build-tools": "^0.
|
|
53
|
+
"@fluidframework/build-tools": "^0.13.0",
|
|
54
54
|
"@fluidframework/eslint-config-fluid": "^2.0.0",
|
|
55
|
-
"@fluidframework/mocha-test-setup": "
|
|
55
|
+
"@fluidframework/mocha-test-setup": "^2.0.0-internal.3.4.0",
|
|
56
56
|
"@fluidframework/runtime-utils-previous": "npm:@fluidframework/runtime-utils@2.0.0-internal.3.2.0",
|
|
57
|
-
"@microsoft/api-extractor": "^7.
|
|
58
|
-
"@rushstack/eslint-config": "^2.5.1",
|
|
57
|
+
"@microsoft/api-extractor": "^7.34.4",
|
|
59
58
|
"@types/mocha": "^9.1.1",
|
|
60
|
-
"@types/node": "^14.18.
|
|
61
|
-
"concurrently": "^6.
|
|
59
|
+
"@types/node": "^14.18.38",
|
|
60
|
+
"concurrently": "^7.6.0",
|
|
62
61
|
"copyfiles": "^2.4.1",
|
|
63
|
-
"cross-env": "^7.0.
|
|
62
|
+
"cross-env": "^7.0.3",
|
|
64
63
|
"eslint": "~8.6.0",
|
|
65
|
-
"mocha": "^10.
|
|
66
|
-
"nyc": "^15.
|
|
64
|
+
"mocha": "^10.2.0",
|
|
65
|
+
"nyc": "^15.1.0",
|
|
67
66
|
"prettier": "~2.6.2",
|
|
68
|
-
"rimraf": "^
|
|
67
|
+
"rimraf": "^4.4.0",
|
|
69
68
|
"sinon": "^7.4.2",
|
|
70
69
|
"ts-node": "^7.0.1",
|
|
71
70
|
"typescript": "~4.5.5"
|
package/src/packageVersion.ts
CHANGED
|
@@ -547,7 +547,7 @@ export class SummarizerNode implements IRootSummarizerNode {
|
|
|
547
547
|
// There may be additional state that has to be updated in this child. For example, if a summary is being
|
|
548
548
|
// tracked, the child's summary tracking state needs to be updated too. Same goes for pendingSummaries we might
|
|
549
549
|
// have outstanding on the parent in case we realize nodes in between Summary Op and Summary Ack.
|
|
550
|
-
this.maybeUpdateChildState(child);
|
|
550
|
+
this.maybeUpdateChildState(child, id);
|
|
551
551
|
|
|
552
552
|
this.children.set(id, child);
|
|
553
553
|
return child;
|
|
@@ -663,8 +663,10 @@ export class SummarizerNode implements IRootSummarizerNode {
|
|
|
663
663
|
* Also, in case a child node gets realized in between Summary Op and Summary Ack, let's initialize the child's
|
|
664
664
|
* pending summary as well.
|
|
665
665
|
* @param child - The child node whose state is to be updated.
|
|
666
|
+
* @param id - Initial id or path part of this node
|
|
667
|
+
*
|
|
666
668
|
*/
|
|
667
|
-
protected maybeUpdateChildState(child: SummarizerNode) {
|
|
669
|
+
protected maybeUpdateChildState(child: SummarizerNode, id: string) {
|
|
668
670
|
// If a summary is in progress, this child was created after the summary started. So, we need to update the
|
|
669
671
|
// child's summary state as well.
|
|
670
672
|
if (this.isSummaryInProgress()) {
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
getGCDataFromSnapshot,
|
|
11
11
|
runGarbageCollection,
|
|
12
12
|
unpackChildNodesGCDetails,
|
|
13
|
+
unpackChildNodesUsedRoutes,
|
|
13
14
|
} from "@fluidframework/garbage-collector";
|
|
14
15
|
import { ISnapshotTree } from "@fluidframework/protocol-definitions";
|
|
15
16
|
import {
|
|
@@ -24,6 +25,7 @@ import {
|
|
|
24
25
|
SummarizeInternalFn,
|
|
25
26
|
ITelemetryContext,
|
|
26
27
|
} from "@fluidframework/runtime-definitions";
|
|
28
|
+
import { LoggingError, TelemetryDataTag } from "@fluidframework/telemetry-utils";
|
|
27
29
|
import { ReadAndParseBlob } from "../utils";
|
|
28
30
|
import { SummarizerNode } from "./summarizerNode";
|
|
29
31
|
import {
|
|
@@ -81,9 +83,14 @@ class SummarizerNodeWithGC extends SummarizerNode implements IRootSummarizerNode
|
|
|
81
83
|
// The base GC details of this node used to initialize the GC state.
|
|
82
84
|
private readonly baseGCDetailsP: LazyPromise<IGarbageCollectionDetailsBase>;
|
|
83
85
|
|
|
84
|
-
// Keeps track of whether we have loaded the base details to ensure that we
|
|
86
|
+
// Keeps track of whether we have loaded the base details to ensure that we only do it once.
|
|
85
87
|
private baseGCDetailsLoaded: boolean = false;
|
|
86
88
|
|
|
89
|
+
// The base GC details for the child nodes. This is passed to child nodes when creating them.
|
|
90
|
+
private readonly childNodesBaseGCDetailsP: LazyPromise<
|
|
91
|
+
Map<string, IGarbageCollectionDetailsBase>
|
|
92
|
+
>;
|
|
93
|
+
|
|
87
94
|
private gcData: IGarbageCollectionData | undefined;
|
|
88
95
|
|
|
89
96
|
// Set used routes to have self route by default. This makes the node referenced by default. This is done to ensure
|
|
@@ -133,6 +140,11 @@ class SummarizerNodeWithGC extends SummarizerNode implements IRootSummarizerNode
|
|
|
133
140
|
this.baseGCDetailsP = new LazyPromise(async () => {
|
|
134
141
|
return (await getBaseGCDetailsFn?.()) ?? { usedRoutes: [] };
|
|
135
142
|
});
|
|
143
|
+
|
|
144
|
+
this.childNodesBaseGCDetailsP = new LazyPromise(async () => {
|
|
145
|
+
await this.loadBaseGCDetails();
|
|
146
|
+
return unpackChildNodesGCDetails({ gcData: this.gcData, usedRoutes: this.usedRoutes });
|
|
147
|
+
});
|
|
136
148
|
}
|
|
137
149
|
|
|
138
150
|
/**
|
|
@@ -297,9 +309,28 @@ class SummarizerNodeWithGC extends SummarizerNode implements IRootSummarizerNode
|
|
|
297
309
|
): void {
|
|
298
310
|
// If GC is disabled, skip setting referenced used routes since we are not tracking GC state.
|
|
299
311
|
if (!this.gcDisabled) {
|
|
300
|
-
const summaryNode = this.pendingSummaries.get(proposalHandle)
|
|
301
|
-
if (summaryNode
|
|
302
|
-
|
|
312
|
+
const summaryNode = this.pendingSummaries.get(proposalHandle);
|
|
313
|
+
if (summaryNode !== undefined) {
|
|
314
|
+
// If a pending summary exists, it must have used routes since GC is enabled.
|
|
315
|
+
const summaryNodeWithGC = summaryNode as SummaryNodeWithGC;
|
|
316
|
+
if (summaryNodeWithGC.serializedUsedRoutes === undefined) {
|
|
317
|
+
const error = new LoggingError("MissingGCStateInPendingSummary", {
|
|
318
|
+
proposalHandle,
|
|
319
|
+
referenceSequenceNumber,
|
|
320
|
+
id: {
|
|
321
|
+
tag: TelemetryDataTag.CodeArtifact,
|
|
322
|
+
value: this.telemetryNodeId,
|
|
323
|
+
},
|
|
324
|
+
});
|
|
325
|
+
this.logger.sendErrorEvent(
|
|
326
|
+
{
|
|
327
|
+
eventName: error.message,
|
|
328
|
+
},
|
|
329
|
+
error,
|
|
330
|
+
);
|
|
331
|
+
throw error;
|
|
332
|
+
}
|
|
333
|
+
this.referenceUsedRoutes = JSON.parse(summaryNodeWithGC.serializedUsedRoutes);
|
|
303
334
|
}
|
|
304
335
|
}
|
|
305
336
|
|
|
@@ -434,23 +465,16 @@ class SummarizerNodeWithGC extends SummarizerNode implements IRootSummarizerNode
|
|
|
434
465
|
getBaseGCDetailsFn?: () => Promise<IGarbageCollectionDetailsBase>,
|
|
435
466
|
): ISummarizerNodeWithGC {
|
|
436
467
|
assert(!this.children.has(id), 0x1b6 /* "Create SummarizerNode child already exists" */);
|
|
437
|
-
|
|
438
468
|
/**
|
|
439
469
|
* Update the child node's base GC details from this node's current GC details instead of updating from the base
|
|
440
470
|
* GC details of this node. This will handle scenarios where the GC details was updated during refresh from
|
|
441
471
|
* snapshot and the child node wasn't created then. If a child is created after that, its GC details should be
|
|
442
472
|
* the one from the downloaded snapshot and not the base GC details.
|
|
443
473
|
*/
|
|
444
|
-
const
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
const childBaseGCDetails = unpackChildNodesGCDetails({
|
|
449
|
-
gcData: this.gcData,
|
|
450
|
-
usedRoutes: this.usedRoutes,
|
|
451
|
-
});
|
|
452
|
-
return childBaseGCDetails.get(id) ?? {};
|
|
453
|
-
});
|
|
474
|
+
const getChildBaseGCDetailsFn = async () => {
|
|
475
|
+
const childNodesBaseGCDetails = await this.childNodesBaseGCDetailsP;
|
|
476
|
+
return childNodesBaseGCDetails.get(id) ?? {};
|
|
477
|
+
};
|
|
454
478
|
|
|
455
479
|
const createDetails: ICreateChildDetails = this.getCreateDetailsForChild(id, createParam);
|
|
456
480
|
const child = new SummarizerNodeWithGC(
|
|
@@ -466,18 +490,53 @@ class SummarizerNodeWithGC extends SummarizerNode implements IRootSummarizerNode
|
|
|
466
490
|
createDetails.initialSummary,
|
|
467
491
|
this.wipSummaryLogger,
|
|
468
492
|
getGCDataFn,
|
|
469
|
-
|
|
493
|
+
getChildBaseGCDetailsFn,
|
|
470
494
|
createDetails.telemetryNodeId,
|
|
471
495
|
);
|
|
472
496
|
|
|
473
497
|
// There may be additional state that has to be updated in this child. For example, if a summary is being
|
|
474
498
|
// tracked, the child's summary tracking state needs to be updated too.
|
|
475
|
-
this.maybeUpdateChildState(child);
|
|
499
|
+
this.maybeUpdateChildState(child, id);
|
|
476
500
|
|
|
477
501
|
this.children.set(id, child);
|
|
478
502
|
return child;
|
|
479
503
|
}
|
|
480
504
|
|
|
505
|
+
/**
|
|
506
|
+
* Updates the state of the child if required. For example, if a summary is currently being tracked, the child's
|
|
507
|
+
* summary tracking state needs to be updated too.
|
|
508
|
+
* Also, in case a child node gets realized in between Summary Op and Summary Ack, let's initialize the child's
|
|
509
|
+
* pending summary as well. Finally, if the pendingSummaries entries have serializedRoutes, replicate them to the
|
|
510
|
+
* pendingSummaries from the child nodes.
|
|
511
|
+
* @param child - The child node whose state is to be updated.
|
|
512
|
+
* @param id - Initial id or path part of this node
|
|
513
|
+
*/
|
|
514
|
+
protected maybeUpdateChildState(child: SummarizerNodeWithGC, id: string) {
|
|
515
|
+
super.maybeUpdateChildState(child, id);
|
|
516
|
+
|
|
517
|
+
// In case we have pending summaries on the parent, let's initialize it on the child.
|
|
518
|
+
if (child.latestSummary !== undefined) {
|
|
519
|
+
for (const [key, value] of this.pendingSummaries.entries()) {
|
|
520
|
+
const summaryNodeWithGC = value as SummaryNodeWithGC;
|
|
521
|
+
if (summaryNodeWithGC.serializedUsedRoutes !== undefined) {
|
|
522
|
+
const childNodeUsedRoutes = unpackChildNodesUsedRoutes(
|
|
523
|
+
JSON.parse(summaryNodeWithGC.serializedUsedRoutes),
|
|
524
|
+
);
|
|
525
|
+
const newSerializedRoutes = childNodeUsedRoutes.get(id) ?? [""];
|
|
526
|
+
const newLatestSummaryNode = new SummaryNodeWithGC(
|
|
527
|
+
JSON.stringify(newSerializedRoutes),
|
|
528
|
+
{
|
|
529
|
+
referenceSequenceNumber: value.referenceSequenceNumber,
|
|
530
|
+
basePath: value.basePath,
|
|
531
|
+
localPath: value.localPath,
|
|
532
|
+
},
|
|
533
|
+
);
|
|
534
|
+
child.addPendingSummary(key, newLatestSummaryNode);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
481
540
|
/**
|
|
482
541
|
* Deletes the child node with the given id.
|
|
483
542
|
*/
|