@fluidframework/container-runtime 2.33.2 → 2.40.0
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 +26 -10
- package/dist/channelCollection.d.ts.map +1 -1
- package/dist/channelCollection.js +42 -11
- 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 +15 -16
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +37 -19
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/index.d.ts +1 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -9
- 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 +26 -10
- package/lib/channelCollection.d.ts.map +1 -1
- package/lib/channelCollection.js +43 -12
- 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 +15 -16
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +38 -20
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/index.d.ts +1 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +0 -3
- 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 +77 -19
- package/src/compatUtils.ts +53 -30
- package/src/containerRuntime.ts +102 -81
- package/src/dataStoreContext.ts +48 -38
- package/src/index.ts +1 -13
- 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
package/src/compatUtils.ts
CHANGED
|
@@ -16,7 +16,7 @@ import { pkgVersion } from "./packageVersion.js";
|
|
|
16
16
|
/**
|
|
17
17
|
* Our policy is to support N/N-1 compatibility by default, where N is the most
|
|
18
18
|
* recent public major release of the runtime.
|
|
19
|
-
* Therefore, if the customer does not provide a
|
|
19
|
+
* Therefore, if the customer does not provide a minVersionForCollab, we will
|
|
20
20
|
* default to use N-1.
|
|
21
21
|
*
|
|
22
22
|
* However, this is not consistent with today's behavior. Some options (i.e.
|
|
@@ -26,12 +26,21 @@ import { pkgVersion } from "./packageVersion.js";
|
|
|
26
26
|
* Importantly though, N/N-2 compatibility is still guaranteed with the proper
|
|
27
27
|
* configurations set.
|
|
28
28
|
*
|
|
29
|
-
* Further to distinguish unspecified `
|
|
29
|
+
* Further to distinguish unspecified `minVersionForCollab` from a specified
|
|
30
30
|
* version and allow `enableExplicitSchemaControl` to default to `true` for
|
|
31
31
|
* any 2.0.0+ version, we will use a special value of `2.0.0-defaults`, which
|
|
32
32
|
* is semantically less than 2.0.0.
|
|
33
33
|
*/
|
|
34
|
-
export const
|
|
34
|
+
export const defaultMinVersionForCollab =
|
|
35
|
+
"2.0.0-defaults" as const satisfies MinimumVersionForCollab;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* We don't want allow a version before the major public release of the LTS version.
|
|
39
|
+
* Today we use "1.0.0", because our policy supports N/N-1 & N/N-2, which includes
|
|
40
|
+
* all minor versions of N. Though LTS starts at 1.4.0, we should stay consistent
|
|
41
|
+
* with our policy and allow all 1.x versions to be compatible with 2.x.
|
|
42
|
+
*/
|
|
43
|
+
const lowestMinVersionForCollab = "1.0.0" as const satisfies MinimumVersionForCollab;
|
|
35
44
|
|
|
36
45
|
/**
|
|
37
46
|
* String in a valid semver format specifying bottom of a minor version
|
|
@@ -43,6 +52,18 @@ export type MinimumMinorSemanticVersion = `${bigint}.${bigint}.0` | `${bigint}.0
|
|
|
43
52
|
|
|
44
53
|
/**
|
|
45
54
|
* String in a valid semver format of a specific version at least specifying minor.
|
|
55
|
+
*
|
|
56
|
+
* @legacy
|
|
57
|
+
* @alpha
|
|
58
|
+
*/
|
|
59
|
+
export type MinimumVersionForCollab =
|
|
60
|
+
| `${1 | 2}.${bigint}.${bigint}`
|
|
61
|
+
| `${1 | 2}.${bigint}.${bigint}-${string}`;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* String in a valid semver format of a specific version at least specifying minor.
|
|
65
|
+
* Unlike {@link MinimumVersionForCollab}, this type allows any bigint for the major version.
|
|
66
|
+
* Used as a more generic type that allows major versions other than 1 or 2.
|
|
46
67
|
*/
|
|
47
68
|
export type SemanticVersion =
|
|
48
69
|
| `${bigint}.${bigint}.${bigint}`
|
|
@@ -84,13 +105,13 @@ export type RuntimeOptionsAffectingDocSchema = Omit<
|
|
|
84
105
|
/**
|
|
85
106
|
* Mapping of RuntimeOptionsAffectingDocSchema to their compatibility related configs.
|
|
86
107
|
*
|
|
87
|
-
* Each key in this map corresponds to a property in RuntimeOptionsAffectingDocSchema. The value is an object that maps
|
|
88
|
-
* to the appropriate default value for that property to supporting that
|
|
89
|
-
* the format changes introduced by the property, then the default value for that
|
|
108
|
+
* Each key in this map corresponds to a property in RuntimeOptionsAffectingDocSchema. The value is an object that maps MinimumVersionForCollab
|
|
109
|
+
* to the appropriate default value for that property to supporting that MinimumVersionForCollab. If clients running MinimumVersionForCollab X are able to understand
|
|
110
|
+
* the format changes introduced by the property, then the default value for that MinimumVersionForCollab will enable the feature associated with the property.
|
|
90
111
|
* Otherwise, the feature will be disabled.
|
|
91
112
|
*
|
|
92
|
-
* For example if the
|
|
93
|
-
* clients do not understand the document format when batching is enabled. If the
|
|
113
|
+
* For example if the minVersionForCollab is a 1.x version (i.e. "1.5.0"), then the default value for `enableGroupedBatching` will be false since 1.x
|
|
114
|
+
* clients do not understand the document format when batching is enabled. If the minVersionForCollab is a 2.x client (i.e. "2.0.0" or later), then the
|
|
94
115
|
* default value for `enableGroupedBatching` will be true because clients running 2.0 or later will be able to understand the format changes associated
|
|
95
116
|
* with the batching feature.
|
|
96
117
|
*/
|
|
@@ -118,14 +139,14 @@ const runtimeOptionsAffectingDocSchemaConfigMap = {
|
|
|
118
139
|
explicitSchemaControl: {
|
|
119
140
|
"1.0.0": false,
|
|
120
141
|
// This option's intention is to prevent 1.x clients from joining sessions
|
|
121
|
-
// when enabled. This is set to true when the
|
|
142
|
+
// when enabled. This is set to true when the minVersionForCollab is set
|
|
122
143
|
// to >=2.0.0 (explicitly). This is different than other 2.0 defaults
|
|
123
144
|
// because it was not enabled by default prior to the implementation of
|
|
124
|
-
// `
|
|
125
|
-
// `
|
|
145
|
+
// `minVersionForCollab`.
|
|
146
|
+
// `defaultMinVersionForCollab` is set to "2.0.0-defaults" which "2.0.0"
|
|
126
147
|
// does not satisfy to avoiding enabling this option by default as of
|
|
127
|
-
// `
|
|
128
|
-
// Only enable as a default when `
|
|
148
|
+
// `minVersionForCollab` introduction, which could be unexpected.
|
|
149
|
+
// Only enable as a default when `minVersionForCollab` is specified at
|
|
129
150
|
// 2.0.0+.
|
|
130
151
|
"2.0.0": true,
|
|
131
152
|
} as const,
|
|
@@ -138,7 +159,7 @@ const runtimeOptionsAffectingDocSchemaConfigMap = {
|
|
|
138
159
|
} as const,
|
|
139
160
|
gcOptions: {
|
|
140
161
|
"1.0.0": {},
|
|
141
|
-
// Although sweep is supported in 2.x, it is disabled by default until
|
|
162
|
+
// Although sweep is supported in 2.x, it is disabled by default until minVersionForCollab>=3.0.0 to be extra safe.
|
|
142
163
|
"3.0.0": { enableGCSweep: true },
|
|
143
164
|
} as const,
|
|
144
165
|
createBlobPayloadPending: {
|
|
@@ -150,13 +171,13 @@ const runtimeOptionsAffectingDocSchemaConfigMap = {
|
|
|
150
171
|
} as const satisfies ConfigMap<RuntimeOptionsAffectingDocSchema>;
|
|
151
172
|
|
|
152
173
|
/**
|
|
153
|
-
* Returns the default RuntimeOptionsAffectingDocSchema configuration for a given
|
|
174
|
+
* Returns the default RuntimeOptionsAffectingDocSchema configuration for a given minVersionForCollab.
|
|
154
175
|
*/
|
|
155
|
-
export function
|
|
156
|
-
|
|
176
|
+
export function getMinVersionForCollabDefaults(
|
|
177
|
+
minVersionForCollab: MinimumVersionForCollab,
|
|
157
178
|
): RuntimeOptionsAffectingDocSchema {
|
|
158
179
|
return getConfigsForCompatMode(
|
|
159
|
-
|
|
180
|
+
minVersionForCollab,
|
|
160
181
|
runtimeOptionsAffectingDocSchemaConfigMap,
|
|
161
182
|
// This is a bad cast away from Partial that getConfigsForCompatMode provides.
|
|
162
183
|
// ConfigMap should be restructured to provide RuntimeOptionsAffectingDocSchema guarantee.
|
|
@@ -164,10 +185,10 @@ export function getCompatibilityVersionDefaults(
|
|
|
164
185
|
}
|
|
165
186
|
|
|
166
187
|
/**
|
|
167
|
-
* Returns a default configuration given
|
|
188
|
+
* Returns a default configuration given minVersionForCollab and configuration version map.
|
|
168
189
|
*/
|
|
169
190
|
export function getConfigsForCompatMode<T extends Record<SemanticVersion, unknown>>(
|
|
170
|
-
|
|
191
|
+
minVersionForCollab: SemanticVersion,
|
|
171
192
|
configMap: ConfigMap<T>,
|
|
172
193
|
): Partial<T> {
|
|
173
194
|
const defaultConfigs: Partial<T> = {};
|
|
@@ -176,14 +197,14 @@ export function getConfigsForCompatMode<T extends Record<SemanticVersion, unknow
|
|
|
176
197
|
const config = configMap[key as keyof T];
|
|
177
198
|
// Sort the versions in ascending order so we can short circuit the loop.
|
|
178
199
|
const versions = Object.keys(config).sort(compare);
|
|
179
|
-
// For each config, we iterate over the keys and check if
|
|
200
|
+
// For each config, we iterate over the keys and check if minVersionForCollab is greater than or equal to the version.
|
|
180
201
|
// If so, we set it as the default value for the option. At the end of the loop we should have the most recent default
|
|
181
|
-
// value that is compatible with the version specified as the
|
|
202
|
+
// value that is compatible with the version specified as the minVersionForCollab.
|
|
182
203
|
for (const version of versions) {
|
|
183
|
-
if (gte(
|
|
204
|
+
if (gte(minVersionForCollab, version)) {
|
|
184
205
|
defaultConfigs[key] = config[version as MinimumMinorSemanticVersion];
|
|
185
206
|
} else {
|
|
186
|
-
// If the
|
|
207
|
+
// If the minVersionForCollab is less than the version, we break out of the loop since we don't need to check
|
|
187
208
|
// any later versions.
|
|
188
209
|
break;
|
|
189
210
|
}
|
|
@@ -193,13 +214,15 @@ export function getConfigsForCompatMode<T extends Record<SemanticVersion, unknow
|
|
|
193
214
|
}
|
|
194
215
|
|
|
195
216
|
/**
|
|
196
|
-
* Checks if the
|
|
197
|
-
* A valid
|
|
217
|
+
* Checks if the minVersionForCollab is valid.
|
|
218
|
+
* A valid minVersionForCollab is a MinimumVersionForCollab that is at least `lowestMinVersionForCollab` and less than or equal to the current package version.
|
|
198
219
|
*/
|
|
199
|
-
export function
|
|
220
|
+
export function isValidMinVersionForCollab(
|
|
221
|
+
minVersionForCollab: MinimumVersionForCollab,
|
|
222
|
+
): boolean {
|
|
200
223
|
return (
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
lte(
|
|
224
|
+
valid(minVersionForCollab) !== null &&
|
|
225
|
+
gte(minVersionForCollab, lowestMinVersionForCollab) &&
|
|
226
|
+
lte(minVersionForCollab, pkgVersion)
|
|
204
227
|
);
|
|
205
228
|
}
|
package/src/containerRuntime.ts
CHANGED
|
@@ -74,6 +74,11 @@ import type {
|
|
|
74
74
|
SerializedIdCompressorWithNoSession,
|
|
75
75
|
SerializedIdCompressorWithOngoingSession,
|
|
76
76
|
} from "@fluidframework/id-compressor/internal";
|
|
77
|
+
import {
|
|
78
|
+
createIdCompressor,
|
|
79
|
+
createSessionId,
|
|
80
|
+
deserializeIdCompressor,
|
|
81
|
+
} from "@fluidframework/id-compressor/internal";
|
|
77
82
|
import type {
|
|
78
83
|
ISummaryTreeWithStats,
|
|
79
84
|
ITelemetryContext,
|
|
@@ -158,10 +163,11 @@ import {
|
|
|
158
163
|
wrapContext,
|
|
159
164
|
} from "./channelCollection.js";
|
|
160
165
|
import {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
166
|
+
defaultMinVersionForCollab,
|
|
167
|
+
getMinVersionForCollabDefaults,
|
|
168
|
+
isValidMinVersionForCollab,
|
|
164
169
|
type RuntimeOptionsAffectingDocSchema,
|
|
170
|
+
type MinimumVersionForCollab,
|
|
165
171
|
} from "./compatUtils.js";
|
|
166
172
|
import type { ICompressionRuntimeOptions } from "./compressionDefinitions.js";
|
|
167
173
|
import { CompressionAlgorithms, disabledCompressionConfig } from "./compressionDefinitions.js";
|
|
@@ -197,7 +203,6 @@ import {
|
|
|
197
203
|
} from "./messageTypes.js";
|
|
198
204
|
import { ISavedOpMetadata } from "./metadata.js";
|
|
199
205
|
import {
|
|
200
|
-
BatchId,
|
|
201
206
|
LocalBatchMessage,
|
|
202
207
|
BatchStartInfo,
|
|
203
208
|
DuplicateBatchDetector,
|
|
@@ -210,12 +215,14 @@ import {
|
|
|
210
215
|
Outbox,
|
|
211
216
|
RemoteMessageProcessor,
|
|
212
217
|
type OutboundBatch,
|
|
218
|
+
type BatchResubmitInfo,
|
|
213
219
|
} from "./opLifecycle/index.js";
|
|
214
220
|
import { pkgVersion } from "./packageVersion.js";
|
|
215
221
|
import {
|
|
216
222
|
PendingMessageResubmitData,
|
|
217
223
|
IPendingLocalState,
|
|
218
224
|
PendingStateManager,
|
|
225
|
+
type PendingBatchResubmitMetadata,
|
|
219
226
|
} from "./pendingStateManager.js";
|
|
220
227
|
import { RunCounter } from "./runCounter.js";
|
|
221
228
|
import {
|
|
@@ -504,6 +511,8 @@ export const defaultRuntimeHeaderData: Required<RuntimeHeaderData> = {
|
|
|
504
511
|
allowTombstone: false,
|
|
505
512
|
};
|
|
506
513
|
|
|
514
|
+
const defaultStagingCommitOptions = { squash: false };
|
|
515
|
+
|
|
507
516
|
/**
|
|
508
517
|
* @deprecated
|
|
509
518
|
* Untagged logger is unsupported going forward. There are old loaders with old ContainerContexts that only
|
|
@@ -702,6 +711,27 @@ export interface LoadContainerRuntimeParams {
|
|
|
702
711
|
* @deprecated Will be removed once Loader LTS version is "2.0.0-internal.7.0.0". Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
|
|
703
712
|
* */
|
|
704
713
|
requestHandler?: (request: IRequest, runtime: IContainerRuntime) => Promise<IResponse>;
|
|
714
|
+
|
|
715
|
+
/**
|
|
716
|
+
* Minimum version of the FF runtime that is required to collaborate on new documents.
|
|
717
|
+
* The input should be a string that represents the minimum version of the FF runtime that should be
|
|
718
|
+
* supported for collaboration. The format of the string must be in valid semver format.
|
|
719
|
+
*
|
|
720
|
+
* The inputted version will be used to determine the default configuration for
|
|
721
|
+
* {@link IContainerRuntimeOptionsInternal} to ensure compatibility with the specified version.
|
|
722
|
+
*
|
|
723
|
+
* @example
|
|
724
|
+
* minVersionForCollab: "2.0.0"
|
|
725
|
+
*
|
|
726
|
+
* @privateRemarks
|
|
727
|
+
* Used to determine the default configuration for {@link IContainerRuntimeOptionsInternal} that affect the document schema.
|
|
728
|
+
* For example, let's say that feature `foo` was added in 2.0 which introduces a new op type. Additionally, option `bar`
|
|
729
|
+
* was added to `IContainerRuntimeOptionsInternal` in 2.0 to enable/disable `foo` since clients prior to 2.0 would not
|
|
730
|
+
* understand the new op type. If a customer were to set minVersionForCollab to 2.0.0, then `bar` would be set to
|
|
731
|
+
* enable `foo` by default. If a customer were to set minVersionForCollab to 1.0.0, then `bar` would be set to
|
|
732
|
+
* disable `foo` by default.
|
|
733
|
+
*/
|
|
734
|
+
minVersionForCollab?: MinimumVersionForCollab;
|
|
705
735
|
}
|
|
706
736
|
/**
|
|
707
737
|
* This is meant to be used by a {@link @fluidframework/container-definitions#IRuntimeFactory} to instantiate a container runtime.
|
|
@@ -751,6 +781,7 @@ export class ContainerRuntime
|
|
|
751
781
|
* - containerRuntimeCtor - Constructor to use to create the ContainerRuntime instance.
|
|
752
782
|
* This allows mixin classes to leverage this method to define their own async initializer.
|
|
753
783
|
* - provideEntryPoint - Promise that resolves to an object which will act as entryPoint for the Container.
|
|
784
|
+
* - minVersionForCollab - Minimum version of the FF runtime that this runtime supports collaboration with.
|
|
754
785
|
* This object should provide all the functionality that the Container is expected to provide to the loader layer.
|
|
755
786
|
*/
|
|
756
787
|
public static async loadRuntime(params: {
|
|
@@ -765,6 +796,7 @@ export class ContainerRuntime
|
|
|
765
796
|
*/
|
|
766
797
|
requestHandler?: (request: IRequest, runtime: IContainerRuntime) => Promise<IResponse>;
|
|
767
798
|
provideEntryPoint: (containerRuntime: IContainerRuntime) => Promise<FluidObject>;
|
|
799
|
+
minVersionForCollab?: MinimumVersionForCollab;
|
|
768
800
|
}): Promise<ContainerRuntime> {
|
|
769
801
|
const {
|
|
770
802
|
context,
|
|
@@ -775,6 +807,7 @@ export class ContainerRuntime
|
|
|
775
807
|
runtimeOptions = {} satisfies IContainerRuntimeOptionsInternal,
|
|
776
808
|
containerScope = {},
|
|
777
809
|
containerRuntimeCtor = ContainerRuntime,
|
|
810
|
+
minVersionForCollab = defaultMinVersionForCollab,
|
|
778
811
|
} = params;
|
|
779
812
|
|
|
780
813
|
// If taggedLogger exists, use it. Otherwise, wrap the vanilla logger:
|
|
@@ -796,23 +829,21 @@ export class ContainerRuntime
|
|
|
796
829
|
const mc = loggerToMonitoringContext(logger);
|
|
797
830
|
|
|
798
831
|
// Some options require a minimum version of the FF runtime to operate, so the default configs will be generated
|
|
799
|
-
// based on the
|
|
800
|
-
// For example, if
|
|
801
|
-
// 1.0.0 or later. If the
|
|
832
|
+
// based on the minVersionForCollab.
|
|
833
|
+
// For example, if minVersionForCollab is set to "1.0.0", the default configs will ensure compatibility with FF runtime
|
|
834
|
+
// 1.0.0 or later. If the minVersionForCollab is set to "2.10.0", the default values will be generated to ensure compatibility
|
|
802
835
|
// with FF runtime 2.10.0 or later.
|
|
803
|
-
|
|
804
|
-
const compatibilityVersion = defaultCompatibilityVersion;
|
|
805
|
-
if (!isValidCompatVersion(compatibilityVersion)) {
|
|
836
|
+
if (!isValidMinVersionForCollab(minVersionForCollab)) {
|
|
806
837
|
throw new UsageError(
|
|
807
|
-
`Invalid
|
|
838
|
+
`Invalid minVersionForCollab: ${minVersionForCollab}. It must be an existing FF version (i.e. 2.22.1).`,
|
|
808
839
|
);
|
|
809
840
|
}
|
|
810
|
-
const
|
|
811
|
-
getCompatibilityVersionDefaults(compatibilityVersion);
|
|
841
|
+
const defaultsAffectingDocSchema = getMinVersionForCollabDefaults(minVersionForCollab);
|
|
812
842
|
|
|
813
843
|
// The following are the default values for the options that do not affect the DocumentSchema.
|
|
814
|
-
const
|
|
815
|
-
|
|
844
|
+
const defaultsNotAffectingDocSchema: Omit<
|
|
845
|
+
ContainerRuntimeOptionsInternal,
|
|
846
|
+
keyof RuntimeOptionsAffectingDocSchema
|
|
816
847
|
> = {
|
|
817
848
|
summaryOptions: {},
|
|
818
849
|
loadSequenceNumberVerification: "close",
|
|
@@ -821,8 +852,8 @@ export class ContainerRuntime
|
|
|
821
852
|
};
|
|
822
853
|
|
|
823
854
|
const defaultConfigs = {
|
|
824
|
-
...
|
|
825
|
-
...
|
|
855
|
+
...defaultsAffectingDocSchema,
|
|
856
|
+
...defaultsNotAffectingDocSchema,
|
|
826
857
|
};
|
|
827
858
|
|
|
828
859
|
// Here we set each option to its corresponding default config value if it's not provided in runtimeOptions.
|
|
@@ -976,11 +1007,7 @@ export class ContainerRuntime
|
|
|
976
1007
|
idCompressorMode = desiredIdCompressorMode;
|
|
977
1008
|
}
|
|
978
1009
|
|
|
979
|
-
const createIdCompressorFn =
|
|
980
|
-
const { createIdCompressor, deserializeIdCompressor, createSessionId } = await import(
|
|
981
|
-
"@fluidframework/id-compressor/internal"
|
|
982
|
-
);
|
|
983
|
-
|
|
1010
|
+
const createIdCompressorFn = (): IIdCompressor & IIdCompressorCore => {
|
|
984
1011
|
/**
|
|
985
1012
|
* Because the IdCompressor emits so much telemetry, this function is used to sample
|
|
986
1013
|
* approximately 5% of all clients. Only the given percentage of sessions will emit telemetry.
|
|
@@ -1072,6 +1099,7 @@ export class ContainerRuntime
|
|
|
1072
1099
|
documentSchemaController,
|
|
1073
1100
|
featureGatesForTelemetry,
|
|
1074
1101
|
provideEntryPoint,
|
|
1102
|
+
minVersionForCollab,
|
|
1075
1103
|
requestHandler,
|
|
1076
1104
|
undefined, // summaryConfiguration
|
|
1077
1105
|
recentBatchInfo,
|
|
@@ -1190,12 +1218,6 @@ export class ContainerRuntime
|
|
|
1190
1218
|
}
|
|
1191
1219
|
}
|
|
1192
1220
|
|
|
1193
|
-
/**
|
|
1194
|
-
* True if we have ID compressor loading in-flight (async operation). Useful only for
|
|
1195
|
-
* this.sessionSchema.idCompressorMode === "delayed" mode
|
|
1196
|
-
*/
|
|
1197
|
-
protected _loadIdCompressor: Promise<void> | undefined;
|
|
1198
|
-
|
|
1199
1221
|
/**
|
|
1200
1222
|
* {@inheritDoc @fluidframework/runtime-definitions#IContainerRuntimeBase.generateDocumentUniqueId}
|
|
1201
1223
|
*/
|
|
@@ -1401,11 +1423,12 @@ export class ContainerRuntime
|
|
|
1401
1423
|
|
|
1402
1424
|
blobManagerLoadInfo: IBlobManagerLoadInfo,
|
|
1403
1425
|
private readonly _storage: IDocumentStorageService,
|
|
1404
|
-
private readonly
|
|
1426
|
+
private readonly createIdCompressorFn: () => IIdCompressor & IIdCompressorCore,
|
|
1405
1427
|
|
|
1406
1428
|
private readonly documentsSchemaController: DocumentsSchemaController,
|
|
1407
1429
|
featureGatesForTelemetry: Record<string, boolean | number | undefined>,
|
|
1408
1430
|
provideEntryPoint: (containerRuntime: IContainerRuntime) => Promise<FluidObject>,
|
|
1431
|
+
private readonly minVersionForCollab: MinimumVersionForCollab,
|
|
1409
1432
|
private readonly requestHandler?: (
|
|
1410
1433
|
request: IRequest,
|
|
1411
1434
|
runtime: IContainerRuntime,
|
|
@@ -1914,6 +1937,7 @@ export class ContainerRuntime
|
|
|
1914
1937
|
telemetryDocumentId: this.telemetryDocumentId,
|
|
1915
1938
|
groupedBatchingEnabled: this.groupedBatchingEnabled,
|
|
1916
1939
|
initialSequenceNumber: this.deltaManager.initialSequenceNumber,
|
|
1940
|
+
minVersionForCollab: this.minVersionForCollab,
|
|
1917
1941
|
});
|
|
1918
1942
|
|
|
1919
1943
|
ReportOpPerfTelemetry(this.clientId, this._deltaManager, this, this.baseLogger);
|
|
@@ -1946,7 +1970,6 @@ export class ContainerRuntime
|
|
|
1946
1970
|
// As it's implemented right now (with async initialization), this will only work for "off" -> "delayed" transitions.
|
|
1947
1971
|
// Anything else is too risky, and requires ability to initialize ID compressor synchronously!
|
|
1948
1972
|
if (schema.runtime.idCompressorMode !== undefined) {
|
|
1949
|
-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
1950
1973
|
this.loadIdCompressor();
|
|
1951
1974
|
}
|
|
1952
1975
|
}
|
|
@@ -1994,7 +2017,7 @@ export class ContainerRuntime
|
|
|
1994
2017
|
this.sessionSchema.idCompressorMode === "on" ||
|
|
1995
2018
|
(this.sessionSchema.idCompressorMode === "delayed" && this.connected)
|
|
1996
2019
|
) {
|
|
1997
|
-
this._idCompressor =
|
|
2020
|
+
this._idCompressor = this.createIdCompressorFn();
|
|
1998
2021
|
// This is called from loadRuntime(), long before we process any ops, so there should be no ops accumulated yet.
|
|
1999
2022
|
assert(this.pendingIdCompressorOps.length === 0, 0x8ec /* no pending ops */);
|
|
2000
2023
|
}
|
|
@@ -2592,29 +2615,20 @@ export class ContainerRuntime
|
|
|
2592
2615
|
}
|
|
2593
2616
|
}
|
|
2594
2617
|
|
|
2595
|
-
private
|
|
2618
|
+
private loadIdCompressor(): void {
|
|
2596
2619
|
if (
|
|
2597
2620
|
this._idCompressor === undefined &&
|
|
2598
|
-
this.sessionSchema.idCompressorMode !== undefined
|
|
2599
|
-
this._loadIdCompressor === undefined
|
|
2621
|
+
this.sessionSchema.idCompressorMode !== undefined
|
|
2600
2622
|
) {
|
|
2601
|
-
this.
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
assert(this.pendingIdCompressorOps.length === 0, 0x976 /* No new ops added */);
|
|
2610
|
-
this._idCompressor = compressor;
|
|
2611
|
-
})
|
|
2612
|
-
.catch((error) => {
|
|
2613
|
-
this.mc.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
|
|
2614
|
-
throw error;
|
|
2615
|
-
});
|
|
2623
|
+
this._idCompressor = this.createIdCompressorFn();
|
|
2624
|
+
// Finalize any ranges we received while the compressor was turned off.
|
|
2625
|
+
const ops = this.pendingIdCompressorOps;
|
|
2626
|
+
this.pendingIdCompressorOps = [];
|
|
2627
|
+
for (const range of ops) {
|
|
2628
|
+
this._idCompressor.finalizeCreationRange(range);
|
|
2629
|
+
}
|
|
2630
|
+
assert(this.pendingIdCompressorOps.length === 0, 0x976 /* No new ops added */);
|
|
2616
2631
|
}
|
|
2617
|
-
return this._loadIdCompressor;
|
|
2618
2632
|
}
|
|
2619
2633
|
|
|
2620
2634
|
private readonly notifyReadOnlyState = (readonly: boolean): void =>
|
|
@@ -2630,7 +2644,6 @@ export class ContainerRuntime
|
|
|
2630
2644
|
);
|
|
2631
2645
|
|
|
2632
2646
|
if (connected && this.sessionSchema.idCompressorMode === "delayed") {
|
|
2633
|
-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
2634
2647
|
this.loadIdCompressor();
|
|
2635
2648
|
}
|
|
2636
2649
|
if (connected === false && this.delayConnectClientId !== undefined) {
|
|
@@ -3190,23 +3203,20 @@ export class ContainerRuntime
|
|
|
3190
3203
|
}
|
|
3191
3204
|
|
|
3192
3205
|
/**
|
|
3193
|
-
* Flush the
|
|
3194
|
-
* This method is expected to be called
|
|
3206
|
+
* Flush the current batch of ops to the ordering service for sequencing
|
|
3207
|
+
* This method is not expected to be called in the middle of a batch.
|
|
3195
3208
|
* @remarks - If it throws (e.g. if the batch is too large to send), the container will be closed.
|
|
3196
3209
|
*
|
|
3197
|
-
* @param
|
|
3198
|
-
* with the given Batch ID, which must be preserved
|
|
3199
|
-
* @param resubmittingStagedBatch - If defined, indicates this is a resubmission of a batch that is staged,
|
|
3200
|
-
* meaning it should not be sent to the ordering service yet.
|
|
3210
|
+
* @param resubmitInfo - If defined, indicates this is a resubmission of a batch with the given Batch info needed for resubmit.
|
|
3201
3211
|
*/
|
|
3202
|
-
private flush(
|
|
3212
|
+
private flush(resubmitInfo?: BatchResubmitInfo): void {
|
|
3203
3213
|
try {
|
|
3204
3214
|
assert(
|
|
3205
3215
|
!this.batchRunner.running,
|
|
3206
3216
|
0x24c /* "Cannot call `flush()` while manually accumulating a batch (e.g. under orderSequentially) */,
|
|
3207
3217
|
);
|
|
3208
3218
|
|
|
3209
|
-
this.outbox.flush(
|
|
3219
|
+
this.outbox.flush(resubmitInfo);
|
|
3210
3220
|
assert(this.outbox.isEmpty, 0x3cf /* reentrancy */);
|
|
3211
3221
|
} catch (error) {
|
|
3212
3222
|
const error2 = normalizeError(error, {
|
|
@@ -3282,7 +3292,8 @@ export class ContainerRuntime
|
|
|
3282
3292
|
throw error; // throw the original error for the consumer of the runtime
|
|
3283
3293
|
}
|
|
3284
3294
|
});
|
|
3285
|
-
|
|
3295
|
+
|
|
3296
|
+
stageControls?.commitChanges({ squash: false });
|
|
3286
3297
|
|
|
3287
3298
|
// We don't flush on TurnBased since we expect all messages in the same JS turn to be part of the same batch
|
|
3288
3299
|
if (this.flushMode !== FlushMode.TurnBased && !this.batchRunner.running) {
|
|
@@ -3318,16 +3329,19 @@ export class ContainerRuntime
|
|
|
3318
3329
|
// Make sure all BatchManagers are empty before entering staging mode,
|
|
3319
3330
|
// since we mark whole batches as "staged" or not to indicate whether to submit them.
|
|
3320
3331
|
this.outbox.flush();
|
|
3332
|
+
|
|
3321
3333
|
const exitStagingMode = (discardOrCommit: () => void) => (): void => {
|
|
3322
3334
|
// Final flush of any last staged changes
|
|
3323
|
-
this.outbox.flush(
|
|
3335
|
+
this.outbox.flush();
|
|
3324
3336
|
|
|
3325
3337
|
this.stageControls = undefined;
|
|
3326
3338
|
|
|
3327
3339
|
discardOrCommit();
|
|
3340
|
+
this.channelCollection.notifyStagingMode(false);
|
|
3328
3341
|
};
|
|
3329
3342
|
|
|
3330
|
-
|
|
3343
|
+
// eslint-disable-next-line import/no-deprecated
|
|
3344
|
+
const stageControls: StageControlsExperimental = {
|
|
3331
3345
|
discardChanges: exitStagingMode(() => {
|
|
3332
3346
|
// Pop all staged batches from the PSM and roll them back in LIFO order
|
|
3333
3347
|
this.pendingStateManager.popStagedBatches(({ runtimeOp, localOpMetadata }) => {
|
|
@@ -3341,18 +3355,21 @@ export class ContainerRuntime
|
|
|
3341
3355
|
this.updateDocumentDirtyState(this.pendingMessagesCount !== 0);
|
|
3342
3356
|
}
|
|
3343
3357
|
}),
|
|
3344
|
-
commitChanges:
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
}
|
|
3352
|
-
}
|
|
3358
|
+
commitChanges: (optionsParam) => {
|
|
3359
|
+
const options = { ...defaultStagingCommitOptions, ...optionsParam };
|
|
3360
|
+
return exitStagingMode(() => {
|
|
3361
|
+
this.pendingStateManager.replayPendingStates({
|
|
3362
|
+
onlyStagedBatches: true,
|
|
3363
|
+
squash: options.squash ?? false,
|
|
3364
|
+
});
|
|
3365
|
+
})();
|
|
3366
|
+
},
|
|
3353
3367
|
};
|
|
3354
3368
|
|
|
3355
|
-
|
|
3369
|
+
this.stageControls = stageControls;
|
|
3370
|
+
this.channelCollection.notifyStagingMode(true);
|
|
3371
|
+
|
|
3372
|
+
return this.stageControls;
|
|
3356
3373
|
};
|
|
3357
3374
|
|
|
3358
3375
|
/**
|
|
@@ -3587,8 +3604,7 @@ export class ContainerRuntime
|
|
|
3587
3604
|
wrapSummaryInChannelsTree(summarizeResult);
|
|
3588
3605
|
const pathPartsForChildren = [channelsTreeName];
|
|
3589
3606
|
|
|
3590
|
-
|
|
3591
|
-
await this.loadIdCompressor();
|
|
3607
|
+
this.loadIdCompressor();
|
|
3592
3608
|
|
|
3593
3609
|
this.addContainerStateToSummary(summarizeResult, fullTree, trackState, telemetryContext);
|
|
3594
3610
|
return {
|
|
@@ -4547,22 +4563,21 @@ export class ContainerRuntime
|
|
|
4547
4563
|
*/
|
|
4548
4564
|
private reSubmitBatch(
|
|
4549
4565
|
batch: PendingMessageResubmitData[],
|
|
4550
|
-
batchId:
|
|
4551
|
-
staged: boolean,
|
|
4566
|
+
{ batchId, staged, squash }: PendingBatchResubmitMetadata,
|
|
4552
4567
|
): void {
|
|
4553
4568
|
this.batchRunner.run(() => {
|
|
4554
4569
|
for (const message of batch) {
|
|
4555
|
-
this.reSubmit(message);
|
|
4570
|
+
this.reSubmit(message, squash);
|
|
4556
4571
|
}
|
|
4557
4572
|
});
|
|
4558
4573
|
|
|
4559
4574
|
// Only include Batch ID if "Offline Load" feature is enabled
|
|
4560
4575
|
// It's only needed to identify batches across container forks arising from misuse of offline load.
|
|
4561
|
-
this.flush(this.offlineEnabled ? batchId : undefined, staged);
|
|
4576
|
+
this.flush({ batchId: this.offlineEnabled ? batchId : undefined, staged });
|
|
4562
4577
|
}
|
|
4563
4578
|
|
|
4564
|
-
private reSubmit(message: PendingMessageResubmitData): void {
|
|
4565
|
-
this.reSubmitCore(message.runtimeOp, message.localOpMetadata, message.opMetadata);
|
|
4579
|
+
private reSubmit(message: PendingMessageResubmitData, squash: boolean): void {
|
|
4580
|
+
this.reSubmitCore(message.runtimeOp, message.localOpMetadata, message.opMetadata, squash);
|
|
4566
4581
|
}
|
|
4567
4582
|
|
|
4568
4583
|
/**
|
|
@@ -4576,6 +4591,7 @@ export class ContainerRuntime
|
|
|
4576
4591
|
message: LocalContainerRuntimeMessage,
|
|
4577
4592
|
localOpMetadata: unknown,
|
|
4578
4593
|
opMetadata: Record<string, unknown> | undefined,
|
|
4594
|
+
squash: boolean,
|
|
4579
4595
|
): void {
|
|
4580
4596
|
assert(
|
|
4581
4597
|
this._summarizer === undefined,
|
|
@@ -4587,7 +4603,12 @@ export class ContainerRuntime
|
|
|
4587
4603
|
case ContainerMessageType.Alias: {
|
|
4588
4604
|
// For Operations, call resubmitDataStoreOp which will find the right store
|
|
4589
4605
|
// and trigger resubmission on it.
|
|
4590
|
-
this.channelCollection.reSubmit(
|
|
4606
|
+
this.channelCollection.reSubmit(
|
|
4607
|
+
message.type,
|
|
4608
|
+
message.contents,
|
|
4609
|
+
localOpMetadata,
|
|
4610
|
+
squash,
|
|
4611
|
+
);
|
|
4591
4612
|
break;
|
|
4592
4613
|
}
|
|
4593
4614
|
case ContainerMessageType.IdAllocation: {
|