@fluidframework/container-runtime 0.53.0-46105 → 0.54.1

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.
Files changed (98) hide show
  1. package/dist/containerRuntime.d.ts +25 -16
  2. package/dist/containerRuntime.d.ts.map +1 -1
  3. package/dist/containerRuntime.js +125 -77
  4. package/dist/containerRuntime.js.map +1 -1
  5. package/dist/dataStoreContext.d.ts +29 -3
  6. package/dist/dataStoreContext.d.ts.map +1 -1
  7. package/dist/dataStoreContext.js +29 -4
  8. package/dist/dataStoreContext.js.map +1 -1
  9. package/dist/dataStores.d.ts +7 -3
  10. package/dist/dataStores.d.ts.map +1 -1
  11. package/dist/dataStores.js +54 -5
  12. package/dist/dataStores.js.map +1 -1
  13. package/dist/garbageCollection.d.ts +22 -2
  14. package/dist/garbageCollection.d.ts.map +1 -1
  15. package/dist/garbageCollection.js +112 -34
  16. package/dist/garbageCollection.js.map +1 -1
  17. package/dist/packageVersion.d.ts +1 -1
  18. package/dist/packageVersion.d.ts.map +1 -1
  19. package/dist/packageVersion.js +1 -1
  20. package/dist/packageVersion.js.map +1 -1
  21. package/dist/runningSummarizer.d.ts +3 -2
  22. package/dist/runningSummarizer.d.ts.map +1 -1
  23. package/dist/runningSummarizer.js +6 -6
  24. package/dist/runningSummarizer.js.map +1 -1
  25. package/dist/summarizer.d.ts +22 -0
  26. package/dist/summarizer.d.ts.map +1 -1
  27. package/dist/summarizer.js +135 -33
  28. package/dist/summarizer.js.map +1 -1
  29. package/dist/summarizerTypes.d.ts +1 -8
  30. package/dist/summarizerTypes.d.ts.map +1 -1
  31. package/dist/summarizerTypes.js.map +1 -1
  32. package/dist/summaryFormat.d.ts +1 -0
  33. package/dist/summaryFormat.d.ts.map +1 -1
  34. package/dist/summaryFormat.js +2 -1
  35. package/dist/summaryFormat.js.map +1 -1
  36. package/dist/summaryManager.d.ts +0 -15
  37. package/dist/summaryManager.d.ts.map +1 -1
  38. package/dist/summaryManager.js +1 -35
  39. package/dist/summaryManager.js.map +1 -1
  40. package/lib/containerRuntime.d.ts +25 -16
  41. package/lib/containerRuntime.d.ts.map +1 -1
  42. package/lib/containerRuntime.js +131 -83
  43. package/lib/containerRuntime.js.map +1 -1
  44. package/lib/dataStoreContext.d.ts +29 -3
  45. package/lib/dataStoreContext.d.ts.map +1 -1
  46. package/lib/dataStoreContext.js +29 -4
  47. package/lib/dataStoreContext.js.map +1 -1
  48. package/lib/dataStores.d.ts +7 -3
  49. package/lib/dataStores.d.ts.map +1 -1
  50. package/lib/dataStores.js +54 -5
  51. package/lib/dataStores.js.map +1 -1
  52. package/lib/garbageCollection.d.ts +22 -2
  53. package/lib/garbageCollection.d.ts.map +1 -1
  54. package/lib/garbageCollection.js +114 -36
  55. package/lib/garbageCollection.js.map +1 -1
  56. package/lib/packageVersion.d.ts +1 -1
  57. package/lib/packageVersion.d.ts.map +1 -1
  58. package/lib/packageVersion.js +1 -1
  59. package/lib/packageVersion.js.map +1 -1
  60. package/lib/runningSummarizer.d.ts +3 -2
  61. package/lib/runningSummarizer.d.ts.map +1 -1
  62. package/lib/runningSummarizer.js +6 -6
  63. package/lib/runningSummarizer.js.map +1 -1
  64. package/lib/summarizer.d.ts +22 -0
  65. package/lib/summarizer.d.ts.map +1 -1
  66. package/lib/summarizer.js +135 -33
  67. package/lib/summarizer.js.map +1 -1
  68. package/lib/summarizerTypes.d.ts +1 -8
  69. package/lib/summarizerTypes.d.ts.map +1 -1
  70. package/lib/summarizerTypes.js.map +1 -1
  71. package/lib/summaryFormat.d.ts +1 -0
  72. package/lib/summaryFormat.d.ts.map +1 -1
  73. package/lib/summaryFormat.js +1 -0
  74. package/lib/summaryFormat.js.map +1 -1
  75. package/lib/summaryManager.d.ts +0 -15
  76. package/lib/summaryManager.d.ts.map +1 -1
  77. package/lib/summaryManager.js +1 -34
  78. package/lib/summaryManager.js.map +1 -1
  79. package/package.json +14 -14
  80. package/src/containerRuntime.ts +176 -93
  81. package/src/dataStoreContext.ts +44 -6
  82. package/src/dataStores.ts +84 -4
  83. package/src/garbageCollection.ts +137 -46
  84. package/src/packageVersion.ts +1 -1
  85. package/src/runningSummarizer.ts +12 -10
  86. package/src/summarizer.ts +154 -38
  87. package/src/summarizerTypes.ts +2 -9
  88. package/src/summaryFormat.ts +1 -0
  89. package/src/summaryManager.ts +2 -49
  90. package/dist/localStorageFeatureGates.d.ts +0 -13
  91. package/dist/localStorageFeatureGates.d.ts.map +0 -1
  92. package/dist/localStorageFeatureGates.js +0 -31
  93. package/dist/localStorageFeatureGates.js.map +0 -1
  94. package/lib/localStorageFeatureGates.d.ts +0 -13
  95. package/lib/localStorageFeatureGates.d.ts.map +0 -1
  96. package/lib/localStorageFeatureGates.js +0 -27
  97. package/lib/localStorageFeatureGates.js.map +0 -1
  98. package/src/localStorageFeatureGates.ts +0 -27
