From 0764b0440c3b29230de4cdd360188fd512960e03 Mon Sep 17 00:00:00 2001 From: Navin Agarwal Date: Tue, 3 Jun 2025 13:49:10 -0700 Subject: [PATCH 1/5] (tree) Unfiy summarize and getAttachSummary methods on summarizables --- .changeset/loud-dolls-appear.md | 8 +++++ .../shared-object-base.legacy.alpha.api.md | 2 +- .../shared-object-base/src/sharedObject.ts | 9 ++++- .../src/sharedObjectKernel.ts | 9 ++++- .../detachedFieldIndexSummarizer.ts | 13 ++------ .../forest-summary/forestSummarizer.ts | 13 ++------ .../schema-index/schemaSummarizer.ts | 19 +++-------- .../shared-tree-core/editManagerSummarizer.ts | 13 ++------ .../src/shared-tree-core/sharedTreeCore.ts | 33 +++++++++---------- .../chunkEncodingEndToEnd.spec.ts | 10 +++--- .../shared-tree-core/sharedTreeCore.spec.ts | 14 ++------ 11 files changed, 62 insertions(+), 81 deletions(-) create mode 100644 .changeset/loud-dolls-appear.md diff --git a/.changeset/loud-dolls-appear.md b/.changeset/loud-dolls-appear.md new file mode 100644 index 000000000000..b055070259ae --- /dev/null +++ b/.changeset/loud-dolls-appear.md @@ -0,0 +1,8 @@ +--- +"@fluidframework/shared-object-base": minor +"__section": legacy +--- +Added an optional boolean parameter `fullTree` to `SharedObject`'s `summarizeCore` method + +This parameter tells the shared object that it should generate a full tree summary, i.e., it must not summarize incrementally. +Currently, none of the shared object's do incremental summaries. However, if one decides to do it, it needs to take "fullTree" parameter into consideration. diff --git a/packages/dds/shared-object-base/api-report/shared-object-base.legacy.alpha.api.md b/packages/dds/shared-object-base/api-report/shared-object-base.legacy.alpha.api.md index 75a8ea9d309a..667067939f8c 100644 --- a/packages/dds/shared-object-base/api-report/shared-object-base.legacy.alpha.api.md +++ b/packages/dds/shared-object-base/api-report/shared-object-base.legacy.alpha.api.md @@ -47,7 +47,7 @@ export abstract class SharedObject; - protected abstract summarizeCore(serializer: IFluidSerializer, telemetryContext?: ITelemetryContext, incrementalSummaryContext?: IExperimentalIncrementalSummaryContext): ISummaryTreeWithStats; + protected abstract summarizeCore(serializer: IFluidSerializer, telemetryContext?: ITelemetryContext, incrementalSummaryContext?: IExperimentalIncrementalSummaryContext, fullTree?: boolean): ISummaryTreeWithStats; } // @alpha @legacy diff --git a/packages/dds/shared-object-base/src/sharedObject.ts b/packages/dds/shared-object-base/src/sharedObject.ts index 620a61ba6308..7d26ef4e6bdf 100644 --- a/packages/dds/shared-object-base/src/sharedObject.ts +++ b/packages/dds/shared-object-base/src/sharedObject.ts @@ -842,7 +842,12 @@ export abstract class SharedObject< trackState: boolean = false, telemetryContext?: ITelemetryContext, ): ISummaryTreeWithStats { - const result = this.summarizeCore(this.serializer, telemetryContext); + const result = this.summarizeCore( + this.serializer, + telemetryContext, + undefined /* incrementalSummaryContext */, + fullTree, + ); this.incrementTelemetryMetric( blobCountPropertyName, result.stats.blobNodeCount, @@ -869,6 +874,7 @@ export abstract class SharedObject< this.serializer, telemetryContext, incrementalSummaryContext, + fullTree, ); this.incrementTelemetryMetric( blobCountPropertyName, @@ -937,6 +943,7 @@ export abstract class SharedObject< serializer: IFluidSerializer, telemetryContext?: ITelemetryContext, incrementalSummaryContext?: IExperimentalIncrementalSummaryContext, + fullTree?: boolean, ): ISummaryTreeWithStats; private incrementTelemetryMetric( diff --git a/packages/dds/shared-object-base/src/sharedObjectKernel.ts b/packages/dds/shared-object-base/src/sharedObjectKernel.ts index 433ffee05dcd..cbfa8d78c257 100644 --- a/packages/dds/shared-object-base/src/sharedObjectKernel.ts +++ b/packages/dds/shared-object-base/src/sharedObjectKernel.ts @@ -62,6 +62,7 @@ export interface SharedKernel { serializer: IFluidSerializer, telemetryContext: ITelemetryContext | undefined, incrementalSummaryContext: IExperimentalIncrementalSummaryContext | undefined, + fullTree?: boolean, ): ISummaryTreeWithStats; /** @@ -146,8 +147,14 @@ class SharedObjectFromKernel< serializer: IFluidSerializer, telemetryContext?: ITelemetryContext, incrementalSummaryContext?: IExperimentalIncrementalSummaryContext, + fullTree?: boolean, ): ISummaryTreeWithStats { - return this.#kernel.summarizeCore(serializer, telemetryContext, incrementalSummaryContext); + return this.#kernel.summarizeCore( + serializer, + telemetryContext, + incrementalSummaryContext, + fullTree, + ); } protected override initializeLocalCore(): void { diff --git a/packages/dds/tree/src/feature-libraries/detachedFieldIndexSummarizer.ts b/packages/dds/tree/src/feature-libraries/detachedFieldIndexSummarizer.ts index dbb3bedd5085..542c6cf7974d 100644 --- a/packages/dds/tree/src/feature-libraries/detachedFieldIndexSummarizer.ts +++ b/packages/dds/tree/src/feature-libraries/detachedFieldIndexSummarizer.ts @@ -6,6 +6,7 @@ import { bufferToString } from "@fluid-internal/client-utils"; import type { IChannelStorageService } from "@fluidframework/datastore-definitions/internal"; import type { + IExperimentalIncrementalSummaryContext, ISummaryTreeWithStats, ITelemetryContext, } from "@fluidframework/runtime-definitions/internal"; @@ -32,25 +33,17 @@ export class DetachedFieldIndexSummarizer implements Summarizable { public constructor(private readonly detachedFieldIndex: DetachedFieldIndex) {} - public getAttachSummary( + public summarize( stringify: SummaryElementStringifier, fullTree?: boolean, trackState?: boolean, telemetryContext?: ITelemetryContext, + incrementalSummaryContext?: IExperimentalIncrementalSummaryContext, ): ISummaryTreeWithStats { const data = this.detachedFieldIndex.encode(); return createSingleBlobSummary(detachedFieldIndexBlobKey, stringify(data)); } - public async summarize( - stringify: SummaryElementStringifier, - fullTree?: boolean, - trackState?: boolean, - telemetryContext?: ITelemetryContext, - ): Promise { - return this.getAttachSummary(stringify, fullTree, trackState, telemetryContext); - } - public async load( services: IChannelStorageService, parse: SummaryElementParser, diff --git a/packages/dds/tree/src/feature-libraries/forest-summary/forestSummarizer.ts b/packages/dds/tree/src/feature-libraries/forest-summary/forestSummarizer.ts index a23b4d3afe57..b20f5799f086 100644 --- a/packages/dds/tree/src/feature-libraries/forest-summary/forestSummarizer.ts +++ b/packages/dds/tree/src/feature-libraries/forest-summary/forestSummarizer.ts @@ -8,6 +8,7 @@ import { assert } from "@fluidframework/core-utils/internal"; import type { IChannelStorageService } from "@fluidframework/datastore-definitions/internal"; import type { IIdCompressor } from "@fluidframework/id-compressor"; import type { + IExperimentalIncrementalSummaryContext, ISummaryTreeWithStats, ITelemetryContext, } from "@fluidframework/runtime-definitions/internal"; @@ -95,24 +96,16 @@ export class ForestSummarizer implements Summarizable { return stringify(encoded); } - public getAttachSummary( + public summarize( stringify: SummaryElementStringifier, fullTree?: boolean, trackState?: boolean, telemetryContext?: ITelemetryContext, + incrementalSummaryContext?: IExperimentalIncrementalSummaryContext, ): ISummaryTreeWithStats { return createSingleBlobSummary(treeBlobKey, this.getTreeString(stringify)); } - public async summarize( - stringify: SummaryElementStringifier, - fullTree?: boolean, - trackState?: boolean, - telemetryContext?: ITelemetryContext, - ): Promise { - return createSingleBlobSummary(treeBlobKey, this.getTreeString(stringify)); - } - public async load( services: IChannelStorageService, parse: SummaryElementParser, diff --git a/packages/dds/tree/src/feature-libraries/schema-index/schemaSummarizer.ts b/packages/dds/tree/src/feature-libraries/schema-index/schemaSummarizer.ts index 143ef16b81e3..265f29a13df5 100644 --- a/packages/dds/tree/src/feature-libraries/schema-index/schemaSummarizer.ts +++ b/packages/dds/tree/src/feature-libraries/schema-index/schemaSummarizer.ts @@ -51,15 +51,16 @@ export class SchemaSummarizer implements Summarizable { }); } - public getAttachSummary( + public summarize( stringify: SummaryElementStringifier, - fullTree?: boolean, + fullTree: boolean = false, trackState?: boolean, telemetryContext?: ITelemetryContext, - incrementalSummaryContext?: IExperimentalIncrementalSummaryContext | undefined, + incrementalSummaryContext?: IExperimentalIncrementalSummaryContext, ): ISummaryTreeWithStats { const builder = new SummaryTreeBuilder(); if ( + !fullTree && incrementalSummaryContext !== undefined && this.schemaIndexLastChangedSeq !== undefined && incrementalSummaryContext.latestSummarySequenceNumber >= this.schemaIndexLastChangedSeq @@ -67,7 +68,7 @@ export class SchemaSummarizer implements Summarizable { builder.addHandle( schemaStringKey, SummaryType.Blob, - `${incrementalSummaryContext.summaryPath}/indexes/${this.key}/${schemaStringKey}`, + `${incrementalSummaryContext.summaryPath}/${schemaStringKey}`, ); } else { const dataString = JSON.stringify(this.codec.encode(this.schema)); @@ -76,16 +77,6 @@ export class SchemaSummarizer implements Summarizable { return builder.getSummaryTree(); } - public async summarize( - stringify: SummaryElementStringifier, - fullTree?: boolean, - trackState?: boolean, - telemetryContext?: ITelemetryContext, - incrementalSummaryContext?: IExperimentalIncrementalSummaryContext | undefined, - ): Promise { - throw new Error("Method not implemented."); - } - public async load( services: IChannelStorageService, parse: SummaryElementParser, diff --git a/packages/dds/tree/src/shared-tree-core/editManagerSummarizer.ts b/packages/dds/tree/src/shared-tree-core/editManagerSummarizer.ts index c475f0604596..d259c18bb2c5 100644 --- a/packages/dds/tree/src/shared-tree-core/editManagerSummarizer.ts +++ b/packages/dds/tree/src/shared-tree-core/editManagerSummarizer.ts @@ -8,6 +8,7 @@ import { assert } from "@fluidframework/core-utils/internal"; import type { IChannelStorageService } from "@fluidframework/datastore-definitions/internal"; import type { IIdCompressor } from "@fluidframework/id-compressor"; import type { + IExperimentalIncrementalSummaryContext, ISummaryTreeWithStats, ITelemetryContext, } from "@fluidframework/runtime-definitions/internal"; @@ -49,24 +50,16 @@ export class EditManagerSummarizer implements Summarizable { private readonly schemaAndPolicy?: SchemaAndPolicy, ) {} - public getAttachSummary( + public summarize( stringify: SummaryElementStringifier, fullTree?: boolean, trackState?: boolean, telemetryContext?: ITelemetryContext, + incrementalSummaryContext?: IExperimentalIncrementalSummaryContext, ): ISummaryTreeWithStats { return this.summarizeCore(stringify); } - public async summarize( - stringify: SummaryElementStringifier, - fullTree?: boolean, - trackState?: boolean, - telemetryContext?: ITelemetryContext, - ): Promise { - return this.summarizeCore(stringify); - } - private summarizeCore(stringify: SummaryElementStringifier): ISummaryTreeWithStats { const context: EditManagerEncodingContext = this.schemaAndPolicy !== undefined diff --git a/packages/dds/tree/src/shared-tree-core/sharedTreeCore.ts b/packages/dds/tree/src/shared-tree-core/sharedTreeCore.ts index f647ee28d2f3..5a5180f45b2a 100644 --- a/packages/dds/tree/src/shared-tree-core/sharedTreeCore.ts +++ b/packages/dds/tree/src/shared-tree-core/sharedTreeCore.ts @@ -212,19 +212,29 @@ export class SharedTreeCore serializer: IFluidSerializer, telemetryContext?: ITelemetryContext, incrementalSummaryContext?: IExperimentalIncrementalSummaryContext, + fullTree?: boolean, ): ISummaryTreeWithStats { const builder = new SummaryTreeBuilder(); const summarizableBuilder = new SummaryTreeBuilder(); // Merge the summaries of all summarizables together under a single ISummaryTree for (const s of this.summarizables) { + // Add the summarizable's path in the summary tree to the incremental summary context's + // summary path, so that the summarizable can use it to generate incremental summaries. + const childIncrementalSummaryContext = + incrementalSummaryContext === undefined + ? undefined + : { + ...incrementalSummaryContext, + summaryPath: `${incrementalSummaryContext.summaryPath}/${summarizablesTreeKey}/${s.key}`, + }; summarizableBuilder.addWithStats( s.key, - s.getAttachSummary( + s.summarize( (contents) => serializer.stringify(contents, this.sharedObject.handle), - undefined, - undefined, + fullTree, + undefined /* trackState */, telemetryContext, - incrementalSummaryContext, + childIncrementalSummaryContext, ), ); } @@ -434,18 +444,6 @@ export interface Summarizable { */ readonly key: string; - /** - * {@inheritDoc @fluidframework/datastore-definitions#(IChannel:interface).getAttachSummary} - * @param stringify - Serializes the contents of the component (including {@link (IFluidHandle:interface)}s) for storage. - */ - getAttachSummary( - stringify: SummaryElementStringifier, - fullTree?: boolean, - trackState?: boolean, - telemetryContext?: ITelemetryContext, - incrementalSummaryContext?: IExperimentalIncrementalSummaryContext, - ): ISummaryTreeWithStats; - /** * {@inheritDoc @fluidframework/datastore-definitions#(IChannel:interface).summarize} * @param stringify - Serializes the contents of the component (including {@link (IFluidHandle:interface)}s) for storage. @@ -455,7 +453,8 @@ export interface Summarizable { fullTree?: boolean, trackState?: boolean, telemetryContext?: ITelemetryContext, - ): Promise; + incrementalSummaryContext?: IExperimentalIncrementalSummaryContext, + ): ISummaryTreeWithStats; /** * Allows the component to perform custom loading. The storage service is scoped to this component and therefore diff --git a/packages/dds/tree/src/test/feature-libraries/chunked-forest/chunkEncodingEndToEnd.spec.ts b/packages/dds/tree/src/test/feature-libraries/chunked-forest/chunkEncodingEndToEnd.spec.ts index ff566665b78d..23dc150a2187 100644 --- a/packages/dds/tree/src/test/feature-libraries/chunked-forest/chunkEncodingEndToEnd.spec.ts +++ b/packages/dds/tree/src/test/feature-libraries/chunked-forest/chunkEncodingEndToEnd.spec.ts @@ -203,7 +203,7 @@ describe("End to end chunked encoding", () => { assert(chunk.isShared()); return JSON.stringify(content); } - forestSummarizer.getAttachSummary(stringifier); + forestSummarizer.summarize(stringifier); }); // See note on above test. @@ -236,7 +236,7 @@ describe("End to end chunked encoding", () => { assert(chunk.isShared()); return JSON.stringify(content); } - forestSummarizer.getAttachSummary(stringifier); + forestSummarizer.summarize(stringifier); }); describe("identifier field encoding", () => { @@ -257,7 +257,7 @@ describe("End to end chunked encoding", () => { function stringifier(content: unknown) { return JSON.stringify(content); } - const { summary } = forestSummarizer.getAttachSummary(stringifier); + const { summary } = forestSummarizer.summarize(stringifier); const tree = summary.tree.ForestTree; assert(tree.type === SummaryType.Blob); const treeContent = JSON.parse(tree.content as string); @@ -287,7 +287,7 @@ describe("End to end chunked encoding", () => { function stringifier(content: unknown) { return JSON.stringify(content); } - const { summary } = forestSummarizer.getAttachSummary(stringifier); + const { summary } = forestSummarizer.summarize(stringifier); const tree = summary.tree.ForestTree; assert(tree.type === SummaryType.Blob); const treeContent = JSON.parse(tree.content as string); @@ -312,7 +312,7 @@ describe("End to end chunked encoding", () => { function stringifier(content: unknown) { return JSON.stringify(content); } - const { summary } = forestSummarizer.getAttachSummary(stringifier); + const { summary } = forestSummarizer.summarize(stringifier); const tree = summary.tree.ForestTree; assert(tree.type === SummaryType.Blob); const treeContent = JSON.parse(tree.content as string); diff --git a/packages/dds/tree/src/test/shared-tree-core/sharedTreeCore.spec.ts b/packages/dds/tree/src/test/shared-tree-core/sharedTreeCore.spec.ts index 060c524c1084..7e7c1749563d 100644 --- a/packages/dds/tree/src/test/shared-tree-core/sharedTreeCore.spec.ts +++ b/packages/dds/tree/src/test/shared-tree-core/sharedTreeCore.spec.ts @@ -586,7 +586,7 @@ describe("SharedTreeCore", () => { interface MockSummarizableEvents extends IEvent { (event: "loaded", listener: (blobContents?: string) => void): void; - (event: "summarize" | "summarizeAttached" | "summarizeAsync" | "gcRequested"): void; + (event: "summarize" | "summarizeAttached" | "gcRequested"): void; } class MockSummarizable @@ -613,7 +613,7 @@ describe("SharedTreeCore", () => { } } - public getAttachSummary( + public summarize( stringify: SummaryElementStringifier, fullTree?: boolean | undefined, trackState?: boolean | undefined, @@ -623,16 +623,6 @@ describe("SharedTreeCore", () => { return this.summarizeCore(stringify); } - public async summarize( - stringify: SummaryElementStringifier, - fullTree?: boolean | undefined, - trackState?: boolean | undefined, - telemetryContext?: ITelemetryContext | undefined, - ): Promise { - this.emit("summarizeAsync"); - return this.summarizeCore(stringify); - } - private summarizeCore(stringify: SummaryElementStringifier): ISummaryTreeWithStats { this.emit("summarize"); return createSingleBlobSummary( From 54ec0f4b86a7e9a06766241f09662b4d3a3331c9 Mon Sep 17 00:00:00 2001 From: Navin Agarwal Date: Fri, 6 Jun 2025 14:04:41 -0700 Subject: [PATCH 2/5] PR comments --- .changeset/loud-dolls-appear.md | 2 +- .../detachedFieldIndexSummarizer.ts | 16 ++++----- .../forest-summary/forestSummarizer.ts | 16 ++++----- .../schema-index/schemaSummarizer.ts | 16 +++++---- .../shared-tree-core/editManagerSummarizer.ts | 16 ++++----- .../src/shared-tree-core/sharedTreeCore.ts | 34 ++++++++++++------- 6 files changed, 56 insertions(+), 44 deletions(-) diff --git a/.changeset/loud-dolls-appear.md b/.changeset/loud-dolls-appear.md index b055070259ae..ac864e025f3d 100644 --- a/.changeset/loud-dolls-appear.md +++ b/.changeset/loud-dolls-appear.md @@ -5,4 +5,4 @@ Added an optional boolean parameter `fullTree` to `SharedObject`'s `summarizeCore` method This parameter tells the shared object that it should generate a full tree summary, i.e., it must not summarize incrementally. -Currently, none of the shared object's do incremental summaries. However, if one decides to do it, it needs to take "fullTree" parameter into consideration. +Currently no known SharedObjects's do incremental summaries; however any that do exist or are made in the future must take this "fullTree" parameter into consideration to function correctly. diff --git a/packages/dds/tree/src/feature-libraries/detachedFieldIndexSummarizer.ts b/packages/dds/tree/src/feature-libraries/detachedFieldIndexSummarizer.ts index 542c6cf7974d..118fce9be33d 100644 --- a/packages/dds/tree/src/feature-libraries/detachedFieldIndexSummarizer.ts +++ b/packages/dds/tree/src/feature-libraries/detachedFieldIndexSummarizer.ts @@ -33,15 +33,15 @@ export class DetachedFieldIndexSummarizer implements Summarizable { public constructor(private readonly detachedFieldIndex: DetachedFieldIndex) {} - public summarize( - stringify: SummaryElementStringifier, - fullTree?: boolean, - trackState?: boolean, - telemetryContext?: ITelemetryContext, - incrementalSummaryContext?: IExperimentalIncrementalSummaryContext, - ): ISummaryTreeWithStats { + public summarize(props: { + stringify: SummaryElementStringifier; + fullTree?: boolean; + trackState?: boolean; + telemetryContext?: ITelemetryContext; + incrementalSummaryContext?: IExperimentalIncrementalSummaryContext; + }): ISummaryTreeWithStats { const data = this.detachedFieldIndex.encode(); - return createSingleBlobSummary(detachedFieldIndexBlobKey, stringify(data)); + return createSingleBlobSummary(detachedFieldIndexBlobKey, props.stringify(data)); } public async load( diff --git a/packages/dds/tree/src/feature-libraries/forest-summary/forestSummarizer.ts b/packages/dds/tree/src/feature-libraries/forest-summary/forestSummarizer.ts index b20f5799f086..581a89cb46b1 100644 --- a/packages/dds/tree/src/feature-libraries/forest-summary/forestSummarizer.ts +++ b/packages/dds/tree/src/feature-libraries/forest-summary/forestSummarizer.ts @@ -96,14 +96,14 @@ export class ForestSummarizer implements Summarizable { return stringify(encoded); } - public summarize( - stringify: SummaryElementStringifier, - fullTree?: boolean, - trackState?: boolean, - telemetryContext?: ITelemetryContext, - incrementalSummaryContext?: IExperimentalIncrementalSummaryContext, - ): ISummaryTreeWithStats { - return createSingleBlobSummary(treeBlobKey, this.getTreeString(stringify)); + public summarize(props: { + stringify: SummaryElementStringifier; + fullTree?: boolean; + trackState?: boolean; + telemetryContext?: ITelemetryContext; + incrementalSummaryContext?: IExperimentalIncrementalSummaryContext; + }): ISummaryTreeWithStats { + return createSingleBlobSummary(treeBlobKey, this.getTreeString(props.stringify)); } public async load( diff --git a/packages/dds/tree/src/feature-libraries/schema-index/schemaSummarizer.ts b/packages/dds/tree/src/feature-libraries/schema-index/schemaSummarizer.ts index 265f29a13df5..d8970868e72c 100644 --- a/packages/dds/tree/src/feature-libraries/schema-index/schemaSummarizer.ts +++ b/packages/dds/tree/src/feature-libraries/schema-index/schemaSummarizer.ts @@ -51,14 +51,16 @@ export class SchemaSummarizer implements Summarizable { }); } - public summarize( - stringify: SummaryElementStringifier, - fullTree: boolean = false, - trackState?: boolean, - telemetryContext?: ITelemetryContext, - incrementalSummaryContext?: IExperimentalIncrementalSummaryContext, - ): ISummaryTreeWithStats { + public summarize(props: { + stringify: SummaryElementStringifier; + fullTree: boolean; + trackState?: boolean; + telemetryContext?: ITelemetryContext; + incrementalSummaryContext?: IExperimentalIncrementalSummaryContext; + }): ISummaryTreeWithStats { + const incrementalSummaryContext = props.incrementalSummaryContext; const builder = new SummaryTreeBuilder(); + const fullTree = props.fullTree ?? false; if ( !fullTree && incrementalSummaryContext !== undefined && diff --git a/packages/dds/tree/src/shared-tree-core/editManagerSummarizer.ts b/packages/dds/tree/src/shared-tree-core/editManagerSummarizer.ts index d259c18bb2c5..139bd1e28619 100644 --- a/packages/dds/tree/src/shared-tree-core/editManagerSummarizer.ts +++ b/packages/dds/tree/src/shared-tree-core/editManagerSummarizer.ts @@ -50,14 +50,14 @@ export class EditManagerSummarizer implements Summarizable { private readonly schemaAndPolicy?: SchemaAndPolicy, ) {} - public summarize( - stringify: SummaryElementStringifier, - fullTree?: boolean, - trackState?: boolean, - telemetryContext?: ITelemetryContext, - incrementalSummaryContext?: IExperimentalIncrementalSummaryContext, - ): ISummaryTreeWithStats { - return this.summarizeCore(stringify); + public summarize(props: { + stringify: SummaryElementStringifier; + fullTree?: boolean; + trackState?: boolean; + telemetryContext?: ITelemetryContext; + incrementalSummaryContext?: IExperimentalIncrementalSummaryContext; + }): ISummaryTreeWithStats { + return this.summarizeCore(props.stringify); } private summarizeCore(stringify: SummaryElementStringifier): ISummaryTreeWithStats { diff --git a/packages/dds/tree/src/shared-tree-core/sharedTreeCore.ts b/packages/dds/tree/src/shared-tree-core/sharedTreeCore.ts index 5a5180f45b2a..e2cf014c4fd2 100644 --- a/packages/dds/tree/src/shared-tree-core/sharedTreeCore.ts +++ b/packages/dds/tree/src/shared-tree-core/sharedTreeCore.ts @@ -229,13 +229,13 @@ export class SharedTreeCore }; summarizableBuilder.addWithStats( s.key, - s.summarize( - (contents) => serializer.stringify(contents, this.sharedObject.handle), + s.summarize({ + stringify: (contents: unknown) => + serializer.stringify(contents, this.sharedObject.handle), fullTree, - undefined /* trackState */, telemetryContext, - childIncrementalSummaryContext, - ), + incrementalSummaryContext: childIncrementalSummaryContext, + }), ); } @@ -447,14 +447,24 @@ export interface Summarizable { /** * {@inheritDoc @fluidframework/datastore-definitions#(IChannel:interface).summarize} * @param stringify - Serializes the contents of the component (including {@link (IFluidHandle:interface)}s) for storage. + * @param fullTree - flag indicating whether the attempt should generate a full + * summary tree without any handles for unchanged subtrees. It should only be set to true when generating + * a summary from the entire container. + * @param trackState - An optimization for tracking state of objects across summaries. If the state + * of an object did not change since last successful summary, an + * {@link @fluidframework/protocol-definitions#ISummaryHandle} can be used + * instead of re-summarizing it. If this is `false`, the expectation is that you should never + * send an `ISummaryHandle`, since you are not expected to track state. + * @param telemetryContext - See {@link @fluidframework/runtime-definitions#ITelemetryContext}. + * @param incrementalSummaryContext - See {@link @fluidframework/runtime-definitions#IExperimentalIncrementalSummaryContext}. */ - summarize( - stringify: SummaryElementStringifier, - fullTree?: boolean, - trackState?: boolean, - telemetryContext?: ITelemetryContext, - incrementalSummaryContext?: IExperimentalIncrementalSummaryContext, - ): ISummaryTreeWithStats; + summarize(props: { + stringify: SummaryElementStringifier; + fullTree?: boolean; + trackState?: boolean; + telemetryContext?: ITelemetryContext; + incrementalSummaryContext?: IExperimentalIncrementalSummaryContext; + }): ISummaryTreeWithStats; /** * Allows the component to perform custom loading. The storage service is scoped to this component and therefore From dde573ded52551f7212cc4ded2e81ecb886ba40b Mon Sep 17 00:00:00 2001 From: Navin Agarwal Date: Fri, 6 Jun 2025 14:29:43 -0700 Subject: [PATCH 3/5] Fix tests --- .../chunkEncodingEndToEnd.spec.ts | 23 ++++++------------- .../shared-tree-core/sharedTreeCore.spec.ts | 14 +++++------ 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/packages/dds/tree/src/test/feature-libraries/chunked-forest/chunkEncodingEndToEnd.spec.ts b/packages/dds/tree/src/test/feature-libraries/chunked-forest/chunkEncodingEndToEnd.spec.ts index 23dc150a2187..ffe288d6f0a5 100644 --- a/packages/dds/tree/src/test/feature-libraries/chunked-forest/chunkEncodingEndToEnd.spec.ts +++ b/packages/dds/tree/src/test/feature-libraries/chunked-forest/chunkEncodingEndToEnd.spec.ts @@ -194,7 +194,7 @@ describe("End to end chunked encoding", () => { ); // This function is declared in the test to have access to the original uniform chunk for comparison. - function stringifier(content: unknown) { + function stringify(content: unknown) { const insertedChunk = decode((content as Format).fields as EncodedFieldBatch, { idCompressor, originatorId: idCompressor.localSessionId, @@ -203,7 +203,7 @@ describe("End to end chunked encoding", () => { assert(chunk.isShared()); return JSON.stringify(content); } - forestSummarizer.summarize(stringifier); + forestSummarizer.summarize({ stringify }); }); // See note on above test. @@ -227,7 +227,7 @@ describe("End to end chunked encoding", () => { ); // This function is declared in the test to have access to the original uniform chunk for comparison. - function stringifier(content: unknown) { + function stringify(content: unknown) { const insertedChunk = decode((content as Format).fields as EncodedFieldBatch, { idCompressor, originatorId: idCompressor.localSessionId, @@ -236,7 +236,7 @@ describe("End to end chunked encoding", () => { assert(chunk.isShared()); return JSON.stringify(content); } - forestSummarizer.summarize(stringifier); + forestSummarizer.summarize({ stringify }); }); describe("identifier field encoding", () => { @@ -254,10 +254,7 @@ describe("End to end chunked encoding", () => { testIdCompressor, ); - function stringifier(content: unknown) { - return JSON.stringify(content); - } - const { summary } = forestSummarizer.summarize(stringifier); + const { summary } = forestSummarizer.summarize({ stringify: JSON.stringify }); const tree = summary.tree.ForestTree; assert(tree.type === SummaryType.Blob); const treeContent = JSON.parse(tree.content as string); @@ -284,10 +281,7 @@ describe("End to end chunked encoding", () => { testIdCompressor, ); - function stringifier(content: unknown) { - return JSON.stringify(content); - } - const { summary } = forestSummarizer.summarize(stringifier); + const { summary } = forestSummarizer.summarize({ stringify: JSON.stringify }); const tree = summary.tree.ForestTree; assert(tree.type === SummaryType.Blob); const treeContent = JSON.parse(tree.content as string); @@ -309,10 +303,7 @@ describe("End to end chunked encoding", () => { testIdCompressor, ); - function stringifier(content: unknown) { - return JSON.stringify(content); - } - const { summary } = forestSummarizer.summarize(stringifier); + const { summary } = forestSummarizer.summarize({ stringify: JSON.stringify }); const tree = summary.tree.ForestTree; assert(tree.type === SummaryType.Blob); const treeContent = JSON.parse(tree.content as string); diff --git a/packages/dds/tree/src/test/shared-tree-core/sharedTreeCore.spec.ts b/packages/dds/tree/src/test/shared-tree-core/sharedTreeCore.spec.ts index 7e7c1749563d..c8f422227a6b 100644 --- a/packages/dds/tree/src/test/shared-tree-core/sharedTreeCore.spec.ts +++ b/packages/dds/tree/src/test/shared-tree-core/sharedTreeCore.spec.ts @@ -613,14 +613,14 @@ describe("SharedTreeCore", () => { } } - public summarize( - stringify: SummaryElementStringifier, - fullTree?: boolean | undefined, - trackState?: boolean | undefined, - telemetryContext?: ITelemetryContext | undefined, - ): ISummaryTreeWithStats { + public summarize(props: { + stringify: SummaryElementStringifier; + fullTree?: boolean | undefined; + trackState?: boolean | undefined; + telemetryContext?: ITelemetryContext | undefined; + }): ISummaryTreeWithStats { this.emit("summarizeAttached"); - return this.summarizeCore(stringify); + return this.summarizeCore(props.stringify); } private summarizeCore(stringify: SummaryElementStringifier): ISummaryTreeWithStats { From 1e4359ba7d74dc534906f7f5464583ba064a565f Mon Sep 17 00:00:00 2001 From: Navin Agarwal Date: Mon, 9 Jun 2025 14:15:06 -0700 Subject: [PATCH 4/5] typo --- .../tree/src/feature-libraries/schema-index/schemaSummarizer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dds/tree/src/feature-libraries/schema-index/schemaSummarizer.ts b/packages/dds/tree/src/feature-libraries/schema-index/schemaSummarizer.ts index d8970868e72c..551cd12c52fa 100644 --- a/packages/dds/tree/src/feature-libraries/schema-index/schemaSummarizer.ts +++ b/packages/dds/tree/src/feature-libraries/schema-index/schemaSummarizer.ts @@ -53,7 +53,7 @@ export class SchemaSummarizer implements Summarizable { public summarize(props: { stringify: SummaryElementStringifier; - fullTree: boolean; + fullTree?: boolean; trackState?: boolean; telemetryContext?: ITelemetryContext; incrementalSummaryContext?: IExperimentalIncrementalSummaryContext; From 8ebc3fde5343eef4738472bf2c2cb888dfa3b6d8 Mon Sep 17 00:00:00 2001 From: Navin Agarwal Date: Tue, 10 Jun 2025 18:01:55 -0700 Subject: [PATCH 5/5] Doc comments --- .changeset/loud-dolls-appear.md | 4 ++-- packages/dds/tree/src/shared-tree-core/sharedTreeCore.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.changeset/loud-dolls-appear.md b/.changeset/loud-dolls-appear.md index ac864e025f3d..b8cd77f1d4de 100644 --- a/.changeset/loud-dolls-appear.md +++ b/.changeset/loud-dolls-appear.md @@ -2,7 +2,7 @@ "@fluidframework/shared-object-base": minor "__section": legacy --- -Added an optional boolean parameter `fullTree` to `SharedObject`'s `summarizeCore` method +Added an optional boolean parameter "fullTree" to SharedObject's summarizeCore method This parameter tells the shared object that it should generate a full tree summary, i.e., it must not summarize incrementally. -Currently no known SharedObjects's do incremental summaries; however any that do exist or are made in the future must take this "fullTree" parameter into consideration to function correctly. +Currently no known `SharedObject`'s do incremental summaries; however, any that do exist or are made in the future must take this "fullTree" parameter into consideration to function correctly. diff --git a/packages/dds/tree/src/shared-tree-core/sharedTreeCore.ts b/packages/dds/tree/src/shared-tree-core/sharedTreeCore.ts index e2cf014c4fd2..02df39d03fed 100644 --- a/packages/dds/tree/src/shared-tree-core/sharedTreeCore.ts +++ b/packages/dds/tree/src/shared-tree-core/sharedTreeCore.ts @@ -447,14 +447,14 @@ export interface Summarizable { /** * {@inheritDoc @fluidframework/datastore-definitions#(IChannel:interface).summarize} * @param stringify - Serializes the contents of the component (including {@link (IFluidHandle:interface)}s) for storage. - * @param fullTree - flag indicating whether the attempt should generate a full + * @param fullTree - A flag indicating whether the attempt should generate a full * summary tree without any handles for unchanged subtrees. It should only be set to true when generating - * a summary from the entire container. + * a summary from the entire container. The default value is false. * @param trackState - An optimization for tracking state of objects across summaries. If the state * of an object did not change since last successful summary, an * {@link @fluidframework/protocol-definitions#ISummaryHandle} can be used * instead of re-summarizing it. If this is `false`, the expectation is that you should never - * send an `ISummaryHandle`, since you are not expected to track state. + * send an `ISummaryHandle`, since you are not expected to track state. The default value is true. * @param telemetryContext - See {@link @fluidframework/runtime-definitions#ITelemetryContext}. * @param incrementalSummaryContext - See {@link @fluidframework/runtime-definitions#IExperimentalIncrementalSummaryContext}. */