@fluidframework/container-runtime 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/containerRuntime.d.ts +1 -1
  2. package/dist/containerRuntime.d.ts.map +1 -1
  3. package/dist/containerRuntime.js +8 -8
  4. package/dist/containerRuntime.js.map +1 -1
  5. package/dist/dataStore.d.ts +2 -2
  6. package/dist/dataStore.d.ts.map +1 -1
  7. package/dist/dataStore.js +2 -2
  8. package/dist/dataStore.js.map +1 -1
  9. package/dist/dataStoreContext.d.ts +4 -4
  10. package/dist/dataStoreContext.d.ts.map +1 -1
  11. package/dist/dataStoreContext.js.map +1 -1
  12. package/dist/dataStores.d.ts +2 -2
  13. package/dist/dataStores.d.ts.map +1 -1
  14. package/dist/dataStores.js +6 -5
  15. package/dist/dataStores.js.map +1 -1
  16. package/dist/garbageCollection.d.ts +33 -14
  17. package/dist/garbageCollection.d.ts.map +1 -1
  18. package/dist/garbageCollection.js +243 -122
  19. package/dist/garbageCollection.js.map +1 -1
  20. package/dist/packageVersion.d.ts +1 -1
  21. package/dist/packageVersion.js +1 -1
  22. package/dist/packageVersion.js.map +1 -1
  23. package/dist/summarizerTypes.d.ts +5 -2
  24. package/dist/summarizerTypes.d.ts.map +1 -1
  25. package/dist/summarizerTypes.js.map +1 -1
  26. package/dist/summaryFormat.d.ts +6 -3
  27. package/dist/summaryFormat.d.ts.map +1 -1
  28. package/dist/summaryFormat.js +6 -3
  29. package/dist/summaryFormat.js.map +1 -1
  30. package/dist/summaryGenerator.d.ts.map +1 -1
  31. package/dist/summaryGenerator.js +0 -1
  32. package/dist/summaryGenerator.js.map +1 -1
  33. package/garbageCollection.md +7 -7
  34. package/lib/containerRuntime.d.ts +1 -1
  35. package/lib/containerRuntime.d.ts.map +1 -1
  36. package/lib/containerRuntime.js +9 -9
  37. package/lib/containerRuntime.js.map +1 -1
  38. package/lib/dataStore.d.ts +2 -2
  39. package/lib/dataStore.d.ts.map +1 -1
  40. package/lib/dataStore.js +2 -2
  41. package/lib/dataStore.js.map +1 -1
  42. package/lib/dataStoreContext.d.ts +4 -4
  43. package/lib/dataStoreContext.d.ts.map +1 -1
  44. package/lib/dataStoreContext.js.map +1 -1
  45. package/lib/dataStores.d.ts +2 -2
  46. package/lib/dataStores.d.ts.map +1 -1
  47. package/lib/dataStores.js +6 -5
  48. package/lib/dataStores.js.map +1 -1
  49. package/lib/garbageCollection.d.ts +33 -14
  50. package/lib/garbageCollection.d.ts.map +1 -1
  51. package/lib/garbageCollection.js +242 -121
  52. package/lib/garbageCollection.js.map +1 -1
  53. package/lib/packageVersion.d.ts +1 -1
  54. package/lib/packageVersion.js +1 -1
  55. package/lib/packageVersion.js.map +1 -1
  56. package/lib/summarizerTypes.d.ts +5 -2
  57. package/lib/summarizerTypes.d.ts.map +1 -1
  58. package/lib/summarizerTypes.js.map +1 -1
  59. package/lib/summaryFormat.d.ts +6 -3
  60. package/lib/summaryFormat.d.ts.map +1 -1
  61. package/lib/summaryFormat.js +6 -3
  62. package/lib/summaryFormat.js.map +1 -1
  63. package/lib/summaryGenerator.d.ts.map +1 -1
  64. package/lib/summaryGenerator.js +0 -1
  65. package/lib/summaryGenerator.js.map +1 -1
  66. package/package.json +16 -16
  67. package/src/containerRuntime.ts +60 -58
  68. package/src/dataStore.ts +4 -4
  69. package/src/dataStoreContext.ts +4 -4
  70. package/src/dataStores.ts +5 -5
  71. package/src/garbageCollection.ts +308 -167
  72. package/src/packageVersion.ts +1 -1
  73. package/src/summarizerTypes.ts +6 -3
  74. package/src/summaryFormat.ts +6 -3
  75. package/src/summaryGenerator.ts +0 -2
