@fluidframework/container-runtime 2.0.0-rc.3.0.3 → 2.0.0-rc.3.0.5

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 (46) hide show
  1. package/dist/channelCollection.js +1 -1
  2. package/dist/channelCollection.js.map +1 -1
  3. package/dist/containerRuntime.d.ts.map +1 -1
  4. package/dist/containerRuntime.js +30 -43
  5. package/dist/containerRuntime.js.map +1 -1
  6. package/dist/metadata.d.ts +2 -2
  7. package/dist/metadata.d.ts.map +1 -1
  8. package/dist/metadata.js.map +1 -1
  9. package/dist/opLifecycle/batchManager.d.ts +4 -1
  10. package/dist/opLifecycle/batchManager.d.ts.map +1 -1
  11. package/dist/opLifecycle/batchManager.js +0 -10
  12. package/dist/opLifecycle/batchManager.js.map +1 -1
  13. package/dist/opLifecycle/outbox.d.ts +0 -4
  14. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  15. package/dist/opLifecycle/outbox.js +7 -38
  16. package/dist/opLifecycle/outbox.js.map +1 -1
  17. package/dist/packageVersion.d.ts +1 -1
  18. package/dist/packageVersion.js +1 -1
  19. package/dist/packageVersion.js.map +1 -1
  20. package/lib/channelCollection.js +1 -1
  21. package/lib/channelCollection.js.map +1 -1
  22. package/lib/containerRuntime.d.ts.map +1 -1
  23. package/lib/containerRuntime.js +30 -43
  24. package/lib/containerRuntime.js.map +1 -1
  25. package/lib/metadata.d.ts +2 -2
  26. package/lib/metadata.d.ts.map +1 -1
  27. package/lib/metadata.js.map +1 -1
  28. package/lib/opLifecycle/batchManager.d.ts +4 -1
  29. package/lib/opLifecycle/batchManager.d.ts.map +1 -1
  30. package/lib/opLifecycle/batchManager.js +0 -10
  31. package/lib/opLifecycle/batchManager.js.map +1 -1
  32. package/lib/opLifecycle/outbox.d.ts +0 -4
  33. package/lib/opLifecycle/outbox.d.ts.map +1 -1
  34. package/lib/opLifecycle/outbox.js +7 -38
  35. package/lib/opLifecycle/outbox.js.map +1 -1
  36. package/lib/packageVersion.d.ts +1 -1
  37. package/lib/packageVersion.js +1 -1
  38. package/lib/packageVersion.js.map +1 -1
  39. package/package.json +17 -17
  40. package/src/channelCollection.ts +1 -1
  41. package/src/containerRuntime.ts +42 -56
  42. package/src/metadata.ts +2 -2
  43. package/src/opLifecycle/README.md +4 -4
  44. package/src/opLifecycle/batchManager.ts +5 -14
  45. package/src/opLifecycle/outbox.ts +7 -53
  46. package/src/packageVersion.ts +1 -1
@@ -1244,6 +1244,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
1244
1244
  this.emitDirtyDocumentEvent = false;
1245
1245
  let newState;
1246
1246
  try {
1247
+ this.submitIdAllocationOpIfNeeded(true);
1247
1248
  // replay the ops
1248
1249
  this.pendingStateManager.replayPendingStates();
1249
1250
  }
@@ -1420,9 +1421,10 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
1420
1421
  // We do not need to make a deep copy. Each layer will just replace message.contents itself,
1421
1422
  // but will not modify the contents object (likely it will replace it on the message).
1422
1423
  const messageCopy = { ...messageArg };
1424
+ const savedOp = messageCopy.metadata?.savedOp;
1423
1425
  for (const message of this.remoteMessageProcessor.process(messageCopy)) {
1424
- if (modernRuntimeMessage) {
1425
- this.processCore({
1426
+ const msg = modernRuntimeMessage
1427
+ ? {
1426
1428
  // Cast it since we expect it to be this based on modernRuntimeMessage computation above.
1427
1429
  // There is nothing really ensuring that anytime original message.type is Operation that
1428
1430
  // the result messages will be so. In the end modern bool being true only directs to
@@ -1430,12 +1432,16 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
1430
1432
  message: message,
1431
1433
  local,
1432
1434
  modernRuntimeMessage,
1433
- });
1434
- }
1435
- else {
1436
- // Unrecognized message will be ignored.
1437
- this.processCore({ message, local, modernRuntimeMessage });
1438
- }
1435
+ }
1436
+ : // Unrecognized message will be ignored.
1437
+ {
1438
+ message,
1439
+ local,
1440
+ modernRuntimeMessage,
1441
+ };
1442
+ msg.savedOp = savedOp;
1443
+ // ensure that we observe any re-entrancy, and if needed, rebase ops
1444
+ this.ensureNoDataModelChanges(() => this.processCore(msg));
1439
1445
  }
1440
1446
  }
