@fluidframework/runtime-utils 1.2.1 → 2.0.0-internal.1.0.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.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/summarizerNode/summarizerNode.d.ts +10 -12
- package/dist/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/dist/summarizerNode/summarizerNode.js +37 -82
- package/dist/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summarizerNode/summarizerNodeUtils.d.ts +1 -37
- package/dist/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/dist/summarizerNode/summarizerNodeUtils.js +1 -94
- package/dist/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/summarizerNode/summarizerNode.d.ts +10 -12
- package/lib/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/lib/summarizerNode/summarizerNode.js +38 -83
- package/lib/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/summarizerNode/summarizerNodeUtils.d.ts +1 -37
- package/lib/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/lib/summarizerNode/summarizerNodeUtils.js +0 -91
- package/lib/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/package.json +15 -15
- package/src/packageVersion.ts +1 -1
- package/src/summarizerNode/summarizerNode.ts +39 -106
- package/src/summarizerNode/summarizerNodeUtils.ts +0 -126
|
@@ -24,9 +24,6 @@ import { assert, unreachableCase } from "@fluidframework/common-utils";
|
|
|
24
24
|
import { mergeStats, convertToSummaryTree, calculateStats } from "../summaryUtils";
|
|
25
25
|
import { ReadAndParseBlob } from "../utils";
|
|
26
26
|
import {
|
|
27
|
-
decodeSummary,
|
|
28
|
-
encodeSummary,
|
|
29
|
-
EncodeSummaryParam,
|
|
30
27
|
EscapedPath,
|
|
31
28
|
ICreateChildDetails,
|
|
32
29
|
IInitialSummary,
|
|
@@ -63,7 +60,6 @@ export class SummarizerNode implements IRootSummarizerNode {
|
|
|
63
60
|
|
|
64
61
|
protected readonly children = new Map<string, SummarizerNode>();
|
|
65
62
|
protected readonly pendingSummaries = new Map<string, SummaryNode>();
|
|
66
|
-
private readonly outstandingOps: ISequencedDocumentMessage[] = [];
|
|
67
63
|
private wipReferenceSequenceNumber: number | undefined;
|
|
68
64
|
private wipLocalPaths: { localPath: EscapedPath; additionalPath?: EscapedPath; } | undefined;
|
|
69
65
|
private wipSkipRecursion = false;
|
|
@@ -112,52 +108,12 @@ export class SummarizerNode implements IRootSummarizerNode {
|
|
|
112
108
|
}
|
|
113
109
|
}
|
|
114
110
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
this.wipLocalPaths.additionalPath = EscapedPath.createAndConcat(result.pathPartsForChildren);
|
|
120
|
-
}
|
|
121
|
-
return { summary: result.summary, stats: result.stats };
|
|
122
|
-
} catch (error) {
|
|
123
|
-
if (this.throwOnError || this.trackingSequenceNumber < this._changeSequenceNumber) {
|
|
124
|
-
throw error;
|
|
125
|
-
}
|
|
126
|
-
const latestSummary = this._latestSummary;
|
|
127
|
-
const initialSummary = this.initialSummary;
|
|
128
|
-
|
|
129
|
-
let encodeParam: EncodeSummaryParam;
|
|
130
|
-
let localPath: EscapedPath;
|
|
131
|
-
if (latestSummary !== undefined) {
|
|
132
|
-
// Create using handle of latest acked summary
|
|
133
|
-
encodeParam = {
|
|
134
|
-
fromSummary: true,
|
|
135
|
-
summaryNode: latestSummary,
|
|
136
|
-
};
|
|
137
|
-
localPath = latestSummary.localPath;
|
|
138
|
-
} else if (initialSummary?.summary !== undefined) {
|
|
139
|
-
// Create using initial summary from attach op
|
|
140
|
-
encodeParam = {
|
|
141
|
-
fromSummary: false,
|
|
142
|
-
initialSummary: initialSummary.summary,
|
|
143
|
-
};
|
|
144
|
-
localPath = EscapedPath.create(initialSummary.id);
|
|
145
|
-
} else {
|
|
146
|
-
// No base summary to reference
|
|
147
|
-
throw error;
|
|
148
|
-
}
|
|
149
|
-
this.wipSummaryLogger.sendErrorEvent({
|
|
150
|
-
eventName: "SummarizingWithBasePlusOps",
|
|
151
|
-
},
|
|
152
|
-
error);
|
|
153
|
-
const summary = encodeSummary(encodeParam, this.outstandingOps);
|
|
154
|
-
this.wipLocalPaths = {
|
|
155
|
-
localPath,
|
|
156
|
-
additionalPath: summary.additionalPath,
|
|
157
|
-
};
|
|
158
|
-
this.wipSkipRecursion = true;
|
|
159
|
-
return { summary: summary.summary, stats: summary.stats };
|
|
111
|
+
const result = await this.summarizeInternalFn(fullTree, true, telemetryContext);
|
|
112
|
+
this.wipLocalPaths = { localPath: EscapedPath.create(result.id) };
|
|
113
|
+
if (result.pathPartsForChildren !== undefined) {
|
|
114
|
+
this.wipLocalPaths.additionalPath = EscapedPath.createAndConcat(result.pathPartsForChildren);
|
|
160
115
|
}
|
|
116
|
+
return { summary: result.summary, stats: result.stats };
|
|
161
117
|
}
|
|
162
118
|
|
|
163
119
|
/**
|
|
@@ -286,7 +242,12 @@ export class SummarizerNode implements IRootSummarizerNode {
|
|
|
286
242
|
);
|
|
287
243
|
return { latestSummaryUpdated: true, wasSummaryTracked: false, snapshot: snapshotTree };
|
|
288
244
|
}
|
|
289
|
-
|
|
245
|
+
/**
|
|
246
|
+
* Called when we get an ack from the server for a summary we've just sent. Updates the reference state of this node
|
|
247
|
+
* from the state in the pending summary queue.
|
|
248
|
+
* @param proposalHandle - Handle for the current proposal.
|
|
249
|
+
* @param referenceSequenceNumber - reference sequence number of sent summary.
|
|
250
|
+
*/
|
|
290
251
|
protected refreshLatestSummaryFromPending(
|
|
291
252
|
proposalHandle: string,
|
|
292
253
|
referenceSequenceNumber: number,
|
|
@@ -312,7 +273,6 @@ export class SummarizerNode implements IRootSummarizerNode {
|
|
|
312
273
|
this.refreshLatestSummaryCore(referenceSequenceNumber);
|
|
313
274
|
|
|
314
275
|
this._latestSummary = summaryNode;
|
|
315
|
-
|
|
316
276
|
// Propagate update to all child nodes
|
|
317
277
|
for (const child of this.children.values()) {
|
|
318
278
|
child.refreshLatestSummaryFromPending(proposalHandle, referenceSequenceNumber);
|
|
@@ -334,15 +294,14 @@ export class SummarizerNode implements IRootSummarizerNode {
|
|
|
334
294
|
|
|
335
295
|
this.refreshLatestSummaryCore(referenceSequenceNumber);
|
|
336
296
|
|
|
337
|
-
const { baseSummary, pathParts } = decodeSummary(snapshotTree, correlatedSummaryLogger);
|
|
338
|
-
|
|
339
297
|
this._latestSummary = new SummaryNode({
|
|
340
298
|
referenceSequenceNumber,
|
|
341
299
|
basePath,
|
|
342
300
|
localPath,
|
|
343
301
|
});
|
|
344
302
|
|
|
345
|
-
const
|
|
303
|
+
const pathParts: string[] = [];
|
|
304
|
+
const { childrenTree, childrenPathPart } = parseSummaryForSubtrees(snapshotTree);
|
|
346
305
|
if (childrenPathPart !== undefined) {
|
|
347
306
|
pathParts.push(childrenPathPart);
|
|
348
307
|
}
|
|
@@ -376,14 +335,6 @@ export class SummarizerNode implements IRootSummarizerNode {
|
|
|
376
335
|
this.pendingSummaries.delete(key);
|
|
377
336
|
}
|
|
378
337
|
}
|
|
379
|
-
|
|
380
|
-
// Clear earlier outstanding ops
|
|
381
|
-
while (
|
|
382
|
-
this.outstandingOps.length > 0
|
|
383
|
-
&& this.outstandingOps[0].sequenceNumber <= referenceSequenceNumber
|
|
384
|
-
) {
|
|
385
|
-
this.outstandingOps.shift();
|
|
386
|
-
}
|
|
387
338
|
}
|
|
388
339
|
|
|
389
340
|
public loadBaseSummaryWithoutDifferential(snapshot: ISnapshotTree) {
|
|
@@ -398,46 +349,22 @@ export class SummarizerNode implements IRootSummarizerNode {
|
|
|
398
349
|
public async loadBaseSummary(
|
|
399
350
|
snapshot: ISnapshotTree,
|
|
400
351
|
readAndParseBlob: ReadAndParseBlob,
|
|
401
|
-
): Promise<
|
|
402
|
-
const
|
|
403
|
-
const
|
|
404
|
-
|
|
405
|
-
const { childrenPathPart } = parseSummaryForSubtrees(decodedSummary.baseSummary);
|
|
352
|
+
): Promise<ISnapshotTree> {
|
|
353
|
+
const pathParts: string[] = [];
|
|
354
|
+
const { childrenPathPart } = parseSummaryForSubtrees(snapshot);
|
|
406
355
|
if (childrenPathPart !== undefined) {
|
|
407
|
-
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
if (decodedSummary.pathParts.length > 0 && this._latestSummary !== undefined) {
|
|
411
|
-
this._latestSummary.additionalPath = EscapedPath.createAndConcat(decodedSummary.pathParts);
|
|
356
|
+
pathParts.push(childrenPathPart);
|
|
412
357
|
}
|
|
413
358
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
if (outstandingOps.length > 0) {
|
|
417
|
-
const newOpsLatestSeq = outstandingOps[outstandingOps.length - 1].sequenceNumber;
|
|
418
|
-
assert(
|
|
419
|
-
newOpsLatestSeq <= this.trackingSequenceNumber,
|
|
420
|
-
0x1a9 /* "When loading base summary, expected outstanding ops <= tracking sequence number" */,
|
|
421
|
-
);
|
|
359
|
+
if (pathParts.length > 0 && this._latestSummary !== undefined) {
|
|
360
|
+
this._latestSummary.additionalPath = EscapedPath.createAndConcat(pathParts);
|
|
422
361
|
}
|
|
423
362
|
|
|
424
|
-
return
|
|
425
|
-
baseSummary: decodedSummary.baseSummary,
|
|
426
|
-
outstandingOps,
|
|
427
|
-
};
|
|
363
|
+
return snapshot;
|
|
428
364
|
}
|
|
429
365
|
|
|
430
366
|
public recordChange(op: ISequencedDocumentMessage): void {
|
|
431
|
-
const lastOp = this.outstandingOps[this.outstandingOps.length - 1];
|
|
432
|
-
if (lastOp !== undefined) {
|
|
433
|
-
assert(
|
|
434
|
-
lastOp.sequenceNumber < op.sequenceNumber,
|
|
435
|
-
0x1aa /* Out of order change recorded */,
|
|
436
|
-
);
|
|
437
|
-
}
|
|
438
367
|
this.invalidate(op.sequenceNumber);
|
|
439
|
-
this.trackingSequenceNumber = op.sequenceNumber;
|
|
440
|
-
this.outstandingOps.push(op);
|
|
441
368
|
}
|
|
442
369
|
|
|
443
370
|
public invalidate(sequenceNumber: number): void {
|
|
@@ -460,13 +387,6 @@ export class SummarizerNode implements IRootSummarizerNode {
|
|
|
460
387
|
}
|
|
461
388
|
|
|
462
389
|
private readonly canReuseHandle: boolean;
|
|
463
|
-
private readonly throwOnError: boolean;
|
|
464
|
-
/**
|
|
465
|
-
* Sequence number of latest tracked op. This updates during recordChange,
|
|
466
|
-
* but not for invalidate since we don't have the op. If this drifts from
|
|
467
|
-
* changeSequenceNumber and we try to create a differential summary we assert.
|
|
468
|
-
*/
|
|
469
|
-
private trackingSequenceNumber: number;
|
|
470
390
|
|
|
471
391
|
/**
|
|
472
392
|
* Do not call constructor directly.
|
|
@@ -483,11 +403,6 @@ export class SummarizerNode implements IRootSummarizerNode {
|
|
|
483
403
|
protected wipSummaryLogger?: ITelemetryLogger,
|
|
484
404
|
) {
|
|
485
405
|
this.canReuseHandle = config.canReuseHandle ?? true;
|
|
486
|
-
// BUGBUG: Seeing issues with differential summaries.
|
|
487
|
-
// this will disable them, and throw instead
|
|
488
|
-
// while we continue to investigate
|
|
489
|
-
this.throwOnError = true; // config.throwOnFailure ?? false;
|
|
490
|
-
this.trackingSequenceNumber = this._changeSequenceNumber;
|
|
491
406
|
}
|
|
492
407
|
|
|
493
408
|
public createChild(
|
|
@@ -517,7 +432,8 @@ export class SummarizerNode implements IRootSummarizerNode {
|
|
|
517
432
|
);
|
|
518
433
|
|
|
519
434
|
// There may be additional state that has to be updated in this child. For example, if a summary is being
|
|
520
|
-
// tracked, the child's summary tracking state needs to be updated too.
|
|
435
|
+
// tracked, the child's summary tracking state needs to be updated too. Same goes for pendingSummaries we might
|
|
436
|
+
// have outstanding on the parent in case we realize nodes in between Summary Op and Summary Ack.
|
|
521
437
|
this.maybeUpdateChildState(child);
|
|
522
438
|
|
|
523
439
|
this.children.set(id, child);
|
|
@@ -620,6 +536,8 @@ export class SummarizerNode implements IRootSummarizerNode {
|
|
|
620
536
|
/**
|
|
621
537
|
* Updates the state of the child if required. For example, if a summary is currently being tracked, the child's
|
|
622
538
|
* summary tracking state needs to be updated too.
|
|
539
|
+
* Also, in case a child node gets realized in between Summary Op and Summary Ack, let's initialize the child's
|
|
540
|
+
* pending summary as well.
|
|
623
541
|
* @param child - The child node whose state is to be updated.
|
|
624
542
|
*/
|
|
625
543
|
protected maybeUpdateChildState(child: SummarizerNode) {
|
|
@@ -628,8 +546,23 @@ export class SummarizerNode implements IRootSummarizerNode {
|
|
|
628
546
|
if (this.isTrackingInProgress()) {
|
|
629
547
|
child.wipReferenceSequenceNumber = this.wipReferenceSequenceNumber;
|
|
630
548
|
}
|
|
549
|
+
// In case we have pending summaries on the parent, let's initialize it on the child.
|
|
550
|
+
if (child._latestSummary !== undefined) {
|
|
551
|
+
for (const [key, value] of this.pendingSummaries.entries()) {
|
|
552
|
+
const newLatestSummaryNode = new SummaryNode({
|
|
553
|
+
referenceSequenceNumber: value.referenceSequenceNumber,
|
|
554
|
+
basePath: child._latestSummary.basePath,
|
|
555
|
+
localPath: child._latestSummary.localPath,
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
child.addPendingSummary(key, newLatestSummaryNode);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
631
561
|
}
|
|
632
562
|
|
|
563
|
+
protected addPendingSummary(key: string, summary: SummaryNode) {
|
|
564
|
+
this.pendingSummaries.set(key, summary);
|
|
565
|
+
}
|
|
633
566
|
/**
|
|
634
567
|
* Tells whether summary tracking is in progress. True if "startSummary" API is called before summarize.
|
|
635
568
|
*/
|
|
@@ -4,22 +4,14 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { ITelemetryLogger } from "@fluidframework/common-definitions";
|
|
7
|
-
import { assert } from "@fluidframework/common-utils";
|
|
8
7
|
import {
|
|
9
8
|
ISnapshotTree,
|
|
10
|
-
ISequencedDocumentMessage,
|
|
11
|
-
SummaryType,
|
|
12
9
|
ISummaryTree,
|
|
13
10
|
SummaryObject,
|
|
14
11
|
} from "@fluidframework/protocol-definitions";
|
|
15
12
|
import { channelsTreeName, ISummaryTreeWithStats } from "@fluidframework/runtime-definitions";
|
|
16
|
-
import { SummaryTreeBuilder } from "../summaryUtils";
|
|
17
13
|
import { ReadAndParseBlob } from "../utils";
|
|
18
14
|
|
|
19
|
-
const baseSummaryTreeKey = "_baseSummary";
|
|
20
|
-
const outstandingOpsBlobKey = "_outstandingOps";
|
|
21
|
-
const maxDecodeDepth = 100;
|
|
22
|
-
|
|
23
15
|
/**
|
|
24
16
|
* Return value of refreshSummaryAck function. There can be three different scenarios based on the passed params:
|
|
25
17
|
* 1. The latest summary was not udpated.
|
|
@@ -137,88 +129,6 @@ export class SummaryNode {
|
|
|
137
129
|
}
|
|
138
130
|
}
|
|
139
131
|
|
|
140
|
-
/** Result from decoding summary which may have been a differential summary. */
|
|
141
|
-
interface IDecodedSummary {
|
|
142
|
-
/** The innermost base summary which is not itself a differential summary */
|
|
143
|
-
readonly baseSummary: ISnapshotTree;
|
|
144
|
-
/** The entire path name to the innermost base summary */
|
|
145
|
-
readonly pathParts: string[];
|
|
146
|
-
/** Function to fetch all outstanding ops since the innermost base summary */
|
|
147
|
-
getOutstandingOps(readAndParseBlob: ReadAndParseBlob): Promise<ISequencedDocumentMessage[]>;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Checks if the snapshot is created by referencing a previous successful
|
|
152
|
-
* summary plus outstanding ops. If so, it will recursively "decode" it until
|
|
153
|
-
* it gets to the last successful summary (the base summary) and returns that
|
|
154
|
-
* as well as a function for fetching the outstanding ops. Also returns the
|
|
155
|
-
* full path to the previous base summary for child summarizer nodes to use as
|
|
156
|
-
* their base path when necessary.
|
|
157
|
-
* @param snapshot - snapshot tree to decode
|
|
158
|
-
*/
|
|
159
|
-
export function decodeSummary(
|
|
160
|
-
snapshot: ISnapshotTree,
|
|
161
|
-
logger: Pick<ITelemetryLogger, "sendTelemetryEvent">,
|
|
162
|
-
): IDecodedSummary {
|
|
163
|
-
let baseSummary = snapshot;
|
|
164
|
-
const pathParts: string[] = [];
|
|
165
|
-
const opsBlobs: string[] = [];
|
|
166
|
-
|
|
167
|
-
for (let i = 0; ; i++) {
|
|
168
|
-
if (i > maxDecodeDepth) {
|
|
169
|
-
logger.sendTelemetryEvent({
|
|
170
|
-
eventName: "DecodeSummaryMaxDepth",
|
|
171
|
-
maxDecodeDepth,
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
const outstandingOpsBlob = baseSummary.blobs[outstandingOpsBlobKey];
|
|
175
|
-
const newBaseSummary = baseSummary.trees[baseSummaryTreeKey];
|
|
176
|
-
if (outstandingOpsBlob === undefined && newBaseSummary === undefined) {
|
|
177
|
-
return {
|
|
178
|
-
baseSummary,
|
|
179
|
-
pathParts,
|
|
180
|
-
async getOutstandingOps(readAndParseBlob: ReadAndParseBlob) {
|
|
181
|
-
let outstandingOps: ISequencedDocumentMessage[] = [];
|
|
182
|
-
for (const opsBlob of opsBlobs) {
|
|
183
|
-
const newOutstandingOps = await readAndParseBlob<ISequencedDocumentMessage[]>(opsBlob);
|
|
184
|
-
if (outstandingOps.length > 0 && newOutstandingOps.length > 0) {
|
|
185
|
-
const latestSeq = outstandingOps[outstandingOps.length - 1].sequenceNumber;
|
|
186
|
-
const newEarliestSeq = newOutstandingOps[0].sequenceNumber;
|
|
187
|
-
if (newEarliestSeq <= latestSeq) {
|
|
188
|
-
logger.sendTelemetryEvent({
|
|
189
|
-
eventName: "DuplicateOutstandingOps",
|
|
190
|
-
// eslint-disable-next-line max-len
|
|
191
|
-
message: `newEarliestSeq <= latestSeq in decodeSummary: ${newEarliestSeq} <= ${latestSeq}`,
|
|
192
|
-
});
|
|
193
|
-
while (newOutstandingOps.length > 0
|
|
194
|
-
&& newOutstandingOps[0].sequenceNumber <= latestSeq) {
|
|
195
|
-
newOutstandingOps.shift();
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
outstandingOps = outstandingOps.concat(newOutstandingOps);
|
|
200
|
-
}
|
|
201
|
-
return outstandingOps;
|
|
202
|
-
},
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
assert(!!outstandingOpsBlob, 0x1af /* "Outstanding ops blob missing, but base summary tree exists" */);
|
|
207
|
-
assert(newBaseSummary !== undefined, 0x1b0 /* "Base summary tree missing, but outstanding ops blob exists" */);
|
|
208
|
-
baseSummary = newBaseSummary;
|
|
209
|
-
pathParts.push(baseSummaryTreeKey);
|
|
210
|
-
opsBlobs.unshift(outstandingOpsBlob);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Summary tree which is a handle of the previous successfully acked summary
|
|
216
|
-
* and a blob of the outstanding ops since that summary.
|
|
217
|
-
*/
|
|
218
|
-
interface IEncodedSummary extends ISummaryTreeWithStats {
|
|
219
|
-
readonly additionalPath: EscapedPath;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
132
|
/**
|
|
223
133
|
* Parameter to help encode summary with conditional behavior.
|
|
224
134
|
* When fromSummary is true, it will contain the SummaryNode of
|
|
@@ -234,42 +144,6 @@ export type EncodeSummaryParam = {
|
|
|
234
144
|
initialSummary: ISummaryTreeWithStats;
|
|
235
145
|
};
|
|
236
146
|
|
|
237
|
-
/**
|
|
238
|
-
* Creates a summary tree which is a handle of the previous successfully acked summary
|
|
239
|
-
* and a blob of the outstanding ops since that summary. If there is no acked summary yet,
|
|
240
|
-
* it will create with the tree found in the initial attach op and the blob of outstanding ops.
|
|
241
|
-
* @param summaryParam - information about last acked summary and paths to encode if from summary,
|
|
242
|
-
* otherwise the initial summary from the attach op.
|
|
243
|
-
* @param outstandingOps - outstanding ops since last acked summary
|
|
244
|
-
*/
|
|
245
|
-
export function encodeSummary(
|
|
246
|
-
summaryParam: EncodeSummaryParam,
|
|
247
|
-
outstandingOps: ISequencedDocumentMessage[],
|
|
248
|
-
): IEncodedSummary {
|
|
249
|
-
let additionalPath = EscapedPath.create(baseSummaryTreeKey);
|
|
250
|
-
|
|
251
|
-
const builder = new SummaryTreeBuilder();
|
|
252
|
-
builder.addBlob(outstandingOpsBlobKey, JSON.stringify(outstandingOps));
|
|
253
|
-
|
|
254
|
-
if (summaryParam.fromSummary) {
|
|
255
|
-
// Create using handle of latest acked summary
|
|
256
|
-
const summaryNode = summaryParam.summaryNode;
|
|
257
|
-
if (summaryNode.additionalPath !== undefined) {
|
|
258
|
-
additionalPath = additionalPath.concat(summaryNode.additionalPath);
|
|
259
|
-
}
|
|
260
|
-
builder.addHandle(baseSummaryTreeKey, SummaryType.Tree, summaryNode.fullPath.path);
|
|
261
|
-
} else {
|
|
262
|
-
// Create using initial summary from attach op
|
|
263
|
-
builder.addWithStats(baseSummaryTreeKey, summaryParam.initialSummary);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
const summary = builder.getSummaryTree();
|
|
267
|
-
return {
|
|
268
|
-
...summary,
|
|
269
|
-
additionalPath,
|
|
270
|
-
};
|
|
271
|
-
}
|
|
272
|
-
|
|
273
147
|
/**
|
|
274
148
|
* Information about the initial summary tree found from an attach op.
|
|
275
149
|
*/
|