@fluidframework/container-runtime 2.4.0-297385 → 2.4.0-299707
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 -0
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +94 -111
- package/dist/containerRuntime.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +1 -1
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +2 -6
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts +2 -0
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +16 -10
- package/dist/opLifecycle/outbox.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 +8 -2
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +14 -7
- package/dist/pendingStateManager.js.map +1 -1
- package/lib/containerRuntime.d.ts +8 -0
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +94 -111
- package/lib/containerRuntime.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts +1 -1
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +3 -7
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/opLifecycle/batchManager.d.ts +2 -0
- package/lib/opLifecycle/batchManager.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +16 -10
- package/lib/opLifecycle/outbox.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 +8 -2
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +14 -7
- package/lib/pendingStateManager.js.map +1 -1
- package/package.json +22 -21
- package/src/containerRuntime.ts +133 -147
- package/src/gc/garbageCollection.ts +5 -12
- package/src/opLifecycle/batchManager.ts +3 -0
- package/src/opLifecycle/outbox.ts +21 -10
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +26 -8
package/lib/containerRuntime.js
CHANGED
|
@@ -32,16 +32,23 @@ import { ScheduleManager } from "./scheduleManager.js";
|
|
|
32
32
|
import { DocumentsSchemaController, OrderedClientCollection, OrderedClientElection, RetriableSummaryError, RunWhileConnectedCoordinator, Summarizer, SummarizerClientElection, SummaryCollection, SummaryManager, aliasBlobName, chunksBlobName, createRootSummarizerNodeWithGC, electedSummarizerBlobName, extractSummaryMetadataMessage, idCompressorBlobName, metadataBlobName, rootHasIsolatedChannels, summarizerClientType, wrapSummaryInChannelsTree, } from "./summary/index.js";
|
|
33
33
|
import { Throttler, formExponentialFn } from "./throttler.js";
|
|
34
34
|
/**
|
|
35
|
-
*
|
|
35
|
+
* Creates an error object to be thrown / passed to Container's close fn in case of an unknown message type.
|
|
36
36
|
* The parameters are typed to support compile-time enforcement of handling all known types/behaviors
|
|
37
37
|
*
|
|
38
|
-
* @param
|
|
38
|
+
* @param unknownContainerRuntimeMessageType - Typed as something unexpected, to ensure all known types have been
|
|
39
39
|
* handled before calling this function (e.g. in a switch statement).
|
|
40
|
-
*
|
|
40
|
+
*
|
|
41
|
+
* @param codePath - The code path where the unexpected message type was encountered.
|
|
42
|
+
*
|
|
43
|
+
* @param sequencedMessage - The sequenced message that contained the unexpected message type.
|
|
44
|
+
*
|
|
41
45
|
*/
|
|
42
|
-
function
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
function getUnknownMessageTypeError(unknownContainerRuntimeMessageType, codePath, sequencedMessage) {
|
|
47
|
+
return DataProcessingError.create("Runtime message of unknown type", codePath, sequencedMessage, {
|
|
48
|
+
messageDetails: {
|
|
49
|
+
type: unknownContainerRuntimeMessageType,
|
|
50
|
+
},
|
|
51
|
+
});
|
|
45
52
|
}
|
|
46
53
|
/**
|
|
47
54
|
* @legacy
|
|
@@ -814,7 +821,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
814
821
|
parentContext.submitSignal = (type, content, targetClientId) => {
|
|
815
822
|
const envelope1 = content;
|
|
816
823
|
const envelope2 = this.createNewSignalEnvelope(envelope1.address, type, envelope1.contents);
|
|
817
|
-
return this.
|
|
824
|
+
return this.submitEnvelopedSignal(envelope2, targetClientId);
|
|
818
825
|
};
|
|
819
826
|
let snapshot = getSummaryForDatastores(baseSnapshot, metadata);
|
|
820
827
|
if (snapshot !== undefined && snapshotWithContents !== undefined) {
|
|
@@ -1389,22 +1396,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1389
1396
|
// GC op is only sent in summarizer which should never have stashed ops.
|
|
1390
1397
|
throw new LoggingError("GC op not expected to be stashed in summarizer");
|
|
1391
1398
|
default: {
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
const compatBehavior = opContents.compatDetails?.behavior;
|
|
1396
|
-
if (!compatBehaviorAllowsMessageType(opContents.type, compatBehavior)) {
|
|
1397
|
-
const error = DataProcessingError.create("Stashed runtime message of unexpected type", "applyStashedOp", undefined /* sequencedMessage */, {
|
|
1398
|
-
messageDetails: JSON.stringify({
|
|
1399
|
-
type: opContents.type,
|
|
1400
|
-
compatBehavior,
|
|
1401
|
-
}),
|
|
1402
|
-
});
|
|
1403
|
-
this.closeFn(error);
|
|
1404
|
-
throw error;
|
|
1405
|
-
}
|
|
1406
|
-
// Note: Even if its compat behavior allows it, we don't know how to apply this stashed op.
|
|
1407
|
-
// All we can do is ignore it (similar to on process).
|
|
1399
|
+
const error = getUnknownMessageTypeError(opContents.type, "applyStashedOp" /* codePath */);
|
|
1400
|
+
this.closeFn(error);
|
|
1401
|
+
throw error;
|
|
1408
1402
|
}
|
|
1409
1403
|
}
|
|
1410
1404
|
}
|
|
@@ -1724,23 +1718,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1724
1718
|
this.documentsSchemaController.processDocumentSchemaOp(message.contents, local, message.sequenceNumber);
|
|
1725
1719
|
break;
|
|
1726
1720
|
default: {
|
|
1727
|
-
const
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
// Former assert 0x3ce
|
|
1731
|
-
"Runtime message of unknown type", "OpProcessing", message, {
|
|
1732
|
-
local,
|
|
1733
|
-
messageDetails: JSON.stringify({
|
|
1734
|
-
type: message.type,
|
|
1735
|
-
contentType: typeof message.contents,
|
|
1736
|
-
compatBehavior,
|
|
1737
|
-
batch: message.metadata?.batch,
|
|
1738
|
-
compression: message.compression,
|
|
1739
|
-
}),
|
|
1740
|
-
});
|
|
1741
|
-
this.closeFn(error);
|
|
1742
|
-
throw error;
|
|
1743
|
-
}
|
|
1721
|
+
const error = getUnknownMessageTypeError(message.type, "validateAndProcessRuntimeMessage" /* codePath */, message);
|
|
1722
|
+
this.closeFn(error);
|
|
1723
|
+
throw error;
|
|
1744
1724
|
}
|
|
1745
1725
|
}
|
|
1746
1726
|
this.emit("op", message, true /* runtimeMessage */);
|
|
@@ -1763,6 +1743,60 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1763
1743
|
this._signalTracking.signalTimestamp = 0;
|
|
1764
1744
|
this._signalTracking.totalSignalsSentInLatencyWindow = 0;
|
|
1765
1745
|
}
|
|
1746
|
+
/**
|
|
1747
|
+
* Updates signal telemetry including emitting telemetry events.
|
|
1748
|
+
*/
|
|
1749
|
+
processSignalForTelemetry(envelope) {
|
|
1750
|
+
const { clientBroadcastSignalSequenceNumber } = envelope;
|
|
1751
|
+
if (clientBroadcastSignalSequenceNumber === undefined) {
|
|
1752
|
+
return;
|
|
1753
|
+
}
|
|
1754
|
+
if (this._signalTracking.trackingSignalSequenceNumber === undefined ||
|
|
1755
|
+
this._signalTracking.minimumTrackingSignalSequenceNumber === undefined) {
|
|
1756
|
+
return;
|
|
1757
|
+
}
|
|
1758
|
+
if (clientBroadcastSignalSequenceNumber >= this._signalTracking.trackingSignalSequenceNumber) {
|
|
1759
|
+
// Calculate the number of signals lost and log the event.
|
|
1760
|
+
const signalsLost = clientBroadcastSignalSequenceNumber -
|
|
1761
|
+
this._signalTracking.trackingSignalSequenceNumber;
|
|
1762
|
+
if (signalsLost > 0) {
|
|
1763
|
+
this._signalTracking.signalsLost += signalsLost;
|
|
1764
|
+
this.mc.logger.sendErrorEvent({
|
|
1765
|
+
eventName: "SignalLost",
|
|
1766
|
+
signalsLost, // Number of lost signals detected.
|
|
1767
|
+
trackingSequenceNumber: this._signalTracking.trackingSignalSequenceNumber, // The next expected signal sequence number.
|
|
1768
|
+
clientBroadcastSignalSequenceNumber, // Actual signal sequence number received.
|
|
1769
|
+
});
|
|
1770
|
+
}
|
|
1771
|
+
// Update the tracking signal sequence number to the next expected signal in the sequence.
|
|
1772
|
+
this._signalTracking.trackingSignalSequenceNumber =
|
|
1773
|
+
clientBroadcastSignalSequenceNumber + 1;
|
|
1774
|
+
}
|
|
1775
|
+
else if (
|
|
1776
|
+
// Check if this is a signal in range of interest.
|
|
1777
|
+
clientBroadcastSignalSequenceNumber >=
|
|
1778
|
+
this._signalTracking.minimumTrackingSignalSequenceNumber) {
|
|
1779
|
+
this._signalTracking.signalsOutOfOrder++;
|
|
1780
|
+
this.mc.logger.sendTelemetryEvent({
|
|
1781
|
+
eventName: "SignalOutOfOrder",
|
|
1782
|
+
type: envelope.contents.type, // Type of signal that was received out of order.
|
|
1783
|
+
trackingSequenceNumber: this._signalTracking.trackingSignalSequenceNumber, // The next expected signal sequence number.
|
|
1784
|
+
clientBroadcastSignalSequenceNumber, // Sequence number of the out of order signal.
|
|
1785
|
+
});
|
|
1786
|
+
}
|
|
1787
|
+
if (this._signalTracking.roundTripSignalSequenceNumber !== undefined &&
|
|
1788
|
+
clientBroadcastSignalSequenceNumber >= this._signalTracking.roundTripSignalSequenceNumber) {
|
|
1789
|
+
if (clientBroadcastSignalSequenceNumber ===
|
|
1790
|
+
this._signalTracking.roundTripSignalSequenceNumber) {
|
|
1791
|
+
// Latency tracked signal has been received.
|
|
1792
|
+
// We now log the roundtrip duration of the tracked signal.
|
|
1793
|
+
// This telemetry event also logs metrics for signals sent, signals lost, and out of order signals received.
|
|
1794
|
+
// These metrics are reset after logging the telemetry event.
|
|
1795
|
+
this.sendSignalTelemetryEvent();
|
|
1796
|
+
}
|
|
1797
|
+
this._signalTracking.roundTripSignalSequenceNumber = undefined;
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1766
1800
|
processSignal(message, local) {
|
|
1767
1801
|
const envelope = message.content;
|
|
1768
1802
|
const transformed = {
|
|
@@ -1773,52 +1807,14 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1773
1807
|
};
|
|
1774
1808
|
// Only collect signal telemetry for broadcast messages sent by the current client.
|
|
1775
1809
|
if (message.clientId === this.clientId &&
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
this._signalTracking.trackingSignalSequenceNumber;
|
|
1785
|
-
if (signalsLost > 0) {
|
|
1786
|
-
this._signalTracking.signalsLost += signalsLost;
|
|
1787
|
-
this.mc.logger.sendErrorEvent({
|
|
1788
|
-
eventName: "SignalLost",
|
|
1789
|
-
signalsLost, // Number of lost signals detected.
|
|
1790
|
-
trackingSequenceNumber: this._signalTracking.trackingSignalSequenceNumber, // The next expected signal sequence number.
|
|
1791
|
-
clientBroadcastSignalSequenceNumber: envelope.clientBroadcastSignalSequenceNumber, // Actual signal sequence number received.
|
|
1792
|
-
});
|
|
1793
|
-
}
|
|
1794
|
-
// Update the tracking signal sequence number to the next expected signal in the sequence.
|
|
1795
|
-
this._signalTracking.trackingSignalSequenceNumber =
|
|
1796
|
-
envelope.clientBroadcastSignalSequenceNumber + 1;
|
|
1797
|
-
}
|
|
1798
|
-
else if (envelope.clientBroadcastSignalSequenceNumber >=
|
|
1799
|
-
this._signalTracking.minimumTrackingSignalSequenceNumber) {
|
|
1800
|
-
this._signalTracking.signalsOutOfOrder++;
|
|
1801
|
-
this.mc.logger.sendTelemetryEvent({
|
|
1802
|
-
eventName: "SignalOutOfOrder",
|
|
1803
|
-
type: envelope.contents.type, // Type of signal that was received out of order.
|
|
1804
|
-
trackingSequenceNumber: this._signalTracking.trackingSignalSequenceNumber, // The next expected signal sequence number.
|
|
1805
|
-
clientBroadcastSignalSequenceNumber: envelope.clientBroadcastSignalSequenceNumber, // Sequence number of the out of order signal.
|
|
1806
|
-
});
|
|
1807
|
-
}
|
|
1808
|
-
if (this._signalTracking.roundTripSignalSequenceNumber !== undefined &&
|
|
1809
|
-
envelope.clientBroadcastSignalSequenceNumber >=
|
|
1810
|
-
this._signalTracking.roundTripSignalSequenceNumber) {
|
|
1811
|
-
if (envelope.clientBroadcastSignalSequenceNumber ===
|
|
1812
|
-
this._signalTracking.roundTripSignalSequenceNumber) {
|
|
1813
|
-
// Latency tracked signal has been received.
|
|
1814
|
-
// We now log the roundtrip duration of the tracked signal.
|
|
1815
|
-
// This telemetry event also logs metrics for signals sent, signals lost, and out of order signals received.
|
|
1816
|
-
// These metrics are reset after logging the telemetry event.
|
|
1817
|
-
this.sendSignalTelemetryEvent();
|
|
1818
|
-
}
|
|
1819
|
-
this._signalTracking.roundTripSignalSequenceNumber = undefined;
|
|
1820
|
-
}
|
|
1821
|
-
}
|
|
1810
|
+
// jason-ha: This `connected` check seems incorrect. Signals that come through
|
|
1811
|
+
// here must have been received while connected to service and there is no need
|
|
1812
|
+
// to avoid processing when connection has dropped. Because container runtime's
|
|
1813
|
+
// `connected` (and `_connected`) state also reflects some ops state, it may
|
|
1814
|
+
// easily be false when newly connected and signal tracking may very well
|
|
1815
|
+
// complain lost signals (that were simply skipped per this check).
|
|
1816
|
+
this.connected) {
|
|
1817
|
+
this.processSignalForTelemetry(envelope);
|
|
1822
1818
|
}
|
|
1823
1819
|
if (envelope.address === undefined) {
|
|
1824
1820
|
// No address indicates a container signal message.
|
|
@@ -1993,16 +1989,20 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1993
1989
|
}
|
|
1994
1990
|
return true;
|
|
1995
1991
|
}
|
|
1996
|
-
createNewSignalEnvelope(address, type, content
|
|
1992
|
+
createNewSignalEnvelope(address, type, content) {
|
|
1997
1993
|
const newEnvelope = {
|
|
1998
1994
|
address,
|
|
1999
1995
|
contents: { type, content },
|
|
2000
1996
|
};
|
|
1997
|
+
return newEnvelope;
|
|
1998
|
+
}
|
|
1999
|
+
submitEnvelopedSignal(envelope, targetClientId) {
|
|
2001
2000
|
const isBroadcastSignal = targetClientId === undefined;
|
|
2002
2001
|
if (isBroadcastSignal) {
|
|
2003
2002
|
const clientBroadcastSignalSequenceNumber = ++this._signalTracking
|
|
2004
2003
|
.broadcastSignalSequenceNumber;
|
|
2005
|
-
|
|
2004
|
+
// Stamp with the broadcast signal sequence number.
|
|
2005
|
+
envelope.clientBroadcastSignalSequenceNumber = clientBroadcastSignalSequenceNumber;
|
|
2006
2006
|
this._signalTracking.signalsSentSinceLastLatencyMeasurement++;
|
|
2007
2007
|
if (this._signalTracking.minimumTrackingSignalSequenceNumber === undefined ||
|
|
2008
2008
|
this._signalTracking.trackingSignalSequenceNumber === undefined) {
|
|
@@ -2024,7 +2024,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2024
2024
|
this._signalTracking.signalsSentSinceLastLatencyMeasurement = 0;
|
|
2025
2025
|
}
|
|
2026
2026
|
}
|
|
2027
|
-
|
|
2027
|
+
this.submitSignalFn(envelope, targetClientId);
|
|
2028
2028
|
}
|
|
2029
2029
|
/**
|
|
2030
2030
|
* Submits the signal to be sent to other clients.
|
|
@@ -2040,8 +2040,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2040
2040
|
*/
|
|
2041
2041
|
submitSignal(type, content, targetClientId) {
|
|
2042
2042
|
this.verifyNotClosed();
|
|
2043
|
-
const envelope = this.createNewSignalEnvelope(undefined /* address */, type, content
|
|
2044
|
-
return this.
|
|
2043
|
+
const envelope = this.createNewSignalEnvelope(undefined /* address */, type, content);
|
|
2044
|
+
return this.submitEnvelopedSignal(envelope, targetClientId);
|
|
2045
2045
|
}
|
|
2046
2046
|
setAttachState(attachState) {
|
|
2047
2047
|
if (attachState === AttachState.Attaching) {
|
|
@@ -2828,26 +2828,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2828
2828
|
// send any ops, as some other client already changed schema.
|
|
2829
2829
|
break;
|
|
2830
2830
|
default: {
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
if (compatBehaviorAllowsMessageType(message.type, compatBehavior)) {
|
|
2835
|
-
// We do not ultimately resubmit it, to be consistent with this version of the code.
|
|
2836
|
-
this.logger.sendTelemetryEvent({
|
|
2837
|
-
eventName: "resubmitUnrecognizedMessageTypeAllowed",
|
|
2838
|
-
messageDetails: { type: message.type, compatBehavior },
|
|
2839
|
-
});
|
|
2840
|
-
}
|
|
2841
|
-
else {
|
|
2842
|
-
const error = DataProcessingError.create("Resubmitting runtime message of unexpected type", "reSubmitCore", undefined /* sequencedMessage */, {
|
|
2843
|
-
messageDetails: JSON.stringify({
|
|
2844
|
-
type: message.type,
|
|
2845
|
-
compatBehavior,
|
|
2846
|
-
}),
|
|
2847
|
-
});
|
|
2848
|
-
this.closeFn(error);
|
|
2849
|
-
throw error;
|
|
2850
|
-
}
|
|
2831
|
+
const error = getUnknownMessageTypeError(message.type, "reSubmitCore" /* codePath */);
|
|
2832
|
+
this.closeFn(error);
|
|
2833
|
+
throw error;
|
|
2851
2834
|
}
|
|
2852
2835
|
}
|
|
2853
2836
|
}
|