1441
1447
  /**
@@ -1500,9 +1506,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
1500
1506
  // stashed ops flow. The compressor is stashed with these ops already processed.
1501
1507
  // That said, in idCompressorMode === "delayed", we might not serialize ID compressor, and
1502
1508
  // thus we need to process all the ops.
1503
- if (!(this.skipSavedCompressorOps &&
1504
- messageWithContext.message.metadata?.savedOp ===
1505
- true)) {
1509
+ if (!(this.skipSavedCompressorOps && messageWithContext.savedOp === true)) {
1506
1510
  const range = messageWithContext.message.contents;
1507
1511
  // Some other client turned on the id compressor. If we have not turned it on,
1508
1512
  // put it in a pending queue and delay finalization.
@@ -1631,9 +1635,9 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
1631
1635
  let checkpoint;
1632
1636
  let result;
1633
1637
  if (this.mc.config.getBoolean("Fluid.ContainerRuntime.EnableRollback")) {
1634
- // Note: we are not touching this.pendingAttachBatch here, for two reasons:
1635
- // 1. It would not help, as we flush attach ops as they become available.
1636
- // 2. There is no way to undo process of data store creation.
1638
+ // Note: we are not touching any batches other than mainBatch here, for two reasons:
1639
+ // 1. It would not help, as other batches are flushed independently from main batch.
1640
+ // 2. There is no way to undo process of data store creation, blob creation, ID compressor ops, or other things tracked by other batches.
1637
1641
  checkpoint = this.outbox.checkpoint().mainBatch;
1638
1642
  }
1639
1643
  try {
@@ -2378,9 +2382,11 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
2378
2382
  this.verifyNotClosed();
2379
2383
  return this.blobManager.createBlob(blob, signal);
2380
2384
  }
2381
- submitIdAllocationOpIfNeeded() {
2385
+ submitIdAllocationOpIfNeeded(resubmitOutstandingRanges = false) {
2382
2386
  if (this._idCompressor) {
2383
- const idRange = this._idCompressor.takeNextCreationRange();
2387
+ const idRange = resubmitOutstandingRanges
2388
+ ? this.idCompressor?.takeUnfinalizedCreationRange()
2389
+ : this._idCompressor.takeNextCreationRange();
2384
2390
  // Don't include the idRange if there weren't any Ids allocated
2385
2391
  if (idRange?.ids !== undefined) {
2386
2392
  const idAllocationMessage = {
@@ -2442,32 +2448,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
2442
2448
  referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
2443
2449
  });
2444
2450
  }
2445
- // If this is attach message for new data store, and we are in a batch, send this op out of order
2446
- // Is it safe:
2447
- // Yes, this should be safe reordering. Newly created data stores are not visible through API surface.
2448
- // They become visible only when aliased, or handle to some sub-element of newly created datastore
2449
- // is stored in some DDS, i.e. only after some other op.
2450
- // Why:
2451
- // Attach ops are large, and expensive to process. Plus there are scenarios where a lot of new data
2452
- // stores are created, causing issues like relay service throttling (too many ops) and catastrophic
2453
- // failure (batch is too large). Pushing them earlier and outside of main batch should alleviate
2454
- // these issues.
2455
- // Cons:
2456
- // 1. With large batches, relay service may throttle clients. Clients may disconnect while throttled.
2457
- // This change creates new possibility of a lot of newly created data stores never being referenced
2458
- // because client died before it had a change to submit the rest of the ops. This will create more
2459
- // garbage that needs to be collected leveraging GC (Garbage Collection) feature.
2460
- // 2. Sending ops out of order means they are excluded from rollback functionality. This is not an issue
2461
- // today as rollback can't undo creation of data store. To some extent not sending them is a bigger
2462
- // issue than sending.
2463
- // Please note that this does not change file format, so it can be disabled in the future if this
2464
- // optimization no longer makes sense (for example, batch compression may make it less appealing).
2465
- if (this.currentlyBatching() &&
2466
- type === messageTypes_js_1.ContainerMessageType.Attach &&
2467
- this.disableAttachReorder !== true) {
2468
- this.outbox.submitAttach(message);
2469
- }
2470
- else if (type === messageTypes_js_1.ContainerMessageType.BlobAttach) {
2451
+ if (type === messageTypes_js_1.ContainerMessageType.BlobAttach) {
2471
2452
  // BlobAttach ops must have their metadata visible and cannot be grouped (see opGroupingManager.ts)
2472
2453
  this.outbox.submitBlobAttach(message);
2473
2454
  }
@@ -2599,7 +2580,13 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
2599
2580
  this.channelCollection.reSubmit(message.type, message.contents, localOpMetadata);
2600
2581
  break;
2601
2582
  case messageTypes_js_1.ContainerMessageType.IdAllocation: {
2602
- this.submit(message, localOpMetadata);
2583
+ // Allocation ops are never resubmitted/rebased. This is because they require special handling to
2584
+ // avoid being submitted out of order. For example, if the pending state manager contained
2585
+ // [idOp1, dataOp1, idOp2, dataOp2] and the resubmission of dataOp1 generated idOp3, that would be
2586
+ // placed into the outbox in the same batch as idOp1, but before idOp2 is resubmitted.
2587
+ // To avoid this, allocation ops are simply never resubmitted. Prior to invoking the pending state
2588
+ // manager to replay pending ops, the runtime will always submit a new allocation range that includes
2589
+ // all pending IDs. The resubmitted allocation ops are then ignored here.
2603
2590
  break;
2604
2591
  }
2605
2592
  case messageTypes_js_1.ContainerMessageType.ChunkedOp: