@fluidframework/container-runtime 2.42.0 → 2.43.0-343119

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.
Files changed (50) hide show
  1. package/container-runtime.test-files.tar +0 -0
  2. package/dist/compatUtils.d.ts +2 -0
  3. package/dist/compatUtils.d.ts.map +1 -1
  4. package/dist/compatUtils.js.map +1 -1
  5. package/dist/containerRuntime.d.ts +2 -2
  6. package/dist/containerRuntime.d.ts.map +1 -1
  7. package/dist/containerRuntime.js +28 -12
  8. package/dist/containerRuntime.js.map +1 -1
  9. package/dist/index.d.ts +2 -2
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js.map +1 -1
  12. package/dist/packageVersion.d.ts +1 -1
  13. package/dist/packageVersion.d.ts.map +1 -1
  14. package/dist/packageVersion.js +1 -1
  15. package/dist/packageVersion.js.map +1 -1
  16. package/dist/summary/documentSchema.d.ts +40 -1
  17. package/dist/summary/documentSchema.d.ts.map +1 -1
  18. package/dist/summary/documentSchema.js +57 -1
  19. package/dist/summary/documentSchema.js.map +1 -1
  20. package/dist/summary/index.d.ts +1 -1
  21. package/dist/summary/index.d.ts.map +1 -1
  22. package/dist/summary/index.js.map +1 -1
  23. package/lib/compatUtils.d.ts +2 -0
  24. package/lib/compatUtils.d.ts.map +1 -1
  25. package/lib/compatUtils.js.map +1 -1
  26. package/lib/containerRuntime.d.ts +2 -2
  27. package/lib/containerRuntime.d.ts.map +1 -1
  28. package/lib/containerRuntime.js +28 -12
  29. package/lib/containerRuntime.js.map +1 -1
  30. package/lib/index.d.ts +2 -2
  31. package/lib/index.d.ts.map +1 -1
  32. package/lib/index.js.map +1 -1
  33. package/lib/packageVersion.d.ts +1 -1
  34. package/lib/packageVersion.d.ts.map +1 -1
  35. package/lib/packageVersion.js +1 -1
  36. package/lib/packageVersion.js.map +1 -1
  37. package/lib/summary/documentSchema.d.ts +40 -1
  38. package/lib/summary/documentSchema.d.ts.map +1 -1
  39. package/lib/summary/documentSchema.js +57 -1
  40. package/lib/summary/documentSchema.js.map +1 -1
  41. package/lib/summary/index.d.ts +1 -1
  42. package/lib/summary/index.d.ts.map +1 -1
  43. package/lib/summary/index.js.map +1 -1
  44. package/package.json +18 -18
  45. package/src/compatUtils.ts +2 -0
  46. package/src/containerRuntime.ts +33 -12
  47. package/src/index.ts +2 -1
  48. package/src/packageVersion.ts +1 -1
  49. package/src/summary/documentSchema.ts +125 -5
  50. package/src/summary/index.ts +1 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/container-runtime",
3
- "version": "2.42.0",
3
+ "version": "2.43.0-343119",
4
4
  "description": "Fluid container runtime",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -119,18 +119,18 @@
119
119
  "temp-directory": "nyc/.nyc_output"
120
120
  },
