@fluidframework/container-runtime 2.2.0 → 2.2.2

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 (43) hide show
  1. package/container-runtime.test-files.tar +0 -0
  2. package/dist/containerRuntime.d.ts +8 -3
  3. package/dist/containerRuntime.d.ts.map +1 -1
  4. package/dist/containerRuntime.js +27 -15
  5. package/dist/containerRuntime.js.map +1 -1
  6. package/dist/opLifecycle/index.d.ts +1 -1
  7. package/dist/opLifecycle/index.d.ts.map +1 -1
  8. package/dist/opLifecycle/index.js.map +1 -1
  9. package/dist/opLifecycle/remoteMessageProcessor.d.ts +37 -17
  10. package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  11. package/dist/opLifecycle/remoteMessageProcessor.js +44 -33
  12. package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
  13. package/dist/packageVersion.d.ts +1 -1
  14. package/dist/packageVersion.js +1 -1
  15. package/dist/packageVersion.js.map +1 -1
  16. package/dist/pendingStateManager.d.ts +13 -13
  17. package/dist/pendingStateManager.d.ts.map +1 -1
  18. package/dist/pendingStateManager.js +31 -27
  19. package/dist/pendingStateManager.js.map +1 -1
  20. package/lib/containerRuntime.d.ts +8 -3
  21. package/lib/containerRuntime.d.ts.map +1 -1
  22. package/lib/containerRuntime.js +27 -15
  23. package/lib/containerRuntime.js.map +1 -1
  24. package/lib/opLifecycle/index.d.ts +1 -1
  25. package/lib/opLifecycle/index.d.ts.map +1 -1
  26. package/lib/opLifecycle/index.js.map +1 -1
  27. package/lib/opLifecycle/remoteMessageProcessor.d.ts +37 -17
  28. package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  29. package/lib/opLifecycle/remoteMessageProcessor.js +44 -33
  30. package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
  31. package/lib/packageVersion.d.ts +1 -1
  32. package/lib/packageVersion.js +1 -1
  33. package/lib/packageVersion.js.map +1 -1
  34. package/lib/pendingStateManager.d.ts +13 -13
  35. package/lib/pendingStateManager.d.ts.map +1 -1
  36. package/lib/pendingStateManager.js +32 -28
  37. package/lib/pendingStateManager.js.map +1 -1
  38. package/package.json +19 -23
  39. package/src/containerRuntime.ts +40 -18
  40. package/src/opLifecycle/index.ts +2 -1
  41. package/src/opLifecycle/remoteMessageProcessor.ts +84 -55
  42. package/src/packageVersion.ts +1 -1
  43. package/src/pendingStateManager.ts +42 -31
@@ -20,7 +20,13 @@ import {
20
20
  type LocalContainerRuntimeMessage,
21
21
  } from "./messageTypes.js";
22
22
  import { asBatchMetadata, asEmptyBatchLocalOpMetadata } from "./metadata.js";
23
- import { BatchId, BatchMessage, generateBatchId, InboundBatch } from "./opLifecycle/index.js";
23
+ import {
24
+ BatchId,
25
+ BatchMessage,
26
+ BatchStartInfo,
27
+ generateBatchId,
28
+ InboundMessageResult,
29
+ } from "./opLifecycle/index.js";
24
30
 
25
31
  /**
26
32
  * This represents a message that has been submitted and is added to the pending queue when `submit` is called on the
@@ -326,49 +332,50 @@ export class PendingStateManager implements IDisposable {
326
332
  }
327
333
 
328
334
  /**
329
- * Processes an inbound batch of messages - May be local or remote.
335
+ * Processes an inbound message or batch of messages - May be local or remote.
330
336
  *
331
- * @param batch - The inbound batch of messages to process. Could be local or remote.
332
- * @param local - true if we submitted this batch and expect corresponding pending messages
333
- * @returns The inbound batch's messages with localOpMetadata "zipped" in.
337
+ * @param inbound - The inbound message(s) to process, with extra info (e.g. about the start of a batch). Could be local or remote.
338
+ * @param local - true if we submitted these messages and expect corresponding pending messages
339
+ * @returns The inbound messages with localOpMetadata "zipped" in.
334
340
  *
335
- * @remarks Closes the container if:
336
- * - The batchStartCsn doesn't match for local batches
341
+ * @throws a DataProcessingError if the pending message content doesn't match the incoming message content (for local messages)
337
342
  */