@@ -46,7 +46,7 @@ import {
46
46
  TelemetryDataTag,
47
47
  } from "@fluidframework/telemetry-utils";
48
48
  import { DriverHeader, IDocumentStorageService, ISummaryContext } from "@fluidframework/driver-definitions";
49
- import { readAndParse } from "@fluidframework/driver-utils";
49
+ import { readAndParse, isUnpackedRuntimeMessage } from "@fluidframework/driver-utils";
50
50
  import {
51
51
  DataCorruptionError,
52
52
  DataProcessingError,
@@ -253,9 +253,9 @@ export interface ISummaryConfigurationDisableHeuristics extends ISummaryBaseConf
253
253
  }
254
254
 
255
255
  export type ISummaryConfiguration =
256
- | ISummaryConfigurationDisableSummarizer
257
- | ISummaryConfigurationDisableHeuristics
258
- | ISummaryConfigurationHeuristics;
256
+ | ISummaryConfigurationDisableSummarizer
257
+ | ISummaryConfigurationDisableHeuristics
258
+ | ISummaryConfigurationHeuristics;
259
259
 
260
260
  export const DefaultSummaryConfiguration: ISummaryConfiguration = {
261
261
  state: "enabled",
@@ -341,11 +341,11 @@ export interface ISummaryRuntimeOptions {
341
341
  */
342
342
  maxOpsSinceLastSummary?: number;
343
343
 
344
- /**
345
- * @deprecated - use `summaryConfigOverrides.summarizerClientElection` instead.
346
- * Flag that will enable changing elected summarizer client after maxOpsSinceLastSummary.
347
- * This defaults to false (disabled) and must be explicitly set to true to enable.
348
- */
344
+ /**
345
+ * @deprecated - use `summaryConfigOverrides.summarizerClientElection` instead.
346
+ * Flag that will enable changing elected summarizer client after maxOpsSinceLastSummary.
347
+ * This defaults to false (disabled) and must be explicitly set to true to enable.
348
+ */
349
349
  summarizerClientElection?: boolean;
350
350
 
351
351
  /**
@@ -502,7 +502,7 @@ export function unpackRuntimeMessage(message: ISequencedDocumentMessage) {
502
502
  message.type = innerContents.type;
503
503
  message.contents = innerContents.contents;
504
504
  }
505
- assert(isRuntimeMessage(message), 0x122 /* "Message to unpack is not proper runtime message" */);
505
+ assert(isUnpackedRuntimeMessage(message), 0x122 /* "Message to unpack is not proper runtime message" */);
506
506
  } else {
507
507
  // Legacy format, but it's already "unpacked",
508
508
  // i.e. message.type is actually ContainerMessageType.
@@ -574,7 +574,7 @@ class ScheduleManagerCore {
574
574
  * The only public function in this class - called when we processed an op,
575
575
  * to make decision if op processing should be paused or not afer that.
576
576
  */
577
- public afterOpProcessing(sequenceNumber: number) {
577
+ public afterOpProcessing(sequenceNumber: number) {
578
578
  assert(!this.localPaused, 0x294 /* "can't have op processing paused if we are processing an op" */);
579
579
 
580
580
  // If the inbound queue is ever empty, nothing to do!
@@ -659,7 +659,7 @@ class ScheduleManagerCore {
659
659
  const batchMetadata = metadata?.batch;
660
660
 
661
661
  // Protocol messages are never part of a runtime batch of messages
662
- if (!isRuntimeMessage(message)) {
662
+ if (!isUnpackedRuntimeMessage(message)) {
663
663
  // Protocol messages should never show up in the middle of the batch!
664
664
  assert(this.currentBatchClientId === undefined, 0x29a /* "System message in the middle of batch!" */);
665
665
  assert(batchMetadata === undefined, 0x29b /* "system op in a batch?" */);
@@ -681,6 +681,7 @@ class ScheduleManagerCore {
681
681
  throw new DataCorruptionError(
682
682
  "OpBatchIncomplete",
683
683
  {
684
+ runtimeVersion: pkgVersion,
684
685
  batchClientId: this.currentBatchClientId,
685
686
  ...extractSafePropertiesFromMessage(message),
686
687
  });
@@ -812,11 +813,11 @@ export function getDeviceSpec() {
812
813
  */
813
814
  export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
814
815
  implements
815
- IContainerRuntime,
816
- IGarbageCollectionRuntime,
817
- IRuntime,
818
- ISummarizerRuntime,
819
- ISummarizerInternalsProvider {
816
+ IContainerRuntime,
817
+ IGarbageCollectionRuntime,
818
+ IRuntime,
819
+ ISummarizerRuntime,
820
+ ISummarizerInternalsProvider {
820
821
  public get IContainerRuntime() { return this; }
821
822
  public get IFluidRouter() { return this; }
822
823
 
@@ -905,7 +906,7 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
905
906
  const error = new DataCorruptionError(
906
907
  // pre-0.58 error message: SummaryMetadataMismatch
907
908
  "Summary metadata mismatch",
908
- { runtimeSequenceNumber, protocolSequenceNumber },
909
+ { runtimeVersion: pkgVersion, runtimeSequenceNumber, protocolSequenceNumber },
909
910
  );
910
911
 
911
912
  if (loadSequenceNumberVerification === "log") {
@@ -1177,9 +1178,9 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
1177
1178
  private readonly requestHandler?: (request: IRequest, runtime: IContainerRuntime) => Promise<IResponse>,
1178
1179
  private readonly summaryConfiguration: ISummaryConfiguration = {
1179
1180
  // the defaults
1180
- ... DefaultSummaryConfiguration,
1181
+ ...DefaultSummaryConfiguration,
1181
1182
  // the runtime configuration overrides
1182
- ... runtimeOptions.summaryOptions?.summaryConfigOverrides,
1183
+ ...runtimeOptions.summaryOptions?.summaryConfigOverrides,
1183
1184
  },
1184
1185
  ) {
1185
1186
  super();
@@ -1223,7 +1224,7 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
1223
1224
  existing,
1224
1225
  metadata,
1225
1226
  isSummarizerClient: this.context.clientDetails.type === summarizerClientType,
1226
- getNodePackagePath: (nodePath: string) => this.getGCNodePackagePath(nodePath),
1227
+ getNodePackagePath: async (nodePath: string) => this.getGCNodePackagePath(nodePath),
1227
1228
  getLastSummaryTimestampMs: () => this.messageAtLastSummary?.timestamp,
1228
1229
  readAndParseBlob: async <T>(id: string) => readAndParse<T>(this.storage, id),
1229
1230
  });
@@ -1259,17 +1260,17 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
1259
1260
  this,
1260
1261
  (attachMsg) => this.submit(ContainerMessageType.Attach, attachMsg),
1261
1262
  (id: string, createParam: CreateChildSummarizerNodeParam) => (
1262
- summarizeInternal: SummarizeInternalFn,
1263
- getGCDataFn: (fullGC?: boolean) => Promise<IGarbageCollectionData>,
1264
- getBaseGCDetailsFn: () => Promise<IGarbageCollectionDetailsBase>,
1265
- ) => this.summarizerNode.createChild(
1266
- summarizeInternal,
1267
- id,
1268
- createParam,
1269
- undefined,
1270
- getGCDataFn,
1271
- getBaseGCDetailsFn,
1272
- ),
1263
+ summarizeInternal: SummarizeInternalFn,
1264
+ getGCDataFn: (fullGC?: boolean) => Promise<IGarbageCollectionData>,
1265
+ getBaseGCDetailsFn: () => Promise<IGarbageCollectionDetailsBase>,
1266
+ ) => this.summarizerNode.createChild(
1267
+ summarizeInternal,
1268
+ id,
1269
+ createParam,
1270
+ undefined,
1271
+ getGCDataFn,
1272
+ getBaseGCDetailsFn,
1273
+ ),
1273
1274
  (id: string) => this.summarizerNode.deleteChild(id),
1274
1275
  this.mc.logger,
1275
1276
  async () => this.garbageCollector.getBaseGCDetails(),
@@ -1801,7 +1802,7 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
1801
1802
  this.verifyNotClosed();
1802
1803
 
1803
1804
  // If it's not message for runtime, bail out right away.
1804
- if (!isRuntimeMessage(messageArg)) {
1805
+ if (!isUnpackedRuntimeMessage(messageArg)) {
1805
1806
  return;
1806
1807
  }
1807
1808
 
@@ -2249,7 +2250,7 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
2249
2250
 
2250
2251
  public submitDataStoreSignal(address: string, type: string, content: any) {
2251
2252
  const envelope = this.createNewSignalEnvelope(address, type, content);
2252
- return this.context.submitSignalFn(envelope);
2253
+ return this.context.submitSignalFn(envelope);
2253
2254
  }
2254
2255
 
2255
2256
  public setAttachState(attachState: AttachState.Attaching | AttachState.Attached): void {
@@ -2348,7 +2349,7 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
2348
2349
  const {
2349
2350
  fullTree = false,
2350
2351
  trackState = true,
2351
- summaryLogger = this.logger,
2352
+ summaryLogger = this.mc.logger,
2352
2353
  runGC = this.garbageCollector.shouldRunGC,
2353
2354
  runSweep,
2354
2355
  fullGC,
@@ -2462,7 +2463,7 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
2462
2463
  * Called by GC to retrieve the package path of the node with the given path. The node should belong to a
2463
2464
  * data store or an attachment blob.
2464
2465
  */
2465
- public getGCNodePackagePath(nodePath: string): readonly string[] | undefined {
2466
+ public async getGCNodePackagePath(nodePath: string): Promise<readonly string[] | undefined> {
2466
2467
  switch (this.getNodeType(nodePath)) {
2467
2468
  case GCNodeType.Blob:
2468
2469
  return ["_blobs"];
@@ -2675,16 +2676,16 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
2675
2676
  const lastAck = this.summaryCollection.latestAck;
2676
2677
  const summaryContext: ISummaryContext =
2677
2678
  lastAck === undefined
2678
- ? {
2679
- proposalHandle: undefined,
2680
- ackHandle: this.context.getLoadedFromVersion()?.id,
2681
- referenceSequenceNumber: summaryRefSeqNum,
2682
- }
2683
- : {
2684
- proposalHandle: lastAck.summaryOp.contents.handle,
2685
- ackHandle: lastAck.summaryAck.contents.handle,
2686
- referenceSequenceNumber: summaryRefSeqNum,
2687
- };
2679
+ ? {
2680
+ proposalHandle: undefined,
2681
+ ackHandle: this.context.getLoadedFromVersion()?.id,
2682
+ referenceSequenceNumber: summaryRefSeqNum,
2683
+ }
2684
+ : {
2685
+ proposalHandle: lastAck.summaryOp.contents.handle,
2686
+ ackHandle: lastAck.summaryAck.contents.handle,
2687
+ referenceSequenceNumber: summaryRefSeqNum,
2688
+ };
2688
2689
 
2689
2690
  let handle: string;
2690
2691
  try {
@@ -3091,20 +3092,21 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
3091
3092
  end: (arg0: {
3092
3093
  getVersionDuration?: number | undefined;
3093
3094
  getSnapshotDuration?: number | undefined;
3094
- }) => void; }) => {
3095
- const stats: { getVersionDuration?: number; getSnapshotDuration?: number; } = {};
3096
- const trace = Trace.start();
3095
+ }) => void;
3096
+ }) => {
3097
+ const stats: { getVersionDuration?: number; getSnapshotDuration?: number; } = {};
3098
+ const trace = Trace.start();
3097
3099
 
3098
- const versions = await this.storage.getVersions(versionId, 1);
3099
- assert(!!versions && !!versions[0], 0x137 /* "Failed to get version from storage" */);
3100
- stats.getVersionDuration = trace.trace().duration;
3100
+ const versions = await this.storage.getVersions(versionId, 1);
3101
+ assert(!!versions && !!versions[0], 0x137 /* "Failed to get version from storage" */);
3102
+ stats.getVersionDuration = trace.trace().duration;
3101
3103
 
3102
- const maybeSnapshot = await this.storage.getSnapshotTree(versions[0]);
3103
- assert(!!maybeSnapshot, 0x138 /* "Failed to get snapshot from storage" */);
3104
- stats.getSnapshotDuration = trace.trace().duration;
3104
+ const maybeSnapshot = await this.storage.getSnapshotTree(versions[0]);
3105
+ assert(!!maybeSnapshot, 0x138 /* "Failed to get snapshot from storage" */);
3106
+ stats.getSnapshotDuration = trace.trace().duration;
3105
3107
 
3106
- perfEvent.end(stats);
3107
- return maybeSnapshot;
3108
+ perfEvent.end(stats);
3109
+ return maybeSnapshot;
3108
3110
  });
3109
3111
  }
3110
3112
 
@@ -3173,7 +3175,7 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
3173
3175
  // because it is a misuse of the API rather than an expected failure.
3174
3176
  throw new UsageError(
3175
3177
  `Can't summarize, disableSummaries: ${this.summariesDisabled}`,
3176
- );
3178
+ );
3177
3179
  }
3178
3180
  };
3179
3181
 
package/src/dataStore.ts CHANGED
@@ -26,11 +26,11 @@ export interface IDataStoreAliasMessage {
26
26
 
27
27
  /**
28
28
  * Type guard that returns true if the given alias message is actually an instance of
29
- * a class which implements @see IDataStoreAliasMessage
29
+ * a class which implements {@link IDataStoreAliasMessage}
30
30
  * @param maybeDataStoreAliasMessage - message object to be validated
31
- * @returns True if the @see IDataStoreAliasMessage is fully implemented, false otherwise
31
+ * @returns True if the {@link IDataStoreAliasMessage} is fully implemented, false otherwise
32
32
  */
33
- export const isDataStoreAliasMessage = (
33
+ export const isDataStoreAliasMessage = (
34
34
  maybeDataStoreAliasMessage: any,
35
35
  ): maybeDataStoreAliasMessage is IDataStoreAliasMessage => {
36
36
  return typeof maybeDataStoreAliasMessage?.internalId === "string"
@@ -153,7 +153,7 @@ class DataStore implements IDataStore {
153
153
 
154
154
  private async ackBasedPromise<T>(
155
155
  executor: (resolve: (value: T | PromiseLike<T>) => void,
156
- reject: (reason?: any) => void) => void,
156
+ reject: (reason?: any) => void) => void,
157
157
  ): Promise<T> {
158
158
  let rejectBecauseDispose: () => void;
159
159
  return new Promise<T>((resolve, reject) => {
@@ -704,7 +704,7 @@ export abstract class FluidDataStoreContext extends TypedEventEmitter<IFluidData
704
704
 
705
705
  public abstract generateAttachMessage(): IAttachMessage;
706
706
 
707
- protected abstract getInitialSnapshotDetails(): Promise<ISnapshotDetails>;
707
+ public abstract getInitialSnapshotDetails(): Promise<ISnapshotDetails>;
708
708
 
709
709
  /**
710
710
  * @deprecated - Sets the datastore as root, for aliasing purposes: #7948
@@ -858,7 +858,7 @@ export class RemoteFluidDataStoreContext extends FluidDataStoreContext {
858
858
  };
859
859
  });
860
860
 
861
- protected async getInitialSnapshotDetails(): Promise<ISnapshotDetails> {
861
+ public async getInitialSnapshotDetails(): Promise<ISnapshotDetails> {
862
862
  return this.initialSnapshotDetailsP;
863
863
  }
864
864
 
@@ -947,7 +947,7 @@ export class LocalFluidDataStoreContextBase extends FluidDataStoreContext {
947
947
  return message;
948
948
  }
949
949
 
950
- protected async getInitialSnapshotDetails(): Promise<ISnapshotDetails> {
950
+ public async getInitialSnapshotDetails(): Promise<ISnapshotDetails> {
951
951
  let snapshot = this.snapshotTree;
952
952
  let attributes: ReadFluidDataStoreAttributes;
953
953
  let isRootDataStore = false;
@@ -1050,7 +1050,7 @@ export class LocalDetachedFluidDataStoreContext
1050
1050
  }
1051
1051
  }
1052
1052
 
1053
- protected async getInitialSnapshotDetails(): Promise<ISnapshotDetails> {
1053
+ public async getInitialSnapshotDetails(): Promise<ISnapshotDetails> {
1054
1054
  if (this.detachedRuntimeCreation) {
1055
1055
  throw new Error("Detached Fluid Data Store context can't be realized! Please attach runtime first!");
1056
1056
  }
package/src/dataStores.ts CHANGED
@@ -647,13 +647,13 @@ export class DataStores implements IDisposable {
647
647
  }
648
648
 
649
649
  /**
650
- * Called during GC to retrieve the package path of a data store node with the given path.
650
+ * Called by GC to retrieve the package path of a data store node with the given path.
651
651
  */
652
- public getDataStorePackagePath(nodePath: string): readonly string[] | undefined {
653
- // If the node belongs to a data store, return its package path if the data store is loaded. For DDSs, we return
654
- // the package path of the data store that contains it.
652
+ public async getDataStorePackagePath(nodePath: string): Promise<readonly string[] | undefined> {
653
+ // If the node belongs to a data store, return its package path. For DDSes, we return the package path of the
654
+ // data store that contains it.
655
655
  const context = this.contexts.get(nodePath.split("/")[1]);
656
- return context?.isLoaded ? context.packagePath : undefined;
656
+ return (await context?.getInitialSnapshotDetails())?.pkg;
657
657
  }
658
658
 
659
659
  /**