@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.
- package/container-runtime.test-files.tar +0 -0
- package/dist/containerRuntime.d.ts +8 -3
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +27 -15
- package/dist/containerRuntime.js.map +1 -1
- package/dist/opLifecycle/index.d.ts +1 -1
- package/dist/opLifecycle/index.d.ts.map +1 -1
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts +37 -17
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js +44 -33
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/pendingStateManager.d.ts +13 -13
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +31 -27
- package/dist/pendingStateManager.js.map +1 -1
- package/lib/containerRuntime.d.ts +8 -3
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +27 -15
- package/lib/containerRuntime.js.map +1 -1
- package/lib/opLifecycle/index.d.ts +1 -1
- package/lib/opLifecycle/index.d.ts.map +1 -1
- package/lib/opLifecycle/index.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts +37 -17
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js +44 -33
- package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/pendingStateManager.d.ts +13 -13
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +32 -28
- package/lib/pendingStateManager.js.map +1 -1
- package/package.json +19 -23
- package/src/containerRuntime.ts +40 -18
- package/src/opLifecycle/index.ts +2 -1
- package/src/opLifecycle/remoteMessageProcessor.ts +84 -55
- package/src/packageVersion.ts +1 -1
- 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 {
|
|
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
|
|
332
|
-
* @param local - true if we submitted
|
|
333
|
-
* @returns The inbound
|
|
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
|
-
* @
|
|
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
|
|
339
|
-
|
|
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.
|
|
351
|
+
return this.processPendingLocalMessages(inbound);
|
|
347
352
|
}
|
|
348
353
|
|
|
349
354
|
// No localOpMetadata for remote messages
|
|
350
|
-
|
|
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
|
|
355
|
-
* It verifies that messages are received in the right order and that
|
|
356
|
-
* @param
|
|
357
|
-
* @
|
|
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
|
|
366
|
+
private processPendingLocalMessages(inbound: InboundMessageResult): {
|
|
360
367
|
message: InboundSequencedContainerRuntimeMessage;
|
|
361
368
|
localOpMetadata: unknown;
|
|
362
369
|
}[] {
|
|
363
|
-
|
|
370
|
+
if ("batchStart" in inbound) {
|
|
371
|
+
this.onLocalBatchBegin(inbound.batchStart, inbound.length);
|
|
372
|
+
}
|
|
364
373
|
|
|
365
374
|
// Empty batch
|
|
366
|
-
if (
|
|
367
|
-
|
|
368
|
-
|
|
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
|
-
|
|
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(
|
|
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 =
|
|
464
|
-
|
|
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 !==
|
|
472
|
-
(pendingMessage.batchInfo.length
|
|
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:
|
|
490
|
+
batchStartCsn: batchStart.batchStartCsn,
|
|
480
491
|
pendingBatchLength: pendingMessage.batchInfo.length,
|
|
481
|
-
batchLength
|
|
492
|
+
batchLength,
|
|
482
493
|
pendingMessageBatchMetadata: asBatchMetadata(pendingMessage.opMetadata)?.batch,
|
|
483
494
|
messageBatchMetadata: asBatchMetadata(firstMessage?.metadata)?.batch,
|
|
484
495
|
},
|