@fluidframework/container-runtime 0.58.3000-61081 → 0.59.1001-62246

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 (97) hide show
  1. package/dist/blobManager.d.ts +13 -1
  2. package/dist/blobManager.d.ts.map +1 -1
  3. package/dist/blobManager.js +52 -0
  4. package/dist/blobManager.js.map +1 -1
  5. package/dist/connectionTelemetry.js +7 -7
  6. package/dist/connectionTelemetry.js.map +1 -1
  7. package/dist/containerRuntime.d.ts +27 -3
  8. package/dist/containerRuntime.d.ts.map +1 -1
  9. package/dist/containerRuntime.js +100 -14
  10. package/dist/containerRuntime.js.map +1 -1
  11. package/dist/dataStore.js +8 -1
  12. package/dist/dataStore.js.map +1 -1
  13. package/dist/dataStoreContext.d.ts +9 -3
  14. package/dist/dataStoreContext.d.ts.map +1 -1
  15. package/dist/dataStoreContext.js +22 -6
  16. package/dist/dataStoreContext.js.map +1 -1
  17. package/dist/dataStores.d.ts +13 -5
  18. package/dist/dataStores.d.ts.map +1 -1
  19. package/dist/dataStores.js +39 -18
  20. package/dist/dataStores.js.map +1 -1
  21. package/dist/deltaScheduler.d.ts +4 -5
  22. package/dist/deltaScheduler.d.ts.map +1 -1
  23. package/dist/deltaScheduler.js +54 -35
  24. package/dist/deltaScheduler.js.map +1 -1
  25. package/dist/garbageCollection.d.ts +31 -27
  26. package/dist/garbageCollection.d.ts.map +1 -1
  27. package/dist/garbageCollection.js +76 -75
  28. package/dist/garbageCollection.js.map +1 -1
  29. package/dist/orderedClientElection.d.ts +6 -57
  30. package/dist/orderedClientElection.d.ts.map +1 -1
  31. package/dist/orderedClientElection.js +25 -140
  32. package/dist/orderedClientElection.js.map +1 -1
  33. package/dist/packageVersion.d.ts +1 -1
  34. package/dist/packageVersion.js +1 -1
  35. package/dist/packageVersion.js.map +1 -1
  36. package/dist/summarizerClientElection.d.ts +0 -2
  37. package/dist/summarizerClientElection.d.ts.map +1 -1
  38. package/dist/summarizerClientElection.js +2 -7
  39. package/dist/summarizerClientElection.js.map +1 -1
  40. package/dist/summaryManager.d.ts.map +1 -1
  41. package/dist/summaryManager.js +3 -14
  42. package/dist/summaryManager.js.map +1 -1
  43. package/lib/blobManager.d.ts +13 -1
  44. package/lib/blobManager.d.ts.map +1 -1
  45. package/lib/blobManager.js +52 -0
  46. package/lib/blobManager.js.map +1 -1
  47. package/lib/connectionTelemetry.js +7 -7
  48. package/lib/connectionTelemetry.js.map +1 -1
  49. package/lib/containerRuntime.d.ts +27 -3
  50. package/lib/containerRuntime.d.ts.map +1 -1
  51. package/lib/containerRuntime.js +101 -15
  52. package/lib/containerRuntime.js.map +1 -1
  53. package/lib/dataStore.js +8 -1
  54. package/lib/dataStore.js.map +1 -1
  55. package/lib/dataStoreContext.d.ts +9 -3
  56. package/lib/dataStoreContext.d.ts.map +1 -1
  57. package/lib/dataStoreContext.js +22 -6
  58. package/lib/dataStoreContext.js.map +1 -1
  59. package/lib/dataStores.d.ts +13 -5
  60. package/lib/dataStores.d.ts.map +1 -1
  61. package/lib/dataStores.js +39 -18
  62. package/lib/dataStores.js.map +1 -1
  63. package/lib/deltaScheduler.d.ts +4 -5
  64. package/lib/deltaScheduler.d.ts.map +1 -1
  65. package/lib/deltaScheduler.js +54 -35
  66. package/lib/deltaScheduler.js.map +1 -1
  67. package/lib/garbageCollection.d.ts +31 -27
  68. package/lib/garbageCollection.d.ts.map +1 -1
  69. package/lib/garbageCollection.js +75 -74
  70. package/lib/garbageCollection.js.map +1 -1
  71. package/lib/orderedClientElection.d.ts +6 -57
  72. package/lib/orderedClientElection.d.ts.map +1 -1
  73. package/lib/orderedClientElection.js +25 -140
  74. package/lib/orderedClientElection.js.map +1 -1
  75. package/lib/packageVersion.d.ts +1 -1
  76. package/lib/packageVersion.js +1 -1
  77. package/lib/packageVersion.js.map +1 -1
  78. package/lib/summarizerClientElection.d.ts +0 -2
  79. package/lib/summarizerClientElection.d.ts.map +1 -1
  80. package/lib/summarizerClientElection.js +2 -7
  81. package/lib/summarizerClientElection.js.map +1 -1
  82. package/lib/summaryManager.d.ts.map +1 -1
  83. package/lib/summaryManager.js +3 -14
  84. package/lib/summaryManager.js.map +1 -1
  85. package/package.json +33 -21
  86. package/src/blobManager.ts +60 -1
  87. package/src/connectionTelemetry.ts +7 -7
  88. package/src/containerRuntime.ts +106 -17
  89. package/src/dataStore.ts +7 -1
  90. package/src/dataStoreContext.ts +22 -7
  91. package/src/dataStores.ts +40 -19
  92. package/src/deltaScheduler.ts +65 -39
  93. package/src/garbageCollection.ts +92 -78
  94. package/src/orderedClientElection.ts +25 -154
  95. package/src/packageVersion.ts +1 -1
  96. package/src/summarizerClientElection.ts +2 -7
  97. package/src/summaryManager.ts +4 -15
