@fluidframework/container-runtime 2.4.0-294316 → 2.4.0-297385
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/container-runtime.test-files.tar +0 -0
- package/dist/containerRuntime.d.ts +1 -3
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +11 -12
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +0 -3
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/summary/orderedClientElection.d.ts +0 -7
- package/dist/summary/orderedClientElection.d.ts.map +1 -1
- package/dist/summary/orderedClientElection.js +0 -16
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.d.ts +30 -13
- package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +84 -102
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +15 -42
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.js +10 -88
- package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +5 -6
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +28 -38
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/lib/containerRuntime.d.ts +1 -3
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +9 -10
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +0 -3
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.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/summary/orderedClientElection.d.ts +0 -7
- package/lib/summary/orderedClientElection.d.ts.map +1 -1
- package/lib/summary/orderedClientElection.js +0 -16
- package/lib/summary/orderedClientElection.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.d.ts +30 -13
- package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js +85 -103
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts +15 -42
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.js +8 -84
- package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +5 -6
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js +29 -39
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/package.json +24 -20
- package/src/containerRuntime.ts +10 -10
- package/src/dataStoreContext.ts +0 -3
- package/src/index.ts +0 -1
- package/src/packageVersion.ts +1 -1
- package/src/summary/orderedClientElection.ts +0 -19
- package/src/summary/summarizerNode/summarizerNode.ts +90 -123
- package/src/summary/summarizerNode/summarizerNodeUtils.ts +19 -99
- package/src/summary/summarizerNode/summarizerNodeWithGc.ts +37 -53
|
@@ -45,58 +45,37 @@ export interface ISummarizerNodeRootContract {
|
|
|
45
45
|
clearSummary(): void;
|
|
46
46
|
refreshLatestSummary(proposalHandle: string, summaryRefSeq: number): Promise<IRefreshSummaryResult>;
|
|
47
47
|
}
|
|
48
|
-
/**
|
|
48
|
+
/** Class to build paths for nodes in a tree with escaped special characters */
|
|
49
49
|
export declare class EscapedPath {
|
|
50
50
|
readonly path: string;
|
|
51
51
|
private constructor();
|
|
52
|
-
static create(path: string): EscapedPath;
|
|
53
|
-
static createAndConcat(pathParts: string[]): EscapedPath;
|
|
54
|
-
toString(): string;
|
|
55
|
-
concat(path: EscapedPath): EscapedPath;
|
|
56
|
-
}
|
|
57
|
-
/** Information about a summary relevant to a specific node in the tree */
|
|
58
|
-
export declare class SummaryNode {
|
|
59
|
-
private readonly summary;
|
|
60
|
-
/** Creates an instance that is valid for the root with specific basePath and localPath */
|
|
61
|
-
static createForRoot(referenceSequenceNumber: number): SummaryNode;
|
|
62
|
-
/** Summary reference sequence number, i.e. last sequence number seen when it was created */
|
|
63
|
-
get referenceSequenceNumber(): number;
|
|
64
|
-
/** Full path to parent node, or undefined if this is the root */
|
|
65
|
-
get basePath(): EscapedPath | undefined;
|
|
66
|
-
/** Relative path to this node from its parent node */
|
|
67
|
-
get localPath(): EscapedPath;
|
|
68
|
-
/** Relative path from this node to its node innermost base summary */
|
|
69
|
-
get additionalPath(): EscapedPath | undefined;
|
|
70
|
-
set additionalPath(additionalPath: EscapedPath | undefined);
|
|
71
|
-
constructor(summary: {
|
|
72
|
-
readonly referenceSequenceNumber: number;
|
|
73
|
-
readonly basePath: EscapedPath | undefined;
|
|
74
|
-
readonly localPath: EscapedPath;
|
|
75
|
-
additionalPath?: EscapedPath;
|
|
76
|
-
});
|
|
77
|
-
/** Gets the full path to this node, to be used when sending a handle */
|
|
78
|
-
get fullPath(): EscapedPath;
|
|
79
52
|
/**
|
|
80
|
-
*
|
|
81
|
-
*
|
|
53
|
+
* Creates and returns a new instance of this class.
|
|
54
|
+
* @param path - Id or path part of a node
|
|
82
55
|
*/
|
|
83
|
-
|
|
56
|
+
static create(path: string): EscapedPath;
|
|
57
|
+
toString(): string;
|
|
84
58
|
/**
|
|
85
|
-
* Creates a new
|
|
86
|
-
* @param id - id of the child node
|
|
59
|
+
* Creates and returns a new instance of this class for child of the current node.
|
|
87
60
|
*/
|
|
88
|
-
|
|
61
|
+
createChildPath(childNodePath: EscapedPath): EscapedPath;
|
|
62
|
+
}
|
|
63
|
+
export interface PendingSummaryInfo {
|
|
64
|
+
/** The sequence number at which the summary was created. */
|
|
65
|
+
referenceSequenceNumber: number;
|
|
89
66
|
}
|
|
90
67
|
/**
|
|
91
68
|
* Represents the details needed to create a child summarizer node.
|
|
92
69
|
*/
|
|
93
70
|
export interface ICreateChildDetails {
|
|
94
|
-
/** Latest summary from server node data */
|
|
95
|
-
latestSummary: SummaryNode | undefined;
|
|
96
71
|
/** Sequence number of latest known change to the node */
|
|
97
72
|
changeSequenceNumber: number;
|
|
98
73
|
/** A unique id of this child to be logged when sending telemetry. */
|
|
99
74
|
telemetryNodeId: string;
|
|
75
|
+
/** Summary handle for child node */
|
|
76
|
+
summaryHandleId: EscapedPath;
|
|
77
|
+
/** the reference sequence number of the last successful summary. */
|
|
78
|
+
lastSummaryReferenceSequenceNumber: number | undefined;
|
|
100
79
|
}
|
|
101
80
|
export interface ISubtreeInfo<T extends ISnapshotTree | SummaryObject> {
|
|
102
81
|
/** Tree to use to find children subtrees */
|
|
@@ -104,10 +83,4 @@ export interface ISubtreeInfo<T extends ISnapshotTree | SummaryObject> {
|
|
|
104
83
|
/** Additional path part where children are isolated */
|
|
105
84
|
childrenPathPart: string | undefined;
|
|
106
85
|
}
|
|
107
|
-
/**
|
|
108
|
-
* Checks if the summary contains .channels subtree where the children subtrees
|
|
109
|
-
* would be located if exists.
|
|
110
|
-
* @param baseSummary - summary to check
|
|
111
|
-
*/
|
|
112
|
-
export declare function parseSummaryForSubtrees(baseSummary: ISnapshotTree): ISubtreeInfo<ISnapshotTree>;
|
|
113
86
|
//# sourceMappingURL=summarizerNodeUtils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summarizerNodeUtils.d.ts","sourceRoot":"","sources":["../../../src/summary/summarizerNode/summarizerNodeUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAC;AAE5E,OAAO,EACN,mBAAmB,EACnB,gBAAgB,EAChB,MAAM,0CAA0C,CAAC;AAElD,MAAM,WAAW,qBAAqB;IACrC,4DAA4D;IAC5D,gBAAgB,EAAE,OAAO,CAAC;IAC1B,sFAAsF;IACtF,cAAc,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IACnC,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,YAAY,EAAE,MAAM,CAAC;IACrB,6HAA6H;IAC7H,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC7B;AAED;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAC9B;IACA,OAAO,EAAE,IAAI,CAAC;CACb,GACD;IACA,OAAO,EAAE,KAAK,CAAC;IACf,yBAAyB;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,EAAE,EAAE;QACH,GAAG,EAAE,gBAAgB,CAAC,YAAY,CAAC;QACnC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;KAC1B,CAAC;IACF,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEL,MAAM,WAAW,2BAA2B;IAC3C,YAAY,CACX,uBAAuB,EAAE,MAAM,EAC/B,aAAa,EAAE,mBAAmB,EAClC,sBAAsB,EAAE,MAAM,GAC5B,mBAAmB,CAAC;IACvB,eAAe,IAAI,qBAAqB,CAAC;IACzC,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9C,YAAY,IAAI,IAAI,CAAC;IACrB,oBAAoB,CACnB,cAAc,EAAE,MAAM,EACtB,aAAa,EAAE,MAAM,GACnB,OAAO,CAAC,qBAAqB,CAAC,CAAC;CAClC;AAED,+
|
|
1
|
+
{"version":3,"file":"summarizerNodeUtils.d.ts","sourceRoot":"","sources":["../../../src/summary/summarizerNode/summarizerNodeUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAC;AAE5E,OAAO,EACN,mBAAmB,EACnB,gBAAgB,EAChB,MAAM,0CAA0C,CAAC;AAElD,MAAM,WAAW,qBAAqB;IACrC,4DAA4D;IAC5D,gBAAgB,EAAE,OAAO,CAAC;IAC1B,sFAAsF;IACtF,cAAc,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IACnC,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,YAAY,EAAE,MAAM,CAAC;IACrB,6HAA6H;IAC7H,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC7B;AAED;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAC9B;IACA,OAAO,EAAE,IAAI,CAAC;CACb,GACD;IACA,OAAO,EAAE,KAAK,CAAC;IACf,yBAAyB;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,EAAE,EAAE;QACH,GAAG,EAAE,gBAAgB,CAAC,YAAY,CAAC;QACnC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;KAC1B,CAAC;IACF,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEL,MAAM,WAAW,2BAA2B;IAC3C,YAAY,CACX,uBAAuB,EAAE,MAAM,EAC/B,aAAa,EAAE,mBAAmB,EAClC,sBAAsB,EAAE,MAAM,GAC5B,mBAAmB,CAAC;IACvB,eAAe,IAAI,qBAAqB,CAAC;IACzC,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9C,YAAY,IAAI,IAAI,CAAC;IACrB,oBAAoB,CACnB,cAAc,EAAE,MAAM,EACtB,aAAa,EAAE,MAAM,GACnB,OAAO,CAAC,qBAAqB,CAAC,CAAC;CAClC;AAED,+EAA+E;AAC/E,qBAAa,WAAW;aACa,IAAI,EAAE,MAAM;IAAhD,OAAO;IAEP;;;OAGG;WACW,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW;IAGxC,QAAQ,IAAI,MAAM;IAGzB;;OAEG;IACI,eAAe,CAAC,aAAa,EAAE,WAAW,GAAG,WAAW;CAK/D;AACD,MAAM,WAAW,kBAAkB;IAClC,4DAA4D;IAC5D,uBAAuB,EAAE,MAAM,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IACnC,yDAAyD;IACzD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,qEAAqE;IACrE,eAAe,EAAE,MAAM,CAAC;IACxB,oCAAoC;IACpC,eAAe,EAAE,WAAW,CAAC;IAC7B,oEAAoE;IACpE,kCAAkC,EAAE,MAAM,GAAG,SAAS,CAAC;CACvD;AAED,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa;IACpE,4CAA4C;IAC5C,YAAY,EAAE,CAAC,CAAC;IAChB,uDAAuD;IACvD,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC"}
|
|
@@ -4,107 +4,29 @@
|
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.
|
|
7
|
+
exports.EscapedPath = void 0;
|
|
8
8
|
const internal_1 = require("@fluidframework/runtime-definitions/internal");
|
|
9
|
-
/**
|
|
9
|
+
/** Class to build paths for nodes in a tree with escaped special characters */
|
|
10
10
|
class EscapedPath {
|
|
11
11
|
constructor(path) {
|
|
12
12
|
this.path = path;
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Creates and returns a new instance of this class.
|
|
16
|
+
* @param path - Id or path part of a node
|
|
17
|
+
*/
|
|
14
18
|
static create(path) {
|
|
15
19
|
return new EscapedPath(encodeURIComponent(path));
|
|
16
20
|
}
|
|
17
|
-
static createAndConcat(pathParts) {
|
|
18
|
-
let ret = EscapedPath.create(pathParts[0] ?? "");
|
|
19
|
-
for (let i = 1; i < pathParts.length; i++) {
|
|
20
|
-
ret = ret.concat(EscapedPath.create(pathParts[i]));
|
|
21
|
-
}
|
|
22
|
-
return ret;
|
|
23
|
-
}
|
|
24
21
|
toString() {
|
|
25
22
|
return this.path;
|
|
26
23
|
}
|
|
27
|
-
concat(path) {
|
|
28
|
-
return new EscapedPath(`${this.path}/${path.path}`);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
exports.EscapedPath = EscapedPath;
|
|
32
|
-
/** Information about a summary relevant to a specific node in the tree */
|
|
33
|
-
class SummaryNode {
|
|
34
|
-
/** Creates an instance that is valid for the root with specific basePath and localPath */
|
|
35
|
-
static createForRoot(referenceSequenceNumber) {
|
|
36
|
-
return new SummaryNode({
|
|
37
|
-
referenceSequenceNumber,
|
|
38
|
-
basePath: undefined,
|
|
39
|
-
localPath: EscapedPath.create(""), // root hard-coded to ""
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
/** Summary reference sequence number, i.e. last sequence number seen when it was created */
|
|
43
|
-
get referenceSequenceNumber() {
|
|
44
|
-
return this.summary.referenceSequenceNumber;
|
|
45
|
-
}
|
|
46
|
-
/** Full path to parent node, or undefined if this is the root */
|
|
47
|
-
get basePath() {
|
|
48
|
-
return this.summary.basePath;
|
|
49
|
-
}
|
|
50
|
-
/** Relative path to this node from its parent node */
|
|
51
|
-
get localPath() {
|
|
52
|
-
return this.summary.localPath;
|
|
53
|
-
}
|
|
54
|
-
/** Relative path from this node to its node innermost base summary */
|
|
55
|
-
get additionalPath() {
|
|
56
|
-
return this.summary.additionalPath;
|
|
57
|
-
}
|
|
58
|
-
set additionalPath(additionalPath) {
|
|
59
|
-
this.summary.additionalPath = additionalPath;
|
|
60
|
-
}
|
|
61
|
-
constructor(summary) {
|
|
62
|
-
this.summary = summary;
|
|
63
|
-
}
|
|
64
|
-
/** Gets the full path to this node, to be used when sending a handle */
|
|
65
|
-
get fullPath() {
|
|
66
|
-
return this.basePath?.concat(this.localPath) ?? this.localPath;
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Gets the full path to this node's innermost base summary.
|
|
70
|
-
* The children nodes can use this as their basePath to determine their path.
|
|
71
|
-
*/
|
|
72
|
-
get fullPathForChildren() {
|
|
73
|
-
return this.additionalPath !== undefined
|
|
74
|
-
? this.fullPath.concat(this.additionalPath)
|
|
75
|
-
: this.fullPath;
|
|
76
|
-
}
|
|
77
24
|
/**
|
|
78
|
-
* Creates a new
|
|
79
|
-
* @param id - id of the child node
|
|
25
|
+
* Creates and returns a new instance of this class for child of the current node.
|
|
80
26
|
*/
|
|
81
|
-
|
|
82
|
-
return new
|
|
83
|
-
referenceSequenceNumber: this.referenceSequenceNumber,
|
|
84
|
-
basePath: this.fullPathForChildren,
|
|
85
|
-
localPath: EscapedPath.create(id),
|
|
86
|
-
});
|
|
27
|
+
createChildPath(childNodePath) {
|
|
28
|
+
return new EscapedPath(`${this.path}/${encodeURIComponent(internal_1.channelsTreeName)}/${childNodePath.path}`);
|
|
87
29
|
}
|
|
88
30
|
}
|
|
89
|
-
exports.
|
|
90
|
-
/**
|
|
91
|
-
* Checks if the summary contains .channels subtree where the children subtrees
|
|
92
|
-
* would be located if exists.
|
|
93
|
-
* @param baseSummary - summary to check
|
|
94
|
-
*/
|
|
95
|
-
function parseSummaryForSubtrees(baseSummary) {
|
|
96
|
-
// New versions of snapshots have child nodes isolated in .channels subtree
|
|
97
|
-
const channelsSubtree = baseSummary.trees[internal_1.channelsTreeName];
|
|
98
|
-
if (channelsSubtree !== undefined) {
|
|
99
|
-
return {
|
|
100
|
-
childrenTree: channelsSubtree,
|
|
101
|
-
childrenPathPart: internal_1.channelsTreeName,
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
return {
|
|
105
|
-
childrenTree: baseSummary,
|
|
106
|
-
childrenPathPart: undefined,
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
exports.parseSummaryForSubtrees = parseSummaryForSubtrees;
|
|
31
|
+
exports.EscapedPath = EscapedPath;
|
|
110
32
|
//# sourceMappingURL=summarizerNodeUtils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summarizerNodeUtils.js","sourceRoot":"","sources":["../../../src/summary/summarizerNode/summarizerNodeUtils.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAIH,2EAAgF;AA2DhF,+
|
|
1
|
+
{"version":3,"file":"summarizerNodeUtils.js","sourceRoot":"","sources":["../../../src/summary/summarizerNode/summarizerNodeUtils.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAIH,2EAAgF;AA2DhF,+EAA+E;AAC/E,MAAa,WAAW;IACvB,YAAoC,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;IAAG,CAAC;IAEpD;;;OAGG;IACI,MAAM,CAAC,MAAM,CAAC,IAAY;QAChC,OAAO,IAAI,WAAW,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;IAClD,CAAC;IACM,QAAQ;QACd,OAAO,IAAI,CAAC,IAAI,CAAC;IAClB,CAAC;IACD;;OAEG;IACI,eAAe,CAAC,aAA0B;QAChD,OAAO,IAAI,WAAW,CACrB,GAAG,IAAI,CAAC,IAAI,IAAI,kBAAkB,CAAC,2BAAgB,CAAC,IAAI,aAAa,CAAC,IAAI,EAAE,CAC5E,CAAC;IACH,CAAC;CACD;AArBD,kCAqBC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { SummaryObject } from \"@fluidframework/driver-definitions\";\nimport { ISnapshotTree } from \"@fluidframework/driver-definitions/internal\";\nimport { channelsTreeName } from \"@fluidframework/runtime-definitions/internal\";\nimport {\n\tITelemetryLoggerExt,\n\tTelemetryDataTag,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nexport interface IRefreshSummaryResult {\n\t/** Tells whether this summary is tracked by this client. */\n\tisSummaryTracked: boolean;\n\t/** Tells whether this summary is newer than the latest one tracked by this client. */\n\tisSummaryNewer: boolean;\n}\n\nexport interface IStartSummaryResult {\n\t/** The number of summarizerNodes at the start of the summary. */\n\tnodes: number;\n\t/** The number of summarizerNodes in the wrong state. */\n\tinvalidNodes: number;\n\t/** The invalid sequence numbers and their values. It should be in the format of validateSequenceNumber-nodeSequenceNumber */\n\tmismatchNumbers: Set<string>;\n}\n\n/**\n * Return type of validateSummary function. In case of success, the object returned should have success: true.\n * In case of failure, the object returned should have success: false and additional properties to indicate what\n * the failure was, where it was, can it be retried, etc.\n */\nexport type ValidateSummaryResult =\n\t| {\n\t\t\tsuccess: true;\n\t }\n\t| {\n\t\t\tsuccess: false;\n\t\t\t/** The failure reason */\n\t\t\treason: string;\n\t\t\t/** id of the node that failed during validation */\n\t\t\tid: {\n\t\t\t\ttag: TelemetryDataTag.CodeArtifact;\n\t\t\t\tvalue: string | undefined;\n\t\t\t};\n\t\t\t/** If the error can be retried, time to wait before retrying */\n\t\t\tretryAfterSeconds?: number;\n\t };\n\nexport interface ISummarizerNodeRootContract {\n\tstartSummary(\n\t\treferenceSequenceNumber: number,\n\t\tsummaryLogger: ITelemetryLoggerExt,\n\t\tlatestSummaryRefSeqNum: number,\n\t): IStartSummaryResult;\n\tvalidateSummary(): ValidateSummaryResult;\n\tcompleteSummary(proposalHandle: string): void;\n\tclearSummary(): void;\n\trefreshLatestSummary(\n\t\tproposalHandle: string,\n\t\tsummaryRefSeq: number,\n\t): Promise<IRefreshSummaryResult>;\n}\n\n/** Class to build paths for nodes in a tree with escaped special characters */\nexport class EscapedPath {\n\tprivate constructor(public readonly path: string) {}\n\n\t/**\n\t * Creates and returns a new instance of this class.\n\t * @param path - Id or path part of a node\n\t */\n\tpublic static create(path: string): EscapedPath {\n\t\treturn new EscapedPath(encodeURIComponent(path));\n\t}\n\tpublic toString(): string {\n\t\treturn this.path;\n\t}\n\t/**\n\t * Creates and returns a new instance of this class for child of the current node.\n\t */\n\tpublic createChildPath(childNodePath: EscapedPath): EscapedPath {\n\t\treturn new EscapedPath(\n\t\t\t`${this.path}/${encodeURIComponent(channelsTreeName)}/${childNodePath.path}`,\n\t\t);\n\t}\n}\nexport interface PendingSummaryInfo {\n\t/** The sequence number at which the summary was created. */\n\treferenceSequenceNumber: number;\n}\n\n/**\n * Represents the details needed to create a child summarizer node.\n */\nexport interface ICreateChildDetails {\n\t/** Sequence number of latest known change to the node */\n\tchangeSequenceNumber: number;\n\t/** A unique id of this child to be logged when sending telemetry. */\n\ttelemetryNodeId: string;\n\t/** Summary handle for child node */\n\tsummaryHandleId: EscapedPath;\n\t/** the reference sequence number of the last successful summary. */\n\tlastSummaryReferenceSequenceNumber: number | undefined;\n}\n\nexport interface ISubtreeInfo<T extends ISnapshotTree | SummaryObject> {\n\t/** Tree to use to find children subtrees */\n\tchildrenTree: T;\n\t/** Additional path part where children are isolated */\n\tchildrenPathPart: string | undefined;\n}\n"]}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
|
|
6
6
|
import { IGarbageCollectionData, CreateChildSummarizerNodeParam, IGarbageCollectionDetailsBase, ISummarizerNodeConfigWithGC, ISummarizerNodeWithGC, SummarizeInternalFn } from "@fluidframework/runtime-definitions/internal";
|
|
7
7
|
import { SummarizerNode } from "./summarizerNode.js";
|
|
8
|
-
import { EscapedPath, IStartSummaryResult, ISummarizerNodeRootContract,
|
|
8
|
+
import { EscapedPath, IStartSummaryResult, ISummarizerNodeRootContract, ValidateSummaryResult } from "./summarizerNodeUtils.js";
|
|
9
9
|
export interface IRootSummarizerNodeWithGC extends ISummarizerNodeWithGC, ISummarizerNodeRootContract {
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
@@ -36,9 +36,9 @@ export declare class SummarizerNodeWithGC extends SummarizerNode implements IRoo
|
|
|
36
36
|
* Do not call constructor directly.
|
|
37
37
|
* Use createRootSummarizerNodeWithGC to create root node, or createChild to create child nodes.
|
|
38
38
|
*/
|
|
39
|
-
constructor(logger: ITelemetryBaseLogger, summarizeInternalFn: SummarizeInternalFn, config: ISummarizerNodeConfigWithGC, changeSequenceNumber: number,
|
|
40
|
-
/**
|
|
41
|
-
|
|
39
|
+
constructor(logger: ITelemetryBaseLogger, summarizeInternalFn: SummarizeInternalFn, config: ISummarizerNodeConfigWithGC, _summaryHandleId: EscapedPath, changeSequenceNumber: number,
|
|
40
|
+
/** Summary reference sequence number, i.e. last sequence number seen when it was created */
|
|
41
|
+
lastSummaryReferenceSequenceNumber?: number, wipSummaryLogger?: ITelemetryBaseLogger, getGCDataFn?: ((fullGC?: boolean) => Promise<IGarbageCollectionData>) | undefined, getBaseGCDetailsFn?: () => Promise<IGarbageCollectionDetailsBase>,
|
|
42
42
|
/** A unique id of this node to be logged when sending telemetry. */
|
|
43
43
|
telemetryId?: string);
|
|
44
44
|
/**
|
|
@@ -72,11 +72,10 @@ export declare class SummarizerNodeWithGC extends SummarizerNode implements IRoo
|
|
|
72
72
|
* Called after summary has been uploaded to the server. Add the work-in-progress state to the pending
|
|
73
73
|
* summary queue. We track this until we get an ack from the server for this summary.
|
|
74
74
|
* @param proposalHandle - The handle of the summary that was uploaded to the server.
|
|
75
|
-
* @param parentPath - The path of the parent node which is used to build the path of this node.
|
|
76
75
|
* @param parentSkipRecursion - true if the parent of this node skipped recursing the child nodes when summarizing.
|
|
77
76
|
* In that case, the children will not have work-in-progress state.
|
|
78
77
|
*/
|
|
79
|
-
protected completeSummaryCore(proposalHandle: string,
|
|
78
|
+
protected completeSummaryCore(proposalHandle: string, parentSkipRecursion: boolean): void;
|
|
80
79
|
/**
|
|
81
80
|
* Clears the work-in-progress state.
|
|
82
81
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summarizerNodeWithGc.d.ts","sourceRoot":"","sources":["../../../src/summary/summarizerNode/summarizerNodeWithGc.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAEvE,OAAO,EACN,sBAAsB,EACtB,8BAA8B,EAC9B,6BAA6B,EAC7B,2BAA2B,EAC3B,qBAAqB,EACrB,mBAAmB,EACnB,MAAM,8CAA8C,CAAC;AAUtD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EACN,WAAW,EAEX,mBAAmB,EACnB,2BAA2B,
|
|
1
|
+
{"version":3,"file":"summarizerNodeWithGc.d.ts","sourceRoot":"","sources":["../../../src/summary/summarizerNode/summarizerNodeWithGc.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,13 +11,6 @@ const internal_3 = require("@fluidframework/telemetry-utils/internal");
|
|
|
11
11
|
const index_js_1 = require("../../gc/index.js");
|
|
12
12
|
const summarizerNode_js_1 = require("./summarizerNode.js");
|
|
13
13
|
const summarizerNodeUtils_js_1 = require("./summarizerNodeUtils.js");
|
|
14
|
-
// Extend SummaryNode to add used routes tracking to it.
|
|
15
|
-
class SummaryNodeWithGC extends summarizerNodeUtils_js_1.SummaryNode {
|
|
16
|
-
constructor(serializedUsedRoutes, summary) {
|
|
17
|
-
super(summary);
|
|
18
|
-
this.serializedUsedRoutes = serializedUsedRoutes;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
14
|
/**
|
|
22
15
|
* Extends the functionality of SummarizerNode to manage this node's garbage collection data:
|
|
23
16
|
*
|
|
@@ -36,12 +29,12 @@ class SummarizerNodeWithGC extends summarizerNode_js_1.SummarizerNode {
|
|
|
36
29
|
* Do not call constructor directly.
|
|
37
30
|
* Use createRootSummarizerNodeWithGC to create root node, or createChild to create child nodes.
|
|
38
31
|
*/
|
|
39
|
-
constructor(logger, summarizeInternalFn, config, changeSequenceNumber,
|
|
40
|
-
/**
|
|
41
|
-
|
|
32
|
+
constructor(logger, summarizeInternalFn, config, _summaryHandleId, changeSequenceNumber,
|
|
33
|
+
/** Summary reference sequence number, i.e. last sequence number seen when it was created */
|
|
34
|
+
lastSummaryReferenceSequenceNumber, wipSummaryLogger, getGCDataFn, getBaseGCDetailsFn,
|
|
42
35
|
/** A unique id of this node to be logged when sending telemetry. */
|
|
43
36
|
telemetryId) {
|
|
44
|
-
super(logger, summarizeInternalFn, config, changeSequenceNumber,
|
|
37
|
+
super(logger, summarizeInternalFn, config, _summaryHandleId, changeSequenceNumber, lastSummaryReferenceSequenceNumber, wipSummaryLogger, telemetryId);
|
|
45
38
|
this.getGCDataFn = getGCDataFn;
|
|
46
39
|
// Keeps track of whether we have loaded the base details to ensure that we only do it once.
|
|
47
40
|
this.baseGCDetailsLoaded = false;
|
|
@@ -167,23 +160,25 @@ class SummarizerNodeWithGC extends summarizerNode_js_1.SummarizerNode {
|
|
|
167
160
|
* Called after summary has been uploaded to the server. Add the work-in-progress state to the pending
|
|
168
161
|
* summary queue. We track this until we get an ack from the server for this summary.
|
|
169
162
|
* @param proposalHandle - The handle of the summary that was uploaded to the server.
|
|
170
|
-
* @param parentPath - The path of the parent node which is used to build the path of this node.
|
|
171
163
|
* @param parentSkipRecursion - true if the parent of this node skipped recursing the child nodes when summarizing.
|
|
172
164
|
* In that case, the children will not have work-in-progress state.
|
|
173
165
|
*/
|
|
174
|
-
completeSummaryCore(proposalHandle,
|
|
166
|
+
completeSummaryCore(proposalHandle, parentSkipRecursion) {
|
|
175
167
|
let wipSerializedUsedRoutes;
|
|
176
168
|
// If GC is disabled, don't set wip used routes.
|
|
177
169
|
if (!this.gcDisabled) {
|
|
178
170
|
wipSerializedUsedRoutes = this.wipSerializedUsedRoutes;
|
|
179
171
|
}
|
|
180
|
-
super.completeSummaryCore(proposalHandle,
|
|
172
|
+
super.completeSummaryCore(proposalHandle, parentSkipRecursion);
|
|
181
173
|
// If GC is disabled, skip setting pending summary with GC state.
|
|
182
174
|
if (!this.gcDisabled) {
|
|
183
|
-
const
|
|
184
|
-
if (
|
|
185
|
-
const
|
|
186
|
-
|
|
175
|
+
const pendingSummaryInfo = this.pendingSummaries.get(proposalHandle);
|
|
176
|
+
if (pendingSummaryInfo !== undefined) {
|
|
177
|
+
const pendingSummaryInfoWithGC = {
|
|
178
|
+
serializedUsedRoutes: wipSerializedUsedRoutes,
|
|
179
|
+
...pendingSummaryInfo,
|
|
180
|
+
};
|
|
181
|
+
this.pendingSummaries.set(proposalHandle, pendingSummaryInfoWithGC);
|
|
187
182
|
}
|
|
188
183
|
}
|
|
189
184
|
}
|
|
@@ -202,10 +197,10 @@ class SummarizerNodeWithGC extends summarizerNode_js_1.SummarizerNode {
|
|
|
202
197
|
refreshLatestSummaryFromPending(proposalHandle, referenceSequenceNumber) {
|
|
203
198
|
// If GC is disabled, skip setting referenced used routes since we are not tracking GC state.
|
|
204
199
|
if (!this.gcDisabled) {
|
|
205
|
-
const
|
|
206
|
-
if (
|
|
200
|
+
const pendingSummaryInfo = this.pendingSummaries.get(proposalHandle);
|
|
201
|
+
if (pendingSummaryInfo !== undefined) {
|
|
207
202
|
// If a pending summary exists, it must have used routes since GC is enabled.
|
|
208
|
-
const summaryNodeWithGC =
|
|
203
|
+
const summaryNodeWithGC = pendingSummaryInfo;
|
|
209
204
|
if (summaryNodeWithGC.serializedUsedRoutes === undefined) {
|
|
210
205
|
const error = new internal_3.LoggingError("MissingGCStateInPendingSummary", {
|
|
211
206
|
proposalHandle,
|
|
@@ -254,7 +249,7 @@ class SummarizerNodeWithGC extends summarizerNode_js_1.SummarizerNode {
|
|
|
254
249
|
...config,
|
|
255
250
|
// Propagate our gcDisabled state to the child if its not explicity specified in child's config.
|
|
256
251
|
gcDisabled: config.gcDisabled ?? this.gcDisabled,
|
|
257
|
-
}, createDetails.changeSequenceNumber, createDetails.
|
|
252
|
+
}, createDetails.summaryHandleId, createDetails.changeSequenceNumber, createDetails.lastSummaryReferenceSequenceNumber, this.wipSummaryLogger, getGCDataFn, getChildBaseGCDetailsFn, createDetails.telemetryNodeId);
|
|
258
253
|
// There may be additional state that has to be updated in this child. For example, if a summary is being
|
|
259
254
|
// tracked, the child's summary tracking state needs to be updated too.
|
|
260
255
|
this.maybeUpdateChildState(child, id);
|
|
@@ -286,19 +281,16 @@ class SummarizerNodeWithGC extends summarizerNode_js_1.SummarizerNode {
|
|
|
286
281
|
child.updateUsedRoutes(this.wipChildNodesUsedRoutes.get(id) ?? [""]);
|
|
287
282
|
}
|
|
288
283
|
// In case we have pending summaries on the parent, let's initialize it on the child.
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
});
|
|
300
|
-
child.addPendingSummary(key, newLatestSummaryNode);
|
|
301
|
-
}
|
|
284
|
+
for (const [key, pendingSummary] of this.pendingSummaries.entries()) {
|
|
285
|
+
const pendingSummaryWithGC = pendingSummary;
|
|
286
|
+
if (pendingSummaryWithGC.serializedUsedRoutes !== undefined) {
|
|
287
|
+
const childNodeUsedRoutes = (0, internal_2.unpackChildNodesUsedRoutes)(JSON.parse(pendingSummaryWithGC.serializedUsedRoutes));
|
|
288
|
+
const newSerializedRoutes = childNodeUsedRoutes.get(id) ?? [""];
|
|
289
|
+
const childPendingSummaryInfo = {
|
|
290
|
+
...pendingSummaryWithGC,
|
|
291
|
+
serializedUsedRoutes: JSON.stringify(newSerializedRoutes),
|
|
292
|
+
};
|
|
293
|
+
child.addPendingSummary(key, childPendingSummaryInfo);
|
|
302
294
|
}
|
|
303
295
|
}
|
|
304
296
|
}
|
|
@@ -365,8 +357,6 @@ exports.SummarizerNodeWithGC = SummarizerNodeWithGC;
|
|
|
365
357
|
* @param getGCDataFn - Function to get the GC data of this node
|
|
366
358
|
* @param baseGCDetailsP - Function to get the initial GC details of this node
|
|
367
359
|
*/
|
|
368
|
-
const createRootSummarizerNodeWithGC = (logger, summarizeInternalFn, changeSequenceNumber, referenceSequenceNumber, config = {}, getGCDataFn, getBaseGCDetailsFn) => new SummarizerNodeWithGC(logger, summarizeInternalFn, config, changeSequenceNumber, referenceSequenceNumber
|
|
369
|
-
? undefined
|
|
370
|
-
: summarizerNodeUtils_js_1.SummaryNode.createForRoot(referenceSequenceNumber), undefined /* wipSummaryLogger */, getGCDataFn, getBaseGCDetailsFn, "" /* telemetryId */);
|
|
360
|
+
const createRootSummarizerNodeWithGC = (logger, summarizeInternalFn, changeSequenceNumber, referenceSequenceNumber, config = {}, getGCDataFn, getBaseGCDetailsFn) => new SummarizerNodeWithGC(logger, summarizeInternalFn, config, summarizerNodeUtils_js_1.EscapedPath.create("") /* summaryHandleId */, changeSequenceNumber, referenceSequenceNumber, undefined /* wipSummaryLogger */, getGCDataFn, getBaseGCDetailsFn, "" /* telemetryId */);
|
|
371
361
|
exports.createRootSummarizerNodeWithGC = createRootSummarizerNodeWithGC;
|
|
372
362
|
//# sourceMappingURL=summarizerNodeWithGc.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summarizerNodeWithGc.js","sourceRoot":"","sources":["../../../src/summary/summarizerNode/summarizerNodeWithGc.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { assert, LazyPromise } from \"@fluidframework/core-utils/internal\";\nimport {\n\tIGarbageCollectionData,\n\tCreateChildSummarizerNodeParam,\n\tIGarbageCollectionDetailsBase,\n\tISummarizerNodeConfigWithGC,\n\tISummarizerNodeWithGC,\n\tSummarizeInternalFn,\n} from \"@fluidframework/runtime-definitions/internal\";\nimport { unpackChildNodesUsedRoutes } from \"@fluidframework/runtime-utils/internal\";\nimport {\n\tLoggingError,\n\tTelemetryDataTag,\n\ttagCodeArtifacts,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport { cloneGCData, unpackChildNodesGCDetails } from \"../../gc/index.js\";\n\nimport { SummarizerNode } from \"./summarizerNode.js\";\nimport {\n\tEscapedPath,\n\tICreateChildDetails,\n\tIStartSummaryResult,\n\tISummarizerNodeRootContract,\n\tSummaryNode,\n\tValidateSummaryResult,\n} from \"./summarizerNodeUtils.js\";\n\nexport interface IRootSummarizerNodeWithGC\n\textends ISummarizerNodeWithGC,\n\t\tISummarizerNodeRootContract {}\n\n// Extend SummaryNode to add used routes tracking to it.\nclass SummaryNodeWithGC extends SummaryNode {\n\tconstructor(\n\t\tpublic readonly serializedUsedRoutes: string | undefined,\n\t\tsummary: {\n\t\t\treadonly referenceSequenceNumber: number;\n\t\t\treadonly basePath: EscapedPath | undefined;\n\t\t\treadonly localPath: EscapedPath;\n\t\t\tadditionalPath?: EscapedPath;\n\t\t},\n\t) {\n\t\tsuper(summary);\n\t}\n}\n\n/**\n * Extends the functionality of SummarizerNode to manage this node's garbage collection data:\n *\n * - Adds a new API `getGCData` to return GC data of this node.\n *\n * - Caches the result of `getGCData` to be used if nothing changes between summaries.\n *\n * - Manages the used routes of this node. These are used to identify if this node is referenced in the document\n * and to determine if the node's used state changed since last summary.\n *\n * - Adds trackState param to summarize. If trackState is false, it bypasses the SummarizerNode and calls\n * directly into summarizeInternal method.\n */\nexport class SummarizerNodeWithGC extends SummarizerNode implements IRootSummarizerNodeWithGC {\n\t// Tracks the work-in-progress used routes during summary.\n\tprivate wipSerializedUsedRoutes: string | undefined;\n\n\t// Tracks the work-in-progress used routes of child nodes during summary.\n\tprivate wipChildNodesUsedRoutes: Map<string, string[]> | undefined;\n\n\t// This is the last known used routes of this node as seen by the server as part of a summary.\n\tprivate referenceUsedRoutes: string[] | undefined;\n\n\t// The base GC details of this node used to initialize the GC state.\n\tprivate readonly baseGCDetailsP: Promise<IGarbageCollectionDetailsBase>;\n\n\t// Keeps track of whether we have loaded the base details to ensure that we only do it once.\n\tprivate baseGCDetailsLoaded: boolean = false;\n\n\t// The base GC details for the child nodes. This is passed to child nodes when creating them.\n\tprivate readonly childNodesBaseGCDetailsP: Promise<\n\t\tMap<string, IGarbageCollectionDetailsBase>\n\t>;\n\n\tprivate gcData: IGarbageCollectionData | undefined;\n\n\t// Set used routes to have self route by default. This makes the node referenced by default. This is done to ensure\n\t// that this node is not marked as collected when running GC has been disabled. Once, the option to disable GC is\n\t// removed (from runGC flag in IContainerRuntimeOptions), this should be changed to be have no routes by default.\n\tprivate usedRoutes: string[] = [\"\"];\n\n\t// True if GC is disabled for this node. If so, do not track GC specific state for a summary.\n\tprivate readonly gcDisabled: boolean;\n\n\t/**\n\t * Do not call constructor directly.\n\t * Use createRootSummarizerNodeWithGC to create root node, or createChild to create child nodes.\n\t */\n\tpublic constructor(\n\t\tlogger: ITelemetryBaseLogger,\n\t\tsummarizeInternalFn: SummarizeInternalFn,\n\t\tconfig: ISummarizerNodeConfigWithGC,\n\t\tchangeSequenceNumber: number,\n\t\t/** Undefined means created without summary */\n\t\tlatestSummary?: SummaryNode,\n\t\twipSummaryLogger?: ITelemetryBaseLogger,\n\t\tprivate readonly getGCDataFn?: (fullGC?: boolean) => Promise<IGarbageCollectionData>,\n\t\tgetBaseGCDetailsFn?: () => Promise<IGarbageCollectionDetailsBase>,\n\t\t/** A unique id of this node to be logged when sending telemetry. */\n\t\ttelemetryId?: string,\n\t) {\n\t\tsuper(\n\t\t\tlogger,\n\t\t\tsummarizeInternalFn,\n\t\t\tconfig,\n\t\t\tchangeSequenceNumber,\n\t\t\tlatestSummary,\n\t\t\twipSummaryLogger,\n\t\t\ttelemetryId,\n\t\t);\n\n\t\tthis.gcDisabled = config.gcDisabled === true;\n\n\t\tthis.baseGCDetailsP = new LazyPromise(async () => {\n\t\t\treturn (await getBaseGCDetailsFn?.()) ?? { usedRoutes: [] };\n\t\t});\n\n\t\tthis.childNodesBaseGCDetailsP = new LazyPromise(async () => {\n\t\t\tawait this.loadBaseGCDetails();\n\t\t\treturn unpackChildNodesGCDetails({ gcData: this.gcData, usedRoutes: this.usedRoutes });\n\t\t});\n\t}\n\n\t/**\n\t * Loads state from this node's initial GC summary details. This contains the following data from the last summary\n\t * seen by the server for this client:\n\t * - usedRoutes: This is used to figure out if the used state of this node changed since last summary.\n\t * - gcData: The garbage collection data of this node that is required for running GC.\n\t */\n\tprivate async loadBaseGCDetails() {\n\t\tif (this.baseGCDetailsLoaded) {\n\t\t\treturn;\n\t\t}\n\t\tconst baseGCDetails = await this.baseGCDetailsP;\n\n\t\t// Possible race - If there were parallel calls to loadBaseGCDetails, we want to make sure that we update\n\t\t// the state from the base details only once.\n\t\tif (this.baseGCDetailsLoaded) {\n\t\t\treturn;\n\t\t}\n\t\tthis.baseGCDetailsLoaded = true;\n\n\t\t// Update GC data, used routes and reference used routes. The used routes are sorted because they are compared\n\t\t// across GC runs to check if they changed. Sorting ensures that the elements are in the same order.\n\t\t// If the GC details has GC data, initialize our GC data from it.\n\t\tif (baseGCDetails.gcData !== undefined) {\n\t\t\tthis.gcData = cloneGCData(baseGCDetails.gcData);\n\t\t}\n\t\tif (baseGCDetails.usedRoutes !== undefined) {\n\t\t\tthis.usedRoutes = Array.from(baseGCDetails.usedRoutes).sort();\n\t\t\tthis.referenceUsedRoutes = Array.from(baseGCDetails.usedRoutes).sort();\n\t\t}\n\t}\n\n\t/**\n\t * Returns the GC data of this node. If nothing has changed since last summary, it tries to reuse the data from\n\t * the previous summary. Else, it gets new GC data from the underlying Fluid object.\n\t * @param fullGC - true to bypass optimizations and force full generation of GC data.\n\t */\n\tpublic async getGCData(fullGC: boolean = false): Promise<IGarbageCollectionData> {\n\t\tassert(\n\t\t\t!this.gcDisabled,\n\t\t\t0x1b2 /* \"Getting GC data should not be called when GC is disabled!\" */,\n\t\t);\n\t\tassert(\n\t\t\tthis.getGCDataFn !== undefined,\n\t\t\t0x1b3 /* \"GC data cannot be retrieved without getGCDataFn\" */,\n\t\t);\n\n\t\t// Load GC details from the initial summary, if not already loaded. If this is the first time this function is\n\t\t// called and the node's data has not changed since last summary, the GC data in initial details is returned.\n\t\tawait this.loadBaseGCDetails();\n\n\t\t// If there is no new data since last summary and we have GC data from the previous run, return it. The previous\n\t\t// GC data may not be available if loaded from a snapshot with either GC disabled or before GC was added.\n\t\t// Note - canReuseHandle is checked to be consistent with summarize - generate GC data for nodes for which\n\t\t// summary must be generated.\n\t\tif (\n\t\t\tthis.canReuseHandle &&\n\t\t\t!fullGC &&\n\t\t\t!this.hasDataChanged() &&\n\t\t\tthis.gcData !== undefined\n\t\t) {\n\t\t\treturn cloneGCData(this.gcData);\n\t\t}\n\n\t\tconst gcData = await this.getGCDataFn(fullGC);\n\t\tthis.gcData = cloneGCData(gcData);\n\t\treturn gcData;\n\t}\n\n\t/**\n\t * Called during the start of a summary. Updates the work-in-progress used routes.\n\t */\n\tpublic startSummary(\n\t\treferenceSequenceNumber: number,\n\t\tsummaryLogger: ITelemetryBaseLogger,\n\t\tlatestSummaryRefSeqNum: number,\n\t): IStartSummaryResult {\n\t\t// If GC is disabled, skip setting wip used routes since we should not track GC state.\n\t\tif (!this.gcDisabled) {\n\t\t\tassert(\n\t\t\t\tthis.wipSerializedUsedRoutes === undefined,\n\t\t\t\t0x1b4 /* \"We should not already be tracking used routes when to track a new summary\" */,\n\t\t\t);\n\t\t}\n\t\treturn super.startSummary(referenceSequenceNumber, summaryLogger, latestSummaryRefSeqNum);\n\t}\n\n\t/**\n\t * Validates that the in-progress summary is correct for all nodes, i.e., GC should have run for non-skipped nodes.\n\t * @param parentSkipRecursion - true if the parent of this node skipped recursing the child nodes when running GC.\n\t * In that case, the children will not have work-in-progress state.\n\t *\n\t * @returns ValidateSummaryResult which contains a boolean success indicating whether the validation was successful.\n\t * In case of failure, additional information is returned indicating type of failure and where it was.\n\t */\n\tprotected validateSummaryCore(parentSkipRecursion: boolean): ValidateSummaryResult {\n\t\tif (this.wasGCMissed()) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\treason: \"NodeDidNotRunGC\",\n\t\t\t\tid: {\n\t\t\t\t\ttag: TelemetryDataTag.CodeArtifact,\n\t\t\t\t\tvalue: this.telemetryNodeId,\n\t\t\t\t},\n\t\t\t\t// These errors are usually transient and should go away when summarize / GC is retried.\n\t\t\t\tretryAfterSeconds: 1,\n\t\t\t};\n\t\t}\n\t\treturn super.validateSummaryCore(parentSkipRecursion);\n\t}\n\n\tprivate wasGCMissed(): boolean {\n\t\t// If GC is disabled, it should not have run so it was not missed.\n\t\t// Otherwise, GC should have been called on this node and wipSerializedUsedRoutes must be set.\n\t\tif (this.gcDisabled || this.wipSerializedUsedRoutes !== undefined) {\n\t\t\treturn false;\n\t\t}\n\t\t/**\n\t\t * The absence of wip used routes indicates that GC was not run on this node. This can happen if:\n\t\t * 1. A child node was created after GC was already run on the parent. For example, a data store\n\t\t * is realized (loaded) after GC was run on it creating summarizer nodes for its DDSes. In this\n\t\t * case, the parent will pass on used routes to the child nodes and it will have wip used routes.\n\t\t * 2. A new node was created but GC was never run on it. This can mean that the GC data generated\n\t\t * during summarize is incomplete.\n\t\t *\n\t\t * This happens due to scenarios such as data store created during summarize. Such errors should go away when\n\t\t * summarize is attempted again.\n\t\t */\n\t\treturn true;\n\t}\n\n\t/**\n\t * Called after summary has been uploaded to the server. Add the work-in-progress state to the pending\n\t * summary queue. We track this until we get an ack from the server for this summary.\n\t * @param proposalHandle - The handle of the summary that was uploaded to the server.\n\t * @param parentPath - The path of the parent node which is used to build the path of this node.\n\t * @param parentSkipRecursion - true if the parent of this node skipped recursing the child nodes when summarizing.\n\t * In that case, the children will not have work-in-progress state.\n\t */\n\tprotected completeSummaryCore(\n\t\tproposalHandle: string,\n\t\tparentPath: EscapedPath | undefined,\n\t\tparentSkipRecursion: boolean,\n\t) {\n\t\tlet wipSerializedUsedRoutes: string | undefined;\n\t\t// If GC is disabled, don't set wip used routes.\n\t\tif (!this.gcDisabled) {\n\t\t\twipSerializedUsedRoutes = this.wipSerializedUsedRoutes;\n\t\t}\n\n\t\tsuper.completeSummaryCore(proposalHandle, parentPath, parentSkipRecursion);\n\n\t\t// If GC is disabled, skip setting pending summary with GC state.\n\t\tif (!this.gcDisabled) {\n\t\t\tconst summaryNode = this.pendingSummaries.get(proposalHandle);\n\t\t\tif (summaryNode !== undefined) {\n\t\t\t\tconst summaryNodeWithGC = new SummaryNodeWithGC(wipSerializedUsedRoutes, summaryNode);\n\t\t\t\tthis.pendingSummaries.set(proposalHandle, summaryNodeWithGC);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Clears the work-in-progress state.\n\t */\n\tpublic clearSummary() {\n\t\tthis.wipSerializedUsedRoutes = undefined;\n\t\tthis.wipChildNodesUsedRoutes = undefined;\n\t\tsuper.clearSummary();\n\t}\n\n\t/**\n\t * Called when we get an ack from the server for a summary we sent. Update the reference state of this node\n\t * from the state in the pending summary queue.\n\t */\n\tprotected refreshLatestSummaryFromPending(\n\t\tproposalHandle: string,\n\t\treferenceSequenceNumber: number,\n\t): void {\n\t\t// If GC is disabled, skip setting referenced used routes since we are not tracking GC state.\n\t\tif (!this.gcDisabled) {\n\t\t\tconst summaryNode = this.pendingSummaries.get(proposalHandle);\n\t\t\tif (summaryNode !== undefined) {\n\t\t\t\t// If a pending summary exists, it must have used routes since GC is enabled.\n\t\t\t\tconst summaryNodeWithGC = summaryNode as SummaryNodeWithGC;\n\t\t\t\tif (summaryNodeWithGC.serializedUsedRoutes === undefined) {\n\t\t\t\t\tconst error = new LoggingError(\"MissingGCStateInPendingSummary\", {\n\t\t\t\t\t\tproposalHandle,\n\t\t\t\t\t\treferenceSequenceNumber,\n\t\t\t\t\t\t...tagCodeArtifacts({\n\t\t\t\t\t\t\tid: this.telemetryNodeId,\n\t\t\t\t\t\t}),\n\t\t\t\t\t});\n\t\t\t\t\tthis.logger.sendErrorEvent(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\teventName: error.message,\n\t\t\t\t\t\t},\n\t\t\t\t\t\terror,\n\t\t\t\t\t);\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tthis.referenceUsedRoutes = JSON.parse(summaryNodeWithGC.serializedUsedRoutes);\n\t\t\t}\n\t\t}\n\n\t\treturn super.refreshLatestSummaryFromPending(proposalHandle, referenceSequenceNumber);\n\t}\n\n\t/**\n\t * Override the createChild method to return an instance of SummarizerNodeWithGC.\n\t */\n\tpublic createChild(\n\t\t/** Summarize function */\n\t\tsummarizeInternalFn: SummarizeInternalFn,\n\t\t/** Initial id or path part of this node */\n\t\tid: string,\n\t\t/**\n\t\t * Information needed to create the node.\n\t\t * If it is from a base summary, it will assert that a summary has been seen.\n\t\t * Attach information if it is created from an attach op.\n\t\t */\n\t\tcreateParam: CreateChildSummarizerNodeParam,\n\t\tconfig: ISummarizerNodeConfigWithGC = {},\n\t\tgetGCDataFn?: (fullGC?: boolean) => Promise<IGarbageCollectionData>,\n\t): ISummarizerNodeWithGC {\n\t\tassert(!this.children.has(id), 0x1b6 /* \"Create SummarizerNode child already exists\" */);\n\t\t/**\n\t\t * Update the child node's base GC details from this node's current GC details instead of updating from the base\n\t\t * GC details of this node. This will handle scenarios where the GC details was updated during refresh from\n\t\t * snapshot and the child node wasn't created then. If a child is created after that, its GC details should be\n\t\t * the one from the downloaded snapshot and not the base GC details.\n\t\t */\n\t\tconst getChildBaseGCDetailsFn = async () => {\n\t\t\tconst childNodesBaseGCDetails = await this.childNodesBaseGCDetailsP;\n\t\t\treturn childNodesBaseGCDetails.get(id) ?? {};\n\t\t};\n\n\t\tconst createDetails: ICreateChildDetails = this.getCreateDetailsForChild(id, createParam);\n\t\tconst child = new SummarizerNodeWithGC(\n\t\t\tthis.logger,\n\t\t\tsummarizeInternalFn,\n\t\t\t{\n\t\t\t\t...config,\n\t\t\t\t// Propagate our gcDisabled state to the child if its not explicity specified in child's config.\n\t\t\t\tgcDisabled: config.gcDisabled ?? this.gcDisabled,\n\t\t\t},\n\t\t\tcreateDetails.changeSequenceNumber,\n\t\t\tcreateDetails.latestSummary,\n\t\t\tthis.wipSummaryLogger,\n\t\t\tgetGCDataFn,\n\t\t\tgetChildBaseGCDetailsFn,\n\t\t\tcreateDetails.telemetryNodeId,\n\t\t);\n\n\t\t// There may be additional state that has to be updated in this child. For example, if a summary is being\n\t\t// tracked, the child's summary tracking state needs to be updated too.\n\t\tthis.maybeUpdateChildState(child, id);\n\n\t\tthis.children.set(id, child);\n\t\treturn child;\n\t}\n\n\t/**\n\t * Updates the state of the child if required. For example, if a summary is currently being tracked, the child's\n\t * summary tracking state needs to be updated too.\n\t * Also, in case a child node gets realized in between Summary Op and Summary Ack, let's initialize the child's\n\t * pending summary as well. Finally, if the pendingSummaries entries have serializedRoutes, replicate them to the\n\t * pendingSummaries from the child nodes.\n\t * @param child - The child node whose state is to be updated.\n\t * @param id - Initial id or path part of this node\n\t */\n\tprotected maybeUpdateChildState(child: SummarizerNodeWithGC, id: string) {\n\t\tsuper.maybeUpdateChildState(child, id);\n\n\t\t// If GC has run on this node and summarization isn't complete, this.wipSerializedUsedRoutes will be defined.\n\t\t// In that case, update the used routes of the child node. This can happen in scenarios where a data store\n\t\t// doesn't have any ops but its reference state changed. So, it gets realized during summarize after GC ran\n\t\t// so GC would not have run on this node which is fine.\n\t\tif (this.wipSerializedUsedRoutes !== undefined) {\n\t\t\t// If the child route used routes are not defined, initialize it now and it can be used for all child nodes\n\t\t\t// created until this summarization process is completed. This is an optimization to unpack the used routes\n\t\t\t// only when needed.\n\t\t\tif (this.wipChildNodesUsedRoutes === undefined) {\n\t\t\t\tthis.wipChildNodesUsedRoutes = unpackChildNodesUsedRoutes(this.usedRoutes);\n\t\t\t}\n\t\t\tchild.updateUsedRoutes(this.wipChildNodesUsedRoutes.get(id) ?? [\"\"]);\n\t\t}\n\n\t\t// In case we have pending summaries on the parent, let's initialize it on the child.\n\t\tif (child.latestSummary !== undefined) {\n\t\t\tfor (const [key, value] of this.pendingSummaries.entries()) {\n\t\t\t\tconst summaryNodeWithGC = value as SummaryNodeWithGC;\n\t\t\t\tif (summaryNodeWithGC.serializedUsedRoutes !== undefined) {\n\t\t\t\t\tconst childNodeUsedRoutes = unpackChildNodesUsedRoutes(\n\t\t\t\t\t\tJSON.parse(summaryNodeWithGC.serializedUsedRoutes),\n\t\t\t\t\t);\n\t\t\t\t\tconst newSerializedRoutes = childNodeUsedRoutes.get(id) ?? [\"\"];\n\t\t\t\t\tconst newLatestSummaryNode = new SummaryNodeWithGC(\n\t\t\t\t\t\tJSON.stringify(newSerializedRoutes),\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treferenceSequenceNumber: value.referenceSequenceNumber,\n\t\t\t\t\t\t\tbasePath: child.latestSummary.basePath,\n\t\t\t\t\t\t\tlocalPath: child.latestSummary.localPath,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t\tchild.addPendingSummary(key, newLatestSummaryNode);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Deletes the child node with the given id.\n\t */\n\tpublic deleteChild(id: string): void {\n\t\tthis.children.delete(id);\n\t}\n\n\t/**\n\t * Override the getChild method to return an instance of SummarizerNodeWithGC.\n\t */\n\tpublic getChild(id: string): ISummarizerNodeWithGC | undefined {\n\t\treturn this.children.get(id) as SummarizerNodeWithGC;\n\t}\n\n\tpublic isReferenced(): boolean {\n\t\treturn this.usedRoutes.includes(\"\") || this.usedRoutes.includes(\"/\");\n\t}\n\n\tpublic updateUsedRoutes(usedRoutes: string[]) {\n\t\t// Sort the given routes before updating. This will ensure that the routes compared in hasUsedStateChanged()\n\t\t// are in the same order.\n\t\tthis.usedRoutes = usedRoutes.sort();\n\n\t\t// If GC is not disabled and a summary is in progress, update the work-in-progress used routes so that it can\n\t\t// be tracked for this summary.\n\t\tif (!this.gcDisabled && this.isSummaryInProgress()) {\n\t\t\tthis.wipSerializedUsedRoutes = JSON.stringify(this.usedRoutes);\n\t\t}\n\t}\n\n\t/**\n\t * Override the hasChanged method. If this node data or its used state changed, the node is considered changed.\n\t */\n\tprotected hasChanged(): boolean {\n\t\treturn this.hasDataChanged() || this.hasUsedStateChanged();\n\t}\n\n\t/**\n\t * This tells whether the data in this node has changed or not.\n\t */\n\tprivate hasDataChanged(): boolean {\n\t\treturn super.hasChanged();\n\t}\n\n\t/**\n\t * This tells whether the used state of this node has changed since last successful summary. If the used routes\n\t * of this node changed, its used state is considered changed. Basically, if this node or any of its child nodes\n\t * was previously used and became unused (or vice versa), its used state has changed.\n\t */\n\tprivate hasUsedStateChanged(): boolean {\n\t\t// If GC is disabled, it should not affect summary state, return false.\n\t\tif (this.gcDisabled) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn (\n\t\t\tthis.referenceUsedRoutes === undefined ||\n\t\t\tJSON.stringify(this.usedRoutes) !== JSON.stringify(this.referenceUsedRoutes)\n\t\t);\n\t}\n}\n\n/**\n * Creates a root summarizer node with GC functionality built-in.\n * @param logger - Logger to use within SummarizerNode\n * @param summarizeInternalFn - Function to generate summary\n * @param changeSequenceNumber - Sequence number of latest change to new node/subtree\n * @param referenceSequenceNumber - Reference sequence number of last acked summary,\n * or undefined if not loaded from summary\n * @param config - Configure behavior of summarizer node\n * @param getGCDataFn - Function to get the GC data of this node\n * @param baseGCDetailsP - Function to get the initial GC details of this node\n */\nexport const createRootSummarizerNodeWithGC = (\n\tlogger: ITelemetryBaseLogger,\n\tsummarizeInternalFn: SummarizeInternalFn,\n\tchangeSequenceNumber: number,\n\treferenceSequenceNumber: number | undefined,\n\tconfig: ISummarizerNodeConfigWithGC = {},\n\tgetGCDataFn?: (fullGC?: boolean) => Promise<IGarbageCollectionData>,\n\tgetBaseGCDetailsFn?: () => Promise<IGarbageCollectionDetailsBase>,\n): IRootSummarizerNodeWithGC =>\n\tnew SummarizerNodeWithGC(\n\t\tlogger,\n\t\tsummarizeInternalFn,\n\t\tconfig,\n\t\tchangeSequenceNumber,\n\t\treferenceSequenceNumber === undefined\n\t\t\t? undefined\n\t\t\t: SummaryNode.createForRoot(referenceSequenceNumber),\n\t\tundefined /* wipSummaryLogger */,\n\t\tgetGCDataFn,\n\t\tgetBaseGCDetailsFn,\n\t\t\"\" /* telemetryId */,\n\t);\n"]}
|
|
1
|
+
{"version":3,"file":"summarizerNodeWithGc.js","sourceRoot":"","sources":["../../../src/summary/summarizerNode/summarizerNodeWithGc.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { assert, LazyPromise } from \"@fluidframework/core-utils/internal\";\nimport {\n\tIGarbageCollectionData,\n\tCreateChildSummarizerNodeParam,\n\tIGarbageCollectionDetailsBase,\n\tISummarizerNodeConfigWithGC,\n\tISummarizerNodeWithGC,\n\tSummarizeInternalFn,\n} from \"@fluidframework/runtime-definitions/internal\";\nimport { unpackChildNodesUsedRoutes } from \"@fluidframework/runtime-utils/internal\";\nimport {\n\tLoggingError,\n\tTelemetryDataTag,\n\ttagCodeArtifacts,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport { cloneGCData, unpackChildNodesGCDetails } from \"../../gc/index.js\";\n\nimport { SummarizerNode } from \"./summarizerNode.js\";\nimport {\n\tEscapedPath,\n\tICreateChildDetails,\n\tIStartSummaryResult,\n\tISummarizerNodeRootContract,\n\tPendingSummaryInfo,\n\tValidateSummaryResult,\n} from \"./summarizerNodeUtils.js\";\n\nexport interface IRootSummarizerNodeWithGC\n\textends ISummarizerNodeWithGC,\n\t\tISummarizerNodeRootContract {}\n\n// Extend PendingSummaryInfo to add used routes tracking it.\ninterface PendingSummaryInfoWithGC extends PendingSummaryInfo {\n\tserializedUsedRoutes: string | undefined;\n}\n\n/**\n * Extends the functionality of SummarizerNode to manage this node's garbage collection data:\n *\n * - Adds a new API `getGCData` to return GC data of this node.\n *\n * - Caches the result of `getGCData` to be used if nothing changes between summaries.\n *\n * - Manages the used routes of this node. These are used to identify if this node is referenced in the document\n * and to determine if the node's used state changed since last summary.\n *\n * - Adds trackState param to summarize. If trackState is false, it bypasses the SummarizerNode and calls\n * directly into summarizeInternal method.\n */\nexport class SummarizerNodeWithGC extends SummarizerNode implements IRootSummarizerNodeWithGC {\n\t// Tracks the work-in-progress used routes during summary.\n\tprivate wipSerializedUsedRoutes: string | undefined;\n\n\t// Tracks the work-in-progress used routes of child nodes during summary.\n\tprivate wipChildNodesUsedRoutes: Map<string, string[]> | undefined;\n\n\t// This is the last known used routes of this node as seen by the server as part of a summary.\n\tprivate referenceUsedRoutes: string[] | undefined;\n\n\t// The base GC details of this node used to initialize the GC state.\n\tprivate readonly baseGCDetailsP: Promise<IGarbageCollectionDetailsBase>;\n\n\t// Keeps track of whether we have loaded the base details to ensure that we only do it once.\n\tprivate baseGCDetailsLoaded: boolean = false;\n\n\t// The base GC details for the child nodes. This is passed to child nodes when creating them.\n\tprivate readonly childNodesBaseGCDetailsP: Promise<\n\t\tMap<string, IGarbageCollectionDetailsBase>\n\t>;\n\n\tprivate gcData: IGarbageCollectionData | undefined;\n\n\t// Set used routes to have self route by default. This makes the node referenced by default. This is done to ensure\n\t// that this node is not marked as collected when running GC has been disabled. Once, the option to disable GC is\n\t// removed (from runGC flag in IContainerRuntimeOptions), this should be changed to be have no routes by default.\n\tprivate usedRoutes: string[] = [\"\"];\n\n\t// True if GC is disabled for this node. If so, do not track GC specific state for a summary.\n\tprivate readonly gcDisabled: boolean;\n\n\t/**\n\t * Do not call constructor directly.\n\t * Use createRootSummarizerNodeWithGC to create root node, or createChild to create child nodes.\n\t */\n\tpublic constructor(\n\t\tlogger: ITelemetryBaseLogger,\n\t\tsummarizeInternalFn: SummarizeInternalFn,\n\t\tconfig: ISummarizerNodeConfigWithGC,\n\t\t_summaryHandleId: EscapedPath,\n\t\tchangeSequenceNumber: number,\n\t\t/** Summary reference sequence number, i.e. last sequence number seen when it was created */\n\t\tlastSummaryReferenceSequenceNumber?: number,\n\t\twipSummaryLogger?: ITelemetryBaseLogger,\n\t\tprivate readonly getGCDataFn?: (fullGC?: boolean) => Promise<IGarbageCollectionData>,\n\t\tgetBaseGCDetailsFn?: () => Promise<IGarbageCollectionDetailsBase>,\n\t\t/** A unique id of this node to be logged when sending telemetry. */\n\t\ttelemetryId?: string,\n\t) {\n\t\tsuper(\n\t\t\tlogger,\n\t\t\tsummarizeInternalFn,\n\t\t\tconfig,\n\t\t\t_summaryHandleId,\n\t\t\tchangeSequenceNumber,\n\t\t\tlastSummaryReferenceSequenceNumber,\n\t\t\twipSummaryLogger,\n\t\t\ttelemetryId,\n\t\t);\n\n\t\tthis.gcDisabled = config.gcDisabled === true;\n\n\t\tthis.baseGCDetailsP = new LazyPromise(async () => {\n\t\t\treturn (await getBaseGCDetailsFn?.()) ?? { usedRoutes: [] };\n\t\t});\n\n\t\tthis.childNodesBaseGCDetailsP = new LazyPromise(async () => {\n\t\t\tawait this.loadBaseGCDetails();\n\t\t\treturn unpackChildNodesGCDetails({ gcData: this.gcData, usedRoutes: this.usedRoutes });\n\t\t});\n\t}\n\n\t/**\n\t * Loads state from this node's initial GC summary details. This contains the following data from the last summary\n\t * seen by the server for this client:\n\t * - usedRoutes: This is used to figure out if the used state of this node changed since last summary.\n\t * - gcData: The garbage collection data of this node that is required for running GC.\n\t */\n\tprivate async loadBaseGCDetails() {\n\t\tif (this.baseGCDetailsLoaded) {\n\t\t\treturn;\n\t\t}\n\t\tconst baseGCDetails = await this.baseGCDetailsP;\n\n\t\t// Possible race - If there were parallel calls to loadBaseGCDetails, we want to make sure that we update\n\t\t// the state from the base details only once.\n\t\tif (this.baseGCDetailsLoaded) {\n\t\t\treturn;\n\t\t}\n\t\tthis.baseGCDetailsLoaded = true;\n\n\t\t// Update GC data, used routes and reference used routes. The used routes are sorted because they are compared\n\t\t// across GC runs to check if they changed. Sorting ensures that the elements are in the same order.\n\t\t// If the GC details has GC data, initialize our GC data from it.\n\t\tif (baseGCDetails.gcData !== undefined) {\n\t\t\tthis.gcData = cloneGCData(baseGCDetails.gcData);\n\t\t}\n\t\tif (baseGCDetails.usedRoutes !== undefined) {\n\t\t\tthis.usedRoutes = Array.from(baseGCDetails.usedRoutes).sort();\n\t\t\tthis.referenceUsedRoutes = Array.from(baseGCDetails.usedRoutes).sort();\n\t\t}\n\t}\n\n\t/**\n\t * Returns the GC data of this node. If nothing has changed since last summary, it tries to reuse the data from\n\t * the previous summary. Else, it gets new GC data from the underlying Fluid object.\n\t * @param fullGC - true to bypass optimizations and force full generation of GC data.\n\t */\n\tpublic async getGCData(fullGC: boolean = false): Promise<IGarbageCollectionData> {\n\t\tassert(\n\t\t\t!this.gcDisabled,\n\t\t\t0x1b2 /* \"Getting GC data should not be called when GC is disabled!\" */,\n\t\t);\n\t\tassert(\n\t\t\tthis.getGCDataFn !== undefined,\n\t\t\t0x1b3 /* \"GC data cannot be retrieved without getGCDataFn\" */,\n\t\t);\n\n\t\t// Load GC details from the initial summary, if not already loaded. If this is the first time this function is\n\t\t// called and the node's data has not changed since last summary, the GC data in initial details is returned.\n\t\tawait this.loadBaseGCDetails();\n\n\t\t// If there is no new data since last summary and we have GC data from the previous run, return it. The previous\n\t\t// GC data may not be available if loaded from a snapshot with either GC disabled or before GC was added.\n\t\t// Note - canReuseHandle is checked to be consistent with summarize - generate GC data for nodes for which\n\t\t// summary must be generated.\n\t\tif (\n\t\t\tthis.canReuseHandle &&\n\t\t\t!fullGC &&\n\t\t\t!this.hasDataChanged() &&\n\t\t\tthis.gcData !== undefined\n\t\t) {\n\t\t\treturn cloneGCData(this.gcData);\n\t\t}\n\n\t\tconst gcData = await this.getGCDataFn(fullGC);\n\t\tthis.gcData = cloneGCData(gcData);\n\t\treturn gcData;\n\t}\n\n\t/**\n\t * Called during the start of a summary. Updates the work-in-progress used routes.\n\t */\n\tpublic startSummary(\n\t\treferenceSequenceNumber: number,\n\t\tsummaryLogger: ITelemetryBaseLogger,\n\t\tlatestSummaryRefSeqNum: number,\n\t): IStartSummaryResult {\n\t\t// If GC is disabled, skip setting wip used routes since we should not track GC state.\n\t\tif (!this.gcDisabled) {\n\t\t\tassert(\n\t\t\t\tthis.wipSerializedUsedRoutes === undefined,\n\t\t\t\t0x1b4 /* \"We should not already be tracking used routes when to track a new summary\" */,\n\t\t\t);\n\t\t}\n\t\treturn super.startSummary(referenceSequenceNumber, summaryLogger, latestSummaryRefSeqNum);\n\t}\n\n\t/**\n\t * Validates that the in-progress summary is correct for all nodes, i.e., GC should have run for non-skipped nodes.\n\t * @param parentSkipRecursion - true if the parent of this node skipped recursing the child nodes when running GC.\n\t * In that case, the children will not have work-in-progress state.\n\t *\n\t * @returns ValidateSummaryResult which contains a boolean success indicating whether the validation was successful.\n\t * In case of failure, additional information is returned indicating type of failure and where it was.\n\t */\n\tprotected validateSummaryCore(parentSkipRecursion: boolean): ValidateSummaryResult {\n\t\tif (this.wasGCMissed()) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\treason: \"NodeDidNotRunGC\",\n\t\t\t\tid: {\n\t\t\t\t\ttag: TelemetryDataTag.CodeArtifact,\n\t\t\t\t\tvalue: this.telemetryNodeId,\n\t\t\t\t},\n\t\t\t\t// These errors are usually transient and should go away when summarize / GC is retried.\n\t\t\t\tretryAfterSeconds: 1,\n\t\t\t};\n\t\t}\n\t\treturn super.validateSummaryCore(parentSkipRecursion);\n\t}\n\n\tprivate wasGCMissed(): boolean {\n\t\t// If GC is disabled, it should not have run so it was not missed.\n\t\t// Otherwise, GC should have been called on this node and wipSerializedUsedRoutes must be set.\n\t\tif (this.gcDisabled || this.wipSerializedUsedRoutes !== undefined) {\n\t\t\treturn false;\n\t\t}\n\t\t/**\n\t\t * The absence of wip used routes indicates that GC was not run on this node. This can happen if:\n\t\t * 1. A child node was created after GC was already run on the parent. For example, a data store\n\t\t * is realized (loaded) after GC was run on it creating summarizer nodes for its DDSes. In this\n\t\t * case, the parent will pass on used routes to the child nodes and it will have wip used routes.\n\t\t * 2. A new node was created but GC was never run on it. This can mean that the GC data generated\n\t\t * during summarize is incomplete.\n\t\t *\n\t\t * This happens due to scenarios such as data store created during summarize. Such errors should go away when\n\t\t * summarize is attempted again.\n\t\t */\n\t\treturn true;\n\t}\n\n\t/**\n\t * Called after summary has been uploaded to the server. Add the work-in-progress state to the pending\n\t * summary queue. We track this until we get an ack from the server for this summary.\n\t * @param proposalHandle - The handle of the summary that was uploaded to the server.\n\t * @param parentSkipRecursion - true if the parent of this node skipped recursing the child nodes when summarizing.\n\t * In that case, the children will not have work-in-progress state.\n\t */\n\tprotected completeSummaryCore(proposalHandle: string, parentSkipRecursion: boolean) {\n\t\tlet wipSerializedUsedRoutes: string | undefined;\n\t\t// If GC is disabled, don't set wip used routes.\n\t\tif (!this.gcDisabled) {\n\t\t\twipSerializedUsedRoutes = this.wipSerializedUsedRoutes;\n\t\t}\n\n\t\tsuper.completeSummaryCore(proposalHandle, parentSkipRecursion);\n\n\t\t// If GC is disabled, skip setting pending summary with GC state.\n\t\tif (!this.gcDisabled) {\n\t\t\tconst pendingSummaryInfo = this.pendingSummaries.get(proposalHandle);\n\t\t\tif (pendingSummaryInfo !== undefined) {\n\t\t\t\tconst pendingSummaryInfoWithGC = {\n\t\t\t\t\tserializedUsedRoutes: wipSerializedUsedRoutes,\n\t\t\t\t\t...pendingSummaryInfo,\n\t\t\t\t};\n\t\t\t\tthis.pendingSummaries.set(proposalHandle, pendingSummaryInfoWithGC);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Clears the work-in-progress state.\n\t */\n\tpublic clearSummary() {\n\t\tthis.wipSerializedUsedRoutes = undefined;\n\t\tthis.wipChildNodesUsedRoutes = undefined;\n\t\tsuper.clearSummary();\n\t}\n\n\t/**\n\t * Called when we get an ack from the server for a summary we sent. Update the reference state of this node\n\t * from the state in the pending summary queue.\n\t */\n\tprotected refreshLatestSummaryFromPending(\n\t\tproposalHandle: string,\n\t\treferenceSequenceNumber: number,\n\t): void {\n\t\t// If GC is disabled, skip setting referenced used routes since we are not tracking GC state.\n\t\tif (!this.gcDisabled) {\n\t\t\tconst pendingSummaryInfo = this.pendingSummaries.get(proposalHandle);\n\t\t\tif (pendingSummaryInfo !== undefined) {\n\t\t\t\t// If a pending summary exists, it must have used routes since GC is enabled.\n\t\t\t\tconst summaryNodeWithGC = pendingSummaryInfo as PendingSummaryInfoWithGC;\n\t\t\t\tif (summaryNodeWithGC.serializedUsedRoutes === undefined) {\n\t\t\t\t\tconst error = new LoggingError(\"MissingGCStateInPendingSummary\", {\n\t\t\t\t\t\tproposalHandle,\n\t\t\t\t\t\treferenceSequenceNumber,\n\t\t\t\t\t\t...tagCodeArtifacts({\n\t\t\t\t\t\t\tid: this.telemetryNodeId,\n\t\t\t\t\t\t}),\n\t\t\t\t\t});\n\t\t\t\t\tthis.logger.sendErrorEvent(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\teventName: error.message,\n\t\t\t\t\t\t},\n\t\t\t\t\t\terror,\n\t\t\t\t\t);\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tthis.referenceUsedRoutes = JSON.parse(summaryNodeWithGC.serializedUsedRoutes);\n\t\t\t}\n\t\t}\n\n\t\treturn super.refreshLatestSummaryFromPending(proposalHandle, referenceSequenceNumber);\n\t}\n\n\t/**\n\t * Override the createChild method to return an instance of SummarizerNodeWithGC.\n\t */\n\tpublic createChild(\n\t\t/** Summarize function */\n\t\tsummarizeInternalFn: SummarizeInternalFn,\n\t\t/** Initial id or path part of this node */\n\t\tid: string,\n\t\t/**\n\t\t * Information needed to create the node.\n\t\t * If it is from a base summary, it will assert that a summary has been seen.\n\t\t * Attach information if it is created from an attach op.\n\t\t */\n\t\tcreateParam: CreateChildSummarizerNodeParam,\n\t\tconfig: ISummarizerNodeConfigWithGC = {},\n\t\tgetGCDataFn?: (fullGC?: boolean) => Promise<IGarbageCollectionData>,\n\t): ISummarizerNodeWithGC {\n\t\tassert(!this.children.has(id), 0x1b6 /* \"Create SummarizerNode child already exists\" */);\n\t\t/**\n\t\t * Update the child node's base GC details from this node's current GC details instead of updating from the base\n\t\t * GC details of this node. This will handle scenarios where the GC details was updated during refresh from\n\t\t * snapshot and the child node wasn't created then. If a child is created after that, its GC details should be\n\t\t * the one from the downloaded snapshot and not the base GC details.\n\t\t */\n\t\tconst getChildBaseGCDetailsFn = async () => {\n\t\t\tconst childNodesBaseGCDetails = await this.childNodesBaseGCDetailsP;\n\t\t\treturn childNodesBaseGCDetails.get(id) ?? {};\n\t\t};\n\n\t\tconst createDetails: ICreateChildDetails = this.getCreateDetailsForChild(id, createParam);\n\t\tconst child = new SummarizerNodeWithGC(\n\t\t\tthis.logger,\n\t\t\tsummarizeInternalFn,\n\t\t\t{\n\t\t\t\t...config,\n\t\t\t\t// Propagate our gcDisabled state to the child if its not explicity specified in child's config.\n\t\t\t\tgcDisabled: config.gcDisabled ?? this.gcDisabled,\n\t\t\t},\n\t\t\tcreateDetails.summaryHandleId,\n\t\t\tcreateDetails.changeSequenceNumber,\n\t\t\tcreateDetails.lastSummaryReferenceSequenceNumber,\n\t\t\tthis.wipSummaryLogger,\n\t\t\tgetGCDataFn,\n\t\t\tgetChildBaseGCDetailsFn,\n\t\t\tcreateDetails.telemetryNodeId,\n\t\t);\n\n\t\t// There may be additional state that has to be updated in this child. For example, if a summary is being\n\t\t// tracked, the child's summary tracking state needs to be updated too.\n\t\tthis.maybeUpdateChildState(child, id);\n\n\t\tthis.children.set(id, child);\n\t\treturn child;\n\t}\n\n\t/**\n\t * Updates the state of the child if required. For example, if a summary is currently being tracked, the child's\n\t * summary tracking state needs to be updated too.\n\t * Also, in case a child node gets realized in between Summary Op and Summary Ack, let's initialize the child's\n\t * pending summary as well. Finally, if the pendingSummaries entries have serializedRoutes, replicate them to the\n\t * pendingSummaries from the child nodes.\n\t * @param child - The child node whose state is to be updated.\n\t * @param id - Initial id or path part of this node\n\t */\n\tprotected maybeUpdateChildState(child: SummarizerNodeWithGC, id: string) {\n\t\tsuper.maybeUpdateChildState(child, id);\n\n\t\t// If GC has run on this node and summarization isn't complete, this.wipSerializedUsedRoutes will be defined.\n\t\t// In that case, update the used routes of the child node. This can happen in scenarios where a data store\n\t\t// doesn't have any ops but its reference state changed. So, it gets realized during summarize after GC ran\n\t\t// so GC would not have run on this node which is fine.\n\t\tif (this.wipSerializedUsedRoutes !== undefined) {\n\t\t\t// If the child route used routes are not defined, initialize it now and it can be used for all child nodes\n\t\t\t// created until this summarization process is completed. This is an optimization to unpack the used routes\n\t\t\t// only when needed.\n\t\t\tif (this.wipChildNodesUsedRoutes === undefined) {\n\t\t\t\tthis.wipChildNodesUsedRoutes = unpackChildNodesUsedRoutes(this.usedRoutes);\n\t\t\t}\n\t\t\tchild.updateUsedRoutes(this.wipChildNodesUsedRoutes.get(id) ?? [\"\"]);\n\t\t}\n\n\t\t// In case we have pending summaries on the parent, let's initialize it on the child.\n\t\tfor (const [key, pendingSummary] of this.pendingSummaries.entries()) {\n\t\t\tconst pendingSummaryWithGC = pendingSummary as PendingSummaryInfoWithGC;\n\t\t\tif (pendingSummaryWithGC.serializedUsedRoutes !== undefined) {\n\t\t\t\tconst childNodeUsedRoutes = unpackChildNodesUsedRoutes(\n\t\t\t\t\tJSON.parse(pendingSummaryWithGC.serializedUsedRoutes),\n\t\t\t\t);\n\t\t\t\tconst newSerializedRoutes = childNodeUsedRoutes.get(id) ?? [\"\"];\n\t\t\t\tconst childPendingSummaryInfo = {\n\t\t\t\t\t...pendingSummaryWithGC,\n\t\t\t\t\tserializedUsedRoutes: JSON.stringify(newSerializedRoutes),\n\t\t\t\t};\n\t\t\t\tchild.addPendingSummary(key, childPendingSummaryInfo);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Deletes the child node with the given id.\n\t */\n\tpublic deleteChild(id: string): void {\n\t\tthis.children.delete(id);\n\t}\n\n\t/**\n\t * Override the getChild method to return an instance of SummarizerNodeWithGC.\n\t */\n\tpublic getChild(id: string): ISummarizerNodeWithGC | undefined {\n\t\treturn this.children.get(id) as SummarizerNodeWithGC;\n\t}\n\n\tpublic isReferenced(): boolean {\n\t\treturn this.usedRoutes.includes(\"\") || this.usedRoutes.includes(\"/\");\n\t}\n\n\tpublic updateUsedRoutes(usedRoutes: string[]) {\n\t\t// Sort the given routes before updating. This will ensure that the routes compared in hasUsedStateChanged()\n\t\t// are in the same order.\n\t\tthis.usedRoutes = usedRoutes.sort();\n\n\t\t// If GC is not disabled and a summary is in progress, update the work-in-progress used routes so that it can\n\t\t// be tracked for this summary.\n\t\tif (!this.gcDisabled && this.isSummaryInProgress()) {\n\t\t\tthis.wipSerializedUsedRoutes = JSON.stringify(this.usedRoutes);\n\t\t}\n\t}\n\n\t/**\n\t * Override the hasChanged method. If this node data or its used state changed, the node is considered changed.\n\t */\n\tprotected hasChanged(): boolean {\n\t\treturn this.hasDataChanged() || this.hasUsedStateChanged();\n\t}\n\n\t/**\n\t * This tells whether the data in this node has changed or not.\n\t */\n\tprivate hasDataChanged(): boolean {\n\t\treturn super.hasChanged();\n\t}\n\n\t/**\n\t * This tells whether the used state of this node has changed since last successful summary. If the used routes\n\t * of this node changed, its used state is considered changed. Basically, if this node or any of its child nodes\n\t * was previously used and became unused (or vice versa), its used state has changed.\n\t */\n\tprivate hasUsedStateChanged(): boolean {\n\t\t// If GC is disabled, it should not affect summary state, return false.\n\t\tif (this.gcDisabled) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn (\n\t\t\tthis.referenceUsedRoutes === undefined ||\n\t\t\tJSON.stringify(this.usedRoutes) !== JSON.stringify(this.referenceUsedRoutes)\n\t\t);\n\t}\n}\n\n/**\n * Creates a root summarizer node with GC functionality built-in.\n * @param logger - Logger to use within SummarizerNode\n * @param summarizeInternalFn - Function to generate summary\n * @param changeSequenceNumber - Sequence number of latest change to new node/subtree\n * @param referenceSequenceNumber - Reference sequence number of last acked summary,\n * or undefined if not loaded from summary\n * @param config - Configure behavior of summarizer node\n * @param getGCDataFn - Function to get the GC data of this node\n * @param baseGCDetailsP - Function to get the initial GC details of this node\n */\nexport const createRootSummarizerNodeWithGC = (\n\tlogger: ITelemetryBaseLogger,\n\tsummarizeInternalFn: SummarizeInternalFn,\n\tchangeSequenceNumber: number,\n\treferenceSequenceNumber: number | undefined,\n\tconfig: ISummarizerNodeConfigWithGC = {},\n\tgetGCDataFn?: (fullGC?: boolean) => Promise<IGarbageCollectionData>,\n\tgetBaseGCDetailsFn?: () => Promise<IGarbageCollectionDetailsBase>,\n): IRootSummarizerNodeWithGC =>\n\tnew SummarizerNodeWithGC(\n\t\tlogger,\n\t\tsummarizeInternalFn,\n\t\tconfig,\n\t\tEscapedPath.create(\"\") /* summaryHandleId */,\n\t\tchangeSequenceNumber,\n\t\treferenceSequenceNumber,\n\t\tundefined /* wipSummaryLogger */,\n\t\tgetGCDataFn,\n\t\tgetBaseGCDetailsFn,\n\t\t\"\" /* telemetryId */,\n\t);\n"]}
|
|
@@ -308,10 +308,8 @@ export declare const defaultPendingOpsWaitTimeoutMs = 1000;
|
|
|
308
308
|
export declare const defaultPendingOpsRetryDelayMs = 1000;
|
|
309
309
|
/**
|
|
310
310
|
* Checks whether a message.type is one of the values in ContainerMessageType
|
|
311
|
-
* @deprecated please use version in driver-utils
|
|
312
|
-
* @internal
|
|
313
311
|
*/
|
|
314
|
-
export declare function
|
|
312
|
+
export declare function isUnpackedRuntimeMessage(message: ISequencedDocumentMessage): boolean;
|
|
315
313
|
/**
|
|
316
314
|
* Legacy ID for the built-in AgentScheduler. To minimize disruption while removing it, retaining this as a
|
|
317
315
|
* special-case for document dirty state. Ultimately we should have no special-cases from the
|