121
121
  "dependencies": {
122
- "@fluid-internal/client-utils": "~2.42.0",
123
- "@fluidframework/container-definitions": "~2.42.0",
124
- "@fluidframework/container-runtime-definitions": "~2.42.0",
125
- "@fluidframework/core-interfaces": "~2.42.0",
126
- "@fluidframework/core-utils": "~2.42.0",
127
- "@fluidframework/datastore": "~2.42.0",
128
- "@fluidframework/driver-definitions": "~2.42.0",
129
- "@fluidframework/driver-utils": "~2.42.0",
130
- "@fluidframework/id-compressor": "~2.42.0",
131
- "@fluidframework/runtime-definitions": "~2.42.0",
132
- "@fluidframework/runtime-utils": "~2.42.0",
133
- "@fluidframework/telemetry-utils": "~2.42.0",
122
+ "@fluid-internal/client-utils": "2.43.0-343119",
123
+ "@fluidframework/container-definitions": "2.43.0-343119",
124
+ "@fluidframework/container-runtime-definitions": "2.43.0-343119",
125
+ "@fluidframework/core-interfaces": "2.43.0-343119",
126
+ "@fluidframework/core-utils": "2.43.0-343119",
127
+ "@fluidframework/datastore": "2.43.0-343119",
128
+ "@fluidframework/driver-definitions": "2.43.0-343119",
129
+ "@fluidframework/driver-utils": "2.43.0-343119",
130
+ "@fluidframework/id-compressor": "2.43.0-343119",
131
+ "@fluidframework/runtime-definitions": "2.43.0-343119",
132
+ "@fluidframework/runtime-utils": "2.43.0-343119",
133
+ "@fluidframework/telemetry-utils": "2.43.0-343119",
134
134
  "@tylerbu/sorted-btree-es6": "^1.8.0",
135
135
  "double-ended-queue": "^2.1.0-0",
136
136
  "lz4js": "^0.2.0",
@@ -140,16 +140,16 @@
140
140
  "devDependencies": {
141
141
  "@arethetypeswrong/cli": "^0.17.1",
142
142
  "@biomejs/biome": "~1.9.3",
143
- "@fluid-internal/mocha-test-setup": "~2.42.0",
144
- "@fluid-private/stochastic-test-utils": "~2.42.0",
145
- "@fluid-private/test-pairwise-generator": "~2.42.0",
143
+ "@fluid-internal/mocha-test-setup": "2.43.0-343119",
144
+ "@fluid-private/stochastic-test-utils": "2.43.0-343119",
145
+ "@fluid-private/test-pairwise-generator": "2.43.0-343119",
146
146
  "@fluid-tools/benchmark": "^0.51.0",
147
147
  "@fluid-tools/build-cli": "^0.55.0",
148
148
  "@fluidframework/build-common": "^2.0.3",
149
149
  "@fluidframework/build-tools": "^0.55.0",
150
- "@fluidframework/container-runtime-previous": "npm:@fluidframework/container-runtime@2.41.0",
150
+ "@fluidframework/container-runtime-previous": "npm:@fluidframework/container-runtime@2.42.0",
151
151
  "@fluidframework/eslint-config-fluid": "^5.7.4",
152
- "@fluidframework/test-runtime-utils": "~2.42.0",
152
+ "@fluidframework/test-runtime-utils": "2.43.0-343119",
153
153
  "@microsoft/api-extractor": "7.52.8",
154
154
  "@types/double-ended-queue": "^2.1.0",
155
155
  "@types/lz4js": "^0.2.0",
@@ -66,6 +66,8 @@ export type MinimumVersionForCollab =
66
66
  * String in a valid semver format of a specific version at least specifying minor.
67
67
  * Unlike {@link MinimumVersionForCollab}, this type allows any bigint for the major version.
68
68
  * Used as a more generic type that allows major versions other than 1 or 2.
69
+ *
70
+ * @internal
69
71
  */
70
72
  export type SemanticVersion =
71
73
  | `${bigint}.${bigint}.${bigint}`
@@ -160,6 +160,7 @@ import {
160
160
  tagCodeArtifacts,
161
161
  normalizeError,
162
162
  } from "@fluidframework/telemetry-utils/internal";
163
+ import { gt } from "semver-ts";
163
164
  import { v4 as uuid } from "uuid";
164
165
 
165
166
  import { BindBatchTracker } from "./batchTracker.js";
@@ -183,6 +184,7 @@ import {
183
184
  isValidMinVersionForCollab,
184
185
  type RuntimeOptionsAffectingDocSchema,
185
186
  type MinimumVersionForCollab,
187
+ type SemanticVersion,
186
188
  validateRuntimeOptions,
187
189
  } from "./compatUtils.js";
188
190
  import type { ICompressionRuntimeOptions } from "./compressionDefinitions.js";
@@ -1114,8 +1116,19 @@ export class ContainerRuntime
1114
1116
  (schema) => {
1115
1117
  runtime.onSchemaChange(schema);
1116
1118
  },
1119
+ { minVersionForCollab },
1120
+ logger,
1117
1121
  );
1118
1122
 
1123
+ // If the minVersionForCollab for this client is greater than the existing one, we should use that one going forward.
1124
+ const existingMinVersionForCollab =
1125
+ documentSchemaController.sessionSchema.info.minVersionForCollab;
1126
+ const updatedMinVersionForCollab =
1127
+ existingMinVersionForCollab === undefined ||
1128
+ gt(minVersionForCollab, existingMinVersionForCollab)
1129
+ ? minVersionForCollab
1130
+ : existingMinVersionForCollab;
1131
+
1119
1132
  if (compressionLz4 && !enableGroupedBatching) {
1120
1133
  throw new UsageError("If compression is enabled, op grouping must be enabled too");
1121
1134
  }
@@ -1154,7 +1167,7 @@ export class ContainerRuntime
1154
1167
  documentSchemaController,
1155
1168
  featureGatesForTelemetry,
1156
1169
  provideEntryPoint,
1157
- minVersionForCollab,
1170
+ updatedMinVersionForCollab,
1158
1171
  requestHandler,
1159
1172
  undefined, // summaryConfiguration
1160
1173
  recentBatchInfo,
@@ -1491,7 +1504,7 @@ export class ContainerRuntime
1491
1504
  private readonly documentsSchemaController: DocumentsSchemaController,
1492
1505
  featureGatesForTelemetry: Record<string, boolean | number | undefined>,
1493
1506
  provideEntryPoint: (containerRuntime: IContainerRuntime) => Promise<FluidObject>,
1494
- private readonly minVersionForCollab: MinimumVersionForCollab,
1507
+ private readonly minVersionForCollab: SemanticVersion,
1495
1508
  private readonly requestHandler?: (
1496
1509
  request: IRequest,
1497
1510
  runtime: IContainerRuntime,
@@ -3474,22 +3487,29 @@ export class ContainerRuntime
3474
3487
  throw new UsageError("cannot enter staging mode while detached");
3475
3488
  }
3476
3489
 
3477
- // Make sure all BatchManagers are empty before entering staging mode,
3490
+ // Make sure Outbox is empty before entering staging mode,
3478
3491
  // since we mark whole batches as "staged" or not to indicate whether to submit them.
3479
- this.outbox.flush();
3492
+ this.flush();
3480
3493
 
3481
3494
  const exitStagingMode = (discardOrCommit: () => void) => (): void => {
3482
- // Final flush of any last staged changes
3483
- this.outbox.flush();
3495
+ try {
3496
+ // Final flush of any last staged changes
3497
+ // NOTE: We can't use this.flush() here, because orderSequentially uses StagingMode and in the rollback case we'll hit assert 0x24c
3498
+ this.outbox.flush();
3484
3499
 
3485
- this.stageControls = undefined;
3500
+ this.stageControls = undefined;
3486
3501
 
3487
- // During Staging Mode, we avoid submitting any ID Allocation ops (apart from resubmitting pre-staging ops).
3488
- // Now that we've exited, we need to submit an ID Allocation op for any IDs that were generated while in Staging Mode.
3489
- this.submitIdAllocationOpIfNeeded({ staged: false });
3490
- discardOrCommit();
3502
+ // During Staging Mode, we avoid submitting any ID Allocation ops (apart from resubmitting pre-staging ops).
3503
+ // Now that we've exited, we need to submit an ID Allocation op for any IDs that were generated while in Staging Mode.
3504
+ this.submitIdAllocationOpIfNeeded({ staged: false });
3505
+ discardOrCommit();
3491
3506
 
3492
- this.channelCollection.notifyStagingMode(false);
3507
+ this.channelCollection.notifyStagingMode(false);
3508
+ } catch (error) {
3509
+ const normalizedError = normalizeError(error);
3510
+ this.closeFn(normalizedError);
3511
+ throw normalizedError;
3512
+ }
3493
3513
  };
3494
3514
 
3495
3515
  // eslint-disable-next-line import/no-deprecated
@@ -4572,6 +4592,7 @@ export class ContainerRuntime
4572
4592
  newRuntimeSchema: JSON.stringify(schemaChangeMessage.runtime),
4573
4593
  sessionRuntimeSchema: JSON.stringify(this.sessionSchema),
4574
4594
  oldRuntimeSchema: JSON.stringify(this.metadata?.documentSchema?.runtime),
4595
+ minVersionForCollab: schemaChangeMessage.info?.minVersionForCollab,
4575
4596
  });