@@ -7,6 +7,7 @@ import { DataCorruptionError, GenericError, UsageError, extractSafePropertiesFro
7
7
  import { MessageType, SummaryType, } from "@fluidframework/protocol-definitions";
8
8
  import { FlushMode, channelsTreeName, } from "@fluidframework/runtime-definitions";
9
9
  import { addBlobToSummary, addTreeToSummary, createRootSummarizerNodeWithGC, RequestParser, create404Response, exceptionToResponse, requestFluidObject, responseToException, seqFromTree, calculateStats, } from "@fluidframework/runtime-utils";
10
+ import { GCDataBuilder } from "@fluidframework/garbage-collector";
10
11
  import { v4 as uuid } from "uuid";
11
12
  import { ContainerFluidHandleContext } from "./containerHandleContext";
12
13
  import { FluidDataStoreRegistry } from "./dataStoreRegistry";
@@ -24,7 +25,7 @@ import { OrderedClientCollection, OrderedClientElection } from "./orderedClientE
24
25
  import { SummarizerClientElection, summarizerClientType } from "./summarizerClientElection";
25
26
  import { formExponentialFn, Throttler } from "./throttler";
26
27
  import { RunWhileConnectedCoordinator } from "./runWhileConnectedCoordinator";
27
- import { GarbageCollector, gcTreeKey, } from "./garbageCollection";
28
+ import { GarbageCollector, GCNodeType, gcTreeKey, } from "./garbageCollection";
28
29
  import { channelToDataStore, isDataStoreAliasMessage, } from "./dataStore";
29
30
  import { BindBatchTracker } from "./batchTracker";
30
31
  import { OpTracker } from "./opTelemetry";
@@ -312,7 +313,7 @@ export class ScheduleManager {
312
313
  assert(this.batchClientId === undefined, 0x2a2 /* "Batch is interrupted by other client op. Should be caught by trackPending()" */);
313
314
  // This could be the beginning of a new batch or an individual message.
314
315
  this.emitter.emit("batchBegin", message);
315
- this.deltaScheduler.batchBegin();
316
+ this.deltaScheduler.batchBegin(message);
316
317
  const batch = (_a = message === null || message === void 0 ? void 0 : message.metadata) === null || _a === void 0 ? void 0 : _a.batch;
317
318
  if (batch) {
318
319
  this.batchClientId = message.clientId;
@@ -332,7 +333,7 @@ export class ScheduleManager {
332
333
  this.hitError = true;
333
334
  this.batchClientId = undefined;
334
335
  this.emitter.emit("batchEnd", error, message);
335
- this.deltaScheduler.batchEnd();
336
+ this.deltaScheduler.batchEnd(message);
336
337
  return;
337
338
  }
338
339
  const batch = (_a = message === null || message === void 0 ? void 0 : message.metadata) === null || _a === void 0 ? void 0 : _a.batch;
@@ -341,7 +342,7 @@ export class ScheduleManager {
341
342
  if (this.batchClientId === undefined || batch === false) {
342
343
  this.batchClientId = undefined;
343
344
  this.emitter.emit("batchEnd", undefined, message);
344
- this.deltaScheduler.batchEnd();
345
+ this.deltaScheduler.batchEnd(message);
345
346
  return;
346
347
  }
347
348
  }
@@ -466,12 +467,7 @@ export class ContainerRuntime extends TypedEventEmitter {
466
467
  this._maxOpSizeInBytes = ((_d = this.mc.config.getNumber(maxOpSizeInBytesKey)) !== null && _d !== void 0 ? _d : defaultMaxOpSizeInBytes);
467
468
  this.maxConsecutiveReconnects = (_e = this.mc.config.getNumber(maxConsecutiveReconnectsKey)) !== null && _e !== void 0 ? _e : this.defaultMaxConsecutiveReconnects;
468
469
  this._flushMode = runtimeOptions.flushMode;
469
- this.garbageCollector = GarbageCollector.create(this, this.runtimeOptions.gcOptions, (unusedRoutes) => this.dataStores.deleteUnusedRoutes(unusedRoutes), (nodePath) => this.dataStores.getNodePackagePath(nodePath),
470
- /**
471
- * Returns the timestamp of the last message seen by this client. This is used by garbage collector as
472
- * the current reference timestamp for tracking unreferenced objects.
473
- */
474
- () => { var _a, _b, _c; return (_b = (_a = this.deltaManager.lastMessage) === null || _a === void 0 ? void 0 : _a.timestamp) !== null && _b !== void 0 ? _b : (_c = this.messageAtLastSummary) === null || _c === void 0 ? void 0 : _c.timestamp; }, () => { var _a; return (_a = this.messageAtLastSummary) === null || _a === void 0 ? void 0 : _a.timestamp; }, context.baseSnapshot, async (id) => readAndParse(this.storage, id), this.mc.logger, existing, metadata);
470
+ this.garbageCollector = GarbageCollector.create(this, this.runtimeOptions.gcOptions, (nodePath) => this.getGCNodePackagePath(nodePath), () => { var _a; return (_a = this.messageAtLastSummary) === null || _a === void 0 ? void 0 : _a.timestamp; }, context.baseSnapshot, async (id) => readAndParse(this.storage, id), this.mc.logger, existing, metadata);
475
471
  const loadedFromSequenceNumber = this.deltaManager.initialSequenceNumber;
476
472
  this.summarizerNode = createRootSummarizerNodeWithGC(ChildLogger.create(this.logger, "SummarizerNode"),
477
473
  // Summarize function to call when summarize is called. Summarizer node always tracks summary state.
@@ -492,7 +488,7 @@ export class ContainerRuntime extends TypedEventEmitter {
492
488
  if (this.context.baseSnapshot) {
493
489
  this.summarizerNode.loadBaseSummaryWithoutDifferential(this.context.baseSnapshot);
494
490
  }
495
- this.dataStores = new DataStores(getSummaryForDatastores(context.baseSnapshot, metadata), this, (attachMsg) => this.submit(ContainerMessageType.Attach, attachMsg), (id, createParam) => (summarizeInternal, getGCDataFn, getBaseGCDetailsFn) => this.summarizerNode.createChild(summarizeInternal, id, createParam, undefined, getGCDataFn, getBaseGCDetailsFn), (id) => this.summarizerNode.deleteChild(id), this.mc.logger, async () => this.garbageCollector.getDataStoreBaseGCDetails(), (path, timestampMs, packagePath) => this.garbageCollector.nodeUpdated(path, "Changed", timestampMs, packagePath), new Map(dataStoreAliasMap), this.garbageCollector.writeDataAtRoot);
491
+ this.dataStores = new DataStores(getSummaryForDatastores(context.baseSnapshot, metadata), this, (attachMsg) => this.submit(ContainerMessageType.Attach, attachMsg), (id, createParam) => (summarizeInternal, getGCDataFn, getBaseGCDetailsFn) => this.summarizerNode.createChild(summarizeInternal, id, createParam, undefined, getGCDataFn, getBaseGCDetailsFn), (id) => this.summarizerNode.deleteChild(id), this.mc.logger, async () => this.garbageCollector.getBaseGCDetails(), (path, timestampMs, packagePath) => this.garbageCollector.nodeUpdated(path, "Changed", timestampMs, packagePath), new Map(dataStoreAliasMap), this.garbageCollector.writeDataAtRoot);
496
492
  this.blobManager = new BlobManager(this.handleContext, blobManagerSnapshot, () => this.storage, (blobId) => this.submit(ContainerMessageType.BlobAttach, undefined, undefined, { blobId }), this, this.logger);
497
493
  this.scheduleManager = new ScheduleManager(context.deltaManager, this, ChildLogger.create(this.logger, "ScheduleManager"));
498
494
  this.deltaSender = this.deltaManager;
@@ -1163,7 +1159,14 @@ export class ContainerRuntime extends TypedEventEmitter {
1163
1159
  */
1164
1160
  async createRootDataStoreLegacy(pkg, rootDataStoreId) {
1165
1161
  const fluidDataStore = await this._createDataStore(pkg, true /* isRoot */, rootDataStoreId);
1166
- fluidDataStore.bindToContext();
1162
+ // back-compat 0.59.1000 - makeVisibleAndAttachGraph was added in this version to IFluidDataStoreChannel. For
1163
+ // older versions, we still have to call bindToContext.
1164
+ if (fluidDataStore.makeVisibleAndAttachGraph !== undefined) {
1165
+ fluidDataStore.makeVisibleAndAttachGraph();
1166
+ }
1167
+ else {
1168
+ fluidDataStore.bindToContext();
1169
+ }
1167
1170
  return fluidDataStore;
1168
1171
  }
1169
1172
  async createRootDataStore(pkg, rootDataStoreId) {
@@ -1217,7 +1220,14 @@ export class ContainerRuntime extends TypedEventEmitter {
1217
1220
  async _createDataStoreWithPropsLegacy(pkg, props, id = uuid(), isRoot = false) {
1218
1221
  const fluidDataStore = await this.dataStores._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id, isRoot, props).realize();
1219
1222
  if (isRoot) {
1220
- fluidDataStore.bindToContext();
1223
+ // back-compat 0.59.1000 - makeVisibleAndAttachGraph was added in this version to IFluidDataStoreChannel.
1224
+ // For older versions, we still have to call bindToContext.
1225
+ if (fluidDataStore.makeVisibleAndAttachGraph !== undefined) {
1226
+ fluidDataStore.makeVisibleAndAttachGraph();
1227
+ }
1228
+ else {
1229
+ fluidDataStore.bindToContext();
1230
+ }
1221
1231
  this.logger.sendTelemetryEvent({
1222
1232
  eventName: "Root datastore with props",
1223
1233
  hasProps: props !== undefined,
@@ -1364,7 +1374,12 @@ export class ContainerRuntime extends TypedEventEmitter {
1364
1374
  * @param fullGC - true to bypass optimizations and force full generation of GC data.
1365
1375
  */
1366
1376
  async getGCData(fullGC) {
1367
- return this.dataStores.getGCData(fullGC);
1377
+ const builder = new GCDataBuilder();
1378
+ const dsGCData = await this.dataStores.getGCData(fullGC);
1379
+ builder.addNodes(dsGCData.gcNodes);
1380
+ const blobsGCData = this.blobManager.getGCData(fullGC);
1381
+ builder.addNodes(blobsGCData.gcNodes);
1382
+ return builder.getGCData();
1368
1383
  }
1369
1384
  /**
1370
1385
  * Implementation of IGarbageCollectionRuntime::updateUsedRoutes.
@@ -1378,7 +1393,78 @@ export class ContainerRuntime extends TypedEventEmitter {
1378
1393
  // summarizing is required and asserted by the the summarizer node. We are the root and are
1379
1394
  // always referenced, so the used routes is only self-route (empty string).
1380
1395
  this.summarizerNode.updateUsedRoutes([""]);
1381
- return this.dataStores.updateUsedRoutes(usedRoutes, gcTimestamp);
1396
+ const dataStoreUsedRoutes = [];
1397
+ for (const route of usedRoutes) {
1398
+ if (route.split("/")[1] !== BlobManager.basePath) {
1399
+ dataStoreUsedRoutes.push(route);
1400
+ }
1401
+ }
1402
+ return this.dataStores.updateUsedRoutes(dataStoreUsedRoutes, gcTimestamp);
1403
+ }
1404
+ /**
1405
+ * When running GC in test mode, this is called to delete objects whose routes are unused. This enables testing
1406
+ * scenarios with accessing deleted content.
1407
+ * @param unusedRoutes - The routes that are unused in all data stores in this Container.
1408
+ */
1409
+ deleteUnusedRoutes(unusedRoutes) {
1410
+ const blobManagerUnusedRoutes = [];
1411
+ const dataStoreUnusedRoutes = [];
1412
+ for (const route of unusedRoutes) {
1413
+ if (this.isBlobPath(route)) {
1414
+ blobManagerUnusedRoutes.push(route);
1415
+ }
1416
+ else {
1417
+ dataStoreUnusedRoutes.push(route);
1418
+ }
1419
+ }
1420
+ this.blobManager.deleteUnusedRoutes(blobManagerUnusedRoutes);
1421
+ this.dataStores.deleteUnusedRoutes(dataStoreUnusedRoutes);
1422
+ }
1423
+ /**
1424
+ * Returns a server generated referenced timestamp to be used to track unreferenced nodes by GC.
1425
+ */
1426
+ getCurrentReferenceTimestampMs() {
1427
+ var _a, _b, _c;
1428
+ // Use the timestamp of the last message seen by this client as that is server generated. If no messages have
1429
+ // been processed, use the timestamp of the message from the last summary.
1430
+ return (_b = (_a = this.deltaManager.lastMessage) === null || _a === void 0 ? void 0 : _a.timestamp) !== null && _b !== void 0 ? _b : (_c = this.messageAtLastSummary) === null || _c === void 0 ? void 0 : _c.timestamp;
1431
+ }
1432
+ /**
1433
+ * Returns the type of the GC node. Currently, there are nodes that belong to data store and nodes that belong
1434
+ * to the blob manager.
1435
+ */
1436
+ getNodeType(nodePath) {
1437
+ if (this.isBlobPath(nodePath)) {
1438
+ return GCNodeType.Blob;
1439
+ }
1440
+ if (this.dataStores.isDataStoreNode(nodePath)) {
1441
+ return GCNodeType.DataStore;
1442
+ }
1443
+ // Root node ("/") and DDS nodes belong to "Other" node types.
1444
+ return GCNodeType.Other;
1445
+ }
1446
+ /**
1447
+ * Called by GC to retrieve the package path of the node with the given path. The node should belong to a
1448
+ * data store or an attachment blob.
1449
+ */
1450
+ getGCNodePackagePath(nodePath) {
1451
+ // If the node is a blob, return "_blobs" as the package path.
1452
+ if (this.isBlobPath(nodePath)) {
1453
+ return ["_blobs"];
1454
+ }
1455
+ const dataStorePkgPath = this.dataStores.getDataStorePackagePath(nodePath);
1456
+ assert(dataStorePkgPath !== undefined, 0x2d6 /* "Package path requested for unknown node type." */);
1457
+ return dataStorePkgPath;
1458
+ }
1459
+ /**
1460
+ * Returns whether a given path is for attachment blobs that are in the format - "/BlobManager.basePath/...".
1461
+ */
1462
+ isBlobPath(path) {
1463
+ const pathParts = path.split("/");
1464
+ if (pathParts.length < 2 || pathParts[1] !== BlobManager.basePath) {
1465
+ return false;
1466
+ }
1467
+ return true;
1382
1468
  }
1383
1469
  /**
1384
1470
  * Runs garbage collection and updates the reference / used state of the nodes in the container.