@@ -2,28 +2,28 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { AttachState, } from "@fluidframework/container-definitions";
5
+ import { AttachState, LoaderHeader, } from "@fluidframework/container-definitions";
6
6
  import { assert, Trace, TypedEventEmitter, unreachableCase, performance, } from "@fluidframework/common-utils";
7
- import { ChildLogger, raiseConnectedEvent, PerformanceEvent, normalizeError, TaggedLoggerAdapter, } from "@fluidframework/telemetry-utils";
7
+ import { ChildLogger, raiseConnectedEvent, PerformanceEvent, normalizeError, TaggedLoggerAdapter, loggerToMonitoringContext, } from "@fluidframework/telemetry-utils";
8
+ import { DriverHeader } from "@fluidframework/driver-definitions";
8
9
  import { readAndParse, BlobAggregationStorage } from "@fluidframework/driver-utils";
9
- import { DataCorruptionError, GenericError, extractSafePropertiesFromMessage } from "@fluidframework/container-utils";
10
+ import { CreateProcessingError, DataCorruptionError, GenericError, UsageError, extractSafePropertiesFromMessage, } from "@fluidframework/container-utils";
10
11
  import { MessageType, SummaryType, } from "@fluidframework/protocol-definitions";
11
12
  import { FlushMode, channelsTreeName, } from "@fluidframework/runtime-definitions";
12
- import { addBlobToSummary, addTreeToSummary, convertToSummaryTree, createRootSummarizerNodeWithGC, RequestParser, create404Response, exceptionToResponse, responseToException, seqFromTree, convertSummaryTreeToITree, } from "@fluidframework/runtime-utils";
13
+ import { addBlobToSummary, addTreeToSummary, convertToSummaryTree, createRootSummarizerNodeWithGC, RequestParser, create404Response, exceptionToResponse, requestFluidObject, responseToException, seqFromTree, convertSummaryTreeToITree, } from "@fluidframework/runtime-utils";
13
14
  import { v4 as uuid } from "uuid";
14
15
  import { ContainerFluidHandleContext } from "./containerHandleContext";
15
16
  import { FluidDataStoreRegistry } from "./dataStoreRegistry";
16
17
  import { Summarizer } from "./summarizer";
17
- import { formRequestSummarizerFn, SummaryManager } from "./summaryManager";
18
+ import { SummaryManager } from "./summaryManager";
18
19
  import { DeltaScheduler } from "./deltaScheduler";
19
20
  import { ReportOpPerfTelemetry, latencyThreshold } from "./connectionTelemetry";
20
21
  import { PendingStateManager } from "./pendingStateManager";
21
22
  import { pkgVersion } from "./packageVersion";
22
23
  import { BlobManager } from "./blobManager";
23
24
  import { DataStores, getSummaryForDatastores } from "./dataStores";
24
- import { blobsTreeName, chunksBlobName, electedSummarizerBlobName, extractSummaryMetadataMessage, metadataBlobName, wrapSummaryInChannelsTree, } from "./summaryFormat";
25
+ import { aliasBlobName, blobsTreeName, chunksBlobName, electedSummarizerBlobName, extractSummaryMetadataMessage, metadataBlobName, wrapSummaryInChannelsTree, } from "./summaryFormat";
25
26
  import { SummaryCollection } from "./summaryCollection";
26
- import { getLocalStorageFeatureGate } from "./localStorageFeatureGates";
27
27
  import { OrderedClientCollection, OrderedClientElection } from "./orderedClientElection";
28
28
  import { SummarizerClientElection, summarizerClientType } from "./summarizerClientElection";
29
29
  import { formExponentialFn, Throttler } from "./throttler";
@@ -41,6 +41,8 @@ export var ContainerMessageType;
41
41
  ContainerMessageType["BlobAttach"] = "blobAttach";
42
42
  // Ties our new clientId to our old one on reconnect
43
43
  ContainerMessageType["Rejoin"] = "rejoin";
44
+ // Sets the alias of a root data store
45
+ ContainerMessageType["Alias"] = "alias";
44
46
  })(ContainerMessageType || (ContainerMessageType = {}));
45
47
  // Consider idle 5s of no activity. And snapshot if a minute has gone by with no snapshot.