4576
4597
  const msg: OutboundContainerRuntimeDocumentSchemaMessage = {
4577
4598
  type: ContainerMessageType.DocumentSchemaChange,
package/src/index.ts CHANGED
@@ -31,7 +31,7 @@ export {
31
31
  ChannelCollectionFactory,
32
32
  AllowTombstoneRequestHeaderKey,
33
33
  } from "./channelCollection.js";
34
- export type { MinimumVersionForCollab } from "./compatUtils.js";
34
+ export type { MinimumVersionForCollab, SemanticVersion } from "./compatUtils.js";
35
35
  export {
36
36
  GCNodeType,
37
37
  IGCMetadata,
@@ -91,6 +91,7 @@ export {
91
91
  IRetriableFailureError,
92
92
  IdCompressorMode,
93
93
  IDocumentSchema,
94
+ IDocumentSchemaInfo,
94
95
  DocumentSchemaValueType,
95
96
  IDocumentSchemaCurrent,
96
97
  currentDocumentVersionSchema,
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/container-runtime";
9
- export const pkgVersion = "2.42.0";
9
+ export const pkgVersion = "2.43.0-343119";
@@ -4,8 +4,11 @@
4
4
  */
5
5
 
6
6
  import { assert } from "@fluidframework/core-utils/internal";
7
+ import type { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils/internal";
7
8
  import { DataProcessingError } from "@fluidframework/telemetry-utils/internal";
9
+ import { gt, lt, parse } from "semver-ts";
8
10
 
11
+ import type { SemanticVersion } from "../compatUtils.js";
9
12
  import { pkgVersion } from "../packageVersion.js";
10
13
 
11
14
  /**
@@ -80,10 +83,42 @@ export interface IDocumentSchema {
80
83
  * properties to be able to open the document.
81
84
  */
82
85
  runtime: Record<string, DocumentSchemaValueType>;
86
+
87
+ /**
88
+ * Info about this document that can be updated via Document Schema change op, but isn't required
89
+ * to be understood by all clients (unlike the rest of IDocumentSchema properties). Because of this,
90
+ * some older documents may not have this property, so it's an optional property.
91
+ */
92
+ info?: IDocumentSchemaInfo;
93
+ }
94
+
95
+ /**
96
+ * Informational properties of the document that are not subject to strict schema enforcement.
97
+ *
98
+ * @internal
99
+ */
100
+ export interface IDocumentSchemaInfo {
101
+ /**
102
+ * The minimum version of the FF runtime that should be used to load this document.
103
+ * Will likely be advanced over time as applications pick up later FF versions.
104
+ *
105
+ * We use this to issue telemetry warning events if a client tries to open a document
106
+ * with a runtime version lower than this.
107
+ *
108
+ * See {@link @fluidframework/container-runtime#LoadContainerRuntimeParams} for additional details on `minVersionForCollab`.
109
+ *
110
+ * @remarks
111
+ * We use `SemanticVersion` instead of `MinimumVersionForCollab` since we may open future documents that with a
112
+ * minVersionForCollab version that `MinimumVersionForCollab` does not support.
113
+ */
114
+ minVersionForCollab: SemanticVersion;
83
115
  }
84
116
 
85
117
  /**
86
118
  * Content of the type=ContainerMessageType.DocumentSchemaChange ops.
119
+ * The meaning of refSeq field is different in such messages (compared to other usages of IDocumentSchemaCurrent)
120
+ * ContainerMessageType.DocumentSchemaChange messages use CAS (Compare-and-swap) semantics, and convey
121
+ * regSeq of last known schema change (known to a client proposing schema change).
87
122
  * @see InboundContainerRuntimeDocumentSchemaMessage
88
123
  * @internal
89
124
  */
@@ -133,6 +168,8 @@ export interface IDocumentSchemaFeatures {
133
168
  * in a way that all old/new clients are required to understand.
134
169
  * Ex: Adding a new configuration property (under IDocumentSchema.runtime) does not require changing this version since there is logic
135
170
  * in old clients for handling new/unknown properties.
171
+ * Ex: Adding a new property to IDocumentSchema.info does not require changing this version, since info properties are not required to be
172
+ * understood by all clients.
136
173
  * Ex: Changing the 'document schema acceptance' mechanism from convert-and-swap to one requiring consensus does require changing this version
137
174
  * since all clients need to understand the new protocol.
138
175
  * @internal
@@ -141,11 +178,15 @@ export const currentDocumentVersionSchema = 1;
141
178
 
142
179
  /**
143
180
  * Current document schema.
181
+ * This interface represents the schema that we currently understand and know the
182
+ * structure of (which properties will be present).
183
+ *
144
184
  * @internal
145
185
  */
146
186
  export interface IDocumentSchemaCurrent extends Required<IDocumentSchema> {
147
187
  // This is the version of the schema that we currently understand.
148
188
  version: typeof currentDocumentVersionSchema;
189
+ // This narrows the runtime property to only include the properties in IDocumentSchemaFeatures (all as optional)
149
190
  runtime: {
150
191
  [P in keyof IDocumentSchemaFeatures]?: IDocumentSchemaFeatures[P] extends boolean
151
192
  ? true
@@ -153,6 +194,18 @@ export interface IDocumentSchemaCurrent extends Required<IDocumentSchema> {
153
194
  };
154
195
  }
155
196
 
197
+ /**
198
+ * Document schema that is incoming from another client but validated to be "current".
199
+ *
200
+ * This interface represents when we have validated that an incoming IDocumentSchema object
201
+ * is compatible with the current runtime (by calling `checkRuntimeCompatibility()`).
202
+ * However, the `info` property is optional because some older documents may not have this property, but
203
+ * `info` is not required to be understood by all clients to be compatible.
204
+ */
205
+ interface IDocumentSchemaCurrentIncoming extends Omit<IDocumentSchemaCurrent, "info"> {
206
+ info?: IDocumentSchemaInfo;
207
+ }
208
+
156
209
  interface IProperty<T = unknown> {
157
210
  and: (persistedSchema: T, providedSchema: T) => T;
158
211
  or: (persistedSchema: T, providedSchema: T) => T;
@@ -257,7 +310,7 @@ const documentSchemaSupportedConfigs = {
257
310
  function checkRuntimeCompatibility(
258
311
  documentSchema: IDocumentSchema | undefined,
259
312
  schemaName: string,
260
- ): asserts documentSchema is IDocumentSchemaCurrent {
313
+ ): asserts documentSchema is IDocumentSchemaCurrentIncoming {
261
314
  // Back-compat - we can't do anything about legacy documents.
262
315
  // There is no way to validate them, so we are taking a guess that safe deployment processes used by a given app
263
316
  // do not run into compat problems.
@@ -315,7 +368,7 @@ function checkRuntimeCompatibility(
315
368
  }
316
369
 
317
370
  function and(
318
- persistedSchema: IDocumentSchemaCurrent,
371
+ persistedSchema: IDocumentSchemaCurrentIncoming,
319
372
  providedSchema: IDocumentSchemaCurrent,
320
373
  ): IDocumentSchemaCurrent {
321
374
  const runtime = {};
@@ -328,15 +381,22 @@ function and(
328
381
  providedSchema.runtime[key],
329
382
  );
330
383
  }
384
+
385
+ // We keep the persisted minVersionForCollab if present, even if the provided minVersionForCollab
386
+ // is higher.
387
+ const minVersionForCollab =
388
+ persistedSchema.info?.minVersionForCollab ?? providedSchema.info.minVersionForCollab;
389
+
331
390
  return {
332
391
  version: currentDocumentVersionSchema,
333
392
  refSeq: persistedSchema.refSeq,
393
+ info: { minVersionForCollab },
334
394
  runtime,
335
395
  };
336
396
  }
337
397
 
338
398
  function or(
339
- persistedSchema: IDocumentSchemaCurrent,
399
+ persistedSchema: IDocumentSchemaCurrentIncoming,
340
400
  providedSchema: IDocumentSchemaCurrent,
341
401
  ): IDocumentSchemaCurrent {
342
402
  const runtime = {};
@@ -349,17 +409,40 @@ function or(
349
409
  providedSchema.runtime[key],
350
410
  );
351
411
  }
412
+
413
+ // We take the greater of the persisted/provided minVersionForCollab
414
+ const minVersionForCollab =
415
+ persistedSchema.info === undefined
416
+ ? providedSchema.info.minVersionForCollab
417
+ : gt(persistedSchema.info.minVersionForCollab, providedSchema.info.minVersionForCollab)
418
+ ? persistedSchema.info.minVersionForCollab
419
+ : providedSchema.info.minVersionForCollab;
420
+
352
421
  return {
353
422
  version: currentDocumentVersionSchema,
354
423
  refSeq: persistedSchema.refSeq,
424
+ info: { minVersionForCollab },
355
425
  runtime,
356
426
  };
357
427
  }
358
428
 
429
+ /**
430
+ * Determines if two schemas are the "same".
431
+ * Schemas are considered **not** the same if a schema change op is required to make
432
+ * the properties of `persistedSchema` match to the properties of `providedSchema`.
433
+ */
359
434
  function same(
360
- persistedSchema: IDocumentSchemaCurrent,
435
+ persistedSchema: IDocumentSchemaCurrentIncoming,
361
436
  providedSchema: IDocumentSchemaCurrent,
362
437
  ): boolean {
438
+ if (
439
+ persistedSchema.info === undefined ||
440
+ lt(persistedSchema.info.minVersionForCollab, providedSchema.info.minVersionForCollab)
441
+ ) {
442
+ // If the persisted schema's minVersionForCollab is undefined or less than the provided schema's
443
+ // minVersionForCollab, then we should send a schema change op to update the minVersionForCollab.
444
+ return false;
445
+ }
363
446
  for (const key of new Set([
364
447
  ...Object.keys(persistedSchema.runtime),
365
448
  ...Object.keys(providedSchema.runtime),
@@ -483,6 +566,8 @@ export class DocumentsSchemaController {
483
566
  * @param documentMetadataSchema - current document's schema, if present.
484
567
  * @param features - features of the document schema that current session wants to see enabled.
485
568
  * @param onSchemaChange - callback that is called whenever schema is changed (not called on creation / load, only when processing document schema change ops)
569
+ * @param info - Informational properties of the document that are not subject to strict schema enforcement
570
+ * @param logger - telemetry logger from the runtime
486
571
  */
487
572
  constructor(
488
573
  existing: boolean,
@@ -490,6 +575,8 @@ export class DocumentsSchemaController {
490
575
  documentMetadataSchema: IDocumentSchema | undefined,
491
576
  features: IDocumentSchemaFeatures,
492
577
  private readonly onSchemaChange: (schema: IDocumentSchemaCurrent) => void,
578
+ info: IDocumentSchemaInfo,
579
+ logger: ITelemetryLoggerExt,
493
580
  ) {
494
581
  // For simplicity, let's only support new schema features for explicit schema control mode
495
582
  assert(
@@ -497,10 +584,34 @@ export class DocumentsSchemaController {
497
584
  0x949 /* not supported */,
498
585
  );
499
586
 
587
+ // We check the document's metadata to see if there is a minVersionForCollab. If it's not an existing document or
588
+ // if the document is older, then it won't have one. If it does have a minVersionForCollab, we check if it's greater
589
+ // than this client's runtime version. If so, we log a telemetry event to warn the customer that the client is outdated.
590
+ // Note: We only send a warning because we will confirm via `checkRuntimeCompatibility` if this client **can** understand
591
+ // the existing document's schema. We still want to issue a warning regardless if this client can or cannot understand the
592
+ // schema since it may be a sign that the customer is not properly waiting for saturation before updating their
593
+ // `minVersionForCollab` value, which could cause disruptions to users in the future.
594
+ const existingMinVersionForCollab = documentMetadataSchema?.info?.minVersionForCollab;
595
+ if (
596
+ existingMinVersionForCollab !== undefined &&
597
+ gt(existingMinVersionForCollab, pkgVersion) &&
598
+ // We also want to avoid sending the telemetry warning for dev builds, since they currently are formatted as
599
+ // `0.0.0-#####-test`. This will cause the telemetry warning to constantly fire.
600
+ // TODO: This can be removed after ADO:41351
601
+ !isDevBuild(pkgVersion)
602
+ ) {
603
+ const warnMsg = `WARNING: The version of Fluid Framework used by this client (${pkgVersion}) is not supported by this document! Please upgrade to version ${existingMinVersionForCollab} or later to ensure compatibility.`;
604
+ logger.sendTelemetryEvent({
605
+ eventName: "MinVersionForCollabWarning",
606
+ message: warnMsg,
607
+ });
608
+ }
609
+
500
610
  // Desired schema by this session - almost all props are coming from arguments
501
611
  this.desiredSchema = {
502
612
  version: currentDocumentVersionSchema,
503
613
  refSeq: documentMetadataSchema?.refSeq ?? 0,
614
+ info,
504
615
  runtime: {
505
616
  explicitSchemaControl: boolToProp(features.explicitSchemaControl),
506
617
  compressionLz4: boolToProp(features.compressionLz4),
@@ -520,6 +631,7 @@ export class DocumentsSchemaController {
520
631
  version: currentDocumentVersionSchema,
521
632
  // see comment in summarizeDocumentSchema() on why it has to stay zero
522
633
  refSeq: 0,
634
+ info,
523
635
  // If it's existing document and it has no schema, then it was written by legacy client.
524
636
  // If it's a new document, then we define it's legacy-related behaviors.
525
637
  runtime: {
@@ -662,7 +774,7 @@ export class DocumentsSchemaController {
662
774
  const schema = {
663
775
  ...content,
664
776
  refSeq: sequenceNumber,
665
- } satisfies IDocumentSchemaCurrent;
777
+ } satisfies IDocumentSchemaCurrentIncoming;
666
778
  this.documentSchema = schema;
667
779
  this.sessionSchema = and(schema, this.desiredSchema);
668
780
  assert(this.sessionSchema.refSeq === sequenceNumber, 0x97d /* seq# */);
@@ -693,4 +805,12 @@ export class DocumentsSchemaController {
693
805
  }
694
806
  }
695
807
 
808
+ /**
809
+ * Determines if a given version is a dev-build (i.e. `0.0.0-#####-test`).
810
+ */
811
+ function isDevBuild(version: string): boolean {
812
+ const parsed = parse(version);
813
+ return parsed !== null && parsed.prerelease.includes("test");
814
+ }
815
+
696
816
  /* eslint-enable jsdoc/check-indentation */
@@ -103,6 +103,7 @@ export {
103
103
  IdCompressorMode,
104
104
  IDocumentSchemaCurrent,
105
105
  IDocumentSchema,
106
+ IDocumentSchemaInfo,
106
107
  currentDocumentVersionSchema,
107
108
  DocumentSchemaValueType,
108
109
  DocumentsSchemaController,