@fluidframework/driver-utils 0.51.3 → 0.53.0-46105

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.
@@ -5,6 +5,7 @@
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.BlobAggregationStorage = exports.SnapshotExtractor = void 0;
8
+ const protocol_definitions_1 = require("@fluidframework/protocol-definitions");
8
9
  const common_utils_1 = require("@fluidframework/common-utils");
9
10
  // Gate that when flipped, instructs to compress small blobs.
10
11
  // We have to first ship with this gate off, such that we can get to saturation bits
@@ -261,7 +262,7 @@ class BlobAggregationStorage extends SnapshotExtractor {
261
262
  // Get path relative to root of data store (where we do aggregation)
262
263
  const newPath = shouldCompress ? key : `${path}/${key}`;
263
264
  switch (obj.type) {
264
- case 1 /* Tree */:
265
+ case protocol_definitions_1.SummaryType.Tree:
265
266
  // If client created empty tree, keep it as is
266
267
  // Also do not package search blobs - they are part of storage contract
267
268
  if (obj.tree !== {} && key !== "__search") {
@@ -273,14 +274,14 @@ class BlobAggregationStorage extends SnapshotExtractor {
273
274
  }
274
275
  }
275
276
  break;
276
- case 2 /* Blob */:
277
+ case protocol_definitions_1.SummaryType.Blob:
277
278
  if (aggregator && typeof obj.content == "string" && obj.content.length < this.blobCutOffSize) {
278
279
  aggregator.addBlob(newPath, obj.content);
279
280
  // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
280
281
  delete newSummary.tree[key];
281
282
  }
282
283
  break;
283
- case 3 /* Handle */: {
284
+ case protocol_definitions_1.SummaryType.Handle: {
284
285
  // Would be nice to:
285
286
  // Trees: expand the tree
286
287
  // Blobs: parse handle and ensure it points to real blob, not virtual blob.
@@ -294,7 +295,7 @@ class BlobAggregationStorage extends SnapshotExtractor {
294
295
  common_utils_1.assert(handlePath.indexOf("/") === -1, 0x0fd /* "data stores are writing incremental summaries!" */);
295
296
  break;
296
297
  }
297
- case 4 /* Attachment */:
298
+ case protocol_definitions_1.SummaryType.Attachment:
298
299
  common_utils_1.assert(this.isRealStorageId(obj.id), 0x0fe /* "attachment is aggregate blob" */);
299
300
  break;
300
301
  default:
@@ -312,7 +313,7 @@ class BlobAggregationStorage extends SnapshotExtractor {
312
313
  const content = aggregator.getAggregatedBlobContent();
313
314
  if (content !== undefined) {
314
315
  newSummary.tree[this.aggregatedBlobName] = {
315
- type: 2 /* Blob */,
316
+ type: protocol_definitions_1.SummaryType.Blob,
316
317
  content,
317
318
  };
318
319
  }
@@ -1 +1 @@
1
- {"version":3,"file":"blobAggregationStorage.js","sourceRoot":"","sources":["../src/blobAggregationStorage.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 {\n IDocumentStorageService,\n IDocumentStorageServicePolicies,\n ISummaryContext,\n} from \"@fluidframework/driver-definitions\";\nimport {\n ICreateBlobResponse,\n ISnapshotTree,\n ISummaryHandle,\n ISummaryTree,\n IVersion,\n SummaryType,\n ITree,\n} from \"@fluidframework/protocol-definitions\";\nimport {\n assert,\n bufferToString,\n stringToBuffer,\n unreachableCase,\n fromUtf8ToBase64,\n Uint8ArrayToString,\n } from \"@fluidframework/common-utils\";\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\n\n// Gate that when flipped, instructs to compress small blobs.\n// We have to first ship with this gate off, such that we can get to saturation bits\n// that can understand compressed format. And only after that flip it.\nfunction gatesAllowPacking() {\n try {\n // Leave override for testing purposes\n // eslint-disable-next-line no-null/no-null\n if (typeof localStorage === \"object\" && localStorage !== null) {\n if (localStorage.FluidAggregateBlobs === \"1\") {\n return true;\n }\n if (localStorage.FluidAggregateBlobs === \"0\") {\n return false;\n }\n }\n } catch (e) {}\n\n // We are starting disabled.\n return false;\n}\n\n/*\n * Work around for bufferToString having a bug - it can't consume IsoBuffer!\n * To be removed once bufferToString is fixed!\n*/\nfunction bufferToString2(blob: ArrayBufferLike, encoding: \"utf-8\" | \"base64\"): string {\n if (blob instanceof Uint8Array) { // IsoBuffer does not have ctor, so it's not in proto chain :(\n return Uint8ArrayToString(blob, encoding);\n }\n return bufferToString(blob, encoding);\n}\n\n /**\n * Class responsible for aggregating smaller blobs into one and unpacking it later on.\n */\nclass BlobAggregator {\n private readonly content: [string, string][]= [];\n\n public addBlob(key: string, content: string) {\n this.content.push([key, content]);\n }\n\n public getAggregatedBlobContent() {\n if (this.content.length === 0) {\n return undefined;\n }\n return JSON.stringify(this.content);\n }\n\n static load(input: ArrayBufferLike) {\n const data = bufferToString2(input, \"utf-8\");\n return JSON.parse(data) as [string, string][];\n }\n}\n\n/*\n * Base class that deals with unpacking snapshots (in place) containing aggregated blobs\n * It relies on abstract methods for reads and storing unpacked blobs.\n */\nexport abstract class SnapshotExtractor {\n protected readonly aggregatedBlobName = \"__big\";\n protected readonly virtualIdPrefix = \"__\";\n\n // counter for generation of virtual storage IDs\n protected virtualIdCounter = 0;\n protected getNextVirtualId() {\n return `${this.virtualIdPrefix}${++this.virtualIdCounter}`;\n }\n\n abstract getBlob(id: string, tree: ISnapshotTree): Promise<ArrayBufferLike>;\n abstract setBlob(id: string, tree: ISnapshotTree, content: string);\n\n public async unpackSnapshotCore(snapshot: ISnapshotTree, level = 0): Promise<void> {\n for (const key of Object.keys(snapshot.trees)) {\n const obj = snapshot.trees[key];\n await this.unpackSnapshotCore(obj, level + 1);\n }\n\n // For future proof, we will support multiple aggregated blobs with any name\n // that starts with this.aggregatedBlobName\n for (const key of Object.keys(snapshot.blobs)) {\n if (!key.startsWith(this.aggregatedBlobName)) { continue; }\n const blobId = snapshot.blobs[key];\n if (blobId !== undefined) {\n const blob = await this.getBlob(blobId, snapshot);\n for (const [path, value] of BlobAggregator.load(blob)) {\n const id = this.getNextVirtualId();\n this.setBlob(id, snapshot, value);\n const pathSplit = path.split(\"/\");\n let subTree = snapshot;\n for (const subPath of pathSplit.slice(0, pathSplit.length - 1)) {\n if (subTree.trees[subPath] === undefined) {\n subTree.trees[subPath] = { blobs: {}, commits: {}, trees: {}};\n }\n subTree = subTree.trees[subPath];\n }\n const blobName = pathSplit[pathSplit.length - 1];\n assert(subTree.blobs[blobName] === undefined, 0x0f6 /* \"real blob ID exists\" */);\n subTree.blobs[blobName] = id;\n }\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete snapshot.blobs[this.aggregatedBlobName];\n }\n }\n }\n}\n\n/*\n * Snapshot extractor class that works in place, i.e. patches snapshot that has\n * blob content in ISnapshotTree.blobs itself, not in storage.\n * As result, it implements reading and writing of blobs to/from snapshot itself.\n * It follows existing pattern that mixes concerns - ISnapshotTree.blobs is used for two\n * purposes:\n * 1. map path name to blob ID\n * 2. map blob ID to blob content\n * #2 is what storage (IDocumentStorageService) is for, but in places where we do not have it\n * (like loading serialized earlier draft content), blob content is put directly into snapshot.\n * Ideally this should be fixed by using BlobCacheStorageService or something similar and\n * fixing existing flows to allow switching of storage.\n */\nclass SnapshotExtractorInPlace extends SnapshotExtractor {\n public async getBlob(id: string, tree: ISnapshotTree): Promise<ArrayBufferLike> {\n const blob = tree.blobs[id];\n assert(blob !== undefined, 0x0f7 /* \"aggregate blob missing\" */);\n return stringToBuffer(blob, \"base64\");\n }\n\n public setBlob(id: string, tree: ISnapshotTree, content: string) {\n assert(tree.blobs[id] === undefined, 0x0f8 /* \"blob from aggregate blob exists on its own\" */);\n tree.blobs[id] = fromUtf8ToBase64(content);\n }\n}\n\n/*\n * Snapshot packer and extractor.\n * When summary is written it will find and aggregate small blobs into bigger blobs\n * When snapshot is read, it will unpack aggregated blobs and provide them transparently to caller.\n */\nexport class BlobAggregationStorage extends SnapshotExtractor implements IDocumentStorageService {\n // Tells data store if it can use incremental summary (i.e. reuse DDSs from previous summary\n // when only one DDS changed).\n // The answer has to be know long before we enable actual packing. The reason for the is the following:\n // A the moment when we enable packing, we should assume that all clients out there wil already have bits\n // that can unpack properly (i.e. enough time passed since we deployed bits that can unpack)\n // But we can still have clients where some of them already pack, and some do not. If one summary was\n // using packing, then it relies on non-incremental summaries going forward, even if next client who\n // produced summary is not packing!\n // This can have slight improvement by enabling it per file (based on \"did summary we loaded from contain\n // aggregated blobs\"), but that's harder to make reliable, so going for simplicity.\n static readonly fullDataStoreSummaries = true;\n\n protected loadedFromSummary = false;\n\n protected virtualBlobs = new Map<string, ArrayBufferLike>();\n\n static wrap(\n storage: IDocumentStorageService,\n logger: ITelemetryLogger,\n allowPacking = gatesAllowPacking(),\n packingLevel = 2,\n ) {\n if (storage instanceof BlobAggregationStorage) {\n return storage;\n }\n // Always create BlobAggregationStorage even if storage is not asking for packing.\n // This is mostly to avoid cases where future changes in policy would result in inability to\n // load old files that were created with aggregation on.\n const minBlobSize = storage.policies?.minBlobSize;\n return new BlobAggregationStorage(storage, logger, allowPacking, packingLevel, minBlobSize);\n }\n\n static async unpackSnapshot(snapshot: ISnapshotTree) {\n const converter = new SnapshotExtractorInPlace();\n await converter.unpackSnapshotCore(snapshot);\n }\n\n public get policies(): IDocumentStorageServicePolicies | undefined {\n const policies = this.storage.policies;\n if (policies) {\n return { ...policies, minBlobSize: undefined };\n }\n }\n\n public async unpackSnapshot(snapshot: ISnapshotTree) {\n // SummarizerNodeWithGC.refreshLatestSummary can call it when this.loadedFromSummary === false\n // (I assumed after file was created)\n // assert(!this.loadedFromSummary, \"unpack without summary\");\n\n this.loadedFromSummary = true;\n await this.unpackSnapshotCore(snapshot);\n }\n\n protected constructor(\n private readonly storage: IDocumentStorageService,\n private readonly logger: ITelemetryLogger,\n private readonly allowPacking: boolean,\n private readonly packingLevel: number,\n private readonly blobCutOffSize?: number)\n {\n super();\n }\n\n public setBlob(id: string, tree: ISnapshotTree, content: string) {\n this.virtualBlobs.set(id, stringToBuffer(content, \"utf-8\"));\n }\n\n public async getBlob(id: string, tree: ISnapshotTree): Promise<ArrayBufferLike> {\n return this.readBlob(id).catch((error) => {\n this.logger.sendErrorEvent({ eventName: \"BlobDedupNoAggregateBlob\" }, error);\n throw error;\n });\n }\n\n public get repositoryUrl() { return this.storage.repositoryUrl; }\n public async getVersions(versionId: string | null, count: number) {\n return this.storage.getVersions(versionId, count);\n }\n\n public async downloadSummary(handle: ISummaryHandle): Promise<ISummaryTree> {\n throw new Error(\"NYI\");\n }\n\n // This is only used through Container.snapshot() for testing purposes\n public async write(root: ITree, parents: string[], message: string, ref: string) {\n return this.storage.write(root, parents, message, ref);\n }\n\n // for now we are not optimizing these blobs, with assumption that this API is used only\n // for big blobs (images)\n public async createBlob(file: ArrayBufferLike): Promise<ICreateBlobResponse> {\n return this.storage.createBlob(file);\n }\n\n public async getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null> {\n const tree = await this.storage.getSnapshotTree(version);\n if (tree) {\n await this.unpackSnapshot(tree);\n }\n return tree;\n }\n\n public async readBlob(id: string): Promise<ArrayBufferLike> {\n if (this.isRealStorageId(id)) {\n return this.storage.readBlob(id);\n }\n // We support only reading blobs from the summary we loaded from.\n // This may need to be extended to any general summary in the future as runtime usage pattern\n // of storage changes (for example, data stores start to load from recent summary, not from original\n // summary whole container loaded from)\n\n // are there other ways we can get here? createFile is one flow, but we should not be reading blobs\n // in such flow\n assert(this.loadedFromSummary, 0x0f9 /* \"never read summary\" */);\n const blob = this.virtualBlobs.get(id);\n assert(blob !== undefined, 0x0fa /* \"virtual blob not found\" */);\n return blob;\n }\n\n public async uploadSummaryWithContext(summary: ISummaryTree, context: ISummaryContext): Promise<string> {\n const summaryNew = this.allowPacking ? await this.compressSmallBlobs(summary) : summary;\n return this.storage.uploadSummaryWithContext(summaryNew, context);\n }\n\n // For simplification, we assume that\n // - blob aggregation is done at data store level only for now\n // - data store either reuses previous summary, or generates full summary, i.e. there is no partial (some DDS)\n // summary produced by data stores.\n // These simplifications allow us not to touch handles, as they are self-contained (either do not use aggregated\n // blob Or contain aggregated blob that stays relevant for that sub-tree)\n // Note:\n // From perf perspective, it makes sense to place aggregated blobs one level up in the tree not to create extra\n // tree nodes (i.e. have shallow tree with less edges). But that creates problems with reusability of trees at\n // incremental summary time - we would need to understand handles and parse them. In current design we can skip\n // that step because if data store is reused, the hole sub-tree is reused included aggregated blob embedded into it\n // and that means we can do nothing and be correct!\n private async compressSmallBlobs(\n summary: ISummaryTree,\n path = \"\",\n level = 0,\n aggregatorArg?: BlobAggregator): Promise<ISummaryTree>\n {\n if (this.blobCutOffSize === undefined || this.blobCutOffSize < 0) {\n return summary;\n }\n\n let shouldCompress: boolean = false;\n\n let aggregator = aggregatorArg;\n // checking if this is a dataStore tree, since we only pack at data store level\n if (Object.keys(summary.tree).includes(\".component\")) {\n assert(aggregator === undefined, 0x0fb /* \"logic err with aggregator\" */);\n assert(level === this.packingLevel, 0x23b /* \"we are not packing at the right level\" */);\n aggregator = new BlobAggregator();\n shouldCompress = true;\n } else {\n assert(level !== this.packingLevel, 0x23c /* \"we are not packing at the right level\" */);\n }\n\n const newSummary: ISummaryTree = {...summary};\n newSummary.tree = { ...newSummary.tree};\n for (const key of Object.keys(summary.tree)) {\n const obj = summary.tree[key];\n // Get path relative to root of data store (where we do aggregation)\n const newPath = shouldCompress ? key : `${path}/${key}`;\n switch (obj.type) {\n case SummaryType.Tree:\n // If client created empty tree, keep it as is\n // Also do not package search blobs - they are part of storage contract\n if (obj.tree !== {} && key !== \"__search\") {\n const tree = await this.compressSmallBlobs(obj, newPath, level + 1, aggregator);\n newSummary.tree[key] = tree;\n if (tree.tree === {}) {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete newSummary.tree[key];\n }\n }\n break;\n case SummaryType.Blob:\n if (aggregator && typeof obj.content == \"string\" && obj.content.length < this.blobCutOffSize) {\n aggregator.addBlob(newPath, obj.content);\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete newSummary.tree[key];\n }\n break;\n case SummaryType.Handle: {\n // Would be nice to:\n // Trees: expand the tree\n // Blobs: parse handle and ensure it points to real blob, not virtual blob.\n // We can avoid it for now given data store is the granularity of incremental summaries.\n let handlePath = obj.handle;\n if (handlePath.startsWith(\"/\")) {\n handlePath = handlePath.substr(1);\n }\n // Ensure only whole data stores can be reused, no reusing at deeper level!\n assert(level === 0, 0x0fc /* \"tree reuse at lower level\" */);\n assert(handlePath.indexOf(\"/\") === -1,\n 0x0fd /* \"data stores are writing incremental summaries!\" */);\n break;\n }\n case SummaryType.Attachment:\n assert(this.isRealStorageId(obj.id), 0x0fe /* \"attachment is aggregate blob\" */);\n break;\n default:\n unreachableCase(obj, `Unknown type: ${(obj as any).type}`);\n }\n }\n\n assert(newSummary.tree[this.aggregatedBlobName] === undefined, 0x0ff /* \"duplicate aggregate blob\" */);\n if (shouldCompress) {\n // Note: It would be great to add code here to unpack aggregate blob back to normal blobs\n // If only one blob made it into aggregate. Currently that does not happen as we always have\n // at least one .component blob and at least one DDS that has .attributes blob, so it's not an issue.\n // But it's possible that in future that would be great addition!\n // Good news - it's backward compatible change.\n assert(aggregator !== undefined, 0x100 /* \"logic error\" */);\n const content = aggregator.getAggregatedBlobContent();\n if (content !== undefined) {\n newSummary.tree[this.aggregatedBlobName] = {\n type: SummaryType.Blob,\n content,\n };\n }\n }\n return newSummary;\n }\n\n protected isRealStorageId(id: string): boolean {\n return !id.startsWith(this.virtualIdPrefix);\n }\n}\n"]}
1
+ {"version":3,"file":"blobAggregationStorage.js","sourceRoot":"","sources":["../src/blobAggregationStorage.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 {\n IDocumentStorageService,\n IDocumentStorageServicePolicies,\n ISummaryContext,\n} from \"@fluidframework/driver-definitions\";\nimport {\n ICreateBlobResponse,\n ISnapshotTree,\n ISummaryHandle,\n ISummaryTree,\n IVersion,\n SummaryType,\n ITree,\n} from \"@fluidframework/protocol-definitions\";\nimport {\n assert,\n bufferToString,\n stringToBuffer,\n unreachableCase,\n fromUtf8ToBase64,\n Uint8ArrayToString,\n } from \"@fluidframework/common-utils\";\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\n\n// Gate that when flipped, instructs to compress small blobs.\n// We have to first ship with this gate off, such that we can get to saturation bits\n// that can understand compressed format. And only after that flip it.\nfunction gatesAllowPacking() {\n try {\n // Leave override for testing purposes\n // eslint-disable-next-line no-null/no-null\n if (typeof localStorage === \"object\" && localStorage !== null) {\n if (localStorage.FluidAggregateBlobs === \"1\") {\n return true;\n }\n if (localStorage.FluidAggregateBlobs === \"0\") {\n return false;\n }\n }\n } catch (e) {}\n\n // We are starting disabled.\n return false;\n}\n\n/*\n * Work around for bufferToString having a bug - it can't consume IsoBuffer!\n * To be removed once bufferToString is fixed!\n*/\nfunction bufferToString2(blob: ArrayBufferLike, encoding: \"utf-8\" | \"base64\"): string {\n if (blob instanceof Uint8Array) { // IsoBuffer does not have ctor, so it's not in proto chain :(\n return Uint8ArrayToString(blob, encoding);\n }\n return bufferToString(blob, encoding);\n}\n\n /**\n * Class responsible for aggregating smaller blobs into one and unpacking it later on.\n */\nclass BlobAggregator {\n private readonly content: [string, string][]= [];\n\n public addBlob(key: string, content: string) {\n this.content.push([key, content]);\n }\n\n public getAggregatedBlobContent() {\n if (this.content.length === 0) {\n return undefined;\n }\n return JSON.stringify(this.content);\n }\n\n static load(input: ArrayBufferLike) {\n const data = bufferToString2(input, \"utf-8\");\n return JSON.parse(data) as [string, string][];\n }\n}\n\n/*\n * Base class that deals with unpacking snapshots (in place) containing aggregated blobs\n * It relies on abstract methods for reads and storing unpacked blobs.\n */\nexport abstract class SnapshotExtractor {\n protected readonly aggregatedBlobName = \"__big\";\n protected readonly virtualIdPrefix = \"__\";\n\n // counter for generation of virtual storage IDs\n protected virtualIdCounter = 0;\n protected getNextVirtualId() {\n return `${this.virtualIdPrefix}${++this.virtualIdCounter}`;\n }\n\n abstract getBlob(id: string, tree: ISnapshotTree): Promise<ArrayBufferLike>;\n abstract setBlob(id: string, tree: ISnapshotTree, content: string);\n\n public async unpackSnapshotCore(snapshot: ISnapshotTree, level = 0): Promise<void> {\n for (const key of Object.keys(snapshot.trees)) {\n const obj = snapshot.trees[key];\n await this.unpackSnapshotCore(obj, level + 1);\n }\n\n // For future proof, we will support multiple aggregated blobs with any name\n // that starts with this.aggregatedBlobName\n for (const key of Object.keys(snapshot.blobs)) {\n if (!key.startsWith(this.aggregatedBlobName)) { continue; }\n const blobId = snapshot.blobs[key];\n if (blobId !== undefined) {\n const blob = await this.getBlob(blobId, snapshot);\n for (const [path, value] of BlobAggregator.load(blob)) {\n const id = this.getNextVirtualId();\n this.setBlob(id, snapshot, value);\n const pathSplit = path.split(\"/\");\n let subTree = snapshot;\n for (const subPath of pathSplit.slice(0, pathSplit.length - 1)) {\n if (subTree.trees[subPath] === undefined) {\n subTree.trees[subPath] = { blobs: {}, commits: {}, trees: {}};\n }\n subTree = subTree.trees[subPath];\n }\n const blobName = pathSplit[pathSplit.length - 1];\n assert(subTree.blobs[blobName] === undefined, 0x0f6 /* \"real blob ID exists\" */);\n subTree.blobs[blobName] = id;\n }\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete snapshot.blobs[this.aggregatedBlobName];\n }\n }\n }\n}\n\n/*\n * Snapshot extractor class that works in place, i.e. patches snapshot that has\n * blob content in ISnapshotTree.blobs itself, not in storage.\n * As result, it implements reading and writing of blobs to/from snapshot itself.\n * It follows existing pattern that mixes concerns - ISnapshotTree.blobs is used for two\n * purposes:\n * 1. map path name to blob ID\n * 2. map blob ID to blob content\n * #2 is what storage (IDocumentStorageService) is for, but in places where we do not have it\n * (like loading serialized earlier draft content), blob content is put directly into snapshot.\n * Ideally this should be fixed by using BlobCacheStorageService or something similar and\n * fixing existing flows to allow switching of storage.\n */\nclass SnapshotExtractorInPlace extends SnapshotExtractor {\n public async getBlob(id: string, tree: ISnapshotTree): Promise<ArrayBufferLike> {\n const blob = tree.blobs[id];\n assert(blob !== undefined, 0x0f7 /* \"aggregate blob missing\" */);\n return stringToBuffer(blob, \"base64\");\n }\n\n public setBlob(id: string, tree: ISnapshotTree, content: string) {\n assert(tree.blobs[id] === undefined, 0x0f8 /* \"blob from aggregate blob exists on its own\" */);\n tree.blobs[id] = fromUtf8ToBase64(content);\n }\n}\n\n/*\n * Snapshot packer and extractor.\n * When summary is written it will find and aggregate small blobs into bigger blobs\n * When snapshot is read, it will unpack aggregated blobs and provide them transparently to caller.\n */\nexport class BlobAggregationStorage extends SnapshotExtractor implements IDocumentStorageService {\n // Tells data store if it can use incremental summary (i.e. reuse DDSs from previous summary\n // when only one DDS changed).\n // The answer has to be know long before we enable actual packing. The reason for the is the following:\n // A the moment when we enable packing, we should assume that all clients out there wil already have bits\n // that can unpack properly (i.e. enough time passed since we deployed bits that can unpack)\n // But we can still have clients where some of them already pack, and some do not. If one summary was\n // using packing, then it relies on non-incremental summaries going forward, even if next client who\n // produced summary is not packing!\n // This can have slight improvement by enabling it per file (based on \"did summary we loaded from contain\n // aggregated blobs\"), but that's harder to make reliable, so going for simplicity.\n static readonly fullDataStoreSummaries = true;\n\n protected loadedFromSummary = false;\n\n protected virtualBlobs = new Map<string, ArrayBufferLike>();\n\n static wrap(\n storage: IDocumentStorageService,\n logger: ITelemetryLogger,\n allowPacking = gatesAllowPacking(),\n packingLevel = 2,\n ) {\n if (storage instanceof BlobAggregationStorage) {\n return storage;\n }\n // Always create BlobAggregationStorage even if storage is not asking for packing.\n // This is mostly to avoid cases where future changes in policy would result in inability to\n // load old files that were created with aggregation on.\n const minBlobSize = storage.policies?.minBlobSize;\n return new BlobAggregationStorage(storage, logger, allowPacking, packingLevel, minBlobSize);\n }\n\n static async unpackSnapshot(snapshot: ISnapshotTree) {\n const converter = new SnapshotExtractorInPlace();\n await converter.unpackSnapshotCore(snapshot);\n }\n\n public get policies(): IDocumentStorageServicePolicies | undefined {\n const policies = this.storage.policies;\n if (policies) {\n return { ...policies, minBlobSize: undefined };\n }\n }\n\n public async unpackSnapshot(snapshot: ISnapshotTree) {\n // SummarizerNodeWithGC.refreshLatestSummary can call it when this.loadedFromSummary === false\n // (I assumed after file was created)\n // assert(!this.loadedFromSummary, \"unpack without summary\");\n\n this.loadedFromSummary = true;\n await this.unpackSnapshotCore(snapshot);\n }\n\n protected constructor(\n private readonly storage: IDocumentStorageService,\n private readonly logger: ITelemetryLogger,\n private readonly allowPacking: boolean,\n private readonly packingLevel: number,\n private readonly blobCutOffSize?: number)\n {\n super();\n }\n\n public setBlob(id: string, tree: ISnapshotTree, content: string) {\n this.virtualBlobs.set(id, stringToBuffer(content, \"utf-8\"));\n }\n\n public async getBlob(id: string, tree: ISnapshotTree): Promise<ArrayBufferLike> {\n return this.readBlob(id).catch((error) => {\n this.logger.sendErrorEvent({ eventName: \"BlobDedupNoAggregateBlob\" }, error);\n throw error;\n });\n }\n\n public get repositoryUrl() { return this.storage.repositoryUrl; }\n public async getVersions(versionId: string | null, count: number) {\n return this.storage.getVersions(versionId, count);\n }\n\n public async downloadSummary(handle: ISummaryHandle): Promise<ISummaryTree> {\n throw new Error(\"NYI\");\n }\n\n // This is only used through Container.snapshot() for testing purposes\n public async write(root: ITree, parents: string[], message: string, ref: string) {\n return this.storage.write(root, parents, message, ref);\n }\n\n // for now we are not optimizing these blobs, with assumption that this API is used only\n // for big blobs (images)\n public async createBlob(file: ArrayBufferLike): Promise<ICreateBlobResponse> {\n return this.storage.createBlob(file);\n }\n\n public async getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null> {\n const tree = await this.storage.getSnapshotTree(version);\n if (tree) {\n await this.unpackSnapshot(tree);\n }\n return tree;\n }\n\n public async readBlob(id: string): Promise<ArrayBufferLike> {\n if (this.isRealStorageId(id)) {\n return this.storage.readBlob(id);\n }\n // We support only reading blobs from the summary we loaded from.\n // This may need to be extended to any general summary in the future as runtime usage pattern\n // of storage changes (for example, data stores start to load from recent summary, not from original\n // summary whole container loaded from)\n\n // are there other ways we can get here? createFile is one flow, but we should not be reading blobs\n // in such flow\n assert(this.loadedFromSummary, 0x0f9 /* \"never read summary\" */);\n const blob = this.virtualBlobs.get(id);\n assert(blob !== undefined, 0x0fa /* \"virtual blob not found\" */);\n return blob;\n }\n\n public async uploadSummaryWithContext(summary: ISummaryTree, context: ISummaryContext): Promise<string> {\n const summaryNew = this.allowPacking ? await this.compressSmallBlobs(summary) : summary;\n return this.storage.uploadSummaryWithContext(summaryNew, context);\n }\n\n // For simplification, we assume that\n // - blob aggregation is done at data store level only for now\n // - data store either reuses previous summary, or generates full summary, i.e. there is no partial (some DDS)\n // summary produced by data stores.\n // These simplifications allow us not to touch handles, as they are self-contained (either do not use aggregated\n // blob Or contain aggregated blob that stays relevant for that sub-tree)\n // Note:\n // From perf perspective, it makes sense to place aggregated blobs one level up in the tree not to create extra\n // tree nodes (i.e. have shallow tree with less edges). But that creates problems with reusability of trees at\n // incremental summary time - we would need to understand handles and parse them. In current design we can skip\n // that step because if data store is reused, the hole sub-tree is reused included aggregated blob embedded into it\n // and that means we can do nothing and be correct!\n private async compressSmallBlobs(\n summary: ISummaryTree,\n path = \"\",\n level = 0,\n aggregatorArg?: BlobAggregator): Promise<ISummaryTree>\n {\n if (this.blobCutOffSize === undefined || this.blobCutOffSize < 0) {\n return summary;\n }\n\n let shouldCompress: boolean = false;\n\n let aggregator = aggregatorArg;\n // checking if this is a dataStore tree, since we only pack at data store level\n if (Object.keys(summary.tree).includes(\".component\")) {\n assert(aggregator === undefined, 0x0fb /* \"logic err with aggregator\" */);\n assert(level === this.packingLevel, 0x23b /* \"we are not packing at the right level\" */);\n aggregator = new BlobAggregator();\n shouldCompress = true;\n } else {\n assert(level !== this.packingLevel, 0x23c /* \"we are not packing at the right level\" */);\n }\n\n const newSummary: ISummaryTree = {...summary};\n newSummary.tree = { ...newSummary.tree};\n for (const key of Object.keys(summary.tree)) {\n const obj = summary.tree[key];\n // Get path relative to root of data store (where we do aggregation)\n const newPath = shouldCompress ? key : `${path}/${key}`;\n switch (obj.type) {\n case SummaryType.Tree:\n // If client created empty tree, keep it as is\n // Also do not package search blobs - they are part of storage contract\n if (obj.tree !== {} && key !== \"__search\") {\n const tree = await this.compressSmallBlobs(obj, newPath, level + 1, aggregator);\n newSummary.tree[key] = tree;\n if (tree.tree === {}) {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete newSummary.tree[key];\n }\n }\n break;\n case SummaryType.Blob:\n if (aggregator && typeof obj.content == \"string\" && obj.content.length < this.blobCutOffSize) {\n aggregator.addBlob(newPath, obj.content);\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete newSummary.tree[key];\n }\n break;\n case SummaryType.Handle: {\n // Would be nice to:\n // Trees: expand the tree\n // Blobs: parse handle and ensure it points to real blob, not virtual blob.\n // We can avoid it for now given data store is the granularity of incremental summaries.\n let handlePath = obj.handle;\n if (handlePath.startsWith(\"/\")) {\n handlePath = handlePath.substr(1);\n }\n // Ensure only whole data stores can be reused, no reusing at deeper level!\n assert(level === 0, 0x0fc /* \"tree reuse at lower level\" */);\n assert(handlePath.indexOf(\"/\") === -1,\n 0x0fd /* \"data stores are writing incremental summaries!\" */);\n break;\n }\n case SummaryType.Attachment:\n assert(this.isRealStorageId(obj.id), 0x0fe /* \"attachment is aggregate blob\" */);\n break;\n default:\n unreachableCase(obj, `Unknown type: ${(obj as any).type}`);\n }\n }\n\n assert(newSummary.tree[this.aggregatedBlobName] === undefined, 0x0ff /* \"duplicate aggregate blob\" */);\n if (shouldCompress) {\n // Note: It would be great to add code here to unpack aggregate blob back to normal blobs\n // If only one blob made it into aggregate. Currently that does not happen as we always have\n // at least one .component blob and at least one DDS that has .attributes blob, so it's not an issue.\n // But it's possible that in future that would be great addition!\n // Good news - it's backward compatible change.\n assert(aggregator !== undefined, 0x100 /* \"logic error\" */);\n const content = aggregator.getAggregatedBlobContent();\n if (content !== undefined) {\n newSummary.tree[this.aggregatedBlobName] = {\n type: SummaryType.Blob,\n content,\n };\n }\n }\n return newSummary;\n }\n\n protected isRealStorageId(id: string): boolean {\n return !id.startsWith(this.virtualIdPrefix);\n }\n}\n"]}
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export declare const pkgName = "@fluidframework/driver-utils";
8
- export declare const pkgVersion = "0.51.3";
8
+ export declare const pkgVersion = "0.53.0-46105";
9
9
  //# sourceMappingURL=packageVersion.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,iCAAiC,CAAC;AACtD,eAAO,MAAM,UAAU,WAAW,CAAC"}
1
+ {"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,iCAAiC,CAAC;AACtD,eAAO,MAAM,UAAU,iBAAiB,CAAC"}
@@ -8,5 +8,5 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.pkgVersion = exports.pkgName = void 0;
10
10
  exports.pkgName = "@fluidframework/driver-utils";
11
- exports.pkgVersion = "0.51.3";
11
+ exports.pkgVersion = "0.53.0-46105";
12
12
  //# sourceMappingURL=packageVersion.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,8BAA8B,CAAC;AACzC,QAAA,UAAU,GAAG,QAAQ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/driver-utils\";\nexport const pkgVersion = \"0.51.3\";\n"]}
1
+ {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,8BAA8B,CAAC;AACzC,QAAA,UAAU,GAAG,cAAc,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/driver-utils\";\nexport const pkgVersion = \"0.53.0-46105\";\n"]}
@@ -57,7 +57,7 @@ export declare class Queue<T> implements IStream<T> {
57
57
  protected pushCore(value: Promise<IStreamResult<T>>): void;
58
58
  read(): Promise<IStreamResult<T>>;
59
59
  }
60
- export declare function requestOps(get: (from: number, to: number, telemetryProps: ITelemetryProperties) => Promise<IDeltasFetchResult>, concurrency: number, fromTotal: number, toTotal: number | undefined, payloadSize: number, logger: ITelemetryLogger, signal?: AbortSignal): IStream<ISequencedDocumentMessage[]>;
60
+ export declare function requestOps(get: (from: number, to: number, telemetryProps: ITelemetryProperties) => Promise<IDeltasFetchResult>, concurrency: number, fromTotal: number, toTotal: number | undefined, payloadSize: number, logger: ITelemetryLogger, signal?: AbortSignal, fetchReason?: string): IStream<ISequencedDocumentMessage[]>;
61
61
  export declare const emptyMessageStream: IStream<ISequencedDocumentMessage[]>;
62
62
  export declare function streamFromMessages(messagesArg: Promise<ISequencedDocumentMessage[]>): IStream<ISequencedDocumentMessage[]>;
63
63
  export declare function streamObserver<T>(stream: IStream<T>, handler: (value: IStreamResult<T>) => void): IStream<T>;
@@ -1 +1 @@
1
- {"version":3,"file":"parallelRequests.d.ts","sourceRoot":"","sources":["../src/parallelRequests.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAE5F,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AAShG;;;;;;;;;;;GAWG;AACH,qBAAa,gBAAgB,CAAC,CAAC;IAevB,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,eAAe;IAMhC,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IAvBrC,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+B;IACvD,OAAO,CAAC,YAAY,CAA2B;IAC/C,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwB;IACjD,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IAEjC,OAAO,KAAK,OAAO,GAA8C;IACjE,IAAW,QAAQ,YAA+C;gBAG9D,IAAI,EAAE,MAAM,EACJ,EAAE,EAAE,MAAM,GAAG,SAAS,EACb,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,gBAAgB,EACxB,eAAe,EAAE,CAC9B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,OAAO,EACjB,KAAK,EAAE,oBAAoB,KAAK,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,CAAC,EAAE,CAAA;KAAE,CAAC,EAC/E,gBAAgB,EAAE,CAAC,OAAO,EAAE,CAAC,EAAE,KAAK,IAAI;IAOtD,MAAM;IAOA,GAAG,CAAC,WAAW,EAAE,MAAM;IAapC,OAAO,CAAC,IAAI;IAUZ,OAAO,CAAC,IAAI;IAOZ,OAAO,CAAC,QAAQ;IA6BhB,OAAO,CAAC,YAAY;IAyBpB,OAAO,CAAC,UAAU;YAQJ,cAAc;CA4I/B;AAED;;;GAGG;AACH,qBAAa,KAAK,CAAC,CAAC,CAAE,YAAW,OAAO,CAAC,CAAC,CAAC;IACvC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmC;IACzD,OAAO,CAAC,QAAQ,CAAyC;IACzD,OAAO,CAAC,IAAI,CAAS;IAEd,SAAS,CAAC,KAAK,EAAE,CAAC;IAIlB,SAAS,CAAC,KAAK,EAAE,GAAG;IAKpB,QAAQ;IAKf,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAWtC,IAAI,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;CAUjD;AAoGD,wBAAgB,UAAU,CACtB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,oBAAoB,KAAK,OAAO,CAAC,kBAAkB,CAAC,EACpG,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,gBAAgB,EACxB,MAAM,CAAC,EAAE,WAAW,GACrB,OAAO,CAAC,yBAAyB,EAAE,CAAC,CAoFtC;AAED,eAAO,MAAM,kBAAkB,EAAE,OAAO,CAAC,yBAAyB,EAAE,CAEnE,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,OAAO,CAAC,yBAAyB,EAAE,CAAC,GAChF,OAAO,CAAC,yBAAyB,EAAE,CAAC,CAavC;AAGD,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAQ5G"}
1
+ {"version":3,"file":"parallelRequests.d.ts","sourceRoot":"","sources":["../src/parallelRequests.ts"],"names":[],"mappings":"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"}
@@ -307,7 +307,7 @@ exports.Queue = Queue;
307
307
  * If false, returning less ops would mean we reached end of file.
308
308
  * @returns - an object with resulting ops and cancellation / partial result flags
309
309
  */
310
- async function getSingleOpBatch(get, props, strongTo, logger, signal) {
310
+ async function getSingleOpBatch(get, props, strongTo, logger, signal, fetchReason) {
311
311
  let lastSuccessTime;
312
312
  let retry = 0;
313
313
  const deltas = [];
@@ -343,7 +343,8 @@ async function getSingleOpBatch(get, props, strongTo, logger, signal) {
343
343
  const canRetry = network_1.canRetryOnError(error);
344
344
  lastSuccessTime = undefined;
345
345
  const retryAfter = network_1.getRetryDelayFromError(error);
346
- networkUtils_1.logNetworkFailure(logger, Object.assign(Object.assign({ eventName: "GetDeltas_Error" }, props), { retry, duration: common_utils_1.performance.now() - startTime, retryAfter }), error);
346
+ networkUtils_1.logNetworkFailure(logger, Object.assign(Object.assign({ eventName: "GetDeltas_Error" }, props), { retry, duration: common_utils_1.performance.now() - startTime, retryAfter,
347
+ fetchReason }), error);
347
348
  if (!canRetry) {
348
349
  // It's game over scenario.
349
350
  throw error;
@@ -356,7 +357,7 @@ async function getSingleOpBatch(get, props, strongTo, logger, signal) {
356
357
  }
357
358
  return nothing;
358
359
  }
359
- function requestOps(get, concurrency, fromTotal, toTotal, payloadSize, logger, signal) {
360
+ function requestOps(get, concurrency, fromTotal, toTotal, payloadSize, logger, signal, fetchReason) {
360
361
  let requests = 0;
361
362
  let lastFetch;
362
363
  let length = 0;
@@ -365,10 +366,10 @@ function requestOps(get, concurrency, fromTotal, toTotal, payloadSize, logger, s
365
366
  fromTotal,
366
367
  toTotal,
367
368
  };
368
- const telemetryEvent = telemetry_utils_1.PerformanceEvent.start(logger, Object.assign({ eventName: "GetDeltas" }, propsTotal));
369
+ const telemetryEvent = telemetry_utils_1.PerformanceEvent.start(logger, Object.assign(Object.assign({ eventName: "GetDeltas" }, propsTotal), { fetchReason }));
369
370
  const manager = new ParallelRequests(fromTotal, toTotal, payloadSize, logger, async (request, from, to, strongTo, propsPerRequest) => {
370
371
  requests++;
371
- return getSingleOpBatch(async (propsAll) => get(from, to, propsAll), Object.assign(Object.assign({ request, from, to }, propsTotal), propsPerRequest), strongTo, logger, signal);
372
+ return getSingleOpBatch(async (propsAll) => get(from, to, propsAll), Object.assign(Object.assign({ request, from, to }, propsTotal), propsPerRequest), strongTo, logger, signal, fetchReason);
372
373
  }, (deltas) => {
373
374
  // Assert continuing and right start.
374
375
  if (lastFetch === undefined) {
@@ -1 +1 @@
1
- {"version":3,"file":"parallelRequests.js","sourceRoot":"","sources":["../src/parallelRequests.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 */\nimport { assert, Deferred, performance } from \"@fluidframework/common-utils\";\nimport { ITelemetryLogger, ITelemetryProperties } from \"@fluidframework/common-definitions\";\nimport { PerformanceEvent} from \"@fluidframework/telemetry-utils\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { IDeltasFetchResult, IStream, IStreamResult } from \"@fluidframework/driver-definitions\";\nimport { getRetryDelayFromError, canRetryOnError, createGenericNetworkError } from \"./network\";\nimport { waitForConnectedState, logNetworkFailure } from \"./networkUtils\";\n\nconst MaxFetchDelayInMs = 10000;\nconst MissingFetchDelayInMs = 100;\n\ntype WorkingState = \"working\" | \"done\" | \"canceled\";\n\n/**\n * Helper class to organize parallel fetching of data\n * It can be used to concurrently do many requests, while consuming\n * data in the right order. Take a look at UT for examples.\n * @param concurrency - level of concurrency\n * @param from - starting point of fetching data (inclusive)\n * @param to - ending point of fetching data. exclusive, or undefined if unknown\n * @param payloadSize - batch size\n * @param logger - logger to use\n * @param requestCallback - callback to request batches\n * @returns - Queue that can be used to retrieve data\n */\nexport class ParallelRequests<T> {\n private latestRequested: number;\n private nextToDeliver: number;\n private readonly results: Map<number, T[]> = new Map();\n private workingState: WorkingState = \"working\";\n private requestsInFlight = 0;\n private readonly endEvent = new Deferred<void>();\n private requests = 0;\n private readonly knewTo: boolean;\n\n private get working() { return this.workingState === \"working\"; }\n public get canceled() { return this.workingState === \"canceled\"; }\n\n constructor(\n from: number,\n private to: number | undefined,\n private readonly payloadSize: number,\n private readonly logger: ITelemetryLogger,\n private readonly requestCallback: (\n request: number,\n from: number,\n to: number,\n strongTo: boolean,\n props: ITelemetryProperties) => Promise<{ partial: boolean, cancel: boolean, payload: T[] }>,\n private readonly responseCallback: (payload: T[]) => void)\n {\n this.latestRequested = from;\n this.nextToDeliver = from;\n this.knewTo = (to !== undefined);\n }\n\n public cancel() {\n if (this.working) {\n this.workingState = \"canceled\";\n this.endEvent.resolve();\n }\n }\n\n public async run(concurrency: number) {\n assert(concurrency > 0, 0x102 /* \"invalid level of concurrency\" */);\n assert(this.working, 0x103 /* \"trying to parallel run while not working\" */);\n\n let c = concurrency;\n while (c > 0) {\n c--;\n this.addRequest();\n }\n this.dispatch();// will recalculate and trigger this.endEvent if needed\n return this.endEvent.promise;\n }\n\n private done() {\n // We should satisfy request fully.\n assert(this.to !== undefined, 0x104 /* \"undefined end point for parallel fetch\" */);\n assert(this.nextToDeliver >= this.to, 0x105 /* \"unexpected end point for parallel fetch\" */);\n if (this.working) {\n this.workingState = \"done\";\n this.endEvent.resolve();\n }\n }\n\n private fail(error) {\n if (this.working) {\n this.workingState = \"done\";\n this.endEvent.reject(error);\n }\n }\n\n private dispatch() {\n while (this.working) {\n const value = this.results.get(this.nextToDeliver);\n if (value === undefined) {\n break;\n }\n this.results.delete(this.nextToDeliver);\n assert(value.length <= this.payloadSize, 0x1d9 /* \"addRequestCore() should break into smaller chunks\" */);\n this.nextToDeliver += value.length;\n this.responseCallback(value);\n }\n\n // Account for cancellation - state might be not in consistent state on cancelling operation\n if (this.working) {\n if (this.requestsInFlight === 0) {\n // we should have dispatched everything, no matter whether we knew about the end or not.\n // see comment in addRequestCore() around throwing away chunk if it's above this.to\n assert(this.results.size === 0,\n 0x107 /* \"ending dispatch with remaining results to be sent\" */);\n this.done();\n } else if (this.to !== undefined && this.nextToDeliver >= this.to) {\n // Learned about the end and dispatched all the ops up to it.\n // Ignore all the in-flight requests above boundary - unblock caller sooner.\n assert(!this.knewTo, 0x108 /* \"ending results dispatch but knew in advance about more requests\" */);\n this.done();\n }\n }\n }\n\n private getNextChunk() {\n if (!this.working) {\n return undefined;\n }\n\n const from = this.latestRequested;\n if (this.to !== undefined) {\n if (this.to <= from) {\n return undefined;\n }\n }\n\n // this.latestRequested\n // inclusive on the right side! Exclusive on the left.\n this.latestRequested += this.payloadSize;\n\n if (this.to !== undefined) {\n this.latestRequested = Math.min(this.to, this.latestRequested);\n }\n\n assert(from < this.latestRequested, 0x109 /* \"unexpected next chunk position\" */);\n\n return { from, to: this.latestRequested};\n }\n\n private addRequest() {\n const chunk = this.getNextChunk();\n if (chunk === undefined) {\n return;\n }\n this.addRequestCore(chunk.from, chunk.to).catch(this.fail.bind(this));\n }\n\n private async addRequestCore(fromArg: number, toArg: number) {\n assert(this.working, 0x10a /* \"cannot add parallel request while not working\" */);\n\n let from = fromArg;\n let to = toArg;\n\n // to & from are exclusive\n this.requestsInFlight++;\n while (this.working) {\n const requestedLength = to - from;\n assert(requestedLength > 0, 0x10b /* \"invalid parallel request range\" */);\n\n // We should not be wasting time asking for something useless.\n if (this.to !== undefined) {\n assert(from < this.to, 0x10c /* \"invalid parallel request start point\" */);\n assert(to <= this.to, 0x10d /* \"invalid parallel request end point\" */);\n }\n\n this.requests++;\n\n const promise = this.requestCallback(this.requests, from, to, this.to !== undefined, {});\n\n // dispatch any prior received data\n this.dispatch();\n\n const { payload, cancel, partial } = await promise;\n\n if (cancel) {\n this.cancel();\n }\n\n if (this.to !== undefined && from >= this.to) {\n // while we were waiting for response, we learned on what is the boundary\n // We can get here (with actual result!) if situation changed while this request was in\n // flight, i.e. the end was extended over what we learn in some other request\n // While it's useful not to throw this result, this is very corner cases and makes logic\n // (including consistency checks) much harder to write correctly.\n // So for now, we are throwing this result out the window.\n assert(!this.knewTo, 0x10e /* \"should not throw result if we knew about boundary in advance\" */);\n // Learn how often it happens and if it's too wasteful to throw these chunks.\n // If it pops into our view a lot, we would need to reconsider how we approach it.\n // Note that this is not visible to user other than potentially not hitting 100% of\n // what we can in perf domain.\n if (payload.length !== 0) {\n this.logger.sendErrorEvent({\n eventName: \"ParallelRequests_GotExtra\",\n from,\n to,\n end: this.to,\n length: payload.length,\n });\n }\n\n break;\n }\n\n if (this.working) {\n const fromOrig = from;\n const length = payload.length;\n let fullChunk = (requestedLength <= length); // we can possible get more than we asked.\n\n if (length !== 0) {\n // We can get more than we asked for!\n // This can screw up logic in dispatch!\n // So push only batch size, and keep the rest for later - if conditions are favorable, we\n // will be able to use it. If not (parallel request overlapping these ops), it's easier to\n // discard them and wait for another (overlapping) request to come in later.\n if (requestedLength < length) {\n // This is error in a sense that it's not expected and likely points bug in other layer.\n // This layer copes with this situation just fine.\n this.logger.sendTelemetryEvent({\n eventName: \"ParallelRequests_Over\",\n from,\n to,\n length,\n });\n }\n const data = payload.splice(0, requestedLength);\n this.results.set(from, data);\n from += data.length;\n } else {\n // 1. empty (partial) chunks should not be returned by various caching / adapter layers -\n // they should fall back to next layer. This might be important invariant to hold to ensure\n // that we are less likely have bugs where such layer would keep returning empty partial\n // result on each call.\n // 2. Current invariant is that callback does retries until it gets something,\n // with the goal of failing if zero data is retrieved in given amount of time.\n // This is very specific property of storage / ops, so this logic is not here, but given only\n // one user of this class, we assert that to catch issues earlier.\n // These invariant can be relaxed if needed.\n assert(!partial, 0x10f /* \"empty/partial chunks should not be returned by caching\" */);\n assert(!this.knewTo,\n 0x110 /* \"callback should retry until valid fetch before it learns new boundary\" */);\n }\n\n if (!partial && !fullChunk) {\n if (!this.knewTo) {\n if (this.to === undefined || this.to > from) {\n // The END\n this.to = from;\n }\n break;\n }\n // We know that there are more items to be retrieved\n // Can we get partial chunk? Ideally storage indicates that's not a full chunk\n // Note that it's possible that not all ops hit storage yet.\n // We will come back to request more, and if we can't get any more ops soon, it's\n // catastrophic failure (see comment above on responsibility of callback to return something)\n // This layer will just keep trying until it gets full set.\n this.logger.sendPerformanceEvent({\n eventName: \"ParallelRequests_Partial\",\n from: fromOrig,\n to,\n length,\n });\n }\n\n if (to === this.latestRequested) {\n // we can go after full chunk at the end if we received partial chunk, or more than asked\n // Also if we got more than we asked to, we can actually use those ops!\n if (payload.length !== 0) {\n this.results.set(from, payload);\n from += payload.length;\n }\n\n this.latestRequested = from;\n fullChunk = true;\n }\n\n if (fullChunk) {\n const chunk = this.getNextChunk();\n if (chunk === undefined) { break; }\n from = chunk.from;\n to = chunk.to;\n }\n }\n }\n this.requestsInFlight--;\n this.dispatch();\n }\n}\n\n/**\n * Helper queue class to allow async push / pull\n * It's essentially a pipe allowing multiple writers, and single reader\n */\nexport class Queue<T> implements IStream<T> {\n private readonly queue: Promise<IStreamResult<T>>[] = [];\n private deferred: Deferred<IStreamResult<T>> | undefined;\n private done = false;\n\n public pushValue(value: T) {\n this.pushCore(Promise.resolve({ done: false, value }));\n }\n\n public pushError(error: any) {\n this.pushCore(Promise.reject(error));\n this.done = true;\n }\n\n public pushDone() {\n this.pushCore(Promise.resolve({ done: true }));\n this.done = true;\n }\n\n protected pushCore(value: Promise<IStreamResult<T>>) {\n assert(!this.done, 0x112 /* \"cannot push onto queue if done\" */);\n if (this.deferred) {\n assert(this.queue.length === 0, 0x113 /* \"deferred queue should be empty\" */);\n this.deferred.resolve(value);\n this.deferred = undefined;\n } else {\n this.queue.push(value);\n }\n }\n\n public async read(): Promise<IStreamResult<T>> {\n assert(this.deferred === undefined, 0x114 /* \"cannot pop if deferred\" */);\n const value = this.queue.shift();\n if (value !== undefined) {\n return value;\n }\n assert(!this.done, 0x115 /* \"queue should not be done during pop\" */);\n this.deferred = new Deferred<IStreamResult<T>>();\n return this.deferred.promise;\n }\n}\n\n/**\n * Retrieve single batch of ops\n * @param request - request index\n * @param from - inclusive boundary\n * @param to - exclusive boundary\n * @param telemetryEvent - telemetry event used to track consecutive batch of requests\n * @param strongTo - tells if ops in range from...to have to be there and have to be retrieved.\n * If false, returning less ops would mean we reached end of file.\n * @returns - an object with resulting ops and cancellation / partial result flags\n */\nasync function getSingleOpBatch(\n get: (telemetryProps: ITelemetryProperties) => Promise<IDeltasFetchResult>,\n props: ITelemetryProperties,\n strongTo: boolean,\n logger: ITelemetryLogger,\n signal?: AbortSignal):\n Promise<{ partial: boolean, cancel: boolean, payload: ISequencedDocumentMessage[] }>\n{\n let lastSuccessTime: number | undefined;\n\n let retry: number = 0;\n const deltas: ISequencedDocumentMessage[] = [];\n const nothing = { partial: false, cancel: true, payload: []};\n\n while (signal?.aborted !== true) {\n retry++;\n let delay = Math.min(MaxFetchDelayInMs, MissingFetchDelayInMs * Math.pow(2, retry));\n const startTime = performance.now();\n\n try {\n // Issue async request for deltas - limit the number fetched to MaxBatchDeltas\n const deltasP = get({ ...props, retry } /* telemetry props */);\n\n const { messages, partialResult } = await deltasP;\n deltas.push(...messages);\n\n const deltasRetrievedLast = messages.length;\n\n if (deltasRetrievedLast !== 0 || !strongTo) {\n return { payload: deltas, cancel: false, partial: partialResult};\n }\n\n // Storage does not have ops we need.\n // Attempt to fetch more deltas. If we didn't receive any in the previous call we up our retry\n // count since something prevented us from seeing those deltas\n\n if (lastSuccessTime === undefined) {\n lastSuccessTime = performance.now();\n } else if (performance.now() - lastSuccessTime > 30000) {\n // If we are connected and receiving proper responses from server, but can't get any ops back,\n // then give up after some time. This likely indicates the issue with ordering service not flushing\n // ops to storage quick enough, and possibly waiting for summaries, while summarizer can't get\n // current as it can't get ops.\n throw createGenericNetworkError(\n \"failedToRetrieveOpsFromStorage:TooManyRetries\",\n undefined,\n false /* canRetry */,\n undefined /* retryAfterSeconds */,\n {\n retry,\n ...props,\n },\n );\n }\n } catch (error) {\n const canRetry = canRetryOnError(error);\n\n lastSuccessTime = undefined;\n\n const retryAfter = getRetryDelayFromError(error);\n\n logNetworkFailure(\n logger,\n {\n eventName: \"GetDeltas_Error\",\n ...props,\n retry,\n duration: performance.now() - startTime,\n retryAfter,\n },\n error);\n\n if (!canRetry) {\n // It's game over scenario.\n throw error;\n }\n\n if (retryAfter !== undefined && retryAfter >= 0) {\n delay = retryAfter;\n }\n }\n\n await waitForConnectedState(delay);\n }\n\n return nothing;\n}\n\nexport function requestOps(\n get: (from: number, to: number, telemetryProps: ITelemetryProperties) => Promise<IDeltasFetchResult>,\n concurrency: number,\n fromTotal: number,\n toTotal: number | undefined,\n payloadSize: number,\n logger: ITelemetryLogger,\n signal?: AbortSignal,\n): IStream<ISequencedDocumentMessage[]> {\n let requests = 0;\n let lastFetch: number | undefined;\n let length = 0;\n const queue = new Queue<ISequencedDocumentMessage[]>();\n\n const propsTotal: ITelemetryProperties = {\n fromTotal,\n toTotal,\n };\n\n const telemetryEvent = PerformanceEvent.start(logger, {\n eventName: \"GetDeltas\",\n ...propsTotal,\n });\n\n const manager = new ParallelRequests<ISequencedDocumentMessage>(\n fromTotal,\n toTotal,\n payloadSize,\n logger,\n async (request: number, from: number, to: number, strongTo: boolean, propsPerRequest: ITelemetryProperties) => {\n requests++;\n return getSingleOpBatch(\n async (propsAll) => get(from, to, propsAll),\n { request, from, to, ...propsTotal, ...propsPerRequest },\n strongTo,\n logger,\n signal,\n );\n },\n (deltas: ISequencedDocumentMessage[]) => {\n // Assert continuing and right start.\n if (lastFetch === undefined) {\n assert(deltas[0].sequenceNumber === fromTotal, 0x26d /* \"wrong start\" */);\n } else {\n assert(deltas[0].sequenceNumber === lastFetch + 1, 0x26e /* \"wrong start\" */);\n }\n lastFetch = deltas[deltas.length - 1].sequenceNumber;\n assert(lastFetch - deltas[0].sequenceNumber + 1 === deltas.length,\n 0x26f /* \"continuous and no duplicates\" */);\n length += deltas.length;\n queue.pushValue(deltas);\n });\n\n // Implement faster cancellation. getSingleOpBatch() checks signal, but only in between\n // waits (up to 10 seconds) and fetches (can take infinite amount of time).\n // While every such case should be improved and take into account signal (and thus cancel immediately),\n // it is beneficial to have catch-all\n const listener = (event: Event) => { manager.cancel(); };\n if (signal !== undefined) {\n signal.addEventListener(\"abort\", listener);\n }\n\n manager.run(concurrency)\n .finally(() => {\n if (signal !== undefined) {\n signal.removeEventListener(\"abort\", listener);\n }\n }).then(() => {\n const props = {\n lastFetch,\n length,\n requests,\n };\n if (manager.canceled) {\n telemetryEvent.cancel({ ...props, error: \"ops request cancelled by client\" });\n } else {\n assert(toTotal === undefined || lastFetch !== undefined && lastFetch >= toTotal - 1,\n 0x270 /* \"All requested ops fetched\" */);\n telemetryEvent.end(props);\n }\n queue.pushDone();\n })\n .catch((error) => {\n telemetryEvent.cancel({\n lastFetch,\n length,\n requests,\n }, error);\n queue.pushError(error);\n });\n\n return queue;\n}\n\nexport const emptyMessageStream: IStream<ISequencedDocumentMessage[]> = {\n read: async () => { return { done: true };},\n};\n\nexport function streamFromMessages(messagesArg: Promise<ISequencedDocumentMessage[]>):\n IStream<ISequencedDocumentMessage[]>\n{\n let messages: Promise<ISequencedDocumentMessage[]> | undefined = messagesArg;\n return {\n read: async () => {\n if (messages === undefined) {\n return { done: true };\n }\n const value = await messages;\n messages = undefined;\n return value.length === 0 ? { done: true } : { done: false, value };\n },\n };\n}\n\n// eslint-disable-next-line prefer-arrow/prefer-arrow-functions\nexport function streamObserver<T>(stream: IStream<T>, handler: (value: IStreamResult<T>) => void): IStream<T> {\n return {\n read: async () => {\n const value = await stream.read();\n handler(value);\n return value;\n },\n };\n}\n"]}
1
+ {"version":3,"file":"parallelRequests.js","sourceRoot":"","sources":["../src/parallelRequests.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 */\nimport { assert, Deferred, performance } from \"@fluidframework/common-utils\";\nimport { ITelemetryLogger, ITelemetryProperties } from \"@fluidframework/common-definitions\";\nimport { PerformanceEvent} from \"@fluidframework/telemetry-utils\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { IDeltasFetchResult, IStream, IStreamResult } from \"@fluidframework/driver-definitions\";\nimport { getRetryDelayFromError, canRetryOnError, createGenericNetworkError } from \"./network\";\nimport { waitForConnectedState, logNetworkFailure } from \"./networkUtils\";\n\nconst MaxFetchDelayInMs = 10000;\nconst MissingFetchDelayInMs = 100;\n\ntype WorkingState = \"working\" | \"done\" | \"canceled\";\n\n/**\n * Helper class to organize parallel fetching of data\n * It can be used to concurrently do many requests, while consuming\n * data in the right order. Take a look at UT for examples.\n * @param concurrency - level of concurrency\n * @param from - starting point of fetching data (inclusive)\n * @param to - ending point of fetching data. exclusive, or undefined if unknown\n * @param payloadSize - batch size\n * @param logger - logger to use\n * @param requestCallback - callback to request batches\n * @returns - Queue that can be used to retrieve data\n */\nexport class ParallelRequests<T> {\n private latestRequested: number;\n private nextToDeliver: number;\n private readonly results: Map<number, T[]> = new Map();\n private workingState: WorkingState = \"working\";\n private requestsInFlight = 0;\n private readonly endEvent = new Deferred<void>();\n private requests = 0;\n private readonly knewTo: boolean;\n\n private get working() { return this.workingState === \"working\"; }\n public get canceled() { return this.workingState === \"canceled\"; }\n\n constructor(\n from: number,\n private to: number | undefined,\n private readonly payloadSize: number,\n private readonly logger: ITelemetryLogger,\n private readonly requestCallback: (\n request: number,\n from: number,\n to: number,\n strongTo: boolean,\n props: ITelemetryProperties) => Promise<{ partial: boolean, cancel: boolean, payload: T[] }>,\n private readonly responseCallback: (payload: T[]) => void)\n {\n this.latestRequested = from;\n this.nextToDeliver = from;\n this.knewTo = (to !== undefined);\n }\n\n public cancel() {\n if (this.working) {\n this.workingState = \"canceled\";\n this.endEvent.resolve();\n }\n }\n\n public async run(concurrency: number) {\n assert(concurrency > 0, 0x102 /* \"invalid level of concurrency\" */);\n assert(this.working, 0x103 /* \"trying to parallel run while not working\" */);\n\n let c = concurrency;\n while (c > 0) {\n c--;\n this.addRequest();\n }\n this.dispatch();// will recalculate and trigger this.endEvent if needed\n return this.endEvent.promise;\n }\n\n private done() {\n // We should satisfy request fully.\n assert(this.to !== undefined, 0x104 /* \"undefined end point for parallel fetch\" */);\n assert(this.nextToDeliver >= this.to, 0x105 /* \"unexpected end point for parallel fetch\" */);\n if (this.working) {\n this.workingState = \"done\";\n this.endEvent.resolve();\n }\n }\n\n private fail(error) {\n if (this.working) {\n this.workingState = \"done\";\n this.endEvent.reject(error);\n }\n }\n\n private dispatch() {\n while (this.working) {\n const value = this.results.get(this.nextToDeliver);\n if (value === undefined) {\n break;\n }\n this.results.delete(this.nextToDeliver);\n assert(value.length <= this.payloadSize, 0x1d9 /* \"addRequestCore() should break into smaller chunks\" */);\n this.nextToDeliver += value.length;\n this.responseCallback(value);\n }\n\n // Account for cancellation - state might be not in consistent state on cancelling operation\n if (this.working) {\n if (this.requestsInFlight === 0) {\n // we should have dispatched everything, no matter whether we knew about the end or not.\n // see comment in addRequestCore() around throwing away chunk if it's above this.to\n assert(this.results.size === 0,\n 0x107 /* \"ending dispatch with remaining results to be sent\" */);\n this.done();\n } else if (this.to !== undefined && this.nextToDeliver >= this.to) {\n // Learned about the end and dispatched all the ops up to it.\n // Ignore all the in-flight requests above boundary - unblock caller sooner.\n assert(!this.knewTo, 0x108 /* \"ending results dispatch but knew in advance about more requests\" */);\n this.done();\n }\n }\n }\n\n private getNextChunk() {\n if (!this.working) {\n return undefined;\n }\n\n const from = this.latestRequested;\n if (this.to !== undefined) {\n if (this.to <= from) {\n return undefined;\n }\n }\n\n // this.latestRequested\n // inclusive on the right side! Exclusive on the left.\n this.latestRequested += this.payloadSize;\n\n if (this.to !== undefined) {\n this.latestRequested = Math.min(this.to, this.latestRequested);\n }\n\n assert(from < this.latestRequested, 0x109 /* \"unexpected next chunk position\" */);\n\n return { from, to: this.latestRequested};\n }\n\n private addRequest() {\n const chunk = this.getNextChunk();\n if (chunk === undefined) {\n return;\n }\n this.addRequestCore(chunk.from, chunk.to).catch(this.fail.bind(this));\n }\n\n private async addRequestCore(fromArg: number, toArg: number) {\n assert(this.working, 0x10a /* \"cannot add parallel request while not working\" */);\n\n let from = fromArg;\n let to = toArg;\n\n // to & from are exclusive\n this.requestsInFlight++;\n while (this.working) {\n const requestedLength = to - from;\n assert(requestedLength > 0, 0x10b /* \"invalid parallel request range\" */);\n\n // We should not be wasting time asking for something useless.\n if (this.to !== undefined) {\n assert(from < this.to, 0x10c /* \"invalid parallel request start point\" */);\n assert(to <= this.to, 0x10d /* \"invalid parallel request end point\" */);\n }\n\n this.requests++;\n\n const promise = this.requestCallback(this.requests, from, to, this.to !== undefined, {});\n\n // dispatch any prior received data\n this.dispatch();\n\n const { payload, cancel, partial } = await promise;\n\n if (cancel) {\n this.cancel();\n }\n\n if (this.to !== undefined && from >= this.to) {\n // while we were waiting for response, we learned on what is the boundary\n // We can get here (with actual result!) if situation changed while this request was in\n // flight, i.e. the end was extended over what we learn in some other request\n // While it's useful not to throw this result, this is very corner cases and makes logic\n // (including consistency checks) much harder to write correctly.\n // So for now, we are throwing this result out the window.\n assert(!this.knewTo, 0x10e /* \"should not throw result if we knew about boundary in advance\" */);\n // Learn how often it happens and if it's too wasteful to throw these chunks.\n // If it pops into our view a lot, we would need to reconsider how we approach it.\n // Note that this is not visible to user other than potentially not hitting 100% of\n // what we can in perf domain.\n if (payload.length !== 0) {\n this.logger.sendErrorEvent({\n eventName: \"ParallelRequests_GotExtra\",\n from,\n to,\n end: this.to,\n length: payload.length,\n });\n }\n\n break;\n }\n\n if (this.working) {\n const fromOrig = from;\n const length = payload.length;\n let fullChunk = (requestedLength <= length); // we can possible get more than we asked.\n\n if (length !== 0) {\n // We can get more than we asked for!\n // This can screw up logic in dispatch!\n // So push only batch size, and keep the rest for later - if conditions are favorable, we\n // will be able to use it. If not (parallel request overlapping these ops), it's easier to\n // discard them and wait for another (overlapping) request to come in later.\n if (requestedLength < length) {\n // This is error in a sense that it's not expected and likely points bug in other layer.\n // This layer copes with this situation just fine.\n this.logger.sendTelemetryEvent({\n eventName: \"ParallelRequests_Over\",\n from,\n to,\n length,\n });\n }\n const data = payload.splice(0, requestedLength);\n this.results.set(from, data);\n from += data.length;\n } else {\n // 1. empty (partial) chunks should not be returned by various caching / adapter layers -\n // they should fall back to next layer. This might be important invariant to hold to ensure\n // that we are less likely have bugs where such layer would keep returning empty partial\n // result on each call.\n // 2. Current invariant is that callback does retries until it gets something,\n // with the goal of failing if zero data is retrieved in given amount of time.\n // This is very specific property of storage / ops, so this logic is not here, but given only\n // one user of this class, we assert that to catch issues earlier.\n // These invariant can be relaxed if needed.\n assert(!partial, 0x10f /* \"empty/partial chunks should not be returned by caching\" */);\n assert(!this.knewTo,\n 0x110 /* \"callback should retry until valid fetch before it learns new boundary\" */);\n }\n\n if (!partial && !fullChunk) {\n if (!this.knewTo) {\n if (this.to === undefined || this.to > from) {\n // The END\n this.to = from;\n }\n break;\n }\n // We know that there are more items to be retrieved\n // Can we get partial chunk? Ideally storage indicates that's not a full chunk\n // Note that it's possible that not all ops hit storage yet.\n // We will come back to request more, and if we can't get any more ops soon, it's\n // catastrophic failure (see comment above on responsibility of callback to return something)\n // This layer will just keep trying until it gets full set.\n this.logger.sendPerformanceEvent({\n eventName: \"ParallelRequests_Partial\",\n from: fromOrig,\n to,\n length,\n });\n }\n\n if (to === this.latestRequested) {\n // we can go after full chunk at the end if we received partial chunk, or more than asked\n // Also if we got more than we asked to, we can actually use those ops!\n if (payload.length !== 0) {\n this.results.set(from, payload);\n from += payload.length;\n }\n\n this.latestRequested = from;\n fullChunk = true;\n }\n\n if (fullChunk) {\n const chunk = this.getNextChunk();\n if (chunk === undefined) { break; }\n from = chunk.from;\n to = chunk.to;\n }\n }\n }\n this.requestsInFlight--;\n this.dispatch();\n }\n}\n\n/**\n * Helper queue class to allow async push / pull\n * It's essentially a pipe allowing multiple writers, and single reader\n */\nexport class Queue<T> implements IStream<T> {\n private readonly queue: Promise<IStreamResult<T>>[] = [];\n private deferred: Deferred<IStreamResult<T>> | undefined;\n private done = false;\n\n public pushValue(value: T) {\n this.pushCore(Promise.resolve({ done: false, value }));\n }\n\n public pushError(error: any) {\n this.pushCore(Promise.reject(error));\n this.done = true;\n }\n\n public pushDone() {\n this.pushCore(Promise.resolve({ done: true }));\n this.done = true;\n }\n\n protected pushCore(value: Promise<IStreamResult<T>>) {\n assert(!this.done, 0x112 /* \"cannot push onto queue if done\" */);\n if (this.deferred) {\n assert(this.queue.length === 0, 0x113 /* \"deferred queue should be empty\" */);\n this.deferred.resolve(value);\n this.deferred = undefined;\n } else {\n this.queue.push(value);\n }\n }\n\n public async read(): Promise<IStreamResult<T>> {\n assert(this.deferred === undefined, 0x114 /* \"cannot pop if deferred\" */);\n const value = this.queue.shift();\n if (value !== undefined) {\n return value;\n }\n assert(!this.done, 0x115 /* \"queue should not be done during pop\" */);\n this.deferred = new Deferred<IStreamResult<T>>();\n return this.deferred.promise;\n }\n}\n\n/**\n * Retrieve single batch of ops\n * @param request - request index\n * @param from - inclusive boundary\n * @param to - exclusive boundary\n * @param telemetryEvent - telemetry event used to track consecutive batch of requests\n * @param strongTo - tells if ops in range from...to have to be there and have to be retrieved.\n * If false, returning less ops would mean we reached end of file.\n * @returns - an object with resulting ops and cancellation / partial result flags\n */\nasync function getSingleOpBatch(\n get: (telemetryProps: ITelemetryProperties) => Promise<IDeltasFetchResult>,\n props: ITelemetryProperties,\n strongTo: boolean,\n logger: ITelemetryLogger,\n signal?: AbortSignal,\n fetchReason?: string):\n Promise<{ partial: boolean, cancel: boolean, payload: ISequencedDocumentMessage[] }>\n{\n let lastSuccessTime: number | undefined;\n\n let retry: number = 0;\n const deltas: ISequencedDocumentMessage[] = [];\n const nothing = { partial: false, cancel: true, payload: []};\n\n while (signal?.aborted !== true) {\n retry++;\n let delay = Math.min(MaxFetchDelayInMs, MissingFetchDelayInMs * Math.pow(2, retry));\n const startTime = performance.now();\n\n try {\n // Issue async request for deltas - limit the number fetched to MaxBatchDeltas\n const deltasP = get({ ...props, retry } /* telemetry props */);\n\n const { messages, partialResult } = await deltasP;\n deltas.push(...messages);\n\n const deltasRetrievedLast = messages.length;\n\n if (deltasRetrievedLast !== 0 || !strongTo) {\n return { payload: deltas, cancel: false, partial: partialResult};\n }\n\n // Storage does not have ops we need.\n // Attempt to fetch more deltas. If we didn't receive any in the previous call we up our retry\n // count since something prevented us from seeing those deltas\n\n if (lastSuccessTime === undefined) {\n lastSuccessTime = performance.now();\n } else if (performance.now() - lastSuccessTime > 30000) {\n // If we are connected and receiving proper responses from server, but can't get any ops back,\n // then give up after some time. This likely indicates the issue with ordering service not flushing\n // ops to storage quick enough, and possibly waiting for summaries, while summarizer can't get\n // current as it can't get ops.\n throw createGenericNetworkError(\n \"failedToRetrieveOpsFromStorage:TooManyRetries\",\n undefined,\n false /* canRetry */,\n undefined /* retryAfterSeconds */,\n {\n retry,\n ...props,\n },\n );\n }\n } catch (error) {\n const canRetry = canRetryOnError(error);\n\n lastSuccessTime = undefined;\n\n const retryAfter = getRetryDelayFromError(error);\n\n logNetworkFailure(\n logger,\n {\n eventName: \"GetDeltas_Error\",\n ...props,\n retry,\n duration: performance.now() - startTime,\n retryAfter,\n fetchReason,\n },\n error);\n\n if (!canRetry) {\n // It's game over scenario.\n throw error;\n }\n\n if (retryAfter !== undefined && retryAfter >= 0) {\n delay = retryAfter;\n }\n }\n\n await waitForConnectedState(delay);\n }\n\n return nothing;\n}\n\nexport function requestOps(\n get: (from: number, to: number, telemetryProps: ITelemetryProperties) => Promise<IDeltasFetchResult>,\n concurrency: number,\n fromTotal: number,\n toTotal: number | undefined,\n payloadSize: number,\n logger: ITelemetryLogger,\n signal?: AbortSignal,\n fetchReason?: string,\n): IStream<ISequencedDocumentMessage[]> {\n let requests = 0;\n let lastFetch: number | undefined;\n let length = 0;\n const queue = new Queue<ISequencedDocumentMessage[]>();\n\n const propsTotal: ITelemetryProperties = {\n fromTotal,\n toTotal,\n };\n\n const telemetryEvent = PerformanceEvent.start(logger, {\n eventName: \"GetDeltas\",\n ...propsTotal,\n fetchReason,\n });\n\n const manager = new ParallelRequests<ISequencedDocumentMessage>(\n fromTotal,\n toTotal,\n payloadSize,\n logger,\n async (request: number, from: number, to: number, strongTo: boolean, propsPerRequest: ITelemetryProperties) => {\n requests++;\n return getSingleOpBatch(\n async (propsAll) => get(from, to, propsAll),\n { request, from, to, ...propsTotal, ...propsPerRequest },\n strongTo,\n logger,\n signal,\n fetchReason,\n );\n },\n (deltas: ISequencedDocumentMessage[]) => {\n // Assert continuing and right start.\n if (lastFetch === undefined) {\n assert(deltas[0].sequenceNumber === fromTotal, 0x26d /* \"wrong start\" */);\n } else {\n assert(deltas[0].sequenceNumber === lastFetch + 1, 0x26e /* \"wrong start\" */);\n }\n lastFetch = deltas[deltas.length - 1].sequenceNumber;\n assert(lastFetch - deltas[0].sequenceNumber + 1 === deltas.length,\n 0x26f /* \"continuous and no duplicates\" */);\n length += deltas.length;\n queue.pushValue(deltas);\n });\n\n // Implement faster cancellation. getSingleOpBatch() checks signal, but only in between\n // waits (up to 10 seconds) and fetches (can take infinite amount of time).\n // While every such case should be improved and take into account signal (and thus cancel immediately),\n // it is beneficial to have catch-all\n const listener = (event: Event) => { manager.cancel(); };\n if (signal !== undefined) {\n signal.addEventListener(\"abort\", listener);\n }\n\n manager.run(concurrency)\n .finally(() => {\n if (signal !== undefined) {\n signal.removeEventListener(\"abort\", listener);\n }\n }).then(() => {\n const props = {\n lastFetch,\n length,\n requests,\n };\n if (manager.canceled) {\n telemetryEvent.cancel({ ...props, error: \"ops request cancelled by client\" });\n } else {\n assert(toTotal === undefined || lastFetch !== undefined && lastFetch >= toTotal - 1,\n 0x270 /* \"All requested ops fetched\" */);\n telemetryEvent.end(props);\n }\n queue.pushDone();\n })\n .catch((error) => {\n telemetryEvent.cancel({\n lastFetch,\n length,\n requests,\n }, error);\n queue.pushError(error);\n });\n\n return queue;\n}\n\nexport const emptyMessageStream: IStream<ISequencedDocumentMessage[]> = {\n read: async () => { return { done: true };},\n};\n\nexport function streamFromMessages(messagesArg: Promise<ISequencedDocumentMessage[]>):\n IStream<ISequencedDocumentMessage[]>\n{\n let messages: Promise<ISequencedDocumentMessage[]> | undefined = messagesArg;\n return {\n read: async () => {\n if (messages === undefined) {\n return { done: true };\n }\n const value = await messages;\n messages = undefined;\n return value.length === 0 ? { done: true } : { done: false, value };\n },\n };\n}\n\n// eslint-disable-next-line prefer-arrow/prefer-arrow-functions\nexport function streamObserver<T>(stream: IStream<T>, handler: (value: IStreamResult<T>) => void): IStream<T> {\n return {\n read: async () => {\n const value = await stream.read();\n handler(value);\n return value;\n },\n };\n}\n"]}
@@ -5,6 +5,7 @@
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.getQuorumValuesFromProtocolSummary = exports.getDocAttributesFromProtocolSummary = exports.combineAppAndProtocolSummary = void 0;
8
+ const protocol_definitions_1 = require("@fluidframework/protocol-definitions");
8
9
  /**
9
10
  * Combine the app summary and protocol summary in 1 tree.
10
11
  * @param appSummary - Summary of the app.
@@ -12,7 +13,7 @@ exports.getQuorumValuesFromProtocolSummary = exports.getDocAttributesFromProtoco
12
13
  */
13
14
  function combineAppAndProtocolSummary(appSummary, protocolSummary) {
14
15
  const createNewSummary = {
15
- type: 1 /* Tree */,
16
+ type: protocol_definitions_1.SummaryType.Tree,
16
17
  tree: {
17
18
  ".protocol": protocolSummary,
18
19
  ".app": appSummary,
@@ -1 +1 @@
1
- {"version":3,"file":"summaryForCreateNew.js","sourceRoot":"","sources":["../src/summaryForCreateNew.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAUH;;;;GAIG;AACH,SAAgB,4BAA4B,CACxC,UAAwB,EACxB,eAA6B;IAE7B,MAAM,gBAAgB,GAAiB;QACnC,IAAI,cAAkB;QACtB,IAAI,EAAE;YACF,WAAW,EAAE,eAAe;YAC5B,MAAM,EAAE,UAAU;SACrB;KACJ,CAAC;IACF,OAAO,gBAAgB,CAAC;AAC5B,CAAC;AAZD,oEAYC;AAED;;;GAGG;AACH,SAAgB,mCAAmC,CAC/C,eAA6B;;IAE7B,MAAM,cAAc,GAAG,eAAe,CAAC,IAAI,CAAC,UAA0B,CAAC;IACvE,MAAM,kBAAkB,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAiB,CAAwB,CAAC;IAC/F,kBAAkB,CAAC,IAAI,SAAG,kBAAkB,CAAC,IAAI,mCAAI,CAAC,CAAC;IACvD,OAAO,kBAAkB,CAAC;AAC9B,CAAC;AAPD,kFAOC;AAED;;;GAGG;AACH,SAAgB,kCAAkC,CAC9C,eAA6B;IAE7B,MAAM,gBAAgB,GAAG,eAAe,CAAC,IAAI,CAAC,YAA4B,CAAC;IAC3E,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,OAAiB,CAAmC,CAAC;IACtG,OAAO,YAAY,CAAC;AACxB,CAAC;AAND,gFAMC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n ISummaryTree,\n SummaryType,\n ISummaryBlob,\n ICommittedProposal,\n IDocumentAttributes,\n} from \"@fluidframework/protocol-definitions\";\n\n/**\n * Combine the app summary and protocol summary in 1 tree.\n * @param appSummary - Summary of the app.\n * @param protocolSummary - Summary of the protocol.\n */\nexport function combineAppAndProtocolSummary(\n appSummary: ISummaryTree,\n protocolSummary: ISummaryTree,\n): ISummaryTree {\n const createNewSummary: ISummaryTree = {\n type: SummaryType.Tree,\n tree: {\n \".protocol\": protocolSummary,\n \".app\": appSummary,\n },\n };\n return createNewSummary;\n}\n\n/**\n * Extract the attributes from the protocol summary.\n * @param protocolSummary - protocol summary from which the values are to be extracted.\n */\nexport function getDocAttributesFromProtocolSummary(\n protocolSummary: ISummaryTree,\n): IDocumentAttributes {\n const attributesBlob = protocolSummary.tree.attributes as ISummaryBlob;\n const documentAttributes = JSON.parse(attributesBlob.content as string) as IDocumentAttributes;\n documentAttributes.term = documentAttributes.term ?? 1;\n return documentAttributes;\n}\n\n/**\n * Extract quorum values from the protocol summary.\n * @param protocolSummary - protocol summary from which the values are to be extracted.\n */\nexport function getQuorumValuesFromProtocolSummary(\n protocolSummary: ISummaryTree,\n): [string, ICommittedProposal][] {\n const quorumValuesBlob = protocolSummary.tree.quorumValues as ISummaryBlob;\n const quorumValues = JSON.parse(quorumValuesBlob.content as string) as [string, ICommittedProposal][];\n return quorumValues;\n}\n"]}
1
+ {"version":3,"file":"summaryForCreateNew.js","sourceRoot":"","sources":["../src/summaryForCreateNew.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+EAM8C;AAE9C;;;;GAIG;AACH,SAAgB,4BAA4B,CACxC,UAAwB,EACxB,eAA6B;IAE7B,MAAM,gBAAgB,GAAiB;QACnC,IAAI,EAAE,kCAAW,CAAC,IAAI;QACtB,IAAI,EAAE;YACF,WAAW,EAAE,eAAe;YAC5B,MAAM,EAAE,UAAU;SACrB;KACJ,CAAC;IACF,OAAO,gBAAgB,CAAC;AAC5B,CAAC;AAZD,oEAYC;AAED;;;GAGG;AACH,SAAgB,mCAAmC,CAC/C,eAA6B;;IAE7B,MAAM,cAAc,GAAG,eAAe,CAAC,IAAI,CAAC,UAA0B,CAAC;IACvE,MAAM,kBAAkB,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAiB,CAAwB,CAAC;IAC/F,kBAAkB,CAAC,IAAI,SAAG,kBAAkB,CAAC,IAAI,mCAAI,CAAC,CAAC;IACvD,OAAO,kBAAkB,CAAC;AAC9B,CAAC;AAPD,kFAOC;AAED;;;GAGG;AACH,SAAgB,kCAAkC,CAC9C,eAA6B;IAE7B,MAAM,gBAAgB,GAAG,eAAe,CAAC,IAAI,CAAC,YAA4B,CAAC;IAC3E,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,OAAiB,CAAmC,CAAC;IACtG,OAAO,YAAY,CAAC;AACxB,CAAC;AAND,gFAMC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n ISummaryTree,\n SummaryType,\n ISummaryBlob,\n ICommittedProposal,\n IDocumentAttributes,\n} from \"@fluidframework/protocol-definitions\";\n\n/**\n * Combine the app summary and protocol summary in 1 tree.\n * @param appSummary - Summary of the app.\n * @param protocolSummary - Summary of the protocol.\n */\nexport function combineAppAndProtocolSummary(\n appSummary: ISummaryTree,\n protocolSummary: ISummaryTree,\n): ISummaryTree {\n const createNewSummary: ISummaryTree = {\n type: SummaryType.Tree,\n tree: {\n \".protocol\": protocolSummary,\n \".app\": appSummary,\n },\n };\n return createNewSummary;\n}\n\n/**\n * Extract the attributes from the protocol summary.\n * @param protocolSummary - protocol summary from which the values are to be extracted.\n */\nexport function getDocAttributesFromProtocolSummary(\n protocolSummary: ISummaryTree,\n): IDocumentAttributes {\n const attributesBlob = protocolSummary.tree.attributes as ISummaryBlob;\n const documentAttributes = JSON.parse(attributesBlob.content as string) as IDocumentAttributes;\n documentAttributes.term = documentAttributes.term ?? 1;\n return documentAttributes;\n}\n\n/**\n * Extract quorum values from the protocol summary.\n * @param protocolSummary - protocol summary from which the values are to be extracted.\n */\nexport function getQuorumValuesFromProtocolSummary(\n protocolSummary: ISummaryTree,\n): [string, ICommittedProposal][] {\n const quorumValuesBlob = protocolSummary.tree.quorumValues as ISummaryBlob;\n const quorumValues = JSON.parse(quorumValuesBlob.content as string) as [string, ICommittedProposal][];\n return quorumValues;\n}\n"]}
@@ -2,6 +2,7 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
+ import { SummaryType, } from "@fluidframework/protocol-definitions";
5
6
  import { assert, bufferToString, stringToBuffer, unreachableCase, fromUtf8ToBase64, Uint8ArrayToString, } from "@fluidframework/common-utils";
6
7
  // Gate that when flipped, instructs to compress small blobs.
7
8
  // We have to first ship with this gate off, such that we can get to saturation bits
@@ -257,7 +258,7 @@ export class BlobAggregationStorage extends SnapshotExtractor {
257
258
  // Get path relative to root of data store (where we do aggregation)
258
259
  const newPath = shouldCompress ? key : `${path}/${key}`;
259
260
  switch (obj.type) {
260
- case 1 /* Tree */:
261
+ case SummaryType.Tree:
261
262
  // If client created empty tree, keep it as is
262
263
  // Also do not package search blobs - they are part of storage contract
263
264
  if (obj.tree !== {} && key !== "__search") {
@@ -269,14 +270,14 @@ export class BlobAggregationStorage extends SnapshotExtractor {
269
270
  }
270
271
  }
271
272
  break;
272
- case 2 /* Blob */:
273
+ case SummaryType.Blob:
273
274
  if (aggregator && typeof obj.content == "string" && obj.content.length < this.blobCutOffSize) {
274
275
  aggregator.addBlob(newPath, obj.content);
275
276
  // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
276
277
  delete newSummary.tree[key];
277
278
  }
278
279
  break;
279
- case 3 /* Handle */: {
280
+ case SummaryType.Handle: {
280
281
  // Would be nice to:
281
282
  // Trees: expand the tree
282
283
  // Blobs: parse handle and ensure it points to real blob, not virtual blob.
@@ -290,7 +291,7 @@ export class BlobAggregationStorage extends SnapshotExtractor {
290
291
  assert(handlePath.indexOf("/") === -1, 0x0fd /* "data stores are writing incremental summaries!" */);
291
292
  break;
292
293
  }
293
- case 4 /* Attachment */:
294
+ case SummaryType.Attachment:
294
295
  assert(this.isRealStorageId(obj.id), 0x0fe /* "attachment is aggregate blob" */);
295
296
  break;
296
297
  default:
@@ -308,7 +309,7 @@ export class BlobAggregationStorage extends SnapshotExtractor {
308
309
  const content = aggregator.getAggregatedBlobContent();
309
310
  if (content !== undefined) {
310
311
  newSummary.tree[this.aggregatedBlobName] = {
311
- type: 2 /* Blob */,
312
+ type: SummaryType.Blob,
312
313
  content,
313
314
  };
314
315
  }
@@ -1 +1 @@
1
- {"version":3,"file":"blobAggregationStorage.js","sourceRoot":"","sources":["../src/blobAggregationStorage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAgBH,OAAO,EACH,MAAM,EACN,cAAc,EACd,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,kBAAkB,GACpB,MAAM,8BAA8B,CAAC;AAGvC,6DAA6D;AAC7D,oFAAoF;AACpF,sEAAsE;AACtE,SAAS,iBAAiB;IACtB,IAAI;QACA,sCAAsC;QACtC,2CAA2C;QAC3C,IAAI,OAAO,YAAY,KAAK,QAAQ,IAAI,YAAY,KAAK,IAAI,EAAE;YAC3D,IAAK,YAAY,CAAC,mBAAmB,KAAK,GAAG,EAAE;gBAC3C,OAAO,IAAI,CAAC;aACf;YACD,IAAK,YAAY,CAAC,mBAAmB,KAAK,GAAG,EAAE;gBAC3C,OAAO,KAAK,CAAC;aAChB;SACJ;KACJ;IAAC,OAAO,CAAC,EAAE,GAAE;IAEd,4BAA4B;IAC5B,OAAO,KAAK,CAAC;AACjB,CAAC;AAED;;;EAGE;AACF,SAAS,eAAe,CAAC,IAAqB,EAAE,QAA4B;IACxE,IAAI,IAAI,YAAY,UAAU,EAAE,EAAE,8DAA8D;QAC5F,OAAO,kBAAkB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;KAC7C;IACD,OAAO,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC1C,CAAC;AAEA;;GAEG;AACJ,MAAM,cAAc;IAApB;QACqB,YAAO,GAAsB,EAAE,CAAC;IAiBrD,CAAC;IAfU,OAAO,CAAC,GAAW,EAAE,OAAe;QACvC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;IACtC,CAAC;IAEM,wBAAwB;QAC3B,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;YAC3B,OAAO,SAAS,CAAC;SACpB;QACD,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,KAAsB;QAC9B,MAAM,IAAI,GAAG,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC7C,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAuB,CAAC;IAClD,CAAC;CACJ;AAED;;;GAGG;AACH,MAAM,OAAgB,iBAAiB;IAAvC;QACuB,uBAAkB,GAAG,OAAO,CAAC;QAC7B,oBAAe,GAAG,IAAI,CAAC;QAE1C,gDAAgD;QACtC,qBAAgB,GAAG,CAAC,CAAC;IAyCnC,CAAC;IAxCa,gBAAgB;QACtB,OAAO,GAAG,IAAI,CAAC,eAAe,GAAG,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC;IAC/D,CAAC;IAKM,KAAK,CAAC,kBAAkB,CAAC,QAAuB,EAAE,KAAK,GAAG,CAAC;QAC9D,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE;YAC3C,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAChC,MAAM,IAAI,CAAC,kBAAkB,CAAC,GAAG,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;SACjD;QAED,4EAA4E;QAC5E,2CAA2C;QAC3C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE;YAC3C,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAE;gBAAE,SAAS;aAAE;YAC3D,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACnC,IAAI,MAAM,KAAK,SAAS,EAAE;gBACtB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;gBAClD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;oBACnD,MAAM,EAAE,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;oBACnC,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;oBAClC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;oBAClC,IAAI,OAAO,GAAG,QAAQ,CAAC;oBACvB,KAAK,MAAM,OAAO,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE;wBAC5D,IAAI,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,SAAS,EAAE;4BACtC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAC,CAAC;yBACjE;wBACD,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;qBACpC;oBACD,MAAM,QAAQ,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;oBACjD,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,SAAS,EAAE,KAAK,CAAC,2BAA2B,CAAC,CAAC;oBACjF,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;iBAChC;gBACD,gEAAgE;gBAChE,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;aAClD;SACJ;IACL,CAAC;CACJ;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,wBAAyB,SAAQ,iBAAiB;IAC7C,KAAK,CAAC,OAAO,CAAC,EAAU,EAAE,IAAmB;QAChD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC5B,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,KAAK,CAAC,8BAA8B,CAAC,CAAC;QACjE,OAAO,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC1C,CAAC;IAEM,OAAO,CAAC,EAAU,EAAE,IAAmB,EAAE,OAAe;QAC3D,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,SAAS,EAAE,KAAK,CAAC,kDAAkD,CAAC,CAAC;QAC/F,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC/C,CAAC;CACJ;AAED;;;;GAIG;AACH,MAAM,OAAO,sBAAuB,SAAQ,iBAAiB;IAsDzD,YACqB,OAAgC,EAChC,MAAwB,EACxB,YAAqB,EACrB,YAAoB,EACpB,cAAuB;QAExC,KAAK,EAAE,CAAC;QANS,YAAO,GAAP,OAAO,CAAyB;QAChC,WAAM,GAAN,MAAM,CAAkB;QACxB,iBAAY,GAAZ,YAAY,CAAS;QACrB,iBAAY,GAAZ,YAAY,CAAQ;QACpB,mBAAc,GAAd,cAAc,CAAS;QA9ClC,sBAAiB,GAAG,KAAK,CAAC;QAE1B,iBAAY,GAAG,IAAI,GAAG,EAA2B,CAAC;IA+C5D,CAAC;IA7CD,MAAM,CAAC,IAAI,CACP,OAAgC,EAChC,MAAwB,EACxB,YAAY,GAAG,iBAAiB,EAAE,EAClC,YAAY,GAAG,CAAC;;QAEhB,IAAI,OAAO,YAAY,sBAAsB,EAAE;YAC3C,OAAO,OAAO,CAAC;SAClB;QACD,kFAAkF;QAClF,4FAA4F;QAC5F,wDAAwD;QACxD,MAAM,WAAW,SAAG,OAAO,CAAC,QAAQ,0CAAE,WAAW,CAAC;QAClD,OAAO,IAAI,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;IAChG,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,QAAuB;QAC/C,MAAM,SAAS,GAAG,IAAI,wBAAwB,EAAE,CAAC;QACjD,MAAM,SAAS,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACjD,CAAC;IAED,IAAW,QAAQ;QACf,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;QACvC,IAAI,QAAQ,EAAE;YACV,uCAAY,QAAQ,KAAE,WAAW,EAAE,SAAS,IAAG;SAClD;IACL,CAAC;IAEM,KAAK,CAAC,cAAc,CAAC,QAAuB;QAC/C,8FAA8F;QAC9F,qCAAqC;QACrC,6DAA6D;QAE7D,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAC9B,MAAM,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAC5C,CAAC;IAYM,OAAO,CAAC,EAAU,EAAE,IAAmB,EAAE,OAAe;QAC3D,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,EAAE,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAChE,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,EAAU,EAAE,IAAmB;QAChD,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACrC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,SAAS,EAAE,0BAA0B,EAAE,EAAE,KAAK,CAAC,CAAC;YAC7E,MAAM,KAAK,CAAC;QAChB,CAAC,CAAC,CAAC;IACP,CAAC;IAED,IAAW,aAAa,KAAK,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC;IAC1D,KAAK,CAAC,WAAW,CAAC,SAAwB,EAAE,KAAa;QAC5D,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACtD,CAAC;IAEM,KAAK,CAAC,eAAe,CAAC,MAAsB;QAC/C,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAED,sEAAsE;IAC/D,KAAK,CAAC,KAAK,CAAC,IAAW,EAAE,OAAiB,EAAE,OAAe,EAAE,GAAW;QAC3E,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;IAC3D,CAAC;IAED,wFAAwF;IACxF,yBAAyB;IAClB,KAAK,CAAC,UAAU,CAAC,IAAqB;QACzC,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC;IAEM,KAAK,CAAC,eAAe,CAAC,OAAkB;QAC3C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QACzD,IAAI,IAAI,EAAE;YACN,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;SACnC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IAEM,KAAK,CAAC,QAAQ,CAAC,EAAU;QAC5B,IAAI,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,EAAE;YAC1B,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;SACpC;QACD,iEAAiE;QACjE,6FAA6F;QAC7F,oGAAoG;QACpG,uCAAuC;QAEvC,mGAAmG;QACnG,eAAe;QACf,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE,KAAK,CAAC,0BAA0B,CAAC,CAAC;QACjE,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACvC,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,KAAK,CAAC,8BAA8B,CAAC,CAAC;QACjE,OAAO,IAAI,CAAC;IAChB,CAAC;IAEM,KAAK,CAAC,wBAAwB,CAAC,OAAqB,EAAE,OAAwB;QACjF,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QACxF,OAAO,IAAI,CAAC,OAAO,CAAC,wBAAwB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACtE,CAAC;IAED,qCAAqC;IACrC,8DAA8D;IAC9D,8GAA8G;IAC9G,mCAAmC;IACnC,gHAAgH;IAChH,yEAAyE;IACzE,QAAQ;IACR,+GAA+G;IAC/G,8GAA8G;IAC9G,+GAA+G;IAC/G,mHAAmH;IACnH,mDAAmD;IAC3C,KAAK,CAAC,kBAAkB,CAC5B,OAAqB,EACrB,IAAI,GAAG,EAAE,EACT,KAAK,GAAG,CAAC,EACT,aAA8B;QAE9B,IAAI,IAAI,CAAC,cAAc,KAAK,SAAS,IAAI,IAAI,CAAC,cAAc,GAAG,CAAC,EAAE;YAC9D,OAAO,OAAO,CAAC;SAClB;QAED,IAAI,cAAc,GAAY,KAAK,CAAC;QAEpC,IAAI,UAAU,GAAG,aAAa,CAAC;QAC/B,+EAA+E;QAC/E,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE;YAClD,MAAM,CAAC,UAAU,KAAK,SAAS,EAAE,KAAK,CAAC,iCAAiC,CAAC,CAAC;YAC1E,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,6CAA6C,CAAC,CAAC;YACzF,UAAU,GAAG,IAAI,cAAc,EAAE,CAAC;YAClC,cAAc,GAAG,IAAI,CAAC;SACzB;aAAM;YACH,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,6CAA6C,CAAC,CAAC;SAC5F;QAED,MAAM,UAAU,qBAAqB,OAAO,CAAC,CAAC;QAC9C,UAAU,CAAC,IAAI,qBAAQ,UAAU,CAAC,IAAI,CAAC,CAAC;QACxC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;YACzC,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC9B,oEAAoE;YACpE,MAAM,OAAO,GAAG,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC;YACxD,QAAQ,GAAG,CAAC,IAAI,EAAE;gBACd;oBACI,8CAA8C;oBAC9C,uEAAuE;oBACvE,IAAI,GAAG,CAAC,IAAI,KAAK,EAAE,IAAI,GAAG,KAAK,UAAU,EAAE;wBACvC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,GAAG,CAAC,EAAE,UAAU,CAAC,CAAC;wBAChF,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;wBAC5B,IAAI,IAAI,CAAC,IAAI,KAAK,EAAE,EAAE;4BAClB,gEAAgE;4BAChE,OAAO,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;yBAC/B;qBACJ;oBACD,MAAM;gBACV;oBACI,IAAI,UAAU,IAAI,OAAO,GAAG,CAAC,OAAO,IAAI,QAAQ,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE;wBAC1F,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;wBACzC,gEAAgE;wBAChE,OAAO,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;qBAC/B;oBACD,MAAM;gBACV,mBAAuB,CAAC,CAAC;oBACrB,oBAAoB;oBACpB,yBAAyB;oBACzB,2EAA2E;oBAC3E,wFAAwF;oBACxF,IAAI,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC;oBAC5B,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;wBAC5B,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;qBACrC;oBACD,2EAA2E;oBAC3E,MAAM,CAAC,KAAK,KAAK,CAAC,EAAE,KAAK,CAAC,iCAAiC,CAAC,CAAC;oBAC7D,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EACjC,KAAK,CAAC,sDAAsD,CAAC,CAAC;oBAClE,MAAM;iBACT;gBACD;oBACI,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,oCAAoC,CAAC,CAAC;oBACjF,MAAM;gBACV;oBACI,eAAe,CAAC,GAAG,EAAE,iBAAkB,GAAW,CAAC,IAAI,EAAE,CAAC,CAAC;aAClE;SACJ;QAED,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,KAAK,SAAS,EAAE,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACvG,IAAI,cAAc,EAAE;YAChB,yFAAyF;YACzF,4FAA4F;YAC5F,qGAAqG;YACrG,iEAAiE;YACjE,+CAA+C;YAC/C,MAAM,CAAC,UAAU,KAAK,SAAS,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAC;YAC5D,MAAM,OAAO,GAAG,UAAU,CAAC,wBAAwB,EAAE,CAAC;YACtD,IAAI,OAAO,KAAK,SAAS,EAAE;gBACvB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,GAAG;oBACvC,IAAI,cAAkB;oBACtB,OAAO;iBACV,CAAC;aACL;SACJ;QACD,OAAO,UAAU,CAAC;IACtB,CAAC;IAES,eAAe,CAAC,EAAU;QAChC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAChD,CAAC;;AArOD,4FAA4F;AAC5F,8BAA8B;AAC9B,uGAAuG;AACvG,yGAAyG;AACzG,4FAA4F;AAC5F,qGAAqG;AACrG,oGAAoG;AACpG,mCAAmC;AACnC,yGAAyG;AACzG,mFAAmF;AACnE,6CAAsB,GAAG,IAAI,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n IDocumentStorageService,\n IDocumentStorageServicePolicies,\n ISummaryContext,\n} from \"@fluidframework/driver-definitions\";\nimport {\n ICreateBlobResponse,\n ISnapshotTree,\n ISummaryHandle,\n ISummaryTree,\n IVersion,\n SummaryType,\n ITree,\n} from \"@fluidframework/protocol-definitions\";\nimport {\n assert,\n bufferToString,\n stringToBuffer,\n unreachableCase,\n fromUtf8ToBase64,\n Uint8ArrayToString,\n } from \"@fluidframework/common-utils\";\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\n\n// Gate that when flipped, instructs to compress small blobs.\n// We have to first ship with this gate off, such that we can get to saturation bits\n// that can understand compressed format. And only after that flip it.\nfunction gatesAllowPacking() {\n try {\n // Leave override for testing purposes\n // eslint-disable-next-line no-null/no-null\n if (typeof localStorage === \"object\" && localStorage !== null) {\n if (localStorage.FluidAggregateBlobs === \"1\") {\n return true;\n }\n if (localStorage.FluidAggregateBlobs === \"0\") {\n return false;\n }\n }\n } catch (e) {}\n\n // We are starting disabled.\n return false;\n}\n\n/*\n * Work around for bufferToString having a bug - it can't consume IsoBuffer!\n * To be removed once bufferToString is fixed!\n*/\nfunction bufferToString2(blob: ArrayBufferLike, encoding: \"utf-8\" | \"base64\"): string {\n if (blob instanceof Uint8Array) { // IsoBuffer does not have ctor, so it's not in proto chain :(\n return Uint8ArrayToString(blob, encoding);\n }\n return bufferToString(blob, encoding);\n}\n\n /**\n * Class responsible for aggregating smaller blobs into one and unpacking it later on.\n */\nclass BlobAggregator {\n private readonly content: [string, string][]= [];\n\n public addBlob(key: string, content: string) {\n this.content.push([key, content]);\n }\n\n public getAggregatedBlobContent() {\n if (this.content.length === 0) {\n return undefined;\n }\n return JSON.stringify(this.content);\n }\n\n static load(input: ArrayBufferLike) {\n const data = bufferToString2(input, \"utf-8\");\n return JSON.parse(data) as [string, string][];\n }\n}\n\n/*\n * Base class that deals with unpacking snapshots (in place) containing aggregated blobs\n * It relies on abstract methods for reads and storing unpacked blobs.\n */\nexport abstract class SnapshotExtractor {\n protected readonly aggregatedBlobName = \"__big\";\n protected readonly virtualIdPrefix = \"__\";\n\n // counter for generation of virtual storage IDs\n protected virtualIdCounter = 0;\n protected getNextVirtualId() {\n return `${this.virtualIdPrefix}${++this.virtualIdCounter}`;\n }\n\n abstract getBlob(id: string, tree: ISnapshotTree): Promise<ArrayBufferLike>;\n abstract setBlob(id: string, tree: ISnapshotTree, content: string);\n\n public async unpackSnapshotCore(snapshot: ISnapshotTree, level = 0): Promise<void> {\n for (const key of Object.keys(snapshot.trees)) {\n const obj = snapshot.trees[key];\n await this.unpackSnapshotCore(obj, level + 1);\n }\n\n // For future proof, we will support multiple aggregated blobs with any name\n // that starts with this.aggregatedBlobName\n for (const key of Object.keys(snapshot.blobs)) {\n if (!key.startsWith(this.aggregatedBlobName)) { continue; }\n const blobId = snapshot.blobs[key];\n if (blobId !== undefined) {\n const blob = await this.getBlob(blobId, snapshot);\n for (const [path, value] of BlobAggregator.load(blob)) {\n const id = this.getNextVirtualId();\n this.setBlob(id, snapshot, value);\n const pathSplit = path.split(\"/\");\n let subTree = snapshot;\n for (const subPath of pathSplit.slice(0, pathSplit.length - 1)) {\n if (subTree.trees[subPath] === undefined) {\n subTree.trees[subPath] = { blobs: {}, commits: {}, trees: {}};\n }\n subTree = subTree.trees[subPath];\n }\n const blobName = pathSplit[pathSplit.length - 1];\n assert(subTree.blobs[blobName] === undefined, 0x0f6 /* \"real blob ID exists\" */);\n subTree.blobs[blobName] = id;\n }\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete snapshot.blobs[this.aggregatedBlobName];\n }\n }\n }\n}\n\n/*\n * Snapshot extractor class that works in place, i.e. patches snapshot that has\n * blob content in ISnapshotTree.blobs itself, not in storage.\n * As result, it implements reading and writing of blobs to/from snapshot itself.\n * It follows existing pattern that mixes concerns - ISnapshotTree.blobs is used for two\n * purposes:\n * 1. map path name to blob ID\n * 2. map blob ID to blob content\n * #2 is what storage (IDocumentStorageService) is for, but in places where we do not have it\n * (like loading serialized earlier draft content), blob content is put directly into snapshot.\n * Ideally this should be fixed by using BlobCacheStorageService or something similar and\n * fixing existing flows to allow switching of storage.\n */\nclass SnapshotExtractorInPlace extends SnapshotExtractor {\n public async getBlob(id: string, tree: ISnapshotTree): Promise<ArrayBufferLike> {\n const blob = tree.blobs[id];\n assert(blob !== undefined, 0x0f7 /* \"aggregate blob missing\" */);\n return stringToBuffer(blob, \"base64\");\n }\n\n public setBlob(id: string, tree: ISnapshotTree, content: string) {\n assert(tree.blobs[id] === undefined, 0x0f8 /* \"blob from aggregate blob exists on its own\" */);\n tree.blobs[id] = fromUtf8ToBase64(content);\n }\n}\n\n/*\n * Snapshot packer and extractor.\n * When summary is written it will find and aggregate small blobs into bigger blobs\n * When snapshot is read, it will unpack aggregated blobs and provide them transparently to caller.\n */\nexport class BlobAggregationStorage extends SnapshotExtractor implements IDocumentStorageService {\n // Tells data store if it can use incremental summary (i.e. reuse DDSs from previous summary\n // when only one DDS changed).\n // The answer has to be know long before we enable actual packing. The reason for the is the following:\n // A the moment when we enable packing, we should assume that all clients out there wil already have bits\n // that can unpack properly (i.e. enough time passed since we deployed bits that can unpack)\n // But we can still have clients where some of them already pack, and some do not. If one summary was\n // using packing, then it relies on non-incremental summaries going forward, even if next client who\n // produced summary is not packing!\n // This can have slight improvement by enabling it per file (based on \"did summary we loaded from contain\n // aggregated blobs\"), but that's harder to make reliable, so going for simplicity.\n static readonly fullDataStoreSummaries = true;\n\n protected loadedFromSummary = false;\n\n protected virtualBlobs = new Map<string, ArrayBufferLike>();\n\n static wrap(\n storage: IDocumentStorageService,\n logger: ITelemetryLogger,\n allowPacking = gatesAllowPacking(),\n packingLevel = 2,\n ) {\n if (storage instanceof BlobAggregationStorage) {\n return storage;\n }\n // Always create BlobAggregationStorage even if storage is not asking for packing.\n // This is mostly to avoid cases where future changes in policy would result in inability to\n // load old files that were created with aggregation on.\n const minBlobSize = storage.policies?.minBlobSize;\n return new BlobAggregationStorage(storage, logger, allowPacking, packingLevel, minBlobSize);\n }\n\n static async unpackSnapshot(snapshot: ISnapshotTree) {\n const converter = new SnapshotExtractorInPlace();\n await converter.unpackSnapshotCore(snapshot);\n }\n\n public get policies(): IDocumentStorageServicePolicies | undefined {\n const policies = this.storage.policies;\n if (policies) {\n return { ...policies, minBlobSize: undefined };\n }\n }\n\n public async unpackSnapshot(snapshot: ISnapshotTree) {\n // SummarizerNodeWithGC.refreshLatestSummary can call it when this.loadedFromSummary === false\n // (I assumed after file was created)\n // assert(!this.loadedFromSummary, \"unpack without summary\");\n\n this.loadedFromSummary = true;\n await this.unpackSnapshotCore(snapshot);\n }\n\n protected constructor(\n private readonly storage: IDocumentStorageService,\n private readonly logger: ITelemetryLogger,\n private readonly allowPacking: boolean,\n private readonly packingLevel: number,\n private readonly blobCutOffSize?: number)\n {\n super();\n }\n\n public setBlob(id: string, tree: ISnapshotTree, content: string) {\n this.virtualBlobs.set(id, stringToBuffer(content, \"utf-8\"));\n }\n\n public async getBlob(id: string, tree: ISnapshotTree): Promise<ArrayBufferLike> {\n return this.readBlob(id).catch((error) => {\n this.logger.sendErrorEvent({ eventName: \"BlobDedupNoAggregateBlob\" }, error);\n throw error;\n });\n }\n\n public get repositoryUrl() { return this.storage.repositoryUrl; }\n public async getVersions(versionId: string | null, count: number) {\n return this.storage.getVersions(versionId, count);\n }\n\n public async downloadSummary(handle: ISummaryHandle): Promise<ISummaryTree> {\n throw new Error(\"NYI\");\n }\n\n // This is only used through Container.snapshot() for testing purposes\n public async write(root: ITree, parents: string[], message: string, ref: string) {\n return this.storage.write(root, parents, message, ref);\n }\n\n // for now we are not optimizing these blobs, with assumption that this API is used only\n // for big blobs (images)\n public async createBlob(file: ArrayBufferLike): Promise<ICreateBlobResponse> {\n return this.storage.createBlob(file);\n }\n\n public async getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null> {\n const tree = await this.storage.getSnapshotTree(version);\n if (tree) {\n await this.unpackSnapshot(tree);\n }\n return tree;\n }\n\n public async readBlob(id: string): Promise<ArrayBufferLike> {\n if (this.isRealStorageId(id)) {\n return this.storage.readBlob(id);\n }\n // We support only reading blobs from the summary we loaded from.\n // This may need to be extended to any general summary in the future as runtime usage pattern\n // of storage changes (for example, data stores start to load from recent summary, not from original\n // summary whole container loaded from)\n\n // are there other ways we can get here? createFile is one flow, but we should not be reading blobs\n // in such flow\n assert(this.loadedFromSummary, 0x0f9 /* \"never read summary\" */);\n const blob = this.virtualBlobs.get(id);\n assert(blob !== undefined, 0x0fa /* \"virtual blob not found\" */);\n return blob;\n }\n\n public async uploadSummaryWithContext(summary: ISummaryTree, context: ISummaryContext): Promise<string> {\n const summaryNew = this.allowPacking ? await this.compressSmallBlobs(summary) : summary;\n return this.storage.uploadSummaryWithContext(summaryNew, context);\n }\n\n // For simplification, we assume that\n // - blob aggregation is done at data store level only for now\n // - data store either reuses previous summary, or generates full summary, i.e. there is no partial (some DDS)\n // summary produced by data stores.\n // These simplifications allow us not to touch handles, as they are self-contained (either do not use aggregated\n // blob Or contain aggregated blob that stays relevant for that sub-tree)\n // Note:\n // From perf perspective, it makes sense to place aggregated blobs one level up in the tree not to create extra\n // tree nodes (i.e. have shallow tree with less edges). But that creates problems with reusability of trees at\n // incremental summary time - we would need to understand handles and parse them. In current design we can skip\n // that step because if data store is reused, the hole sub-tree is reused included aggregated blob embedded into it\n // and that means we can do nothing and be correct!\n private async compressSmallBlobs(\n summary: ISummaryTree,\n path = \"\",\n level = 0,\n aggregatorArg?: BlobAggregator): Promise<ISummaryTree>\n {\n if (this.blobCutOffSize === undefined || this.blobCutOffSize < 0) {\n return summary;\n }\n\n let shouldCompress: boolean = false;\n\n let aggregator = aggregatorArg;\n // checking if this is a dataStore tree, since we only pack at data store level\n if (Object.keys(summary.tree).includes(\".component\")) {\n assert(aggregator === undefined, 0x0fb /* \"logic err with aggregator\" */);\n assert(level === this.packingLevel, 0x23b /* \"we are not packing at the right level\" */);\n aggregator = new BlobAggregator();\n shouldCompress = true;\n } else {\n assert(level !== this.packingLevel, 0x23c /* \"we are not packing at the right level\" */);\n }\n\n const newSummary: ISummaryTree = {...summary};\n newSummary.tree = { ...newSummary.tree};\n for (const key of Object.keys(summary.tree)) {\n const obj = summary.tree[key];\n // Get path relative to root of data store (where we do aggregation)\n const newPath = shouldCompress ? key : `${path}/${key}`;\n switch (obj.type) {\n case SummaryType.Tree:\n // If client created empty tree, keep it as is\n // Also do not package search blobs - they are part of storage contract\n if (obj.tree !== {} && key !== \"__search\") {\n const tree = await this.compressSmallBlobs(obj, newPath, level + 1, aggregator);\n newSummary.tree[key] = tree;\n if (tree.tree === {}) {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete newSummary.tree[key];\n }\n }\n break;\n case SummaryType.Blob:\n if (aggregator && typeof obj.content == \"string\" && obj.content.length < this.blobCutOffSize) {\n aggregator.addBlob(newPath, obj.content);\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete newSummary.tree[key];\n }\n break;\n case SummaryType.Handle: {\n // Would be nice to:\n // Trees: expand the tree\n // Blobs: parse handle and ensure it points to real blob, not virtual blob.\n // We can avoid it for now given data store is the granularity of incremental summaries.\n let handlePath = obj.handle;\n if (handlePath.startsWith(\"/\")) {\n handlePath = handlePath.substr(1);\n }\n // Ensure only whole data stores can be reused, no reusing at deeper level!\n assert(level === 0, 0x0fc /* \"tree reuse at lower level\" */);\n assert(handlePath.indexOf(\"/\") === -1,\n 0x0fd /* \"data stores are writing incremental summaries!\" */);\n break;\n }\n case SummaryType.Attachment:\n assert(this.isRealStorageId(obj.id), 0x0fe /* \"attachment is aggregate blob\" */);\n break;\n default:\n unreachableCase(obj, `Unknown type: ${(obj as any).type}`);\n }\n }\n\n assert(newSummary.tree[this.aggregatedBlobName] === undefined, 0x0ff /* \"duplicate aggregate blob\" */);\n if (shouldCompress) {\n // Note: It would be great to add code here to unpack aggregate blob back to normal blobs\n // If only one blob made it into aggregate. Currently that does not happen as we always have\n // at least one .component blob and at least one DDS that has .attributes blob, so it's not an issue.\n // But it's possible that in future that would be great addition!\n // Good news - it's backward compatible change.\n assert(aggregator !== undefined, 0x100 /* \"logic error\" */);\n const content = aggregator.getAggregatedBlobContent();\n if (content !== undefined) {\n newSummary.tree[this.aggregatedBlobName] = {\n type: SummaryType.Blob,\n content,\n };\n }\n }\n return newSummary;\n }\n\n protected isRealStorageId(id: string): boolean {\n return !id.startsWith(this.virtualIdPrefix);\n }\n}\n"]}
1
+ {"version":3,"file":"blobAggregationStorage.js","sourceRoot":"","sources":["../src/blobAggregationStorage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,EAMH,WAAW,GAEd,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EACH,MAAM,EACN,cAAc,EACd,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,kBAAkB,GACpB,MAAM,8BAA8B,CAAC;AAGvC,6DAA6D;AAC7D,oFAAoF;AACpF,sEAAsE;AACtE,SAAS,iBAAiB;IACtB,IAAI;QACA,sCAAsC;QACtC,2CAA2C;QAC3C,IAAI,OAAO,YAAY,KAAK,QAAQ,IAAI,YAAY,KAAK,IAAI,EAAE;YAC3D,IAAK,YAAY,CAAC,mBAAmB,KAAK,GAAG,EAAE;gBAC3C,OAAO,IAAI,CAAC;aACf;YACD,IAAK,YAAY,CAAC,mBAAmB,KAAK,GAAG,EAAE;gBAC3C,OAAO,KAAK,CAAC;aAChB;SACJ;KACJ;IAAC,OAAO,CAAC,EAAE,GAAE;IAEd,4BAA4B;IAC5B,OAAO,KAAK,CAAC;AACjB,CAAC;AAED;;;EAGE;AACF,SAAS,eAAe,CAAC,IAAqB,EAAE,QAA4B;IACxE,IAAI,IAAI,YAAY,UAAU,EAAE,EAAE,8DAA8D;QAC5F,OAAO,kBAAkB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;KAC7C;IACD,OAAO,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC1C,CAAC;AAEA;;GAEG;AACJ,MAAM,cAAc;IAApB;QACqB,YAAO,GAAsB,EAAE,CAAC;IAiBrD,CAAC;IAfU,OAAO,CAAC,GAAW,EAAE,OAAe;QACvC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;IACtC,CAAC;IAEM,wBAAwB;QAC3B,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;YAC3B,OAAO,SAAS,CAAC;SACpB;QACD,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,KAAsB;QAC9B,MAAM,IAAI,GAAG,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC7C,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAuB,CAAC;IAClD,CAAC;CACJ;AAED;;;GAGG;AACH,MAAM,OAAgB,iBAAiB;IAAvC;QACuB,uBAAkB,GAAG,OAAO,CAAC;QAC7B,oBAAe,GAAG,IAAI,CAAC;QAE1C,gDAAgD;QACtC,qBAAgB,GAAG,CAAC,CAAC;IAyCnC,CAAC;IAxCa,gBAAgB;QACtB,OAAO,GAAG,IAAI,CAAC,eAAe,GAAG,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC;IAC/D,CAAC;IAKM,KAAK,CAAC,kBAAkB,CAAC,QAAuB,EAAE,KAAK,GAAG,CAAC;QAC9D,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE;YAC3C,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAChC,MAAM,IAAI,CAAC,kBAAkB,CAAC,GAAG,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;SACjD;QAED,4EAA4E;QAC5E,2CAA2C;QAC3C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE;YAC3C,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAE;gBAAE,SAAS;aAAE;YAC3D,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACnC,IAAI,MAAM,KAAK,SAAS,EAAE;gBACtB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;gBAClD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;oBACnD,MAAM,EAAE,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;oBACnC,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;oBAClC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;oBAClC,IAAI,OAAO,GAAG,QAAQ,CAAC;oBACvB,KAAK,MAAM,OAAO,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE;wBAC5D,IAAI,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,SAAS,EAAE;4BACtC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAC,CAAC;yBACjE;wBACD,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;qBACpC;oBACD,MAAM,QAAQ,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;oBACjD,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,SAAS,EAAE,KAAK,CAAC,2BAA2B,CAAC,CAAC;oBACjF,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;iBAChC;gBACD,gEAAgE;gBAChE,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;aAClD;SACJ;IACL,CAAC;CACJ;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,wBAAyB,SAAQ,iBAAiB;IAC7C,KAAK,CAAC,OAAO,CAAC,EAAU,EAAE,IAAmB;QAChD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC5B,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,KAAK,CAAC,8BAA8B,CAAC,CAAC;QACjE,OAAO,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC1C,CAAC;IAEM,OAAO,CAAC,EAAU,EAAE,IAAmB,EAAE,OAAe;QAC3D,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,SAAS,EAAE,KAAK,CAAC,kDAAkD,CAAC,CAAC;QAC/F,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC/C,CAAC;CACJ;AAED;;;;GAIG;AACH,MAAM,OAAO,sBAAuB,SAAQ,iBAAiB;IAsDzD,YACqB,OAAgC,EAChC,MAAwB,EACxB,YAAqB,EACrB,YAAoB,EACpB,cAAuB;QAExC,KAAK,EAAE,CAAC;QANS,YAAO,GAAP,OAAO,CAAyB;QAChC,WAAM,GAAN,MAAM,CAAkB;QACxB,iBAAY,GAAZ,YAAY,CAAS;QACrB,iBAAY,GAAZ,YAAY,CAAQ;QACpB,mBAAc,GAAd,cAAc,CAAS;QA9ClC,sBAAiB,GAAG,KAAK,CAAC;QAE1B,iBAAY,GAAG,IAAI,GAAG,EAA2B,CAAC;IA+C5D,CAAC;IA7CD,MAAM,CAAC,IAAI,CACP,OAAgC,EAChC,MAAwB,EACxB,YAAY,GAAG,iBAAiB,EAAE,EAClC,YAAY,GAAG,CAAC;;QAEhB,IAAI,OAAO,YAAY,sBAAsB,EAAE;YAC3C,OAAO,OAAO,CAAC;SAClB;QACD,kFAAkF;QAClF,4FAA4F;QAC5F,wDAAwD;QACxD,MAAM,WAAW,SAAG,OAAO,CAAC,QAAQ,0CAAE,WAAW,CAAC;QAClD,OAAO,IAAI,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;IAChG,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,QAAuB;QAC/C,MAAM,SAAS,GAAG,IAAI,wBAAwB,EAAE,CAAC;QACjD,MAAM,SAAS,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACjD,CAAC;IAED,IAAW,QAAQ;QACf,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;QACvC,IAAI,QAAQ,EAAE;YACV,uCAAY,QAAQ,KAAE,WAAW,EAAE,SAAS,IAAG;SAClD;IACL,CAAC;IAEM,KAAK,CAAC,cAAc,CAAC,QAAuB;QAC/C,8FAA8F;QAC9F,qCAAqC;QACrC,6DAA6D;QAE7D,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAC9B,MAAM,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAC5C,CAAC;IAYM,OAAO,CAAC,EAAU,EAAE,IAAmB,EAAE,OAAe;QAC3D,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,EAAE,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAChE,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,EAAU,EAAE,IAAmB;QAChD,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACrC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,SAAS,EAAE,0BAA0B,EAAE,EAAE,KAAK,CAAC,CAAC;YAC7E,MAAM,KAAK,CAAC;QAChB,CAAC,CAAC,CAAC;IACP,CAAC;IAED,IAAW,aAAa,KAAK,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC;IAC1D,KAAK,CAAC,WAAW,CAAC,SAAwB,EAAE,KAAa;QAC5D,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACtD,CAAC;IAEM,KAAK,CAAC,eAAe,CAAC,MAAsB;QAC/C,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAED,sEAAsE;IAC/D,KAAK,CAAC,KAAK,CAAC,IAAW,EAAE,OAAiB,EAAE,OAAe,EAAE,GAAW;QAC3E,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;IAC3D,CAAC;IAED,wFAAwF;IACxF,yBAAyB;IAClB,KAAK,CAAC,UAAU,CAAC,IAAqB;QACzC,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC;IAEM,KAAK,CAAC,eAAe,CAAC,OAAkB;QAC3C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QACzD,IAAI,IAAI,EAAE;YACN,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;SACnC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IAEM,KAAK,CAAC,QAAQ,CAAC,EAAU;QAC5B,IAAI,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,EAAE;YAC1B,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;SACpC;QACD,iEAAiE;QACjE,6FAA6F;QAC7F,oGAAoG;QACpG,uCAAuC;QAEvC,mGAAmG;QACnG,eAAe;QACf,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE,KAAK,CAAC,0BAA0B,CAAC,CAAC;QACjE,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACvC,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,KAAK,CAAC,8BAA8B,CAAC,CAAC;QACjE,OAAO,IAAI,CAAC;IAChB,CAAC;IAEM,KAAK,CAAC,wBAAwB,CAAC,OAAqB,EAAE,OAAwB;QACjF,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QACxF,OAAO,IAAI,CAAC,OAAO,CAAC,wBAAwB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACtE,CAAC;IAED,qCAAqC;IACrC,8DAA8D;IAC9D,8GAA8G;IAC9G,mCAAmC;IACnC,gHAAgH;IAChH,yEAAyE;IACzE,QAAQ;IACR,+GAA+G;IAC/G,8GAA8G;IAC9G,+GAA+G;IAC/G,mHAAmH;IACnH,mDAAmD;IAC3C,KAAK,CAAC,kBAAkB,CAC5B,OAAqB,EACrB,IAAI,GAAG,EAAE,EACT,KAAK,GAAG,CAAC,EACT,aAA8B;QAE9B,IAAI,IAAI,CAAC,cAAc,KAAK,SAAS,IAAI,IAAI,CAAC,cAAc,GAAG,CAAC,EAAE;YAC9D,OAAO,OAAO,CAAC;SAClB;QAED,IAAI,cAAc,GAAY,KAAK,CAAC;QAEpC,IAAI,UAAU,GAAG,aAAa,CAAC;QAC/B,+EAA+E;QAC/E,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE;YAClD,MAAM,CAAC,UAAU,KAAK,SAAS,EAAE,KAAK,CAAC,iCAAiC,CAAC,CAAC;YAC1E,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,6CAA6C,CAAC,CAAC;YACzF,UAAU,GAAG,IAAI,cAAc,EAAE,CAAC;YAClC,cAAc,GAAG,IAAI,CAAC;SACzB;aAAM;YACH,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,6CAA6C,CAAC,CAAC;SAC5F;QAED,MAAM,UAAU,qBAAqB,OAAO,CAAC,CAAC;QAC9C,UAAU,CAAC,IAAI,qBAAQ,UAAU,CAAC,IAAI,CAAC,CAAC;QACxC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;YACzC,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC9B,oEAAoE;YACpE,MAAM,OAAO,GAAG,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC;YACxD,QAAQ,GAAG,CAAC,IAAI,EAAE;gBACd,KAAK,WAAW,CAAC,IAAI;oBACjB,8CAA8C;oBAC9C,uEAAuE;oBACvE,IAAI,GAAG,CAAC,IAAI,KAAK,EAAE,IAAI,GAAG,KAAK,UAAU,EAAE;wBACvC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,GAAG,CAAC,EAAE,UAAU,CAAC,CAAC;wBAChF,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;wBAC5B,IAAI,IAAI,CAAC,IAAI,KAAK,EAAE,EAAE;4BAClB,gEAAgE;4BAChE,OAAO,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;yBAC/B;qBACJ;oBACD,MAAM;gBACV,KAAK,WAAW,CAAC,IAAI;oBACjB,IAAI,UAAU,IAAI,OAAO,GAAG,CAAC,OAAO,IAAI,QAAQ,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE;wBAC1F,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;wBACzC,gEAAgE;wBAChE,OAAO,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;qBAC/B;oBACD,MAAM;gBACV,KAAK,WAAW,CAAC,MAAM,CAAC,CAAC;oBACrB,oBAAoB;oBACpB,yBAAyB;oBACzB,2EAA2E;oBAC3E,wFAAwF;oBACxF,IAAI,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC;oBAC5B,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;wBAC5B,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;qBACrC;oBACD,2EAA2E;oBAC3E,MAAM,CAAC,KAAK,KAAK,CAAC,EAAE,KAAK,CAAC,iCAAiC,CAAC,CAAC;oBAC7D,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EACjC,KAAK,CAAC,sDAAsD,CAAC,CAAC;oBAClE,MAAM;iBACT;gBACD,KAAK,WAAW,CAAC,UAAU;oBACvB,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,oCAAoC,CAAC,CAAC;oBACjF,MAAM;gBACV;oBACI,eAAe,CAAC,GAAG,EAAE,iBAAkB,GAAW,CAAC,IAAI,EAAE,CAAC,CAAC;aAClE;SACJ;QAED,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,KAAK,SAAS,EAAE,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACvG,IAAI,cAAc,EAAE;YAChB,yFAAyF;YACzF,4FAA4F;YAC5F,qGAAqG;YACrG,iEAAiE;YACjE,+CAA+C;YAC/C,MAAM,CAAC,UAAU,KAAK,SAAS,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAC;YAC5D,MAAM,OAAO,GAAG,UAAU,CAAC,wBAAwB,EAAE,CAAC;YACtD,IAAI,OAAO,KAAK,SAAS,EAAE;gBACvB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,GAAG;oBACvC,IAAI,EAAE,WAAW,CAAC,IAAI;oBACtB,OAAO;iBACV,CAAC;aACL;SACJ;QACD,OAAO,UAAU,CAAC;IACtB,CAAC;IAES,eAAe,CAAC,EAAU;QAChC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAChD,CAAC;;AArOD,4FAA4F;AAC5F,8BAA8B;AAC9B,uGAAuG;AACvG,yGAAyG;AACzG,4FAA4F;AAC5F,qGAAqG;AACrG,oGAAoG;AACpG,mCAAmC;AACnC,yGAAyG;AACzG,mFAAmF;AACnE,6CAAsB,GAAG,IAAI,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n IDocumentStorageService,\n IDocumentStorageServicePolicies,\n ISummaryContext,\n} from \"@fluidframework/driver-definitions\";\nimport {\n ICreateBlobResponse,\n ISnapshotTree,\n ISummaryHandle,\n ISummaryTree,\n IVersion,\n SummaryType,\n ITree,\n} from \"@fluidframework/protocol-definitions\";\nimport {\n assert,\n bufferToString,\n stringToBuffer,\n unreachableCase,\n fromUtf8ToBase64,\n Uint8ArrayToString,\n } from \"@fluidframework/common-utils\";\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\n\n// Gate that when flipped, instructs to compress small blobs.\n// We have to first ship with this gate off, such that we can get to saturation bits\n// that can understand compressed format. And only after that flip it.\nfunction gatesAllowPacking() {\n try {\n // Leave override for testing purposes\n // eslint-disable-next-line no-null/no-null\n if (typeof localStorage === \"object\" && localStorage !== null) {\n if (localStorage.FluidAggregateBlobs === \"1\") {\n return true;\n }\n if (localStorage.FluidAggregateBlobs === \"0\") {\n return false;\n }\n }\n } catch (e) {}\n\n // We are starting disabled.\n return false;\n}\n\n/*\n * Work around for bufferToString having a bug - it can't consume IsoBuffer!\n * To be removed once bufferToString is fixed!\n*/\nfunction bufferToString2(blob: ArrayBufferLike, encoding: \"utf-8\" | \"base64\"): string {\n if (blob instanceof Uint8Array) { // IsoBuffer does not have ctor, so it's not in proto chain :(\n return Uint8ArrayToString(blob, encoding);\n }\n return bufferToString(blob, encoding);\n}\n\n /**\n * Class responsible for aggregating smaller blobs into one and unpacking it later on.\n */\nclass BlobAggregator {\n private readonly content: [string, string][]= [];\n\n public addBlob(key: string, content: string) {\n this.content.push([key, content]);\n }\n\n public getAggregatedBlobContent() {\n if (this.content.length === 0) {\n return undefined;\n }\n return JSON.stringify(this.content);\n }\n\n static load(input: ArrayBufferLike) {\n const data = bufferToString2(input, \"utf-8\");\n return JSON.parse(data) as [string, string][];\n }\n}\n\n/*\n * Base class that deals with unpacking snapshots (in place) containing aggregated blobs\n * It relies on abstract methods for reads and storing unpacked blobs.\n */\nexport abstract class SnapshotExtractor {\n protected readonly aggregatedBlobName = \"__big\";\n protected readonly virtualIdPrefix = \"__\";\n\n // counter for generation of virtual storage IDs\n protected virtualIdCounter = 0;\n protected getNextVirtualId() {\n return `${this.virtualIdPrefix}${++this.virtualIdCounter}`;\n }\n\n abstract getBlob(id: string, tree: ISnapshotTree): Promise<ArrayBufferLike>;\n abstract setBlob(id: string, tree: ISnapshotTree, content: string);\n\n public async unpackSnapshotCore(snapshot: ISnapshotTree, level = 0): Promise<void> {\n for (const key of Object.keys(snapshot.trees)) {\n const obj = snapshot.trees[key];\n await this.unpackSnapshotCore(obj, level + 1);\n }\n\n // For future proof, we will support multiple aggregated blobs with any name\n // that starts with this.aggregatedBlobName\n for (const key of Object.keys(snapshot.blobs)) {\n if (!key.startsWith(this.aggregatedBlobName)) { continue; }\n const blobId = snapshot.blobs[key];\n if (blobId !== undefined) {\n const blob = await this.getBlob(blobId, snapshot);\n for (const [path, value] of BlobAggregator.load(blob)) {\n const id = this.getNextVirtualId();\n this.setBlob(id, snapshot, value);\n const pathSplit = path.split(\"/\");\n let subTree = snapshot;\n for (const subPath of pathSplit.slice(0, pathSplit.length - 1)) {\n if (subTree.trees[subPath] === undefined) {\n subTree.trees[subPath] = { blobs: {}, commits: {}, trees: {}};\n }\n subTree = subTree.trees[subPath];\n }\n const blobName = pathSplit[pathSplit.length - 1];\n assert(subTree.blobs[blobName] === undefined, 0x0f6 /* \"real blob ID exists\" */);\n subTree.blobs[blobName] = id;\n }\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete snapshot.blobs[this.aggregatedBlobName];\n }\n }\n }\n}\n\n/*\n * Snapshot extractor class that works in place, i.e. patches snapshot that has\n * blob content in ISnapshotTree.blobs itself, not in storage.\n * As result, it implements reading and writing of blobs to/from snapshot itself.\n * It follows existing pattern that mixes concerns - ISnapshotTree.blobs is used for two\n * purposes:\n * 1. map path name to blob ID\n * 2. map blob ID to blob content\n * #2 is what storage (IDocumentStorageService) is for, but in places where we do not have it\n * (like loading serialized earlier draft content), blob content is put directly into snapshot.\n * Ideally this should be fixed by using BlobCacheStorageService or something similar and\n * fixing existing flows to allow switching of storage.\n */\nclass SnapshotExtractorInPlace extends SnapshotExtractor {\n public async getBlob(id: string, tree: ISnapshotTree): Promise<ArrayBufferLike> {\n const blob = tree.blobs[id];\n assert(blob !== undefined, 0x0f7 /* \"aggregate blob missing\" */);\n return stringToBuffer(blob, \"base64\");\n }\n\n public setBlob(id: string, tree: ISnapshotTree, content: string) {\n assert(tree.blobs[id] === undefined, 0x0f8 /* \"blob from aggregate blob exists on its own\" */);\n tree.blobs[id] = fromUtf8ToBase64(content);\n }\n}\n\n/*\n * Snapshot packer and extractor.\n * When summary is written it will find and aggregate small blobs into bigger blobs\n * When snapshot is read, it will unpack aggregated blobs and provide them transparently to caller.\n */\nexport class BlobAggregationStorage extends SnapshotExtractor implements IDocumentStorageService {\n // Tells data store if it can use incremental summary (i.e. reuse DDSs from previous summary\n // when only one DDS changed).\n // The answer has to be know long before we enable actual packing. The reason for the is the following:\n // A the moment when we enable packing, we should assume that all clients out there wil already have bits\n // that can unpack properly (i.e. enough time passed since we deployed bits that can unpack)\n // But we can still have clients where some of them already pack, and some do not. If one summary was\n // using packing, then it relies on non-incremental summaries going forward, even if next client who\n // produced summary is not packing!\n // This can have slight improvement by enabling it per file (based on \"did summary we loaded from contain\n // aggregated blobs\"), but that's harder to make reliable, so going for simplicity.\n static readonly fullDataStoreSummaries = true;\n\n protected loadedFromSummary = false;\n\n protected virtualBlobs = new Map<string, ArrayBufferLike>();\n\n static wrap(\n storage: IDocumentStorageService,\n logger: ITelemetryLogger,\n allowPacking = gatesAllowPacking(),\n packingLevel = 2,\n ) {\n if (storage instanceof BlobAggregationStorage) {\n return storage;\n }\n // Always create BlobAggregationStorage even if storage is not asking for packing.\n // This is mostly to avoid cases where future changes in policy would result in inability to\n // load old files that were created with aggregation on.\n const minBlobSize = storage.policies?.minBlobSize;\n return new BlobAggregationStorage(storage, logger, allowPacking, packingLevel, minBlobSize);\n }\n\n static async unpackSnapshot(snapshot: ISnapshotTree) {\n const converter = new SnapshotExtractorInPlace();\n await converter.unpackSnapshotCore(snapshot);\n }\n\n public get policies(): IDocumentStorageServicePolicies | undefined {\n const policies = this.storage.policies;\n if (policies) {\n return { ...policies, minBlobSize: undefined };\n }\n }\n\n public async unpackSnapshot(snapshot: ISnapshotTree) {\n // SummarizerNodeWithGC.refreshLatestSummary can call it when this.loadedFromSummary === false\n // (I assumed after file was created)\n // assert(!this.loadedFromSummary, \"unpack without summary\");\n\n this.loadedFromSummary = true;\n await this.unpackSnapshotCore(snapshot);\n }\n\n protected constructor(\n private readonly storage: IDocumentStorageService,\n private readonly logger: ITelemetryLogger,\n private readonly allowPacking: boolean,\n private readonly packingLevel: number,\n private readonly blobCutOffSize?: number)\n {\n super();\n }\n\n public setBlob(id: string, tree: ISnapshotTree, content: string) {\n this.virtualBlobs.set(id, stringToBuffer(content, \"utf-8\"));\n }\n\n public async getBlob(id: string, tree: ISnapshotTree): Promise<ArrayBufferLike> {\n return this.readBlob(id).catch((error) => {\n this.logger.sendErrorEvent({ eventName: \"BlobDedupNoAggregateBlob\" }, error);\n throw error;\n });\n }\n\n public get repositoryUrl() { return this.storage.repositoryUrl; }\n public async getVersions(versionId: string | null, count: number) {\n return this.storage.getVersions(versionId, count);\n }\n\n public async downloadSummary(handle: ISummaryHandle): Promise<ISummaryTree> {\n throw new Error(\"NYI\");\n }\n\n // This is only used through Container.snapshot() for testing purposes\n public async write(root: ITree, parents: string[], message: string, ref: string) {\n return this.storage.write(root, parents, message, ref);\n }\n\n // for now we are not optimizing these blobs, with assumption that this API is used only\n // for big blobs (images)\n public async createBlob(file: ArrayBufferLike): Promise<ICreateBlobResponse> {\n return this.storage.createBlob(file);\n }\n\n public async getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null> {\n const tree = await this.storage.getSnapshotTree(version);\n if (tree) {\n await this.unpackSnapshot(tree);\n }\n return tree;\n }\n\n public async readBlob(id: string): Promise<ArrayBufferLike> {\n if (this.isRealStorageId(id)) {\n return this.storage.readBlob(id);\n }\n // We support only reading blobs from the summary we loaded from.\n // This may need to be extended to any general summary in the future as runtime usage pattern\n // of storage changes (for example, data stores start to load from recent summary, not from original\n // summary whole container loaded from)\n\n // are there other ways we can get here? createFile is one flow, but we should not be reading blobs\n // in such flow\n assert(this.loadedFromSummary, 0x0f9 /* \"never read summary\" */);\n const blob = this.virtualBlobs.get(id);\n assert(blob !== undefined, 0x0fa /* \"virtual blob not found\" */);\n return blob;\n }\n\n public async uploadSummaryWithContext(summary: ISummaryTree, context: ISummaryContext): Promise<string> {\n const summaryNew = this.allowPacking ? await this.compressSmallBlobs(summary) : summary;\n return this.storage.uploadSummaryWithContext(summaryNew, context);\n }\n\n // For simplification, we assume that\n // - blob aggregation is done at data store level only for now\n // - data store either reuses previous summary, or generates full summary, i.e. there is no partial (some DDS)\n // summary produced by data stores.\n // These simplifications allow us not to touch handles, as they are self-contained (either do not use aggregated\n // blob Or contain aggregated blob that stays relevant for that sub-tree)\n // Note:\n // From perf perspective, it makes sense to place aggregated blobs one level up in the tree not to create extra\n // tree nodes (i.e. have shallow tree with less edges). But that creates problems with reusability of trees at\n // incremental summary time - we would need to understand handles and parse them. In current design we can skip\n // that step because if data store is reused, the hole sub-tree is reused included aggregated blob embedded into it\n // and that means we can do nothing and be correct!\n private async compressSmallBlobs(\n summary: ISummaryTree,\n path = \"\",\n level = 0,\n aggregatorArg?: BlobAggregator): Promise<ISummaryTree>\n {\n if (this.blobCutOffSize === undefined || this.blobCutOffSize < 0) {\n return summary;\n }\n\n let shouldCompress: boolean = false;\n\n let aggregator = aggregatorArg;\n // checking if this is a dataStore tree, since we only pack at data store level\n if (Object.keys(summary.tree).includes(\".component\")) {\n assert(aggregator === undefined, 0x0fb /* \"logic err with aggregator\" */);\n assert(level === this.packingLevel, 0x23b /* \"we are not packing at the right level\" */);\n aggregator = new BlobAggregator();\n shouldCompress = true;\n } else {\n assert(level !== this.packingLevel, 0x23c /* \"we are not packing at the right level\" */);\n }\n\n const newSummary: ISummaryTree = {...summary};\n newSummary.tree = { ...newSummary.tree};\n for (const key of Object.keys(summary.tree)) {\n const obj = summary.tree[key];\n // Get path relative to root of data store (where we do aggregation)\n const newPath = shouldCompress ? key : `${path}/${key}`;\n switch (obj.type) {\n case SummaryType.Tree:\n // If client created empty tree, keep it as is\n // Also do not package search blobs - they are part of storage contract\n if (obj.tree !== {} && key !== \"__search\") {\n const tree = await this.compressSmallBlobs(obj, newPath, level + 1, aggregator);\n newSummary.tree[key] = tree;\n if (tree.tree === {}) {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete newSummary.tree[key];\n }\n }\n break;\n case SummaryType.Blob:\n if (aggregator && typeof obj.content == \"string\" && obj.content.length < this.blobCutOffSize) {\n aggregator.addBlob(newPath, obj.content);\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete newSummary.tree[key];\n }\n break;\n case SummaryType.Handle: {\n // Would be nice to:\n // Trees: expand the tree\n // Blobs: parse handle and ensure it points to real blob, not virtual blob.\n // We can avoid it for now given data store is the granularity of incremental summaries.\n let handlePath = obj.handle;\n if (handlePath.startsWith(\"/\")) {\n handlePath = handlePath.substr(1);\n }\n // Ensure only whole data stores can be reused, no reusing at deeper level!\n assert(level === 0, 0x0fc /* \"tree reuse at lower level\" */);\n assert(handlePath.indexOf(\"/\") === -1,\n 0x0fd /* \"data stores are writing incremental summaries!\" */);\n break;\n }\n case SummaryType.Attachment:\n assert(this.isRealStorageId(obj.id), 0x0fe /* \"attachment is aggregate blob\" */);\n break;\n default:\n unreachableCase(obj, `Unknown type: ${(obj as any).type}`);\n }\n }\n\n assert(newSummary.tree[this.aggregatedBlobName] === undefined, 0x0ff /* \"duplicate aggregate blob\" */);\n if (shouldCompress) {\n // Note: It would be great to add code here to unpack aggregate blob back to normal blobs\n // If only one blob made it into aggregate. Currently that does not happen as we always have\n // at least one .component blob and at least one DDS that has .attributes blob, so it's not an issue.\n // But it's possible that in future that would be great addition!\n // Good news - it's backward compatible change.\n assert(aggregator !== undefined, 0x100 /* \"logic error\" */);\n const content = aggregator.getAggregatedBlobContent();\n if (content !== undefined) {\n newSummary.tree[this.aggregatedBlobName] = {\n type: SummaryType.Blob,\n content,\n };\n }\n }\n return newSummary;\n }\n\n protected isRealStorageId(id: string): boolean {\n return !id.startsWith(this.virtualIdPrefix);\n }\n}\n"]}
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export declare const pkgName = "@fluidframework/driver-utils";
8
- export declare const pkgVersion = "0.51.3";
8
+ export declare const pkgVersion = "0.53.0-46105";
9
9
  //# sourceMappingURL=packageVersion.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,iCAAiC,CAAC;AACtD,eAAO,MAAM,UAAU,WAAW,CAAC"}
1
+ {"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,iCAAiC,CAAC;AACtD,eAAO,MAAM,UAAU,iBAAiB,CAAC"}
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export const pkgName = "@fluidframework/driver-utils";
8
- export const pkgVersion = "0.51.3";
8
+ export const pkgVersion = "0.53.0-46105";
9
9
  //# sourceMappingURL=packageVersion.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,8BAA8B,CAAC;AACtD,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/driver-utils\";\nexport const pkgVersion = \"0.51.3\";\n"]}
1
+ {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,8BAA8B,CAAC;AACtD,MAAM,CAAC,MAAM,UAAU,GAAG,cAAc,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/driver-utils\";\nexport const pkgVersion = \"0.53.0-46105\";\n"]}
@@ -57,7 +57,7 @@ export declare class Queue<T> implements IStream<T> {
57
57
  protected pushCore(value: Promise<IStreamResult<T>>): void;
58
58
  read(): Promise<IStreamResult<T>>;
59
59
  }
60
- export declare function requestOps(get: (from: number, to: number, telemetryProps: ITelemetryProperties) => Promise<IDeltasFetchResult>, concurrency: number, fromTotal: number, toTotal: number | undefined, payloadSize: number, logger: ITelemetryLogger, signal?: AbortSignal): IStream<ISequencedDocumentMessage[]>;
60
+ export declare function requestOps(get: (from: number, to: number, telemetryProps: ITelemetryProperties) => Promise<IDeltasFetchResult>, concurrency: number, fromTotal: number, toTotal: number | undefined, payloadSize: number, logger: ITelemetryLogger, signal?: AbortSignal, fetchReason?: string): IStream<ISequencedDocumentMessage[]>;
61
61
  export declare const emptyMessageStream: IStream<ISequencedDocumentMessage[]>;
62
62
  export declare function streamFromMessages(messagesArg: Promise<ISequencedDocumentMessage[]>): IStream<ISequencedDocumentMessage[]>;
63
63
  export declare function streamObserver<T>(stream: IStream<T>, handler: (value: IStreamResult<T>) => void): IStream<T>;
@@ -1 +1 @@
1
- {"version":3,"file":"parallelRequests.d.ts","sourceRoot":"","sources":["../src/parallelRequests.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parallelRequests.d.ts","sourceRoot":"","sources":["../src/parallelRequests.ts"],"names":[],"mappings":"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"}
@@ -302,7 +302,7 @@ export class Queue {
302
302
  * If false, returning less ops would mean we reached end of file.
303
303
  * @returns - an object with resulting ops and cancellation / partial result flags
304
304
  */
305
- async function getSingleOpBatch(get, props, strongTo, logger, signal) {
305
+ async function getSingleOpBatch(get, props, strongTo, logger, signal, fetchReason) {
306
306
  let lastSuccessTime;
307
307
  let retry = 0;
308
308
  const deltas = [];
@@ -338,7 +338,8 @@ async function getSingleOpBatch(get, props, strongTo, logger, signal) {
338
338
  const canRetry = canRetryOnError(error);
339
339
  lastSuccessTime = undefined;
340
340
  const retryAfter = getRetryDelayFromError(error);
341
- logNetworkFailure(logger, Object.assign(Object.assign({ eventName: "GetDeltas_Error" }, props), { retry, duration: performance.now() - startTime, retryAfter }), error);
341
+ logNetworkFailure(logger, Object.assign(Object.assign({ eventName: "GetDeltas_Error" }, props), { retry, duration: performance.now() - startTime, retryAfter,
342
+ fetchReason }), error);
342
343
  if (!canRetry) {
343
344
  // It's game over scenario.
344
345
  throw error;
@@ -351,7 +352,7 @@ async function getSingleOpBatch(get, props, strongTo, logger, signal) {
351
352
  }
352
353
  return nothing;
353
354
  }
354
- export function requestOps(get, concurrency, fromTotal, toTotal, payloadSize, logger, signal) {
355
+ export function requestOps(get, concurrency, fromTotal, toTotal, payloadSize, logger, signal, fetchReason) {
355
356
  let requests = 0;
356
357
  let lastFetch;
357
358
  let length = 0;
@@ -360,10 +361,10 @@ export function requestOps(get, concurrency, fromTotal, toTotal, payloadSize, lo
360
361
  fromTotal,
361
362
  toTotal,
362
363
  };
363
- const telemetryEvent = PerformanceEvent.start(logger, Object.assign({ eventName: "GetDeltas" }, propsTotal));
364
+ const telemetryEvent = PerformanceEvent.start(logger, Object.assign(Object.assign({ eventName: "GetDeltas" }, propsTotal), { fetchReason }));
364
365
  const manager = new ParallelRequests(fromTotal, toTotal, payloadSize, logger, async (request, from, to, strongTo, propsPerRequest) => {
365
366
  requests++;
366
- return getSingleOpBatch(async (propsAll) => get(from, to, propsAll), Object.assign(Object.assign({ request, from, to }, propsTotal), propsPerRequest), strongTo, logger, signal);
367
+ return getSingleOpBatch(async (propsAll) => get(from, to, propsAll), Object.assign(Object.assign({ request, from, to }, propsTotal), propsPerRequest), strongTo, logger, signal, fetchReason);
367
368
  }, (deltas) => {
368
369
  // Assert continuing and right start.
369
370
  if (lastFetch === undefined) {
@@ -1 +1 @@
1
- {"version":3,"file":"parallelRequests.js","sourceRoot":"","sources":["../src/parallelRequests.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 */\nimport { assert, Deferred, performance } from \"@fluidframework/common-utils\";\nimport { ITelemetryLogger, ITelemetryProperties } from \"@fluidframework/common-definitions\";\nimport { PerformanceEvent} from \"@fluidframework/telemetry-utils\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { IDeltasFetchResult, IStream, IStreamResult } from \"@fluidframework/driver-definitions\";\nimport { getRetryDelayFromError, canRetryOnError, createGenericNetworkError } from \"./network\";\nimport { waitForConnectedState, logNetworkFailure } from \"./networkUtils\";\n\nconst MaxFetchDelayInMs = 10000;\nconst MissingFetchDelayInMs = 100;\n\ntype WorkingState = \"working\" | \"done\" | \"canceled\";\n\n/**\n * Helper class to organize parallel fetching of data\n * It can be used to concurrently do many requests, while consuming\n * data in the right order. Take a look at UT for examples.\n * @param concurrency - level of concurrency\n * @param from - starting point of fetching data (inclusive)\n * @param to - ending point of fetching data. exclusive, or undefined if unknown\n * @param payloadSize - batch size\n * @param logger - logger to use\n * @param requestCallback - callback to request batches\n * @returns - Queue that can be used to retrieve data\n */\nexport class ParallelRequests<T> {\n private latestRequested: number;\n private nextToDeliver: number;\n private readonly results: Map<number, T[]> = new Map();\n private workingState: WorkingState = \"working\";\n private requestsInFlight = 0;\n private readonly endEvent = new Deferred<void>();\n private requests = 0;\n private readonly knewTo: boolean;\n\n private get working() { return this.workingState === \"working\"; }\n public get canceled() { return this.workingState === \"canceled\"; }\n\n constructor(\n from: number,\n private to: number | undefined,\n private readonly payloadSize: number,\n private readonly logger: ITelemetryLogger,\n private readonly requestCallback: (\n request: number,\n from: number,\n to: number,\n strongTo: boolean,\n props: ITelemetryProperties) => Promise<{ partial: boolean, cancel: boolean, payload: T[] }>,\n private readonly responseCallback: (payload: T[]) => void)\n {\n this.latestRequested = from;\n this.nextToDeliver = from;\n this.knewTo = (to !== undefined);\n }\n\n public cancel() {\n if (this.working) {\n this.workingState = \"canceled\";\n this.endEvent.resolve();\n }\n }\n\n public async run(concurrency: number) {\n assert(concurrency > 0, 0x102 /* \"invalid level of concurrency\" */);\n assert(this.working, 0x103 /* \"trying to parallel run while not working\" */);\n\n let c = concurrency;\n while (c > 0) {\n c--;\n this.addRequest();\n }\n this.dispatch();// will recalculate and trigger this.endEvent if needed\n return this.endEvent.promise;\n }\n\n private done() {\n // We should satisfy request fully.\n assert(this.to !== undefined, 0x104 /* \"undefined end point for parallel fetch\" */);\n assert(this.nextToDeliver >= this.to, 0x105 /* \"unexpected end point for parallel fetch\" */);\n if (this.working) {\n this.workingState = \"done\";\n this.endEvent.resolve();\n }\n }\n\n private fail(error) {\n if (this.working) {\n this.workingState = \"done\";\n this.endEvent.reject(error);\n }\n }\n\n private dispatch() {\n while (this.working) {\n const value = this.results.get(this.nextToDeliver);\n if (value === undefined) {\n break;\n }\n this.results.delete(this.nextToDeliver);\n assert(value.length <= this.payloadSize, 0x1d9 /* \"addRequestCore() should break into smaller chunks\" */);\n this.nextToDeliver += value.length;\n this.responseCallback(value);\n }\n\n // Account for cancellation - state might be not in consistent state on cancelling operation\n if (this.working) {\n if (this.requestsInFlight === 0) {\n // we should have dispatched everything, no matter whether we knew about the end or not.\n // see comment in addRequestCore() around throwing away chunk if it's above this.to\n assert(this.results.size === 0,\n 0x107 /* \"ending dispatch with remaining results to be sent\" */);\n this.done();\n } else if (this.to !== undefined && this.nextToDeliver >= this.to) {\n // Learned about the end and dispatched all the ops up to it.\n // Ignore all the in-flight requests above boundary - unblock caller sooner.\n assert(!this.knewTo, 0x108 /* \"ending results dispatch but knew in advance about more requests\" */);\n this.done();\n }\n }\n }\n\n private getNextChunk() {\n if (!this.working) {\n return undefined;\n }\n\n const from = this.latestRequested;\n if (this.to !== undefined) {\n if (this.to <= from) {\n return undefined;\n }\n }\n\n // this.latestRequested\n // inclusive on the right side! Exclusive on the left.\n this.latestRequested += this.payloadSize;\n\n if (this.to !== undefined) {\n this.latestRequested = Math.min(this.to, this.latestRequested);\n }\n\n assert(from < this.latestRequested, 0x109 /* \"unexpected next chunk position\" */);\n\n return { from, to: this.latestRequested};\n }\n\n private addRequest() {\n const chunk = this.getNextChunk();\n if (chunk === undefined) {\n return;\n }\n this.addRequestCore(chunk.from, chunk.to).catch(this.fail.bind(this));\n }\n\n private async addRequestCore(fromArg: number, toArg: number) {\n assert(this.working, 0x10a /* \"cannot add parallel request while not working\" */);\n\n let from = fromArg;\n let to = toArg;\n\n // to & from are exclusive\n this.requestsInFlight++;\n while (this.working) {\n const requestedLength = to - from;\n assert(requestedLength > 0, 0x10b /* \"invalid parallel request range\" */);\n\n // We should not be wasting time asking for something useless.\n if (this.to !== undefined) {\n assert(from < this.to, 0x10c /* \"invalid parallel request start point\" */);\n assert(to <= this.to, 0x10d /* \"invalid parallel request end point\" */);\n }\n\n this.requests++;\n\n const promise = this.requestCallback(this.requests, from, to, this.to !== undefined, {});\n\n // dispatch any prior received data\n this.dispatch();\n\n const { payload, cancel, partial } = await promise;\n\n if (cancel) {\n this.cancel();\n }\n\n if (this.to !== undefined && from >= this.to) {\n // while we were waiting for response, we learned on what is the boundary\n // We can get here (with actual result!) if situation changed while this request was in\n // flight, i.e. the end was extended over what we learn in some other request\n // While it's useful not to throw this result, this is very corner cases and makes logic\n // (including consistency checks) much harder to write correctly.\n // So for now, we are throwing this result out the window.\n assert(!this.knewTo, 0x10e /* \"should not throw result if we knew about boundary in advance\" */);\n // Learn how often it happens and if it's too wasteful to throw these chunks.\n // If it pops into our view a lot, we would need to reconsider how we approach it.\n // Note that this is not visible to user other than potentially not hitting 100% of\n // what we can in perf domain.\n if (payload.length !== 0) {\n this.logger.sendErrorEvent({\n eventName: \"ParallelRequests_GotExtra\",\n from,\n to,\n end: this.to,\n length: payload.length,\n });\n }\n\n break;\n }\n\n if (this.working) {\n const fromOrig = from;\n const length = payload.length;\n let fullChunk = (requestedLength <= length); // we can possible get more than we asked.\n\n if (length !== 0) {\n // We can get more than we asked for!\n // This can screw up logic in dispatch!\n // So push only batch size, and keep the rest for later - if conditions are favorable, we\n // will be able to use it. If not (parallel request overlapping these ops), it's easier to\n // discard them and wait for another (overlapping) request to come in later.\n if (requestedLength < length) {\n // This is error in a sense that it's not expected and likely points bug in other layer.\n // This layer copes with this situation just fine.\n this.logger.sendTelemetryEvent({\n eventName: \"ParallelRequests_Over\",\n from,\n to,\n length,\n });\n }\n const data = payload.splice(0, requestedLength);\n this.results.set(from, data);\n from += data.length;\n } else {\n // 1. empty (partial) chunks should not be returned by various caching / adapter layers -\n // they should fall back to next layer. This might be important invariant to hold to ensure\n // that we are less likely have bugs where such layer would keep returning empty partial\n // result on each call.\n // 2. Current invariant is that callback does retries until it gets something,\n // with the goal of failing if zero data is retrieved in given amount of time.\n // This is very specific property of storage / ops, so this logic is not here, but given only\n // one user of this class, we assert that to catch issues earlier.\n // These invariant can be relaxed if needed.\n assert(!partial, 0x10f /* \"empty/partial chunks should not be returned by caching\" */);\n assert(!this.knewTo,\n 0x110 /* \"callback should retry until valid fetch before it learns new boundary\" */);\n }\n\n if (!partial && !fullChunk) {\n if (!this.knewTo) {\n if (this.to === undefined || this.to > from) {\n // The END\n this.to = from;\n }\n break;\n }\n // We know that there are more items to be retrieved\n // Can we get partial chunk? Ideally storage indicates that's not a full chunk\n // Note that it's possible that not all ops hit storage yet.\n // We will come back to request more, and if we can't get any more ops soon, it's\n // catastrophic failure (see comment above on responsibility of callback to return something)\n // This layer will just keep trying until it gets full set.\n this.logger.sendPerformanceEvent({\n eventName: \"ParallelRequests_Partial\",\n from: fromOrig,\n to,\n length,\n });\n }\n\n if (to === this.latestRequested) {\n // we can go after full chunk at the end if we received partial chunk, or more than asked\n // Also if we got more than we asked to, we can actually use those ops!\n if (payload.length !== 0) {\n this.results.set(from, payload);\n from += payload.length;\n }\n\n this.latestRequested = from;\n fullChunk = true;\n }\n\n if (fullChunk) {\n const chunk = this.getNextChunk();\n if (chunk === undefined) { break; }\n from = chunk.from;\n to = chunk.to;\n }\n }\n }\n this.requestsInFlight--;\n this.dispatch();\n }\n}\n\n/**\n * Helper queue class to allow async push / pull\n * It's essentially a pipe allowing multiple writers, and single reader\n */\nexport class Queue<T> implements IStream<T> {\n private readonly queue: Promise<IStreamResult<T>>[] = [];\n private deferred: Deferred<IStreamResult<T>> | undefined;\n private done = false;\n\n public pushValue(value: T) {\n this.pushCore(Promise.resolve({ done: false, value }));\n }\n\n public pushError(error: any) {\n this.pushCore(Promise.reject(error));\n this.done = true;\n }\n\n public pushDone() {\n this.pushCore(Promise.resolve({ done: true }));\n this.done = true;\n }\n\n protected pushCore(value: Promise<IStreamResult<T>>) {\n assert(!this.done, 0x112 /* \"cannot push onto queue if done\" */);\n if (this.deferred) {\n assert(this.queue.length === 0, 0x113 /* \"deferred queue should be empty\" */);\n this.deferred.resolve(value);\n this.deferred = undefined;\n } else {\n this.queue.push(value);\n }\n }\n\n public async read(): Promise<IStreamResult<T>> {\n assert(this.deferred === undefined, 0x114 /* \"cannot pop if deferred\" */);\n const value = this.queue.shift();\n if (value !== undefined) {\n return value;\n }\n assert(!this.done, 0x115 /* \"queue should not be done during pop\" */);\n this.deferred = new Deferred<IStreamResult<T>>();\n return this.deferred.promise;\n }\n}\n\n/**\n * Retrieve single batch of ops\n * @param request - request index\n * @param from - inclusive boundary\n * @param to - exclusive boundary\n * @param telemetryEvent - telemetry event used to track consecutive batch of requests\n * @param strongTo - tells if ops in range from...to have to be there and have to be retrieved.\n * If false, returning less ops would mean we reached end of file.\n * @returns - an object with resulting ops and cancellation / partial result flags\n */\nasync function getSingleOpBatch(\n get: (telemetryProps: ITelemetryProperties) => Promise<IDeltasFetchResult>,\n props: ITelemetryProperties,\n strongTo: boolean,\n logger: ITelemetryLogger,\n signal?: AbortSignal):\n Promise<{ partial: boolean, cancel: boolean, payload: ISequencedDocumentMessage[] }>\n{\n let lastSuccessTime: number | undefined;\n\n let retry: number = 0;\n const deltas: ISequencedDocumentMessage[] = [];\n const nothing = { partial: false, cancel: true, payload: []};\n\n while (signal?.aborted !== true) {\n retry++;\n let delay = Math.min(MaxFetchDelayInMs, MissingFetchDelayInMs * Math.pow(2, retry));\n const startTime = performance.now();\n\n try {\n // Issue async request for deltas - limit the number fetched to MaxBatchDeltas\n const deltasP = get({ ...props, retry } /* telemetry props */);\n\n const { messages, partialResult } = await deltasP;\n deltas.push(...messages);\n\n const deltasRetrievedLast = messages.length;\n\n if (deltasRetrievedLast !== 0 || !strongTo) {\n return { payload: deltas, cancel: false, partial: partialResult};\n }\n\n // Storage does not have ops we need.\n // Attempt to fetch more deltas. If we didn't receive any in the previous call we up our retry\n // count since something prevented us from seeing those deltas\n\n if (lastSuccessTime === undefined) {\n lastSuccessTime = performance.now();\n } else if (performance.now() - lastSuccessTime > 30000) {\n // If we are connected and receiving proper responses from server, but can't get any ops back,\n // then give up after some time. This likely indicates the issue with ordering service not flushing\n // ops to storage quick enough, and possibly waiting for summaries, while summarizer can't get\n // current as it can't get ops.\n throw createGenericNetworkError(\n \"failedToRetrieveOpsFromStorage:TooManyRetries\",\n undefined,\n false /* canRetry */,\n undefined /* retryAfterSeconds */,\n {\n retry,\n ...props,\n },\n );\n }\n } catch (error) {\n const canRetry = canRetryOnError(error);\n\n lastSuccessTime = undefined;\n\n const retryAfter = getRetryDelayFromError(error);\n\n logNetworkFailure(\n logger,\n {\n eventName: \"GetDeltas_Error\",\n ...props,\n retry,\n duration: performance.now() - startTime,\n retryAfter,\n },\n error);\n\n if (!canRetry) {\n // It's game over scenario.\n throw error;\n }\n\n if (retryAfter !== undefined && retryAfter >= 0) {\n delay = retryAfter;\n }\n }\n\n await waitForConnectedState(delay);\n }\n\n return nothing;\n}\n\nexport function requestOps(\n get: (from: number, to: number, telemetryProps: ITelemetryProperties) => Promise<IDeltasFetchResult>,\n concurrency: number,\n fromTotal: number,\n toTotal: number | undefined,\n payloadSize: number,\n logger: ITelemetryLogger,\n signal?: AbortSignal,\n): IStream<ISequencedDocumentMessage[]> {\n let requests = 0;\n let lastFetch: number | undefined;\n let length = 0;\n const queue = new Queue<ISequencedDocumentMessage[]>();\n\n const propsTotal: ITelemetryProperties = {\n fromTotal,\n toTotal,\n };\n\n const telemetryEvent = PerformanceEvent.start(logger, {\n eventName: \"GetDeltas\",\n ...propsTotal,\n });\n\n const manager = new ParallelRequests<ISequencedDocumentMessage>(\n fromTotal,\n toTotal,\n payloadSize,\n logger,\n async (request: number, from: number, to: number, strongTo: boolean, propsPerRequest: ITelemetryProperties) => {\n requests++;\n return getSingleOpBatch(\n async (propsAll) => get(from, to, propsAll),\n { request, from, to, ...propsTotal, ...propsPerRequest },\n strongTo,\n logger,\n signal,\n );\n },\n (deltas: ISequencedDocumentMessage[]) => {\n // Assert continuing and right start.\n if (lastFetch === undefined) {\n assert(deltas[0].sequenceNumber === fromTotal, 0x26d /* \"wrong start\" */);\n } else {\n assert(deltas[0].sequenceNumber === lastFetch + 1, 0x26e /* \"wrong start\" */);\n }\n lastFetch = deltas[deltas.length - 1].sequenceNumber;\n assert(lastFetch - deltas[0].sequenceNumber + 1 === deltas.length,\n 0x26f /* \"continuous and no duplicates\" */);\n length += deltas.length;\n queue.pushValue(deltas);\n });\n\n // Implement faster cancellation. getSingleOpBatch() checks signal, but only in between\n // waits (up to 10 seconds) and fetches (can take infinite amount of time).\n // While every such case should be improved and take into account signal (and thus cancel immediately),\n // it is beneficial to have catch-all\n const listener = (event: Event) => { manager.cancel(); };\n if (signal !== undefined) {\n signal.addEventListener(\"abort\", listener);\n }\n\n manager.run(concurrency)\n .finally(() => {\n if (signal !== undefined) {\n signal.removeEventListener(\"abort\", listener);\n }\n }).then(() => {\n const props = {\n lastFetch,\n length,\n requests,\n };\n if (manager.canceled) {\n telemetryEvent.cancel({ ...props, error: \"ops request cancelled by client\" });\n } else {\n assert(toTotal === undefined || lastFetch !== undefined && lastFetch >= toTotal - 1,\n 0x270 /* \"All requested ops fetched\" */);\n telemetryEvent.end(props);\n }\n queue.pushDone();\n })\n .catch((error) => {\n telemetryEvent.cancel({\n lastFetch,\n length,\n requests,\n }, error);\n queue.pushError(error);\n });\n\n return queue;\n}\n\nexport const emptyMessageStream: IStream<ISequencedDocumentMessage[]> = {\n read: async () => { return { done: true };},\n};\n\nexport function streamFromMessages(messagesArg: Promise<ISequencedDocumentMessage[]>):\n IStream<ISequencedDocumentMessage[]>\n{\n let messages: Promise<ISequencedDocumentMessage[]> | undefined = messagesArg;\n return {\n read: async () => {\n if (messages === undefined) {\n return { done: true };\n }\n const value = await messages;\n messages = undefined;\n return value.length === 0 ? { done: true } : { done: false, value };\n },\n };\n}\n\n// eslint-disable-next-line prefer-arrow/prefer-arrow-functions\nexport function streamObserver<T>(stream: IStream<T>, handler: (value: IStreamResult<T>) => void): IStream<T> {\n return {\n read: async () => {\n const value = await stream.read();\n handler(value);\n return value;\n },\n };\n}\n"]}
1
+ {"version":3,"file":"parallelRequests.js","sourceRoot":"","sources":["../src/parallelRequests.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 */\nimport { assert, Deferred, performance } from \"@fluidframework/common-utils\";\nimport { ITelemetryLogger, ITelemetryProperties } from \"@fluidframework/common-definitions\";\nimport { PerformanceEvent} from \"@fluidframework/telemetry-utils\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { IDeltasFetchResult, IStream, IStreamResult } from \"@fluidframework/driver-definitions\";\nimport { getRetryDelayFromError, canRetryOnError, createGenericNetworkError } from \"./network\";\nimport { waitForConnectedState, logNetworkFailure } from \"./networkUtils\";\n\nconst MaxFetchDelayInMs = 10000;\nconst MissingFetchDelayInMs = 100;\n\ntype WorkingState = \"working\" | \"done\" | \"canceled\";\n\n/**\n * Helper class to organize parallel fetching of data\n * It can be used to concurrently do many requests, while consuming\n * data in the right order. Take a look at UT for examples.\n * @param concurrency - level of concurrency\n * @param from - starting point of fetching data (inclusive)\n * @param to - ending point of fetching data. exclusive, or undefined if unknown\n * @param payloadSize - batch size\n * @param logger - logger to use\n * @param requestCallback - callback to request batches\n * @returns - Queue that can be used to retrieve data\n */\nexport class ParallelRequests<T> {\n private latestRequested: number;\n private nextToDeliver: number;\n private readonly results: Map<number, T[]> = new Map();\n private workingState: WorkingState = \"working\";\n private requestsInFlight = 0;\n private readonly endEvent = new Deferred<void>();\n private requests = 0;\n private readonly knewTo: boolean;\n\n private get working() { return this.workingState === \"working\"; }\n public get canceled() { return this.workingState === \"canceled\"; }\n\n constructor(\n from: number,\n private to: number | undefined,\n private readonly payloadSize: number,\n private readonly logger: ITelemetryLogger,\n private readonly requestCallback: (\n request: number,\n from: number,\n to: number,\n strongTo: boolean,\n props: ITelemetryProperties) => Promise<{ partial: boolean, cancel: boolean, payload: T[] }>,\n private readonly responseCallback: (payload: T[]) => void)\n {\n this.latestRequested = from;\n this.nextToDeliver = from;\n this.knewTo = (to !== undefined);\n }\n\n public cancel() {\n if (this.working) {\n this.workingState = \"canceled\";\n this.endEvent.resolve();\n }\n }\n\n public async run(concurrency: number) {\n assert(concurrency > 0, 0x102 /* \"invalid level of concurrency\" */);\n assert(this.working, 0x103 /* \"trying to parallel run while not working\" */);\n\n let c = concurrency;\n while (c > 0) {\n c--;\n this.addRequest();\n }\n this.dispatch();// will recalculate and trigger this.endEvent if needed\n return this.endEvent.promise;\n }\n\n private done() {\n // We should satisfy request fully.\n assert(this.to !== undefined, 0x104 /* \"undefined end point for parallel fetch\" */);\n assert(this.nextToDeliver >= this.to, 0x105 /* \"unexpected end point for parallel fetch\" */);\n if (this.working) {\n this.workingState = \"done\";\n this.endEvent.resolve();\n }\n }\n\n private fail(error) {\n if (this.working) {\n this.workingState = \"done\";\n this.endEvent.reject(error);\n }\n }\n\n private dispatch() {\n while (this.working) {\n const value = this.results.get(this.nextToDeliver);\n if (value === undefined) {\n break;\n }\n this.results.delete(this.nextToDeliver);\n assert(value.length <= this.payloadSize, 0x1d9 /* \"addRequestCore() should break into smaller chunks\" */);\n this.nextToDeliver += value.length;\n this.responseCallback(value);\n }\n\n // Account for cancellation - state might be not in consistent state on cancelling operation\n if (this.working) {\n if (this.requestsInFlight === 0) {\n // we should have dispatched everything, no matter whether we knew about the end or not.\n // see comment in addRequestCore() around throwing away chunk if it's above this.to\n assert(this.results.size === 0,\n 0x107 /* \"ending dispatch with remaining results to be sent\" */);\n this.done();\n } else if (this.to !== undefined && this.nextToDeliver >= this.to) {\n // Learned about the end and dispatched all the ops up to it.\n // Ignore all the in-flight requests above boundary - unblock caller sooner.\n assert(!this.knewTo, 0x108 /* \"ending results dispatch but knew in advance about more requests\" */);\n this.done();\n }\n }\n }\n\n private getNextChunk() {\n if (!this.working) {\n return undefined;\n }\n\n const from = this.latestRequested;\n if (this.to !== undefined) {\n if (this.to <= from) {\n return undefined;\n }\n }\n\n // this.latestRequested\n // inclusive on the right side! Exclusive on the left.\n this.latestRequested += this.payloadSize;\n\n if (this.to !== undefined) {\n this.latestRequested = Math.min(this.to, this.latestRequested);\n }\n\n assert(from < this.latestRequested, 0x109 /* \"unexpected next chunk position\" */);\n\n return { from, to: this.latestRequested};\n }\n\n private addRequest() {\n const chunk = this.getNextChunk();\n if (chunk === undefined) {\n return;\n }\n this.addRequestCore(chunk.from, chunk.to).catch(this.fail.bind(this));\n }\n\n private async addRequestCore(fromArg: number, toArg: number) {\n assert(this.working, 0x10a /* \"cannot add parallel request while not working\" */);\n\n let from = fromArg;\n let to = toArg;\n\n // to & from are exclusive\n this.requestsInFlight++;\n while (this.working) {\n const requestedLength = to - from;\n assert(requestedLength > 0, 0x10b /* \"invalid parallel request range\" */);\n\n // We should not be wasting time asking for something useless.\n if (this.to !== undefined) {\n assert(from < this.to, 0x10c /* \"invalid parallel request start point\" */);\n assert(to <= this.to, 0x10d /* \"invalid parallel request end point\" */);\n }\n\n this.requests++;\n\n const promise = this.requestCallback(this.requests, from, to, this.to !== undefined, {});\n\n // dispatch any prior received data\n this.dispatch();\n\n const { payload, cancel, partial } = await promise;\n\n if (cancel) {\n this.cancel();\n }\n\n if (this.to !== undefined && from >= this.to) {\n // while we were waiting for response, we learned on what is the boundary\n // We can get here (with actual result!) if situation changed while this request was in\n // flight, i.e. the end was extended over what we learn in some other request\n // While it's useful not to throw this result, this is very corner cases and makes logic\n // (including consistency checks) much harder to write correctly.\n // So for now, we are throwing this result out the window.\n assert(!this.knewTo, 0x10e /* \"should not throw result if we knew about boundary in advance\" */);\n // Learn how often it happens and if it's too wasteful to throw these chunks.\n // If it pops into our view a lot, we would need to reconsider how we approach it.\n // Note that this is not visible to user other than potentially not hitting 100% of\n // what we can in perf domain.\n if (payload.length !== 0) {\n this.logger.sendErrorEvent({\n eventName: \"ParallelRequests_GotExtra\",\n from,\n to,\n end: this.to,\n length: payload.length,\n });\n }\n\n break;\n }\n\n if (this.working) {\n const fromOrig = from;\n const length = payload.length;\n let fullChunk = (requestedLength <= length); // we can possible get more than we asked.\n\n if (length !== 0) {\n // We can get more than we asked for!\n // This can screw up logic in dispatch!\n // So push only batch size, and keep the rest for later - if conditions are favorable, we\n // will be able to use it. If not (parallel request overlapping these ops), it's easier to\n // discard them and wait for another (overlapping) request to come in later.\n if (requestedLength < length) {\n // This is error in a sense that it's not expected and likely points bug in other layer.\n // This layer copes with this situation just fine.\n this.logger.sendTelemetryEvent({\n eventName: \"ParallelRequests_Over\",\n from,\n to,\n length,\n });\n }\n const data = payload.splice(0, requestedLength);\n this.results.set(from, data);\n from += data.length;\n } else {\n // 1. empty (partial) chunks should not be returned by various caching / adapter layers -\n // they should fall back to next layer. This might be important invariant to hold to ensure\n // that we are less likely have bugs where such layer would keep returning empty partial\n // result on each call.\n // 2. Current invariant is that callback does retries until it gets something,\n // with the goal of failing if zero data is retrieved in given amount of time.\n // This is very specific property of storage / ops, so this logic is not here, but given only\n // one user of this class, we assert that to catch issues earlier.\n // These invariant can be relaxed if needed.\n assert(!partial, 0x10f /* \"empty/partial chunks should not be returned by caching\" */);\n assert(!this.knewTo,\n 0x110 /* \"callback should retry until valid fetch before it learns new boundary\" */);\n }\n\n if (!partial && !fullChunk) {\n if (!this.knewTo) {\n if (this.to === undefined || this.to > from) {\n // The END\n this.to = from;\n }\n break;\n }\n // We know that there are more items to be retrieved\n // Can we get partial chunk? Ideally storage indicates that's not a full chunk\n // Note that it's possible that not all ops hit storage yet.\n // We will come back to request more, and if we can't get any more ops soon, it's\n // catastrophic failure (see comment above on responsibility of callback to return something)\n // This layer will just keep trying until it gets full set.\n this.logger.sendPerformanceEvent({\n eventName: \"ParallelRequests_Partial\",\n from: fromOrig,\n to,\n length,\n });\n }\n\n if (to === this.latestRequested) {\n // we can go after full chunk at the end if we received partial chunk, or more than asked\n // Also if we got more than we asked to, we can actually use those ops!\n if (payload.length !== 0) {\n this.results.set(from, payload);\n from += payload.length;\n }\n\n this.latestRequested = from;\n fullChunk = true;\n }\n\n if (fullChunk) {\n const chunk = this.getNextChunk();\n if (chunk === undefined) { break; }\n from = chunk.from;\n to = chunk.to;\n }\n }\n }\n this.requestsInFlight--;\n this.dispatch();\n }\n}\n\n/**\n * Helper queue class to allow async push / pull\n * It's essentially a pipe allowing multiple writers, and single reader\n */\nexport class Queue<T> implements IStream<T> {\n private readonly queue: Promise<IStreamResult<T>>[] = [];\n private deferred: Deferred<IStreamResult<T>> | undefined;\n private done = false;\n\n public pushValue(value: T) {\n this.pushCore(Promise.resolve({ done: false, value }));\n }\n\n public pushError(error: any) {\n this.pushCore(Promise.reject(error));\n this.done = true;\n }\n\n public pushDone() {\n this.pushCore(Promise.resolve({ done: true }));\n this.done = true;\n }\n\n protected pushCore(value: Promise<IStreamResult<T>>) {\n assert(!this.done, 0x112 /* \"cannot push onto queue if done\" */);\n if (this.deferred) {\n assert(this.queue.length === 0, 0x113 /* \"deferred queue should be empty\" */);\n this.deferred.resolve(value);\n this.deferred = undefined;\n } else {\n this.queue.push(value);\n }\n }\n\n public async read(): Promise<IStreamResult<T>> {\n assert(this.deferred === undefined, 0x114 /* \"cannot pop if deferred\" */);\n const value = this.queue.shift();\n if (value !== undefined) {\n return value;\n }\n assert(!this.done, 0x115 /* \"queue should not be done during pop\" */);\n this.deferred = new Deferred<IStreamResult<T>>();\n return this.deferred.promise;\n }\n}\n\n/**\n * Retrieve single batch of ops\n * @param request - request index\n * @param from - inclusive boundary\n * @param to - exclusive boundary\n * @param telemetryEvent - telemetry event used to track consecutive batch of requests\n * @param strongTo - tells if ops in range from...to have to be there and have to be retrieved.\n * If false, returning less ops would mean we reached end of file.\n * @returns - an object with resulting ops and cancellation / partial result flags\n */\nasync function getSingleOpBatch(\n get: (telemetryProps: ITelemetryProperties) => Promise<IDeltasFetchResult>,\n props: ITelemetryProperties,\n strongTo: boolean,\n logger: ITelemetryLogger,\n signal?: AbortSignal,\n fetchReason?: string):\n Promise<{ partial: boolean, cancel: boolean, payload: ISequencedDocumentMessage[] }>\n{\n let lastSuccessTime: number | undefined;\n\n let retry: number = 0;\n const deltas: ISequencedDocumentMessage[] = [];\n const nothing = { partial: false, cancel: true, payload: []};\n\n while (signal?.aborted !== true) {\n retry++;\n let delay = Math.min(MaxFetchDelayInMs, MissingFetchDelayInMs * Math.pow(2, retry));\n const startTime = performance.now();\n\n try {\n // Issue async request for deltas - limit the number fetched to MaxBatchDeltas\n const deltasP = get({ ...props, retry } /* telemetry props */);\n\n const { messages, partialResult } = await deltasP;\n deltas.push(...messages);\n\n const deltasRetrievedLast = messages.length;\n\n if (deltasRetrievedLast !== 0 || !strongTo) {\n return { payload: deltas, cancel: false, partial: partialResult};\n }\n\n // Storage does not have ops we need.\n // Attempt to fetch more deltas. If we didn't receive any in the previous call we up our retry\n // count since something prevented us from seeing those deltas\n\n if (lastSuccessTime === undefined) {\n lastSuccessTime = performance.now();\n } else if (performance.now() - lastSuccessTime > 30000) {\n // If we are connected and receiving proper responses from server, but can't get any ops back,\n // then give up after some time. This likely indicates the issue with ordering service not flushing\n // ops to storage quick enough, and possibly waiting for summaries, while summarizer can't get\n // current as it can't get ops.\n throw createGenericNetworkError(\n \"failedToRetrieveOpsFromStorage:TooManyRetries\",\n undefined,\n false /* canRetry */,\n undefined /* retryAfterSeconds */,\n {\n retry,\n ...props,\n },\n );\n }\n } catch (error) {\n const canRetry = canRetryOnError(error);\n\n lastSuccessTime = undefined;\n\n const retryAfter = getRetryDelayFromError(error);\n\n logNetworkFailure(\n logger,\n {\n eventName: \"GetDeltas_Error\",\n ...props,\n retry,\n duration: performance.now() - startTime,\n retryAfter,\n fetchReason,\n },\n error);\n\n if (!canRetry) {\n // It's game over scenario.\n throw error;\n }\n\n if (retryAfter !== undefined && retryAfter >= 0) {\n delay = retryAfter;\n }\n }\n\n await waitForConnectedState(delay);\n }\n\n return nothing;\n}\n\nexport function requestOps(\n get: (from: number, to: number, telemetryProps: ITelemetryProperties) => Promise<IDeltasFetchResult>,\n concurrency: number,\n fromTotal: number,\n toTotal: number | undefined,\n payloadSize: number,\n logger: ITelemetryLogger,\n signal?: AbortSignal,\n fetchReason?: string,\n): IStream<ISequencedDocumentMessage[]> {\n let requests = 0;\n let lastFetch: number | undefined;\n let length = 0;\n const queue = new Queue<ISequencedDocumentMessage[]>();\n\n const propsTotal: ITelemetryProperties = {\n fromTotal,\n toTotal,\n };\n\n const telemetryEvent = PerformanceEvent.start(logger, {\n eventName: \"GetDeltas\",\n ...propsTotal,\n fetchReason,\n });\n\n const manager = new ParallelRequests<ISequencedDocumentMessage>(\n fromTotal,\n toTotal,\n payloadSize,\n logger,\n async (request: number, from: number, to: number, strongTo: boolean, propsPerRequest: ITelemetryProperties) => {\n requests++;\n return getSingleOpBatch(\n async (propsAll) => get(from, to, propsAll),\n { request, from, to, ...propsTotal, ...propsPerRequest },\n strongTo,\n logger,\n signal,\n fetchReason,\n );\n },\n (deltas: ISequencedDocumentMessage[]) => {\n // Assert continuing and right start.\n if (lastFetch === undefined) {\n assert(deltas[0].sequenceNumber === fromTotal, 0x26d /* \"wrong start\" */);\n } else {\n assert(deltas[0].sequenceNumber === lastFetch + 1, 0x26e /* \"wrong start\" */);\n }\n lastFetch = deltas[deltas.length - 1].sequenceNumber;\n assert(lastFetch - deltas[0].sequenceNumber + 1 === deltas.length,\n 0x26f /* \"continuous and no duplicates\" */);\n length += deltas.length;\n queue.pushValue(deltas);\n });\n\n // Implement faster cancellation. getSingleOpBatch() checks signal, but only in between\n // waits (up to 10 seconds) and fetches (can take infinite amount of time).\n // While every such case should be improved and take into account signal (and thus cancel immediately),\n // it is beneficial to have catch-all\n const listener = (event: Event) => { manager.cancel(); };\n if (signal !== undefined) {\n signal.addEventListener(\"abort\", listener);\n }\n\n manager.run(concurrency)\n .finally(() => {\n if (signal !== undefined) {\n signal.removeEventListener(\"abort\", listener);\n }\n }).then(() => {\n const props = {\n lastFetch,\n length,\n requests,\n };\n if (manager.canceled) {\n telemetryEvent.cancel({ ...props, error: \"ops request cancelled by client\" });\n } else {\n assert(toTotal === undefined || lastFetch !== undefined && lastFetch >= toTotal - 1,\n 0x270 /* \"All requested ops fetched\" */);\n telemetryEvent.end(props);\n }\n queue.pushDone();\n })\n .catch((error) => {\n telemetryEvent.cancel({\n lastFetch,\n length,\n requests,\n }, error);\n queue.pushError(error);\n });\n\n return queue;\n}\n\nexport const emptyMessageStream: IStream<ISequencedDocumentMessage[]> = {\n read: async () => { return { done: true };},\n};\n\nexport function streamFromMessages(messagesArg: Promise<ISequencedDocumentMessage[]>):\n IStream<ISequencedDocumentMessage[]>\n{\n let messages: Promise<ISequencedDocumentMessage[]> | undefined = messagesArg;\n return {\n read: async () => {\n if (messages === undefined) {\n return { done: true };\n }\n const value = await messages;\n messages = undefined;\n return value.length === 0 ? { done: true } : { done: false, value };\n },\n };\n}\n\n// eslint-disable-next-line prefer-arrow/prefer-arrow-functions\nexport function streamObserver<T>(stream: IStream<T>, handler: (value: IStreamResult<T>) => void): IStream<T> {\n return {\n read: async () => {\n const value = await stream.read();\n handler(value);\n return value;\n },\n };\n}\n"]}
@@ -2,6 +2,7 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
+ import { SummaryType, } from "@fluidframework/protocol-definitions";
5
6
  /**
6
7
  * Combine the app summary and protocol summary in 1 tree.
7
8
  * @param appSummary - Summary of the app.
@@ -9,7 +10,7 @@
9
10
  */
10
11
  export function combineAppAndProtocolSummary(appSummary, protocolSummary) {
11
12
  const createNewSummary = {
12
- type: 1 /* Tree */,
13
+ type: SummaryType.Tree,
13
14
  tree: {
14
15
  ".protocol": protocolSummary,
15
16
  ".app": appSummary,
@@ -1 +1 @@
1
- {"version":3,"file":"summaryForCreateNew.js","sourceRoot":"","sources":["../src/summaryForCreateNew.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAUH;;;;GAIG;AACH,MAAM,UAAU,4BAA4B,CACxC,UAAwB,EACxB,eAA6B;IAE7B,MAAM,gBAAgB,GAAiB;QACnC,IAAI,cAAkB;QACtB,IAAI,EAAE;YACF,WAAW,EAAE,eAAe;YAC5B,MAAM,EAAE,UAAU;SACrB;KACJ,CAAC;IACF,OAAO,gBAAgB,CAAC;AAC5B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mCAAmC,CAC/C,eAA6B;;IAE7B,MAAM,cAAc,GAAG,eAAe,CAAC,IAAI,CAAC,UAA0B,CAAC;IACvE,MAAM,kBAAkB,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAiB,CAAwB,CAAC;IAC/F,kBAAkB,CAAC,IAAI,SAAG,kBAAkB,CAAC,IAAI,mCAAI,CAAC,CAAC;IACvD,OAAO,kBAAkB,CAAC;AAC9B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kCAAkC,CAC9C,eAA6B;IAE7B,MAAM,gBAAgB,GAAG,eAAe,CAAC,IAAI,CAAC,YAA4B,CAAC;IAC3E,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,OAAiB,CAAmC,CAAC;IACtG,OAAO,YAAY,CAAC;AACxB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n ISummaryTree,\n SummaryType,\n ISummaryBlob,\n ICommittedProposal,\n IDocumentAttributes,\n} from \"@fluidframework/protocol-definitions\";\n\n/**\n * Combine the app summary and protocol summary in 1 tree.\n * @param appSummary - Summary of the app.\n * @param protocolSummary - Summary of the protocol.\n */\nexport function combineAppAndProtocolSummary(\n appSummary: ISummaryTree,\n protocolSummary: ISummaryTree,\n): ISummaryTree {\n const createNewSummary: ISummaryTree = {\n type: SummaryType.Tree,\n tree: {\n \".protocol\": protocolSummary,\n \".app\": appSummary,\n },\n };\n return createNewSummary;\n}\n\n/**\n * Extract the attributes from the protocol summary.\n * @param protocolSummary - protocol summary from which the values are to be extracted.\n */\nexport function getDocAttributesFromProtocolSummary(\n protocolSummary: ISummaryTree,\n): IDocumentAttributes {\n const attributesBlob = protocolSummary.tree.attributes as ISummaryBlob;\n const documentAttributes = JSON.parse(attributesBlob.content as string) as IDocumentAttributes;\n documentAttributes.term = documentAttributes.term ?? 1;\n return documentAttributes;\n}\n\n/**\n * Extract quorum values from the protocol summary.\n * @param protocolSummary - protocol summary from which the values are to be extracted.\n */\nexport function getQuorumValuesFromProtocolSummary(\n protocolSummary: ISummaryTree,\n): [string, ICommittedProposal][] {\n const quorumValuesBlob = protocolSummary.tree.quorumValues as ISummaryBlob;\n const quorumValues = JSON.parse(quorumValuesBlob.content as string) as [string, ICommittedProposal][];\n return quorumValues;\n}\n"]}
1
+ {"version":3,"file":"summaryForCreateNew.js","sourceRoot":"","sources":["../src/summaryForCreateNew.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAEH,WAAW,GAId,MAAM,sCAAsC,CAAC;AAE9C;;;;GAIG;AACH,MAAM,UAAU,4BAA4B,CACxC,UAAwB,EACxB,eAA6B;IAE7B,MAAM,gBAAgB,GAAiB;QACnC,IAAI,EAAE,WAAW,CAAC,IAAI;QACtB,IAAI,EAAE;YACF,WAAW,EAAE,eAAe;YAC5B,MAAM,EAAE,UAAU;SACrB;KACJ,CAAC;IACF,OAAO,gBAAgB,CAAC;AAC5B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mCAAmC,CAC/C,eAA6B;;IAE7B,MAAM,cAAc,GAAG,eAAe,CAAC,IAAI,CAAC,UAA0B,CAAC;IACvE,MAAM,kBAAkB,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAiB,CAAwB,CAAC;IAC/F,kBAAkB,CAAC,IAAI,SAAG,kBAAkB,CAAC,IAAI,mCAAI,CAAC,CAAC;IACvD,OAAO,kBAAkB,CAAC;AAC9B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kCAAkC,CAC9C,eAA6B;IAE7B,MAAM,gBAAgB,GAAG,eAAe,CAAC,IAAI,CAAC,YAA4B,CAAC;IAC3E,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,OAAiB,CAAmC,CAAC;IACtG,OAAO,YAAY,CAAC;AACxB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n ISummaryTree,\n SummaryType,\n ISummaryBlob,\n ICommittedProposal,\n IDocumentAttributes,\n} from \"@fluidframework/protocol-definitions\";\n\n/**\n * Combine the app summary and protocol summary in 1 tree.\n * @param appSummary - Summary of the app.\n * @param protocolSummary - Summary of the protocol.\n */\nexport function combineAppAndProtocolSummary(\n appSummary: ISummaryTree,\n protocolSummary: ISummaryTree,\n): ISummaryTree {\n const createNewSummary: ISummaryTree = {\n type: SummaryType.Tree,\n tree: {\n \".protocol\": protocolSummary,\n \".app\": appSummary,\n },\n };\n return createNewSummary;\n}\n\n/**\n * Extract the attributes from the protocol summary.\n * @param protocolSummary - protocol summary from which the values are to be extracted.\n */\nexport function getDocAttributesFromProtocolSummary(\n protocolSummary: ISummaryTree,\n): IDocumentAttributes {\n const attributesBlob = protocolSummary.tree.attributes as ISummaryBlob;\n const documentAttributes = JSON.parse(attributesBlob.content as string) as IDocumentAttributes;\n documentAttributes.term = documentAttributes.term ?? 1;\n return documentAttributes;\n}\n\n/**\n * Extract quorum values from the protocol summary.\n * @param protocolSummary - protocol summary from which the values are to be extracted.\n */\nexport function getQuorumValuesFromProtocolSummary(\n protocolSummary: ISummaryTree,\n): [string, ICommittedProposal][] {\n const quorumValuesBlob = protocolSummary.tree.quorumValues as ISummaryBlob;\n const quorumValues = JSON.parse(quorumValuesBlob.content as string) as [string, ICommittedProposal][];\n return quorumValues;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/driver-utils",
3
- "version": "0.51.3",
3
+ "version": "0.53.0-46105",
4
4
  "description": "Collection of utility functions for Fluid drivers",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": "https://github.com/microsoft/FluidFramework",
@@ -57,20 +57,20 @@
57
57
  "dependencies": {
58
58
  "@fluidframework/common-definitions": "^0.20.1",
59
59
  "@fluidframework/common-utils": "^0.32.1",
60
- "@fluidframework/core-interfaces": "^0.40.0",
61
- "@fluidframework/driver-definitions": "^0.41.0",
62
- "@fluidframework/gitresources": "^0.1033.0",
63
- "@fluidframework/protocol-base": "^0.1033.0",
64
- "@fluidframework/protocol-definitions": "^0.1025.0",
65
- "@fluidframework/telemetry-utils": "^0.51.3",
66
- "axios": "^0.21.1",
60
+ "@fluidframework/core-interfaces": "^0.41.0",
61
+ "@fluidframework/driver-definitions": "^0.43.0-0",
62
+ "@fluidframework/gitresources": "^0.1034.0",
63
+ "@fluidframework/protocol-base": "^0.1034.0",
64
+ "@fluidframework/protocol-definitions": "^0.1026.0",
65
+ "@fluidframework/telemetry-utils": "0.53.0-46105",
66
+ "axios": "^0.21.2",
67
67
  "uuid": "^8.3.1"
68
68
  },
69
69
  "devDependencies": {
70
70
  "@fluidframework/build-common": "^0.23.0",
71
71
  "@fluidframework/eslint-config-fluid": "^0.24.0",
72
- "@fluidframework/mocha-test-setup": "^0.51.3",
73
- "@fluidframework/runtime-utils": "^0.51.3",
72
+ "@fluidframework/mocha-test-setup": "0.53.0-46105",
73
+ "@fluidframework/runtime-utils": "0.53.0-46105",
74
74
  "@microsoft/api-extractor": "^7.16.1",
75
75
  "@types/mocha": "^8.2.2",
76
76
  "@types/node": "^12.19.0",
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/driver-utils";
9
- export const pkgVersion = "0.51.3";
9
+ export const pkgVersion = "0.53.0-46105";
@@ -360,7 +360,8 @@ async function getSingleOpBatch(
360
360
  props: ITelemetryProperties,
361
361
  strongTo: boolean,
362
362
  logger: ITelemetryLogger,
363
- signal?: AbortSignal):
363
+ signal?: AbortSignal,
364
+ fetchReason?: string):
364
365
  Promise<{ partial: boolean, cancel: boolean, payload: ISequencedDocumentMessage[] }>
365
366
  {
366
367
  let lastSuccessTime: number | undefined;
@@ -424,6 +425,7 @@ async function getSingleOpBatch(
424
425
  retry,
425
426
  duration: performance.now() - startTime,
426
427
  retryAfter,
428
+ fetchReason,
427
429
  },
428
430
  error);
429
431
 
@@ -451,6 +453,7 @@ export function requestOps(
451
453
  payloadSize: number,
452
454
  logger: ITelemetryLogger,
453
455
  signal?: AbortSignal,
456
+ fetchReason?: string,
454
457
  ): IStream<ISequencedDocumentMessage[]> {
455
458
  let requests = 0;
456
459
  let lastFetch: number | undefined;
@@ -465,6 +468,7 @@ export function requestOps(
465
468
  const telemetryEvent = PerformanceEvent.start(logger, {
466
469
  eventName: "GetDeltas",
467
470
  ...propsTotal,
471
+ fetchReason,
468
472
  });
469
473
 
470
474
  const manager = new ParallelRequests<ISequencedDocumentMessage>(
@@ -480,6 +484,7 @@ export function requestOps(
480
484
  strongTo,
481
485
  logger,
482
486
  signal,
487
+ fetchReason,
483
488
  );
484
489
  },
485
490
  (deltas: ISequencedDocumentMessage[]) => {