46
48
  const IdleDetectionTime = 5000;
@@ -55,12 +57,13 @@ const DefaultSummaryConfiguration = {
55
57
  maxAckWaitTime: 120000,
56
58
  };
57
59
  // Local storage key to set the default flush mode to TurnBased
58
- const turnBasedFlushModeKey = "FluidFlushModeTurnBased";
60
+ const turnBasedFlushModeKey = "Fluid.ContainerRuntime.FlushModeTurnBased";
59
61
  export function isRuntimeMessage(message) {
60
62
  switch (message.type) {
61
63
  case ContainerMessageType.FluidDataStoreOp:
62
64
  case ContainerMessageType.ChunkedOp:
63
65
  case ContainerMessageType.Attach:
66
+ case ContainerMessageType.Alias:
64
67
  case ContainerMessageType.BlobAttach:
65
68
  case ContainerMessageType.Rejoin:
66
69
  case MessageType.Operation:
@@ -324,8 +327,8 @@ export function getDeviceSpec() {
324
327
  * It will define the store level mappings.
325
328
  */
326
329
  export class ContainerRuntime extends TypedEventEmitter {
327
- constructor(context, registry, metadata, electedSummarizerData, chunks, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, requestHandler, _storage) {
328
- var _a, _b, _c, _d;
330
+ constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, requestHandler, _storage) {
331
+ var _a, _b, _c, _d, _e;
329
332
  super();
330
333
  this.context = context;
331
334
  this.registry = registry;
@@ -334,14 +337,7 @@ export class ContainerRuntime extends TypedEventEmitter {
334
337
  this.logger = logger;
335
338
  this.requestHandler = requestHandler;
336
339
  this._storage = _storage;
337
- // back-compat: Used by loader in <= 0.35
338
- /**
339
- * @internal
340
- * @deprecated Back-compat only. Used by the loader in versions earlier than 0.35.
341
- */
342
- this.runtimeVersion = pkgVersion;
343
340
  this._orderSequentiallyCalls = 0;
344
- this._flushMode = ContainerRuntime.defaultFlushMode;
345
341
  this.needsFlush = false;
346
342
  this.flushTrigger = false;
347
343
  this.paused = false;
@@ -384,7 +380,7 @@ export class ContainerRuntime extends TypedEventEmitter {
384
380
  // If we're not the summarizer, and we don't have a summaryManager, we expect that
385
381
  // disableSummaries is turned on. We are throwing instead of returning a failure here,
386
382
  // because it is a misuse of the API rather than an expected failure.
387
- throw new Error(`Can't summarize, disableSummaries: ${this.summariesDisabled()}`);
383
+ throw new UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
388
384
  }
389
385
  };
390
386
  this.enqueueSummarize = (...args) => {
@@ -398,7 +394,7 @@ export class ContainerRuntime extends TypedEventEmitter {
398
394
  // If we're not the summarizer, and we don't have a summaryManager, we expect that
399
395
  // generateSummaries is turned off. We are throwing instead of returning a failure here,
400
396
  // because it is a misuse of the API rather than an expected failure.
401
- throw new Error(`Can't summarize, disableSummaries: ${this.summariesDisabled()}`);
397
+ throw new UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
402
398
  }
403
399
  };
404
400
  this.baseSummaryMessage = metadata === null || metadata === void 0 ? void 0 : metadata.message;
@@ -421,20 +417,24 @@ export class ContainerRuntime extends TypedEventEmitter {
421
417
  this.disableIsolatedChannels = (_a = this.runtimeOptions.summaryOptions.disableIsolatedChannels) !== null && _a !== void 0 ? _a : false;
422
418
  this._connected = this.context.connected;
423
419
  this.chunkMap = new Map(chunks);
424
- this.IFluidHandleContext = new ContainerFluidHandleContext("", this);
425
- this._logger = ChildLogger.create(this.logger, "ContainerRuntime");
420
+ this.handleContext = new ContainerFluidHandleContext("", this);
421
+ this.mc = loggerToMonitoringContext(ChildLogger.create(this.logger, "ContainerRuntime"));
422
+ this._flushMode =
423
+ ((_b = this.mc.config.getBoolean(turnBasedFlushModeKey)) !== null && _b !== void 0 ? _b : false) ? FlushMode.TurnBased : FlushMode.Immediate;
426
424
  /**
427
425
  * Function that return the current server timestamp. This is used by the garbage collector to set the
428
426
  * time when a node becomes unreferenced.
429
- * For now, we use the timestamp of the last op for gcTimestamp. However, there can be cases where
427
+ * We use the timestamp of the last op for current timestamp. However, there can be cases where
430
428
  * we don't have an op (on demand summaries for instance). In those cases, we will use the timestamp
431
- * of this client's connection - https://github.com/microsoft/FluidFramework/issues/8375.
429
+ * of this client's connection.
432
430
  */
433
431
  const getCurrentTimestamp = () => {
434
- var _a, _b;
435
- return (_b = (_a = this.deltaManager.lastMessage) === null || _a === void 0 ? void 0 : _a.timestamp) !== null && _b !== void 0 ? _b : Date.now();
432
+ var _a, _b, _c;
433
+ const client = this.clientId !== undefined ? this.getAudience().getMember(this.clientId) : undefined;
434
+ const timestamp = client === null || client === void 0 ? void 0 : client.timestamp;
435
+ return (_c = (_b = (_a = this.deltaManager.lastMessage) === null || _a === void 0 ? void 0 : _a.timestamp) !== null && _b !== void 0 ? _b : timestamp) !== null && _c !== void 0 ? _c : Date.now();
436
436
  };
437
- this.garbageCollector = GarbageCollector.create(this, this.runtimeOptions.gcOptions, (unusedRoutes) => this.dataStores.deleteUnusedRoutes(unusedRoutes), getCurrentTimestamp, context.baseSnapshot, async (id) => readAndParse(this.storage, id), this._logger, existing, metadata);
437
+ this.garbageCollector = GarbageCollector.create(this, this.runtimeOptions.gcOptions, (unusedRoutes) => this.dataStores.deleteUnusedRoutes(unusedRoutes), getCurrentTimestamp, context.baseSnapshot, async (id) => readAndParse(this.storage, id), this.mc.logger, existing, metadata);
438
438
  const loadedFromSequenceNumber = this.deltaManager.initialSequenceNumber;
439
439
  this.summarizerNode = createRootSummarizerNodeWithGC(ChildLogger.create(this.logger, "SummarizerNode"),
440
440
  // Summarize function to call when summarize is called. Summarizer node always tracks summary state.
@@ -455,8 +455,8 @@ export class ContainerRuntime extends TypedEventEmitter {
455
455
  if (this.context.baseSnapshot) {
456
456
  this.summarizerNode.loadBaseSummaryWithoutDifferential(this.context.baseSnapshot);
457
457
  }
458
- this.dataStores = new DataStores(getSummaryForDatastores(context.baseSnapshot, metadata), this, (attachMsg) => this.submit(ContainerMessageType.Attach, attachMsg), (id, createParam) => (summarizeInternal, getGCDataFn, getInitialGCSummaryDetailsFn) => this.summarizerNode.createChild(summarizeInternal, id, createParam, undefined, getGCDataFn, getInitialGCSummaryDetailsFn), (id) => this.summarizerNode.deleteChild(id), this._logger, async () => this.garbageCollector.getDataStoreBaseGCDetails(), (id) => this.garbageCollector.nodeChanged(id));
459
- this.blobManager = new BlobManager(this.IFluidHandleContext, blobManagerSnapshot, () => this.storage, (blobId) => this.submit(ContainerMessageType.BlobAttach, undefined, undefined, { blobId }), this, this.logger);
458
+ this.dataStores = new DataStores(getSummaryForDatastores(context.baseSnapshot, metadata), this, (attachMsg) => this.submit(ContainerMessageType.Attach, attachMsg), (id, createParam) => (summarizeInternal, getGCDataFn, getInitialGCSummaryDetailsFn) => this.summarizerNode.createChild(summarizeInternal, id, createParam, undefined, getGCDataFn, getInitialGCSummaryDetailsFn), (id) => this.summarizerNode.deleteChild(id), this.mc.logger, async () => this.garbageCollector.getDataStoreBaseGCDetails(), (id) => this.garbageCollector.nodeChanged(id), new Map(dataStoreAliasMap));
459
+ this.blobManager = new BlobManager(this.handleContext, blobManagerSnapshot, () => this.storage, (blobId) => this.submit(ContainerMessageType.BlobAttach, undefined, undefined, { blobId }), this, this.logger);
460
460
  this.scheduleManager = new ScheduleManager(context.deltaManager, this, ChildLogger.create(this.logger, "ScheduleManager"));
461
461
  this.deltaSender = this.deltaManager;
462
462
  this.pendingStateManager = new PendingStateManager(this, async (type, content) => this.applyStashedOp(type, content), context.pendingLocalState);
@@ -464,49 +464,45 @@ export class ContainerRuntime extends TypedEventEmitter {
464
464
  this.clearPartialChunks(clientId);
465
465
  });
466
466
  this.summaryCollection = new SummaryCollection(this.deltaManager, this.logger);
467
- // Only create a SummaryManager if summaries are enabled and we are not the summarizer client
468
467
  // Map the deprecated generateSummaries flag to disableSummaries.
469
468
  if (this.runtimeOptions.summaryOptions.generateSummaries === false) {
470
469
  this.runtimeOptions.summaryOptions.disableSummaries = true;
471
470
  }
472
- if (this.summariesDisabled()) {
473
- this._logger.sendTelemetryEvent({ eventName: "SummariesDisabled" });
471
+ if (this.summariesDisabled) {
472
+ this.mc.logger.sendTelemetryEvent({ eventName: "SummariesDisabled" });
474
473
  }
475
474
  else {
476
- const maxOpsSinceLastSummary = (_b = this.runtimeOptions.summaryOptions.maxOpsSinceLastSummary) !== null && _b !== void 0 ? _b : 7000;
477
- const defaultAction = () => {
478
- if (this.summaryCollection.opsSinceLastAck > maxOpsSinceLastSummary) {
479
- this.logger.sendErrorEvent({ eventName: "SummaryStatus:Behind" });
480
- // unregister default to no log on every op after falling behind
481
- // and register summary ack handler to re-register this handler
482
- // after successful summary
483
- this.summaryCollection.once(MessageType.SummaryAck, () => {
484
- this.logger.sendTelemetryEvent({ eventName: "SummaryStatus:CaughtUp" });
485
- // we've caught up, so re-register the default action to monitor for
486
- // falling behind, and unregister ourself
487
- this.summaryCollection.on("default", defaultAction);
488
- });
489
- this.summaryCollection.off("default", defaultAction);
490
- }
491
- };
492
- this.summaryCollection.on("default", defaultAction);
493
475
  const orderedClientLogger = ChildLogger.create(this.logger, "OrderedClientElection");
494
476
  const orderedClientCollection = new OrderedClientCollection(orderedClientLogger, this.context.deltaManager, this.context.quorum);
495
477
  const orderedClientElectionForSummarizer = new OrderedClientElection(orderedClientLogger, orderedClientCollection, electedSummarizerData !== null && electedSummarizerData !== void 0 ? electedSummarizerData : this.context.deltaManager.lastSequenceNumber, SummarizerClientElection.isClientEligible);
496
- const summarizerClientElectionEnabled = (_c = getLocalStorageFeatureGate("summarizerClientElection")) !== null && _c !== void 0 ? _c : ((_d = this.runtimeOptions.summaryOptions) === null || _d === void 0 ? void 0 : _d.summarizerClientElection) === true;
478
+ const summarizerClientElectionEnabled = (_c = this.mc.config.getBoolean("Fluid.ContainerRuntime.summarizerClientElection")) !== null && _c !== void 0 ? _c : ((_d = this.runtimeOptions.summaryOptions) === null || _d === void 0 ? void 0 : _d.summarizerClientElection) === true;
479
+ const maxOpsSinceLastSummary = (_e = this.runtimeOptions.summaryOptions.maxOpsSinceLastSummary) !== null && _e !== void 0 ? _e : 7000;
497
480
  this.summarizerClientElection = new SummarizerClientElection(orderedClientLogger, this.summaryCollection, orderedClientElectionForSummarizer, maxOpsSinceLastSummary, summarizerClientElectionEnabled);
498
481
  if (this.context.clientDetails.type === summarizerClientType) {
499
- this._summarizer = new Summarizer("/_summarizer", this /* ISummarizerRuntime */, () => this.summaryConfiguration, this /* ISummarizerInternalsProvider */, this.IFluidHandleContext, this.summaryCollection, async (runtime) => RunWhileConnectedCoordinator.create(runtime));
482
+ this._summarizer = new Summarizer("/_summarizer", this /* ISummarizerRuntime */, () => this.summaryConfiguration, this /* ISummarizerInternalsProvider */, this.handleContext, this.summaryCollection, async (runtime) => RunWhileConnectedCoordinator.create(runtime));
500
483
  }
501
484
  else if (SummarizerClientElection.clientDetailsPermitElection(this.context.clientDetails)) {
502
- // Create the SummaryManager and mark the initial state
503
- const requestOptions = {
504
- cache: false,
505
- reconnect: false,
506
- summarizingClient: true,
485
+ // Only create a SummaryManager and SummarizerClientElection
486
+ // if summaries are enabled and we are not the summarizer client.
487
+ const defaultAction = () => {
488
+ if (this.summaryCollection.opsSinceLastAck > maxOpsSinceLastSummary) {
489
+ this.logger.sendErrorEvent({ eventName: "SummaryStatus:Behind" });
490
+ // unregister default to no log on every op after falling behind
491
+ // and register summary ack handler to re-register this handler
492
+ // after successful summary
493
+ this.summaryCollection.once(MessageType.SummaryAck, () => {
494
+ this.logger.sendTelemetryEvent({ eventName: "SummaryStatus:CaughtUp" });
495
+ // we've caught up, so re-register the default action to monitor for
496
+ // falling behind, and unregister ourself
497
+ this.summaryCollection.on("default", defaultAction);
498
+ });
499
+ this.summaryCollection.off("default", defaultAction);
500
+ }
507
501
  };
502
+ this.summaryCollection.on("default", defaultAction);
503
+ // Create the SummaryManager and mark the initial state
508
504
  this.summaryManager = new SummaryManager(this.summarizerClientElection, this, // IConnectedState
509
- this.summaryCollection, this.logger, formRequestSummarizerFn(this.context.loader, this.context.deltaManager.lastSequenceNumber, requestOptions), new Throttler(60 * 1000, // 60 sec delay window
505
+ this.summaryCollection, this.logger, this.formRequestSummarizerFn(this.context.loader), new Throttler(60 * 1000, // 60 sec delay window
510
506
  30 * 1000, // 30 sec max delay
511
507
  // throttling function increases exponentially (0ms, 40ms, 80ms, 160ms, etc)
512
508
  formExponentialFn({ coefficient: 20, initialDelay: 0 })), {
@@ -519,7 +515,6 @@ export class ContainerRuntime extends TypedEventEmitter {
519
515
  this.deltaManager.on("readonly", (readonly) => {
520
516
  // we accumulate ops while being in read-only state.
521
517
  // once user gets write permissions and we have active connection, flush all pending ops.
522
- // eslint-disable-next-line max-len
523
518
  assert(readonly === this.deltaManager.readOnlyInfo.readonly, 0x124 /* "inconsistent readonly property/event state" */);
524
519
  // We need to be very careful with when we (re)send pending ops, to ensure that we only send ops
525
520
  // when we either never send an op, or attempted to send it but we know for sure it was not
@@ -556,7 +551,7 @@ export class ContainerRuntime extends TypedEventEmitter {
556
551
  * @param existing - (optional) When loading from an existing snapshot. Precedes context.existing if provided
557
552
  */
558
553
  static async load(context, registryEntries, requestHandler, runtimeOptions = {}, containerScope = context.scope, existing) {
559
- var _a, _b, _c, _d;
554
+ var _a, _b, _c;
560
555
  // If taggedLogger exists, use it. Otherwise, wrap the vanilla logger:
561
556
  const passLogger = (_a = context.taggedLogger) !== null && _a !== void 0 ? _a : new TaggedLoggerAdapter(context.logger);
562
557
  const logger = ChildLogger.create(passLogger, undefined, {
@@ -598,19 +593,22 @@ export class ContainerRuntime extends TypedEventEmitter {
598
593
  return readAndParse(storage, blobId);
599
594
  }
600
595
  };
601
- const chunks = (_b = await tryFetchBlob(chunksBlobName)) !== null && _b !== void 0 ? _b : [];
602
- const metadata = await tryFetchBlob(metadataBlobName);
603
- const electedSummarizerData = await tryFetchBlob(electedSummarizerBlobName);
596
+ const [chunks, metadata, electedSummarizerData, aliases] = await Promise.all([
597
+ tryFetchBlob(chunksBlobName),
598
+ tryFetchBlob(metadataBlobName),
599
+ tryFetchBlob(electedSummarizerBlobName),
600
+ tryFetchBlob(aliasBlobName),
601
+ ]);
604
602
  const loadExisting = existing === true || context.existing === true;
605
603
  // read snapshot blobs needed for BlobManager to load
606
- const blobManagerSnapshot = await BlobManager.load((_c = context.baseSnapshot) === null || _c === void 0 ? void 0 : _c.trees[blobsTreeName], async (id) => {
604
+ const blobManagerSnapshot = await BlobManager.load((_b = context.baseSnapshot) === null || _b === void 0 ? void 0 : _b.trees[blobsTreeName], async (id) => {
607
605
  // IContainerContext storage api return type still has undefined in 0.39 package version.
608
606
  // So once we release 0.40 container-defn package we can remove this check.
609
607
  assert(storage !== undefined, 0x256 /* "storage undefined in attached container" */);
610
608
  return readAndParse(storage, id);
611
609
  });
612
610
  // Verify summary runtime sequence number matches protocol sequence number.
613
- const runtimeSequenceNumber = (_d = metadata === null || metadata === void 0 ? void 0 : metadata.message) === null || _d === void 0 ? void 0 : _d.sequenceNumber;
611
+ const runtimeSequenceNumber = (_c = metadata === null || metadata === void 0 ? void 0 : metadata.message) === null || _c === void 0 ? void 0 : _c.sequenceNumber;
614
612
  if (runtimeSequenceNumber !== undefined) {
615
613
  const protocolSequenceNumber = context.deltaManager.initialSequenceNumber;
616
614
  // Unless bypass is explicitly set, then take action when sequence numbers mismatch.
@@ -625,13 +623,16 @@ export class ContainerRuntime extends TypedEventEmitter {
625
623
  }
626
624
  }
627
625
  }
628
- const runtime = new ContainerRuntime(context, registry, metadata, electedSummarizerData, chunks, {
626
+ const runtime = new ContainerRuntime(context, registry, metadata, electedSummarizerData, chunks !== null && chunks !== void 0 ? chunks : [], aliases !== null && aliases !== void 0 ? aliases : [], {
629
627
  summaryOptions,
630
628
  gcOptions,
631
629
  loadSequenceNumberVerification,
632
630
  }, containerScope, logger, loadExisting, blobManagerSnapshot, requestHandler, storage);
633
631
  return runtime;
634
632
  }
633
+ /**
634
+ * @deprecated This will be removed in a later release. Deprecated in 0.53
635
+ */
635
636
  get id() {
636
637
  return this.context.id;
637
638
  }
@@ -682,6 +683,9 @@ export class ContainerRuntime extends TypedEventEmitter {
682
683
  get attachState() {
683
684
  return this.context.attachState;
684
685
  }
686
+ get IFluidHandleContext() {
687
+ return this.handleContext;
688
+ }
685
689
  get connected() {
686
690
  return this._connected;
687
691
  }
@@ -702,13 +706,15 @@ export class ContainerRuntime extends TypedEventEmitter {
702
706
  get writeGCDataAtRoot() {
703
707
  return this.garbageCollector.writeDataAtRoot;
704
708
  }
705
- static get defaultFlushMode() {
706
- return getLocalStorageFeatureGate(turnBasedFlushModeKey) ? FlushMode.TurnBased : FlushMode.Immediate;
707
- }
708
709
  get summarizer() {
709
710
  assert(this._summarizer !== undefined, 0x257 /* "This is not summarizing container" */);
710
711
  return this._summarizer;
711
712
  }
713
+ get summariesDisabled() {
714
+ var _a;
715
+ return this.runtimeOptions.summaryOptions.disableSummaries === true ||
716
+ ((_a = this.runtimeOptions.summaryOptions.summaryConfigOverrides) === null || _a === void 0 ? void 0 : _a.disableSummaries) === true;
717
+ }
712
718
  dispose(error) {
713
719
  var _a;
714
720
  if (this._disposed) {
@@ -868,6 +874,10 @@ export class ContainerRuntime extends TypedEventEmitter {
868
874
  const content = JSON.stringify([...this.chunkMap]);
869
875
  addBlobToSummary(summaryTree, chunksBlobName, content);
870
876
  }
877
+ const dataStoreAliases = this.dataStores.aliases();
878
+ if (dataStoreAliases.size > 0) {
879
+ addBlobToSummary(summaryTree, aliasBlobName, JSON.stringify([...dataStoreAliases]));
880
+ }
871
881
  if (this.summarizerClientElection) {
872
882
  const electedSummarizerContent = JSON.stringify((_a = this.summarizerClientElection) === null || _a === void 0 ? void 0 : _a.serialize());
873
883
  addBlobToSummary(summaryTree, electedSummarizerBlobName, electedSummarizerContent);
@@ -919,6 +929,7 @@ export class ContainerRuntime extends TypedEventEmitter {
919
929
  return this.dataStores.applyStashedOp(op);
920
930
  case ContainerMessageType.Attach:
921
931
  return this.dataStores.applyStashedAttachOp(op);
932
+ case ContainerMessageType.Alias:
922
933
  case ContainerMessageType.BlobAttach:
923
934
  return;
924
935
  case ContainerMessageType.ChunkedOp:
@@ -940,7 +951,7 @@ export class ContainerRuntime extends TypedEventEmitter {
940
951
  this.replayPendingStates();
941
952
  }
942
953
  this.dataStores.setConnectionState(connected, clientId);
943
- raiseConnectedEvent(this._logger, this, connected, clientId);
954
+ raiseConnectedEvent(this.mc.logger, this, connected, clientId);
944
955
  }
945
956
  process(messageArg, local) {
946
957
  var _a;
@@ -974,6 +985,9 @@ export class ContainerRuntime extends TypedEventEmitter {
974
985
  case ContainerMessageType.Attach:
975
986
  this.dataStores.processAttachMessage(message, local || localAck);
976
987
  break;
988
+ case ContainerMessageType.Alias:
989
+ this.processAliasMessage(message, localOpMetadata, local);
990
+ break;
977
991
  case ContainerMessageType.FluidDataStoreOp:
978
992
  // if localAck === true, treat this as a local op because it's one we sent on a previous container
979
993
  this.dataStores.processFluidDataStoreOp(message, local || localAck, localOpMetadata);
@@ -992,6 +1006,9 @@ export class ContainerRuntime extends TypedEventEmitter {
992
1006
  throw e;
993
1007
  }
994
1008
  }
1009
+ processAliasMessage(message, localOpMetadata, local) {
1010
+ this.dataStores.processAliasMessage(message, localOpMetadata, local);
1011
+ }
995
1012
  processSignal(message, local) {
996
1013
  const envelope = message.content;
997
1014
  const transformed = {
@@ -1041,6 +1058,11 @@ export class ContainerRuntime extends TypedEventEmitter {
1041
1058
  return;
1042
1059
  }
1043
1060
  this.needsFlush = false;
1061
+ // Did we disconnect in the middle of turn-based batch?
1062
+ // If so, do nothing, as pending state manager will resubmit it correctly on reconnect.
1063
+ if (!this.canSendOps()) {
1064
+ return;
1065
+ }
1044
1066
  return this.deltaSender.flush();
1045
1067
  }
1046
1068
  orderSequentially(callback) {
@@ -1057,11 +1079,12 @@ export class ContainerRuntime extends TypedEventEmitter {
1057
1079
  this.setFlushMode(FlushMode.TurnBased);
1058
1080
  try {
1059
1081
  this.trackOrderSequentiallyCalls(callback);
1060
- }
1061
- finally {
1062
1082
  this.flush();
1063
1083
  this.setFlushMode(savedFlushMode);
1064
1084
  }
1085
+ catch (error) {
1086
+ this.closeFn(CreateProcessingError(error, "orderSequentially"));
1087
+ }
1065
1088
  }
1066
1089
  trackOrderSequentiallyCalls(callback) {
1067
1090
  try {
@@ -1229,12 +1252,21 @@ export class ContainerRuntime extends TypedEventEmitter {
1229
1252
  return this.dataStores.updateUsedRoutes(usedRoutes, gcTimestamp);
1230
1253
  }
1231
1254
  /**
1232
- * Runs garbage collection and udpates the reference / used state of the nodes in the container.
1255
+ * Runs garbage collection and updates the reference / used state of the nodes in the container.
1233
1256
  * @returns the statistics of the garbage collection run.
1234
1257
  */
1235
1258
  async collectGarbage(options) {
1236
1259
  return this.garbageCollector.collectGarbage(options);
1237
1260
  }
1261
+ /**
1262
+ * Called when a new outbound reference is added to another node. This is used by garbage collection to identify
1263
+ * all references added in the system.
1264
+ * @param srcHandle - The handle of the node that added the reference.
1265
+ * @param outboundHandle - The handle of the outbound node that is referenced.
1266
+ */
1267
+ addedGCOutboundReference(srcHandle, outboundHandle) {
1268
+ this.garbageCollector.addedOutboundReference(srcHandle.absolutePath, outboundHandle.absolutePath);
1269
+ }
1238
1270
  /**
1239
1271
  * Generates the summary tree, uploads it to storage, and then submits the summarize op.
1240
1272
  * This is intended to be called by the summarizer, since it is the implementation of
@@ -1424,10 +1456,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1424
1456
  this.dirtyContainer = dirty;
1425
1457
  if (this.emitDirtyDocumentEvent) {
1426
1458
  this.emit(dirty ? "dirty" : "saved");
1427
- // back-compat: Loader API added in 0.35 only
1428
- if (this.context.updateDirtyContainerState !== undefined) {
1429
- this.context.updateDirtyContainerState(dirty);
1430
- }
1459
+ this.context.updateDirtyContainerState(dirty);
1431
1460
  }
1432
1461
  }
1433
1462
  submitDataStoreOp(id, contents, localOpMetadata = undefined) {
@@ -1508,7 +1537,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1508
1537
  // That might be not what caller hopes to get, but we can look deeper if telemetry tells us it's a problem.
1509
1538
  const middleOfBatch = this.flushMode === FlushMode.TurnBased && this.needsFlush;
1510
1539
  if (middleOfBatch) {
1511
- this._logger.sendErrorEvent({ eventName: "submitSystemMessageError", type });
1540
+ this.mc.logger.sendErrorEvent({ eventName: "submitSystemMessageError", type });
1512
1541
  }
1513
1542
  return this.context.submitFn(type, contents, middleOfBatch);
1514
1543
  }
@@ -1541,6 +1570,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1541
1570
  this.dataStores.resubmitDataStoreOp(content, localOpMetadata);
1542
1571
  break;
1543
1572
  case ContainerMessageType.Attach:
1573
+ case ContainerMessageType.Alias:
1544
1574
  this.submit(type, content, localOpMetadata);
1545
1575
  break;
1546
1576
  case ContainerMessageType.ChunkedOp:
@@ -1572,7 +1602,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1572
1602
  * @returns downloaded snapshot's reference sequence number
1573
1603
  */
1574
1604
  async refreshLatestSummaryAckFromServer(summaryLogger) {
1575
- const snapshot = await this.fetchSnapshotFromStorage(this.id, summaryLogger, {
1605
+ const snapshot = await this.fetchSnapshotFromStorage(null, summaryLogger, {
1576
1606
  eventName: "RefreshLatestSummaryGetSnapshot",
1577
1607
  fetchLatest: true,
1578
1608
  });
@@ -1601,12 +1631,30 @@ export class ContainerRuntime extends TypedEventEmitter {
1601
1631
  return this.pendingStateManager.getLocalState();
1602
1632
  }
1603
1633
  /**
1604
- * @returns true if summaries are explicitly disabled for this ContainerRuntime, false otherwise
1605
- */
1606
- summariesDisabled() {
1607
- var _a;
1608
- return this.runtimeOptions.summaryOptions.disableSummaries === true ||
1609
- ((_a = this.runtimeOptions.summaryOptions.summaryConfigOverrides) === null || _a === void 0 ? void 0 : _a.disableSummaries) === true;
1634
+ * * Forms a function that will request a Summarizer.
1635
+ * @param loaderRouter - the loader acting as an IFluidRouter
1636
+ * */
1637
+ formRequestSummarizerFn(loaderRouter) {
1638
+ return async () => {
1639
+ const request = {
1640
+ headers: {
1641
+ [LoaderHeader.cache]: false,
1642
+ [LoaderHeader.clientDetails]: {
1643
+ capabilities: { interactive: false },
1644
+ type: summarizerClientType,
1645
+ },
1646
+ [DriverHeader.summarizingClient]: true,
1647
+ [LoaderHeader.reconnect]: false,
1648
+ },
1649
+ url: "/_summarizer",
1650
+ };
1651
+ const fluidObject = await requestFluidObject(loaderRouter, request);
1652
+ const summarizer = fluidObject.ISummarizer;
1653
+ if (!summarizer) {
1654
+ throw new UsageError("Fluid object does not implement ISummarizer");
1655
+ }
1656
+ return summarizer;
1657
+ };
1610
1658
  }
1611
1659
  }
1612
1660
  /**