@fluidframework/container-runtime 2.40.0-336023 → 2.41.0-337492
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/CHANGELOG.md +14 -0
- package/api-report/container-runtime.legacy.alpha.api.md +4 -0
- package/container-runtime.test-files.tar +0 -0
- package/dist/blobManager/blobManager.d.ts +31 -8
- package/dist/blobManager/blobManager.d.ts.map +1 -1
- package/dist/blobManager/blobManager.js +90 -17
- package/dist/blobManager/blobManager.js.map +1 -1
- package/dist/channelCollection.d.ts +8 -2
- package/dist/channelCollection.d.ts.map +1 -1
- package/dist/channelCollection.js +29 -6
- package/dist/channelCollection.js.map +1 -1
- package/dist/compatUtils.d.ts +19 -10
- package/dist/compatUtils.d.ts.map +1 -1
- package/dist/compatUtils.js +39 -32
- package/dist/compatUtils.js.map +1 -1
- package/dist/containerRuntime.d.ts +29 -13
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +139 -149
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.d.ts +12 -4
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +37 -18
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/legacy.d.ts +1 -0
- 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/outbox.d.ts +20 -7
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +16 -20
- 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 +22 -8
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +11 -16
- package/dist/pendingStateManager.js.map +1 -1
- package/lib/blobManager/blobManager.d.ts +31 -8
- package/lib/blobManager/blobManager.d.ts.map +1 -1
- package/lib/blobManager/blobManager.js +91 -18
- package/lib/blobManager/blobManager.js.map +1 -1
- package/lib/channelCollection.d.ts +8 -2
- package/lib/channelCollection.d.ts.map +1 -1
- package/lib/channelCollection.js +29 -6
- package/lib/channelCollection.js.map +1 -1
- package/lib/compatUtils.d.ts +19 -10
- package/lib/compatUtils.d.ts.map +1 -1
- package/lib/compatUtils.js +36 -29
- package/lib/compatUtils.js.map +1 -1
- package/lib/containerRuntime.d.ts +29 -13
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +60 -70
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.d.ts +12 -4
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +38 -19
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/legacy.d.ts +1 -0
- 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/outbox.d.ts +20 -7
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +16 -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/pendingStateManager.d.ts +22 -8
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +11 -16
- package/lib/pendingStateManager.js.map +1 -1
- package/package.json +18 -18
- package/src/blobManager/blobManager.ts +141 -33
- package/src/channelCollection.ts +42 -6
- package/src/compatUtils.ts +53 -30
- package/src/containerRuntime.ts +102 -81
- package/src/dataStoreContext.ts +44 -25
- package/src/index.ts +1 -0
- package/src/opLifecycle/index.ts +1 -0
- package/src/opLifecycle/outbox.ts +42 -33
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +37 -20
|
@@ -66,10 +66,27 @@ export interface IOutboxParameters {
|
|
|
66
66
|
readonly logger: ITelemetryBaseLogger;
|
|
67
67
|
readonly groupingManager: OpGroupingManager;
|
|
68
68
|
readonly getCurrentSequenceNumbers: () => BatchSequenceNumbers;
|
|
69
|
-
readonly reSubmit: (message: PendingMessageResubmitData) => void;
|
|
69
|
+
readonly reSubmit: (message: PendingMessageResubmitData, squash: boolean) => void;
|
|
70
70
|
readonly opReentrancy: () => boolean;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Info needed to correctly resubmit a batch
|
|
75
|
+
*/
|
|
76
|
+
export interface BatchResubmitInfo {
|
|
77
|
+
/**
|
|
78
|
+
* If defined, indicates the Batch ID of the batch being resubmitted.
|
|
79
|
+
* This must be preserved on the new batch about to be submitted so they can be correlated/deduped in case both are sent.
|
|
80
|
+
*/
|
|
81
|
+
batchId?: string;
|
|
82
|
+
/**
|
|
83
|
+
* Indicates whether or not this batch is "staged", meaning it should not be sent to the ordering service yet
|
|
84
|
+
* This is important on resubmit because we may be in Staging Mode for new changes,
|
|
85
|
+
* but resubmitting a non-staged change from before entering Staging Mode
|
|
86
|
+
*/
|
|
87
|
+
staged: boolean;
|
|
88
|
+
}
|
|
89
|
+
|
|
73
90
|
/**
|
|
74
91
|
* Temporarily increase the stack limit while executing the provided action.
|
|
75
92
|
* If a negative value is provided for `length`, no stack frames will be collected.
|
|
@@ -335,37 +352,33 @@ export class Outbox {
|
|
|
335
352
|
* This method is expected to be called at the end of a batch.
|
|
336
353
|
*
|
|
337
354
|
* @throws If called from a reentrant context, or if the batch being flushed is too large.
|
|
338
|
-
* @param
|
|
339
|
-
* with the given Batch ID, which must be preserved
|
|
340
|
-
* @param resubmittingStagedBatch - If defined, indicates this is a resubmission of a batch that is staged,
|
|
341
|
-
* meaning it should not be sent to the ordering service yet.
|
|
355
|
+
* @param resubmitInfo - Key information when flushing a resubmitted batch. Undefined means this is not resubmit.
|
|
342
356
|
*/
|
|
343
|
-
public flush(
|
|
357
|
+
public flush(resubmitInfo?: BatchResubmitInfo): void {
|
|
344
358
|
assert(
|
|
345
359
|
!this.isContextReentrant(),
|
|
346
360
|
0xb7b /* Flushing must not happen while incoming changes are being processed */,
|
|
347
361
|
);
|
|
348
|
-
|
|
349
|
-
this.flushAll(resubmittingBatchId, resubmittingStagedBatch);
|
|
362
|
+
this.flushAll(resubmitInfo);
|
|
350
363
|
}
|
|
351
364
|
|
|
352
|
-
private flushAll(
|
|
365
|
+
private flushAll(resubmitInfo?: BatchResubmitInfo): void {
|
|
353
366
|
const allBatchesEmpty =
|
|
354
367
|
this.idAllocationBatch.empty && this.blobAttachBatch.empty && this.mainBatch.empty;
|
|
355
368
|
if (allBatchesEmpty) {
|
|
356
|
-
// If we're resubmitting and all batches are empty, we need to flush an empty batch.
|
|
357
|
-
// Note that we currently resubmit one batch at a time, so on resubmit,
|
|
369
|
+
// If we're resubmitting with a batchId and all batches are empty, we need to flush an empty batch.
|
|
370
|
+
// Note that we currently resubmit one batch at a time, so on resubmit, 1 of the 2 batches will *always* be empty.
|
|
358
371
|
// It's theoretically possible that we don't *need* to resubmit this empty batch, and in those cases, it'll safely be ignored
|
|
359
372
|
// by the rest of the system, including remote clients.
|
|
360
373
|
// In some cases we *must* resubmit the empty batch (to match up with a non-empty version tracked locally by a container fork), so we do it always.
|
|
361
|
-
if (
|
|
362
|
-
this.flushEmptyBatch(
|
|
374
|
+
if (resubmitInfo?.batchId !== undefined) {
|
|
375
|
+
this.flushEmptyBatch(resubmitInfo.batchId, resubmitInfo.staged);
|
|
363
376
|
}
|
|
364
377
|
return;
|
|
365
378
|
}
|
|
366
379
|
|
|
367
380
|
// Don't use resubmittingBatchId for idAllocationBatch.
|
|
368
|
-
// ID Allocation messages are not directly resubmitted so
|
|
381
|
+
// ID Allocation messages are not directly resubmitted so don't pass the resubmitInfo
|
|
369
382
|
this.flushInternal({
|
|
370
383
|
batchManager: this.idAllocationBatch,
|
|
371
384
|
// Note: For now, we will never stage ID Allocation messages.
|
|
@@ -374,13 +387,11 @@ export class Outbox {
|
|
|
374
387
|
this.flushInternal({
|
|
375
388
|
batchManager: this.blobAttachBatch,
|
|
376
389
|
disableGroupedBatching: true,
|
|
377
|
-
|
|
378
|
-
resubmittingStagedBatch,
|
|
390
|
+
resubmitInfo,
|
|
379
391
|
});
|
|
380
392
|
this.flushInternal({
|
|
381
393
|
batchManager: this.mainBatch,
|
|
382
|
-
|
|
383
|
-
resubmittingStagedBatch,
|
|
394
|
+
resubmitInfo,
|
|
384
395
|
});
|
|
385
396
|
}
|
|
386
397
|
|
|
@@ -416,25 +427,19 @@ export class Outbox {
|
|
|
416
427
|
private flushInternal(params: {
|
|
417
428
|
batchManager: BatchManager;
|
|
418
429
|
disableGroupedBatching?: boolean;
|
|
419
|
-
|
|
420
|
-
resubmittingStagedBatch?: boolean; // undefined if not resubmitting
|
|
430
|
+
resubmitInfo?: BatchResubmitInfo; // undefined if not resubmitting
|
|
421
431
|
}): void {
|
|
422
|
-
const {
|
|
423
|
-
batchManager,
|
|
424
|
-
disableGroupedBatching = false,
|
|
425
|
-
resubmittingBatchId,
|
|
426
|
-
resubmittingStagedBatch,
|
|
427
|
-
} = params;
|
|
432
|
+
const { batchManager, disableGroupedBatching = false, resubmitInfo } = params;
|
|
428
433
|
if (batchManager.empty) {
|
|
429
434
|
return;
|
|
430
435
|
}
|
|
431
436
|
|
|
432
|
-
const rawBatch = batchManager.popBatch(
|
|
437
|
+
const rawBatch = batchManager.popBatch(resubmitInfo?.batchId);
|
|
433
438
|
|
|
434
439
|
// When resubmitting, we respect the staged state of the original batch.
|
|
435
440
|
// In this case rawBatch.staged will match the state of inStagingMode when
|
|
436
441
|
// the resubmit occurred, which is not relevant.
|
|
437
|
-
const staged =
|
|
442
|
+
const staged = resubmitInfo?.staged ?? rawBatch.staged === true;
|
|
438
443
|
|
|
439
444
|
const groupingEnabled =
|
|
440
445
|
!disableGroupedBatching && this.params.groupingManager.groupedBatchingEnabled();
|
|
@@ -490,12 +495,16 @@ export class Outbox {
|
|
|
490
495
|
assert(batchManager.options.canRebase, 0x9a7 /* BatchManager does not support rebase */);
|
|
491
496
|
|
|
492
497
|
this.rebasing = true;
|
|
498
|
+
const squash = false;
|
|
493
499
|
for (const message of rawBatch.messages) {
|
|
494
|
-
this.params.reSubmit(
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
500
|
+
this.params.reSubmit(
|
|
501
|
+
{
|
|
502
|
+
runtimeOp: message.runtimeOp,
|
|
503
|
+
localOpMetadata: message.localOpMetadata,
|
|
504
|
+
opMetadata: message.metadata,
|
|
505
|
+
},
|
|
506
|
+
squash,
|
|
507
|
+
);
|
|
499
508
|
}
|
|
500
509
|
|
|
501
510
|
if (this.batchRebasesToReport > 0) {
|
package/src/packageVersion.ts
CHANGED
|
@@ -22,13 +22,13 @@ import {
|
|
|
22
22
|
} from "./messageTypes.js";
|
|
23
23
|
import { asBatchMetadata, asEmptyBatchLocalOpMetadata } from "./metadata.js";
|
|
24
24
|
import {
|
|
25
|
-
BatchId,
|
|
26
25
|
LocalBatchMessage,
|
|
27
26
|
getEffectiveBatchId,
|
|
28
27
|
BatchStartInfo,
|
|
29
28
|
InboundMessageResult,
|
|
30
29
|
serializeOp,
|
|
31
30
|
type LocalEmptyBatchPlaceholder,
|
|
31
|
+
type BatchResubmitInfo,
|
|
32
32
|
} from "./opLifecycle/index.js";
|
|
33
33
|
|
|
34
34
|
/**
|
|
@@ -114,11 +114,21 @@ export type PendingMessageResubmitData = Pick<
|
|
|
114
114
|
runtimeOp: LocalContainerRuntimeMessage;
|
|
115
115
|
};
|
|
116
116
|
|
|
117
|
+
export interface PendingBatchResubmitMetadata extends BatchResubmitInfo {
|
|
118
|
+
/**
|
|
119
|
+
* Whether changes in this batch should be squashed when resubmitting.
|
|
120
|
+
*/
|
|
121
|
+
squash: boolean;
|
|
122
|
+
}
|
|
123
|
+
|
|
117
124
|
export interface IRuntimeStateHandler {
|
|
118
125
|
connected(): boolean;
|
|
119
126
|
clientId(): string | undefined;
|
|
120
127
|
applyStashedOp(serializedOp: string): Promise<unknown>;
|
|
121
|
-
reSubmitBatch(
|
|
128
|
+
reSubmitBatch(
|
|
129
|
+
batch: PendingMessageResubmitData[],
|
|
130
|
+
metadata: PendingBatchResubmitMetadata,
|
|
131
|
+
): void;
|
|
122
132
|
isActiveConnection: () => boolean;
|
|
123
133
|
isAttached: () => boolean;
|
|
124
134
|
}
|
|
@@ -211,6 +221,24 @@ function toSerializableForm(
|
|
|
211
221
|
};
|
|
212
222
|
}
|
|
213
223
|
|
|
224
|
+
interface ReplayPendingStateOptions {
|
|
225
|
+
/**
|
|
226
|
+
* If true, only replay staged batches. This is used when we are exiting staging mode and want to rebase and submit the staged batches.
|
|
227
|
+
* Default: false
|
|
228
|
+
*/
|
|
229
|
+
onlyStagedBatches: boolean;
|
|
230
|
+
/**
|
|
231
|
+
* @param squash - If true, edits should be squashed when resubmitting.
|
|
232
|
+
* Default: false
|
|
233
|
+
*/
|
|
234
|
+
squash: boolean;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const defaultReplayPendingStatesOptions: ReplayPendingStateOptions = {
|
|
238
|
+
onlyStagedBatches: false,
|
|
239
|
+
squash: false,
|
|
240
|
+
};
|
|
241
|
+
|
|
214
242
|
/**
|
|
215
243
|
* PendingStateManager is responsible for maintaining the messages that have not been sent or have not yet been
|
|
216
244
|
* acknowledged by the server. It also maintains the batch information for both automatically and manually flushed
|
|
@@ -683,11 +711,12 @@ export class PendingStateManager implements IDisposable {
|
|
|
683
711
|
* Called when the Container's connection state changes. If the Container gets connected, it replays all the pending
|
|
684
712
|
* states in its queue. This includes triggering resubmission of unacked ops.
|
|
685
713
|
* ! Note: successfully resubmitting an op that has been successfully sequenced is not possible due to checks in the ConnectionStateHandler (Loader layer)
|
|
686
|
-
* @param onlyStagedBatches - If true, only replay staged batches. This is used when we are exiting staging mode and want to rebase and submit the staged batches.
|
|
687
714
|
*/
|
|
688
|
-
public replayPendingStates(
|
|
715
|
+
public replayPendingStates(optionsParam?: ReplayPendingStateOptions): void {
|
|
716
|
+
const options = { ...defaultReplayPendingStatesOptions, ...optionsParam };
|
|
717
|
+
const { onlyStagedBatches, squash } = options;
|
|
689
718
|
assert(
|
|
690
|
-
this.stateHandler.connected(),
|
|
719
|
+
this.stateHandler.connected() || onlyStagedBatches === true,
|
|
691
720
|
0x172 /* "The connection state is not consistent with the runtime" */,
|
|
692
721
|
);
|
|
693
722
|
|
|
@@ -741,7 +770,7 @@ export class PendingStateManager implements IDisposable {
|
|
|
741
770
|
|
|
742
771
|
if (asEmptyBatchLocalOpMetadata(pendingMessage.localOpMetadata)?.emptyBatch === true) {
|
|
743
772
|
// Resubmit no messages, with the batchId. Will result in another empty batch marker.
|
|
744
|
-
this.stateHandler.reSubmitBatch([], batchId, staged);
|
|
773
|
+
this.stateHandler.reSubmitBatch([], { batchId, staged, squash });
|
|
745
774
|
continue;
|
|
746
775
|
}
|
|
747
776
|
|
|
@@ -766,8 +795,7 @@ export class PendingStateManager implements IDisposable {
|
|
|
766
795
|
opMetadata: pendingMessage.opMetadata,
|
|
767
796
|
},
|
|
768
797
|
],
|
|
769
|
-
batchId,
|
|
770
|
-
staged,
|
|
798
|
+
{ batchId, staged, squash },
|
|
771
799
|
);
|
|
772
800
|
continue;
|
|
773
801
|
}
|
|
@@ -807,7 +835,7 @@ export class PendingStateManager implements IDisposable {
|
|
|
807
835
|
);
|
|
808
836
|
}
|
|
809
837
|
|
|
810
|
-
this.stateHandler.reSubmitBatch(batch, batchId, staged);
|
|
838
|
+
this.stateHandler.reSubmitBatch(batch, { batchId, staged, squash });
|
|
811
839
|
}
|
|
812
840
|
|
|
813
841
|
// pending ops should no longer depend on previous sequenced local ops after resubmit
|
|
@@ -825,17 +853,6 @@ export class PendingStateManager implements IDisposable {
|
|
|
825
853
|
}
|
|
826
854
|
}
|
|
827
855
|
|
|
828
|
-
/**
|
|
829
|
-
* Clears the 'staged' flag off all pending messages.
|
|
830
|
-
*/
|
|
831
|
-
public clearStagingFlags(): void {
|
|
832
|
-
for (const message of this.pendingMessages.toArray()) {
|
|
833
|
-
if (message.batchInfo.staged) {
|
|
834
|
-
message.batchInfo.staged = false;
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
|
|
839
856
|
/**
|
|
840
857
|
* Pops all staged batches, invoking the callback on each one in order (LIFO)
|
|
841
858
|
*/
|