338
- public processInboundBatch(
339
- batch: InboundBatch,
343
+ public processInboundMessages(
344
+ inbound: InboundMessageResult,
340
345
  local: boolean,
341
346
  ): {
342
347
  message: InboundSequencedContainerRuntimeMessage;
343
348
  localOpMetadata?: unknown;
344
349
  }[] {
345
350
  if (local) {
346
- return this.processPendingLocalBatch(batch);
351
+ return this.processPendingLocalMessages(inbound);
347
352
  }
348
353
 
349
354
  // No localOpMetadata for remote messages
350
- return batch.messages.map((message) => ({ message }));
355
+ const messages = inbound.type === "fullBatch" ? inbound.messages : [inbound.nextMessage];
356
+ return messages.map((message) => ({ message }));
351
357
  }
352
358
 
353
359
  /**
354
- * Processes the incoming batch from the server that was submitted by this client.
355
- * It verifies that messages are received in the right order and that the batch information is correct.
356
- * @param batch - The inbound batch (originating from this client) to correlate with the pending local state
357
- * @returns The inbound batch's messages with localOpMetadata "zipped" in.
360
+ * Processes the incoming message(s) from the server that were submitted by this client.
361
+ * It verifies that messages are received in the right order and that any batch information is correct.
362
+ * @param inbound - The inbound message(s) (originating from this client) to correlate with the pending local state
363
+ * @throws DataProcessingError if the pending message content doesn't match the incoming message content for any message here
364
+ * @returns The inbound messages with localOpMetadata "zipped" in.
358
365
  */
359
- private processPendingLocalBatch(batch: InboundBatch): {
366
+ private processPendingLocalMessages(inbound: InboundMessageResult): {
360
367
  message: InboundSequencedContainerRuntimeMessage;
361
368
  localOpMetadata: unknown;
362
369
  }[] {
363
- this.onLocalBatchBegin(batch);
370
+ if ("batchStart" in inbound) {
371
+ this.onLocalBatchBegin(inbound.batchStart, inbound.length);
372
+ }
364
373
 
365
374
  // Empty batch
366
- if (batch.messages.length === 0) {
367
- assert(
368
- batch.emptyBatchSequenceNumber !== undefined,
369
- 0x9fb /* Expected sequence number for empty batch */,
375
+ if (inbound.length === 0) {
376
+ const localOpMetadata = this.processNextPendingMessage(
377
+ inbound.batchStart.keyMessage.sequenceNumber,
370
378
  );
371
- const localOpMetadata = this.processNextPendingMessage(batch.emptyBatchSequenceNumber);
372
379
  assert(
373
380
  asEmptyBatchLocalOpMetadata(localOpMetadata)?.emptyBatch === true,
374
381
  0xa20 /* Expected empty batch marker */,
@@ -376,7 +383,9 @@ export class PendingStateManager implements IDisposable {
376
383
  return [];
377
384
  }
378
385
 
379
- return batch.messages.map((message) => ({
386
+ const messages = inbound.type === "fullBatch" ? inbound.messages : [inbound.nextMessage];
387
+
388
+ return messages.map((message) => ({
380
389
  message,
381
390
  localOpMetadata: this.processNextPendingMessage(message.sequenceNumber, message),
382
391
  }));
@@ -448,7 +457,7 @@ export class PendingStateManager implements IDisposable {
448
457
  /**
449
458
  * Check if the incoming batch matches the batch info for the next pending message.
450
459
  */
451
- private onLocalBatchBegin(batch: InboundBatch) {
460
+ private onLocalBatchBegin(batchStart: BatchStartInfo, batchLength?: number) {
452
461
  // Get the next message from the pending queue. Verify a message exists.
453
462
  const pendingMessage = this.pendingMessages.peekFront();
454
463
  assert(
@@ -460,25 +469,27 @@ export class PendingStateManager implements IDisposable {
460
469
  // In this case the next pending message is an empty batch marker.
461
470
  // Empty batches became empty on Resubmit, and submit them and track them in case
462
471
  // a different fork of this container also submitted the same batch (and it may not be empty for that fork).
463
- const firstMessage = batch.messages.length > 0 ? batch.messages[0] : undefined;
464
- const expectedPendingBatchLength = batch.messages.length === 0 ? 1 : batch.messages.length;
472
+ const firstMessage = batchStart.keyMessage;
473
+ // -1 length is for back compat, undefined length means we actually don't know it
474
+ const skipLengthCheck =
475
+ pendingMessage.batchInfo.length === -1 || batchLength === undefined;
476
+ const expectedPendingBatchLength = batchLength === 0 ? 1 : batchLength;
465
477
 
466
478
  // We expect the incoming batch to be of the same length, starting at the same clientSequenceNumber,
467
479
  // as the batch we originally submitted.
468
480
  // We have another later check to compare the message contents, which we'd expect to fail if this check does,
469
481
  // so we don't throw here, merely log. In a later release this check may replace that one.
470
482
  if (
471
- pendingMessage.batchInfo.batchStartCsn !== batch.batchStartCsn ||
472
- (pendingMessage.batchInfo.length >= 0 && // -1 length is back compat and isn't suitable for this check
473
- pendingMessage.batchInfo.length !== expectedPendingBatchLength)
483
+ pendingMessage.batchInfo.batchStartCsn !== batchStart.batchStartCsn ||
484
+ (!skipLengthCheck && pendingMessage.batchInfo.length !== expectedPendingBatchLength)
474
485
  ) {
475
486
  this.logger?.sendErrorEvent({
476
487
  eventName: "BatchInfoMismatch",
477
488
  details: {
478
489
  pendingBatchCsn: pendingMessage.batchInfo.batchStartCsn,
479
- batchStartCsn: batch.batchStartCsn,
490
+ batchStartCsn: batchStart.batchStartCsn,
480
491
  pendingBatchLength: pendingMessage.batchInfo.length,
481
- batchLength: batch.messages.length,
492
+ batchLength,
482
493
  pendingMessageBatchMetadata: asBatchMetadata(pendingMessage.opMetadata)?.batch,
483
494
  messageBatchMetadata: asBatchMetadata(firstMessage?.metadata)?.batch,
484
495
  },