@fluidframework/container-runtime 2.0.0-internal.3.2.2 → 2.0.0-internal.3.3.1
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/dist/containerRuntime.d.ts +32 -53
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +40 -18
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +8 -3
- package/dist/dataStores.js.map +1 -1
- package/dist/deltaManagerSummarizerProxy.d.ts +19 -0
- package/dist/deltaManagerSummarizerProxy.d.ts.map +1 -0
- package/dist/deltaManagerSummarizerProxy.js +40 -0
- package/dist/deltaManagerSummarizerProxy.js.map +1 -0
- package/dist/gc/garbageCollection.d.ts +2 -33
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +36 -181
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.d.ts +22 -0
- package/dist/gc/gcConfigs.d.ts.map +1 -0
- package/dist/gc/gcConfigs.js +138 -0
- package/dist/gc/gcConfigs.js.map +1 -0
- package/dist/gc/gcDefinitions.d.ts +101 -3
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js +8 -3
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcHelpers.d.ts +12 -1
- package/dist/gc/gcHelpers.d.ts.map +1 -1
- package/dist/gc/gcHelpers.js +55 -1
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcSummaryStateTracker.d.ts +1 -2
- package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/dist/gc/gcSummaryStateTracker.js +28 -37
- package/dist/gc/gcSummaryStateTracker.js.map +1 -1
- package/dist/gc/index.d.ts +3 -2
- package/dist/gc/index.d.ts.map +1 -1
- package/dist/gc/index.js +2 -1
- package/dist/gc/index.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts +9 -0
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js +19 -2
- package/dist/opLifecycle/batchManager.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 +2 -1
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js +24 -10
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts +14 -2
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +35 -18
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +25 -19
- 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/storageServiceWithAttachBlobs.d.ts +17 -0
- package/dist/storageServiceWithAttachBlobs.d.ts.map +1 -0
- package/dist/storageServiceWithAttachBlobs.js +32 -0
- package/dist/storageServiceWithAttachBlobs.js.map +1 -0
- package/dist/summary/runWhileConnectedCoordinator.d.ts +3 -2
- package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.js +5 -4
- package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +2 -0
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/lib/containerRuntime.d.ts +32 -53
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +41 -19
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +9 -4
- package/lib/dataStores.js.map +1 -1
- package/lib/deltaManagerSummarizerProxy.d.ts +19 -0
- package/lib/deltaManagerSummarizerProxy.d.ts.map +1 -0
- package/lib/deltaManagerSummarizerProxy.js +36 -0
- package/lib/deltaManagerSummarizerProxy.js.map +1 -0
- package/lib/gc/garbageCollection.d.ts +2 -33
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +39 -184
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcConfigs.d.ts +22 -0
- package/lib/gc/gcConfigs.d.ts.map +1 -0
- package/lib/gc/gcConfigs.js +134 -0
- package/lib/gc/gcConfigs.js.map +1 -0
- package/lib/gc/gcDefinitions.d.ts +101 -3
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js +7 -2
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/gc/gcHelpers.d.ts +12 -1
- package/lib/gc/gcHelpers.d.ts.map +1 -1
- package/lib/gc/gcHelpers.js +53 -0
- package/lib/gc/gcHelpers.js.map +1 -1
- package/lib/gc/gcSummaryStateTracker.d.ts +1 -2
- package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/lib/gc/gcSummaryStateTracker.js +28 -37
- package/lib/gc/gcSummaryStateTracker.js.map +1 -1
- package/lib/gc/index.d.ts +3 -2
- package/lib/gc/index.d.ts.map +1 -1
- package/lib/gc/index.js +1 -1
- package/lib/gc/index.js.map +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/opLifecycle/batchManager.d.ts +9 -0
- package/lib/opLifecycle/batchManager.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.js +17 -1
- package/lib/opLifecycle/batchManager.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 +1 -1
- package/lib/opLifecycle/index.js.map +1 -1
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opCompressor.js +25 -11
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opSplitter.d.ts +14 -2
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +35 -18
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +26 -20
- 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/storageServiceWithAttachBlobs.d.ts +17 -0
- package/lib/storageServiceWithAttachBlobs.d.ts.map +1 -0
- package/lib/storageServiceWithAttachBlobs.js +28 -0
- package/lib/storageServiceWithAttachBlobs.js.map +1 -0
- package/lib/summary/runWhileConnectedCoordinator.d.ts +3 -2
- package/lib/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/lib/summary/runWhileConnectedCoordinator.js +5 -4
- package/lib/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/lib/summary/summarizerTypes.d.ts +2 -0
- package/lib/summary/summarizerTypes.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -1
- package/package.json +20 -31
- package/src/containerRuntime.ts +71 -74
- package/src/dataStores.ts +9 -4
- package/src/deltaManagerSummarizerProxy.ts +46 -0
- package/src/gc/garbageCollection.ts +50 -290
- package/src/gc/gcConfigs.ts +177 -0
- package/src/gc/gcDefinitions.ts +110 -4
- package/src/gc/gcHelpers.ts +78 -1
- package/src/gc/gcSummaryStateTracker.ts +35 -42
- package/src/gc/index.ts +8 -2
- package/src/index.ts +1 -2
- package/src/opLifecycle/README.md +2 -2
- package/src/opLifecycle/batchManager.ts +19 -1
- package/src/opLifecycle/index.ts +1 -1
- package/src/opLifecycle/opCompressor.ts +31 -12
- package/src/opLifecycle/opSplitter.ts +44 -20
- package/src/opLifecycle/outbox.ts +32 -20
- package/src/packageVersion.ts +1 -1
- package/src/storageServiceWithAttachBlobs.ts +38 -0
- package/src/summary/runWhileConnectedCoordinator.ts +7 -7
- package/src/summary/summarizerTypes.ts +2 -0
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { ITelemetryLogger } from "@fluidframework/common-definitions";
|
|
7
|
-
import { IsoBuffer } from "@fluidframework/common-utils";
|
|
7
|
+
import { assert, IsoBuffer } from "@fluidframework/common-utils";
|
|
8
8
|
import { UsageError } from "@fluidframework/container-utils";
|
|
9
9
|
import { ChildLogger } from "@fluidframework/telemetry-utils";
|
|
10
10
|
import { compress } from "lz4js";
|
|
11
11
|
import { CompressionAlgorithms } from "../containerRuntime";
|
|
12
|
+
import { estimateSocketSize } from "./batchManager";
|
|
12
13
|
import { IBatch, BatchMessage } from "./definitions";
|
|
13
14
|
|
|
14
15
|
/**
|
|
@@ -24,21 +25,17 @@ export class OpCompressor {
|
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
public compressBatch(batch: IBatch): IBatch {
|
|
28
|
+
assert(
|
|
29
|
+
batch.contentSizeInBytes > 0 && batch.content.length > 0,
|
|
30
|
+
0x5a4 /* Batch should not be empty */,
|
|
31
|
+
);
|
|
32
|
+
|
|
27
33
|
const compressionStart = Date.now();
|
|
28
34
|
const contentsAsBuffer = new TextEncoder().encode(this.serializeBatch(batch));
|
|
29
35
|
const compressedContents = compress(contentsAsBuffer);
|
|
30
36
|
const compressedContent = IsoBuffer.from(compressedContents).toString("base64");
|
|
31
37
|
const duration = Date.now() - compressionStart;
|
|
32
38
|
|
|
33
|
-
if (batch.contentSizeInBytes > 200000) {
|
|
34
|
-
this.logger.sendPerformanceEvent({
|
|
35
|
-
eventName: "CompressedBatch",
|
|
36
|
-
duration,
|
|
37
|
-
sizeBeforeCompression: batch.contentSizeInBytes,
|
|
38
|
-
sizeAfterCompression: compressedContent.length,
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
|
|
42
39
|
const messages: BatchMessage[] = [];
|
|
43
40
|
messages.push({
|
|
44
41
|
...batch.content[0],
|
|
@@ -47,15 +44,37 @@ export class OpCompressor {
|
|
|
47
44
|
compression: CompressionAlgorithms.lz4,
|
|
48
45
|
});
|
|
49
46
|
|
|
47
|
+
// Add empty placeholder messages to reserve the sequence numbers
|
|
50
48
|
for (const message of batch.content.slice(1)) {
|
|
51
|
-
messages.push({
|
|
49
|
+
messages.push({
|
|
50
|
+
deserializedContent: {
|
|
51
|
+
contents: undefined,
|
|
52
|
+
type: message.deserializedContent.type,
|
|
53
|
+
},
|
|
54
|
+
localOpMetadata: message.localOpMetadata,
|
|
55
|
+
metadata: message.metadata,
|
|
56
|
+
referenceSequenceNumber: message.referenceSequenceNumber,
|
|
57
|
+
});
|
|
52
58
|
}
|
|
53
59
|
|
|
54
|
-
|
|
60
|
+
const compressedBatch: IBatch = {
|
|
55
61
|
contentSizeInBytes: compressedContent.length,
|
|
56
62
|
content: messages,
|
|
57
63
|
referenceSequenceNumber: batch.referenceSequenceNumber,
|
|
58
64
|
};
|
|
65
|
+
|
|
66
|
+
if (batch.contentSizeInBytes > 200000) {
|
|
67
|
+
this.logger.sendPerformanceEvent({
|
|
68
|
+
eventName: "CompressedBatch",
|
|
69
|
+
duration,
|
|
70
|
+
sizeBeforeCompression: batch.contentSizeInBytes,
|
|
71
|
+
sizeAfterCompression: compressedBatch.contentSizeInBytes,
|
|
72
|
+
opCount: compressedBatch.content.length,
|
|
73
|
+
socketSize: estimateSocketSize(compressedBatch),
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return compressedBatch;
|
|
59
78
|
}
|
|
60
79
|
|
|
61
80
|
private serializeBatch(batch: IBatch): string {
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
|
|
14
14
|
import { ChildLogger } from "@fluidframework/telemetry-utils";
|
|
15
15
|
import { ContainerMessageType, ContainerRuntimeMessage } from "../containerRuntime";
|
|
16
|
+
import { estimateSocketSize } from "./batchManager";
|
|
16
17
|
import { BatchMessage, IBatch, IChunkedOp, IMessageProcessingResult } from "./definitions";
|
|
17
18
|
|
|
18
19
|
/**
|
|
@@ -28,7 +29,7 @@ export class OpSplitter {
|
|
|
28
29
|
private readonly submitBatchFn:
|
|
29
30
|
| ((batch: IBatchMessage[], referenceSequenceNumber?: number) => number)
|
|
30
31
|
| undefined,
|
|
31
|
-
|
|
32
|
+
public readonly chunkSizeInBytes: number,
|
|
32
33
|
private readonly maxBatchSizeInBytes: number,
|
|
33
34
|
logger: ITelemetryLogger,
|
|
34
35
|
) {
|
|
@@ -161,7 +162,15 @@ export class OpSplitter {
|
|
|
161
162
|
);
|
|
162
163
|
|
|
163
164
|
const restOfMessages = batch.content.slice(1); // we expect these to be empty ops, created to reserve sequence numbers
|
|
164
|
-
const
|
|
165
|
+
const socketSize = estimateSocketSize(batch);
|
|
166
|
+
const chunks = splitOp(
|
|
167
|
+
firstMessage,
|
|
168
|
+
this.chunkSizeInBytes,
|
|
169
|
+
// If we estimate that the socket batch size will exceed the batch limit
|
|
170
|
+
// we will inject an empty op to minimize the risk of the payload failing due to
|
|
171
|
+
// the overhead from the trailing empty ops in the batch.
|
|
172
|
+
socketSize >= this.maxBatchSizeInBytes,
|
|
173
|
+
);
|
|
165
174
|
|
|
166
175
|
assert(this.submitBatchFn !== undefined, 0x519 /* We don't support old loaders */);
|
|
167
176
|
// Send the first N-1 chunks immediately
|
|
@@ -181,11 +190,13 @@ export class OpSplitter {
|
|
|
181
190
|
);
|
|
182
191
|
|
|
183
192
|
this.logger.sendPerformanceEvent({
|
|
184
|
-
|
|
193
|
+
// Used to be "Chunked compressed batch"
|
|
194
|
+
eventName: "CompressedChunkedBatch",
|
|
185
195
|
length: batch.content.length,
|
|
186
196
|
sizeInBytes: batch.contentSizeInBytes,
|
|
187
197
|
chunks: chunks.length,
|
|
188
198
|
chunkSizeInBytes: this.chunkSizeInBytes,
|
|
199
|
+
socketSize,
|
|
189
200
|
});
|
|
190
201
|
|
|
191
202
|
return {
|
|
@@ -214,7 +225,23 @@ const chunkToBatchMessage = (
|
|
|
214
225
|
};
|
|
215
226
|
};
|
|
216
227
|
|
|
217
|
-
|
|
228
|
+
/**
|
|
229
|
+
* Splits an op into smaller ops (chunks), based on the size of the op and the `chunkSizeInBytes` parameter.
|
|
230
|
+
*
|
|
231
|
+
* The last op of the result will be bundled with empty ops in the same batch. There is a risk of the batch payload
|
|
232
|
+
* exceeding the 1MB limit due to the overhead from the empty ops. If the last op is large, the risk is even higher.
|
|
233
|
+
* To minimize the odds, an extra empty op can be added to the result using the `extraOp` parameter.
|
|
234
|
+
*
|
|
235
|
+
* @param op - the op to be split
|
|
236
|
+
* @param chunkSizeInBytes - how large should the chunks be
|
|
237
|
+
* @param extraOp - should an extra empty op be added to the result
|
|
238
|
+
* @returns an array of chunked ops
|
|
239
|
+
*/
|
|
240
|
+
export const splitOp = (
|
|
241
|
+
op: BatchMessage,
|
|
242
|
+
chunkSizeInBytes: number,
|
|
243
|
+
extraOp: boolean = false,
|
|
244
|
+
): IChunkedOp[] => {
|
|
218
245
|
const chunks: IChunkedOp[] = [];
|
|
219
246
|
assert(
|
|
220
247
|
op.contents !== undefined && op.contents !== null,
|
|
@@ -222,36 +249,33 @@ export const splitOp = (op: BatchMessage, chunkSizeInBytes: number): IChunkedOp[
|
|
|
222
249
|
);
|
|
223
250
|
|
|
224
251
|
const contentLength = op.contents.length;
|
|
225
|
-
const chunkCount = Math.floor((contentLength - 1) / chunkSizeInBytes) +
|
|
252
|
+
const chunkCount = Math.floor((contentLength - 1) / chunkSizeInBytes) + 1 + (extraOp ? 1 : 0);
|
|
226
253
|
let offset = 0;
|
|
227
|
-
for (let
|
|
254
|
+
for (let chunkId = 1; chunkId <= chunkCount; chunkId++) {
|
|
228
255
|
const chunk: IChunkedOp = {
|
|
229
|
-
chunkId
|
|
256
|
+
chunkId,
|
|
230
257
|
contents: op.contents.substr(offset, chunkSizeInBytes),
|
|
231
258
|
originalType: op.deserializedContent.type,
|
|
232
259
|
totalChunks: chunkCount,
|
|
233
260
|
};
|
|
234
261
|
|
|
262
|
+
if (chunkId === chunkCount) {
|
|
263
|
+
// We don't need to port these to all the chunks,
|
|
264
|
+
// as we rebuild the original op when we process the
|
|
265
|
+
// last chunk, therefore it is the only one that needs it.
|
|
266
|
+
chunk.originalMetadata = op.metadata;
|
|
267
|
+
chunk.originalCompression = op.compression;
|
|
268
|
+
}
|
|
269
|
+
|
|
235
270
|
chunks.push(chunk);
|
|
236
271
|
offset += chunkSizeInBytes;
|
|
237
272
|
assert(
|
|
238
|
-
|
|
273
|
+
chunkId >= chunkCount - 1 || offset <= contentLength,
|
|
239
274
|
0x58b /* Content offset within bounds */,
|
|
240
275
|
);
|
|
241
276
|
}
|
|
242
277
|
|
|
243
278
|
assert(offset >= contentLength, 0x58c /* Content offset equal or larger than content length */);
|
|
244
|
-
|
|
245
|
-
// resulting payload exceeding 1MB due to the overhead from the empty ops
|
|
246
|
-
// which will be bundled with this op.
|
|
247
|
-
chunks.push({
|
|
248
|
-
chunkId: chunkCount,
|
|
249
|
-
contents: "",
|
|
250
|
-
originalType: op.deserializedContent.type,
|
|
251
|
-
totalChunks: chunkCount,
|
|
252
|
-
originalMetadata: op.metadata,
|
|
253
|
-
originalCompression: op.compression,
|
|
254
|
-
});
|
|
255
|
-
|
|
279
|
+
assert(chunks.length === chunkCount, 0x5a5 /* Expected number of chunks */);
|
|
256
280
|
return chunks;
|
|
257
281
|
};
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
} from "@fluidframework/telemetry-utils";
|
|
16
16
|
import { ICompressionRuntimeOptions } from "../containerRuntime";
|
|
17
17
|
import { PendingStateManager } from "../pendingStateManager";
|
|
18
|
-
import { BatchManager } from "./batchManager";
|
|
18
|
+
import { BatchManager, estimateSocketSize } from "./batchManager";
|
|
19
19
|
import { BatchMessage, IBatch } from "./definitions";
|
|
20
20
|
import { OpCompressor } from "./opCompressor";
|
|
21
21
|
import { OpSplitter } from "./opSplitter";
|
|
@@ -184,24 +184,26 @@ export class Outbox {
|
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
const compressedBatch = this.params.compressor.compressBatch(batch);
|
|
187
|
-
if (compressedBatch.contentSizeInBytes <= this.params.config.maxBatchSizeInBytes) {
|
|
188
|
-
// If we don't reach the maximum supported size of a batch, it can safely be sent as is
|
|
189
|
-
return compressedBatch;
|
|
190
|
-
}
|
|
191
187
|
|
|
192
188
|
if (this.params.splitter.isBatchChunkingEnabled) {
|
|
193
|
-
return this.params.splitter.
|
|
189
|
+
return compressedBatch.contentSizeInBytes <= this.params.splitter.chunkSizeInBytes
|
|
190
|
+
? compressedBatch
|
|
191
|
+
: this.params.splitter.splitCompressedBatch(compressedBatch);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (compressedBatch.contentSizeInBytes >= this.params.config.maxBatchSizeInBytes) {
|
|
195
|
+
throw new GenericError("BatchTooLarge", /* error */ undefined, {
|
|
196
|
+
batchSize: batch.contentSizeInBytes,
|
|
197
|
+
compressedBatchSize: compressedBatch.contentSizeInBytes,
|
|
198
|
+
count: compressedBatch.content.length,
|
|
199
|
+
limit: this.params.config.maxBatchSizeInBytes,
|
|
200
|
+
chunkingEnabled: this.params.splitter.isBatchChunkingEnabled,
|
|
201
|
+
compressionOptions: JSON.stringify(this.params.config.compressionOptions),
|
|
202
|
+
socketSize: estimateSocketSize(batch),
|
|
203
|
+
});
|
|
194
204
|
}
|
|
195
205
|
|
|
196
|
-
|
|
197
|
-
throw new GenericError("BatchTooLarge", /* error */ undefined, {
|
|
198
|
-
batchSize: batch.contentSizeInBytes,
|
|
199
|
-
compressedBatchSize: compressedBatch.contentSizeInBytes,
|
|
200
|
-
count: compressedBatch.content.length,
|
|
201
|
-
limit: this.params.config.maxBatchSizeInBytes,
|
|
202
|
-
chunkingEnabled: this.params.splitter.isBatchChunkingEnabled,
|
|
203
|
-
compressionOptions: JSON.stringify(this.params.config.compressionOptions),
|
|
204
|
-
});
|
|
206
|
+
return compressedBatch;
|
|
205
207
|
}
|
|
206
208
|
|
|
207
209
|
/**
|
|
@@ -218,15 +220,25 @@ export class Outbox {
|
|
|
218
220
|
return;
|
|
219
221
|
}
|
|
220
222
|
|
|
223
|
+
const socketSize = estimateSocketSize(batch);
|
|
224
|
+
if (socketSize >= this.params.config.maxBatchSizeInBytes) {
|
|
225
|
+
this.mc.logger.sendPerformanceEvent({
|
|
226
|
+
eventName: "LargeBatch",
|
|
227
|
+
length: batch.content.length,
|
|
228
|
+
sizeInBytes: batch.contentSizeInBytes,
|
|
229
|
+
socketSize,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
221
233
|
if (this.params.containerContext.submitBatchFn === undefined) {
|
|
222
234
|
// Legacy path - supporting old loader versions. Can be removed only when LTS moves above
|
|
223
235
|
// version that has support for batches (submitBatchFn)
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
if
|
|
227
|
-
|
|
228
|
-
}
|
|
236
|
+
assert(
|
|
237
|
+
batch.content[0].compression === undefined,
|
|
238
|
+
0x5a6 /* Compression should not have happened if the loader does not support it */,
|
|
239
|
+
);
|
|
229
240
|
|
|
241
|
+
for (const message of batch.content) {
|
|
230
242
|
this.params.containerContext.submitFn(
|
|
231
243
|
MessageType.Operation,
|
|
232
244
|
message.deserializedContent,
|
package/src/packageVersion.ts
CHANGED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
IDocumentStorageService,
|
|
8
|
+
IDocumentStorageServicePolicies,
|
|
9
|
+
} from "@fluidframework/driver-definitions";
|
|
10
|
+
import { DocumentStorageServiceProxy } from "@fluidframework/driver-utils";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* IDocumentStorageService proxy which intercepts requests if they can be satisfied by the blobs received in the
|
|
14
|
+
* attach message. We use this to avoid an unnecessary request to the storage service.
|
|
15
|
+
*/
|
|
16
|
+
export class StorageServiceWithAttachBlobs extends DocumentStorageServiceProxy {
|
|
17
|
+
constructor(
|
|
18
|
+
internalStorageService: IDocumentStorageService,
|
|
19
|
+
private readonly attachBlobs: Map<string, ArrayBufferLike>,
|
|
20
|
+
) {
|
|
21
|
+
super(internalStorageService);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public get policies(): IDocumentStorageServicePolicies | undefined {
|
|
25
|
+
return this.internalStorageService.policies;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public async readBlob(id: string): Promise<ArrayBufferLike> {
|
|
29
|
+
const blob = this.attachBlobs.get(id);
|
|
30
|
+
if (blob !== undefined) {
|
|
31
|
+
return blob;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Note that it is intentional not to cache the result of this readBlob - we'll trust the real
|
|
35
|
+
// IDocumentStorageService to cache appropriately, no need to double-cache.
|
|
36
|
+
return this.internalStorageService.readBlob(id);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -35,10 +35,7 @@ export class RunWhileConnectedCoordinator implements ICancellableSummarizerContr
|
|
|
35
35
|
|
|
36
36
|
public get cancelled() {
|
|
37
37
|
if (!this._cancelled) {
|
|
38
|
-
assert(
|
|
39
|
-
this.runtime.deltaManager.active,
|
|
40
|
-
0x25d /* "We should never connect as 'read'" */,
|
|
41
|
-
);
|
|
38
|
+
assert(this.active(), 0x25d /* "We should never connect as 'read'" */);
|
|
42
39
|
|
|
43
40
|
// This check can't be enabled in current design due to lastSummary flow, where
|
|
44
41
|
// summarizer for closed container stays around and can produce one more summary.
|
|
@@ -63,13 +60,16 @@ export class RunWhileConnectedCoordinator implements ICancellableSummarizerContr
|
|
|
63
60
|
return this.stopDeferred.promise;
|
|
64
61
|
}
|
|
65
62
|
|
|
66
|
-
public static async create(runtime: IConnectableRuntime) {
|
|
67
|
-
const obj = new RunWhileConnectedCoordinator(runtime);
|
|
63
|
+
public static async create(runtime: IConnectableRuntime, active: () => boolean) {
|
|
64
|
+
const obj = new RunWhileConnectedCoordinator(runtime, active);
|
|
68
65
|
await obj.waitStart();
|
|
69
66
|
return obj;
|
|
70
67
|
}
|
|
71
68
|
|
|
72
|
-
protected constructor(
|
|
69
|
+
protected constructor(
|
|
70
|
+
private readonly runtime: IConnectableRuntime,
|
|
71
|
+
private readonly active: () => boolean,
|
|
72
|
+
) {}
|
|
73
73
|
|
|
74
74
|
/**
|
|
75
75
|
* Starts and waits for a promise which resolves when connected.
|
|
@@ -84,6 +84,7 @@ export interface IConnectableRuntime {
|
|
|
84
84
|
readonly disposed: boolean;
|
|
85
85
|
readonly connected: boolean;
|
|
86
86
|
readonly clientId: string | undefined;
|
|
87
|
+
/** @deprecated - Moved to `ISummarizerRuntime` as it's no longer needed here */
|
|
87
88
|
readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>;
|
|
88
89
|
once(event: "connected" | "disconnected" | "dispose", listener: () => void): this;
|
|
89
90
|
}
|
|
@@ -92,6 +93,7 @@ export interface ISummarizerRuntime extends IConnectableRuntime {
|
|
|
92
93
|
readonly logger: ITelemetryLogger;
|
|
93
94
|
/** clientId of parent (non-summarizing) container that owns summarizer container */
|
|
94
95
|
readonly summarizerClientId: string | undefined;
|
|
96
|
+
readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>;
|
|
95
97
|
disposeFn?(): void;
|
|
96
98
|
closeFn(): void;
|
|
97
99
|
}
|