@fluidframework/container-runtime 2.70.0-361248 → 2.70.0-361788

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 (57) hide show
  1. package/container-runtime.test-files.tar +0 -0
  2. package/dist/blobManager/blobManager.d.ts.map +1 -1
  3. package/dist/blobManager/blobManager.js +0 -1
  4. package/dist/blobManager/blobManager.js.map +1 -1
  5. package/dist/containerRuntime.d.ts +10 -0
  6. package/dist/containerRuntime.d.ts.map +1 -1
  7. package/dist/containerRuntime.js +37 -4
  8. package/dist/containerRuntime.js.map +1 -1
  9. package/dist/dataStoreContext.d.ts.map +1 -1
  10. package/dist/dataStoreContext.js +1 -1
  11. package/dist/dataStoreContext.js.map +1 -1
  12. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  13. package/dist/opLifecycle/outbox.js +7 -0
  14. package/dist/opLifecycle/outbox.js.map +1 -1
  15. package/dist/packageVersion.d.ts +1 -1
  16. package/dist/packageVersion.js +1 -1
  17. package/dist/packageVersion.js.map +1 -1
  18. package/dist/runtimeLayerCompatState.d.ts +4 -3
  19. package/dist/runtimeLayerCompatState.d.ts.map +1 -1
  20. package/dist/runtimeLayerCompatState.js +4 -35
  21. package/dist/runtimeLayerCompatState.js.map +1 -1
  22. package/dist/storageServiceWithAttachBlobs.d.ts +0 -36
  23. package/dist/storageServiceWithAttachBlobs.d.ts.map +1 -1
  24. package/dist/storageServiceWithAttachBlobs.js +0 -55
  25. package/dist/storageServiceWithAttachBlobs.js.map +1 -1
  26. package/lib/blobManager/blobManager.d.ts.map +1 -1
  27. package/lib/blobManager/blobManager.js +0 -1
  28. package/lib/blobManager/blobManager.js.map +1 -1
  29. package/lib/containerRuntime.d.ts +10 -0
  30. package/lib/containerRuntime.d.ts.map +1 -1
  31. package/lib/containerRuntime.js +37 -4
  32. package/lib/containerRuntime.js.map +1 -1
  33. package/lib/dataStoreContext.d.ts.map +1 -1
  34. package/lib/dataStoreContext.js +1 -1
  35. package/lib/dataStoreContext.js.map +1 -1
  36. package/lib/opLifecycle/outbox.d.ts.map +1 -1
  37. package/lib/opLifecycle/outbox.js +7 -0
  38. package/lib/opLifecycle/outbox.js.map +1 -1
  39. package/lib/packageVersion.d.ts +1 -1
  40. package/lib/packageVersion.js +1 -1
  41. package/lib/packageVersion.js.map +1 -1
  42. package/lib/runtimeLayerCompatState.d.ts +4 -3
  43. package/lib/runtimeLayerCompatState.d.ts.map +1 -1
  44. package/lib/runtimeLayerCompatState.js +5 -36
  45. package/lib/runtimeLayerCompatState.js.map +1 -1
  46. package/lib/storageServiceWithAttachBlobs.d.ts +0 -36
  47. package/lib/storageServiceWithAttachBlobs.d.ts.map +1 -1
  48. package/lib/storageServiceWithAttachBlobs.js +0 -55
  49. package/lib/storageServiceWithAttachBlobs.js.map +1 -1
  50. package/package.json +20 -17
  51. package/src/blobManager/blobManager.ts +0 -1
  52. package/src/containerRuntime.ts +47 -8
  53. package/src/dataStoreContext.ts +1 -0
  54. package/src/opLifecycle/outbox.ts +10 -0
  55. package/src/packageVersion.ts +1 -1
  56. package/src/runtimeLayerCompatState.ts +23 -39
  57. package/src/storageServiceWithAttachBlobs.ts +0 -92
@@ -1215,6 +1215,8 @@ export class ContainerRuntime
1215
1215
  recentBatchInfo,
1216
1216
  );
1217
1217
 
1218
+ runtime.sharePendingBlobs();
1219
+
1218
1220
  // Initialize the base state of the runtime before it's returned.
1219
1221
  await runtime.initializeBaseState(context.loader);
1220
1222
 
@@ -1581,13 +1583,6 @@ export class ContainerRuntime
1581
1583
 
1582
1584
  this.isSnapshotInstanceOfISnapshot = snapshotWithContents !== undefined;
1583
1585
 
1584
- // Validate that the Loader is compatible with this Runtime.
1585
- const maybeLoaderCompatDetailsForRuntime = context as FluidObject<ILayerCompatDetails>;
1586
- validateLoaderCompatibility(
1587
- maybeLoaderCompatDetailsForRuntime.ILayerCompatDetails,
1588
- this.disposeFn,
1589
- );
1590
-
1591
1586
  this.mc = createChildMonitoringContext({
1592
1587
  logger: this.baseLogger,
1593
1588
  namespace: "ContainerRuntime",
@@ -1598,6 +1593,14 @@ export class ContainerRuntime
1598
1593
  },
1599
1594
  });
1600
1595
 
1596
+ // Validate that the Loader is compatible with this Runtime.
1597
+ const maybeLoaderCompatDetailsForRuntime = context as FluidObject<ILayerCompatDetails>;
1598
+ validateLoaderCompatibility(
1599
+ maybeLoaderCompatDetailsForRuntime.ILayerCompatDetails,
1600
+ this.disposeFn,
1601
+ this.mc.logger,
1602
+ );
1603
+
1601
1604
  // If we support multiple algorithms in the future, then we would need to manage it here carefully.
1602
1605
  // We can use runtimeOptions.compressionOptions.compressionAlgorithm, but only if it's in the schema list!
1603
1606
  // If it's not in the list, then we will need to either use no compression, or fallback to some other (supported by format)
@@ -4548,7 +4551,6 @@ export class ContainerRuntime
4548
4551
  contents: any,
4549
4552
  localOpMetadata: unknown = undefined,
4550
4553
  ): void {
4551
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
4552
4554
  this.submit({ type, contents }, localOpMetadata);
4553
4555
  }
4554
4556
 
@@ -5133,6 +5135,43 @@ export class ContainerRuntime
5133
5135
  );
5134
5136
  }
5135
5137
 
5138
+ /**
5139
+ * ContainerRuntime knows about additional restrictions on when blob sharing can be resumed as compared
5140
+ * to BlobManager. In particular, it wants to avoid sharing blobs while in readonly state, and it also
5141
+ * wants to avoid sharing blobs before connection completes (otherwise it may cause the sharing to happen
5142
+ * before processing shared ops).
5143
+ *
5144
+ * This method can be called safely before those conditions are met. In the background, it will wait until
5145
+ * it is safe before initiating sharing. It will close the container on any error.
5146
+ */
5147
+ public sharePendingBlobs = (): void => {
5148
+ new Promise<void>((resolve) => {
5149
+ // eslint-disable-next-line unicorn/consistent-function-scoping
5150
+ const canStartSharing = (): boolean =>
5151
+ this.connected && this.deltaManager.readOnlyInfo.readonly !== true;
5152
+
5153
+ if (canStartSharing()) {
5154
+ resolve();
5155
+ return;
5156
+ }
5157
+
5158
+ const checkCanShare = (readonly: boolean): void => {
5159
+ if (canStartSharing()) {
5160
+ this.deltaManager.off("readonly", checkCanShare);
5161
+ this.off("connected", checkCanShare);
5162
+ resolve();
5163
+ }
5164
+ };
5165
+ this.deltaManager.on("readonly", checkCanShare);
5166
+ this.on("connected", checkCanShare);
5167
+ })
5168
+ .then(this.blobManager.sharePendingBlobs)
5169
+ // It may not be necessary to close the container on failures - this should just mean there's
5170
+ // a handle in the container that is stuck pending, which is a scenario that customers need to
5171
+ // handle anyway. Starting with this more aggressive/restrictive behavior to be cautious.
5172
+ .catch(this.closeFn);
5173
+ };
5174
+
5136
5175
  public summarizeOnDemand(options: IOnDemandSummarizeOptions): ISummarizeResults {
5137
5176
  if (this._summarizer !== undefined) {
5138
5177
  return this._summarizer.summarizeOnDemand(options);
@@ -1004,6 +1004,7 @@ export abstract class FluidDataStoreContext
1004
1004
  validateDatastoreCompatibility(
1005
1005
  maybeDataStoreCompatDetails.ILayerCompatDetails,
1006
1006
  this.dispose.bind(this),
1007
+ this.mc.logger,
1007
1008
  );
1008
1009
 
1009
1010
  // And now mark the runtime active
@@ -365,6 +365,16 @@ export class Outbox {
365
365
  * @param resubmitInfo - Key information when flushing a resubmitted batch. Undefined means this is not resubmit.
366
366
  */
367
367
  public flush(resubmitInfo?: BatchResubmitInfo): void {
368
+ // We have nothing to flush if all batchManagers are empty, and we we're not needing to resubmit an empty batch placeholder
369
+ if (
370
+ this.idAllocationBatch.empty &&
371
+ this.blobAttachBatch.empty &&
372
+ this.mainBatch.empty &&
373
+ resubmitInfo?.batchId === undefined
374
+ ) {
375
+ return;
376
+ }
377
+
368
378
  assert(
369
379
  !this.isContextReentrant(),
370
380
  0xb7b /* Flushing must not happen while incoming changes are being processed */,
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/container-runtime";
9
- export const pkgVersion = "2.70.0-361248";
9
+ export const pkgVersion = "2.70.0-361788";
@@ -3,17 +3,19 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import {
7
- checkLayerCompatibility,
8
- type ILayerCompatDetails,
9
- type ILayerCompatSupportRequirements,
6
+ import type {
7
+ ILayerCompatDetails,
8
+ ILayerCompatSupportRequirements,
10
9
  } from "@fluid-internal/client-utils";
11
10
  import type { ICriticalContainerError } from "@fluidframework/container-definitions";
12
11
  import {
13
12
  encodeHandlesInContainerRuntime,
14
13
  notifiesReadOnlyState,
15
14
  } from "@fluidframework/runtime-definitions/internal";
16
- import { UsageError } from "@fluidframework/telemetry-utils/internal";
15
+ import {
16
+ validateLayerCompatibility,
17
+ type ITelemetryLoggerExt,
18
+ } from "@fluidframework/telemetry-utils/internal";
17
19
 
18
20
  import { pkgVersion } from "./packageVersion.js";
19
21
 
@@ -95,26 +97,17 @@ export const dataStoreSupportRequirementsForRuntime: ILayerCompatSupportRequirem
95
97
  export function validateLoaderCompatibility(
96
98
  maybeLoaderCompatDetailsForRuntime: ILayerCompatDetails | undefined,
97
99
  disposeFn: (error?: ICriticalContainerError) => void,
100
+ logger: ITelemetryLoggerExt,
98
101
  ): void {
99
- const layerCheckResult = checkLayerCompatibility(
102
+ validateLayerCompatibility(
103
+ "runtime",
104
+ "loader",
105
+ runtimeCompatDetailsForLoader,
100
106
  loaderSupportRequirementsForRuntime,
101
107
  maybeLoaderCompatDetailsForRuntime,
108
+ disposeFn,
109
+ logger,
102
110
  );
103
- if (!layerCheckResult.isCompatible) {
104
- const error = new UsageError("Runtime is not compatible with Loader", {
105
- errorDetails: JSON.stringify({
106
- runtimeVersion: runtimeCoreCompatDetails.pkgVersion,
107
- loaderVersion: maybeLoaderCompatDetailsForRuntime?.pkgVersion,
108
- runtimeGeneration: runtimeCoreCompatDetails.generation,
109
- loaderGeneration: maybeLoaderCompatDetailsForRuntime?.generation,
110
- minSupportedGeneration: loaderSupportRequirementsForRuntime.minSupportedGeneration,
111
- isGenerationCompatible: layerCheckResult.isGenerationCompatible,
112
- unsupportedFeatures: layerCheckResult.unsupportedFeatures,
113
- }),
114
- });
115
- disposeFn(error);
116
- throw error;
117
- }
118
111
  }
119
112
 
120
113
  /**
@@ -122,26 +115,17 @@ export function validateLoaderCompatibility(
122
115
  * @internal
123
116
  */
124
117
  export function validateDatastoreCompatibility(
125
- maybeDataStoreCompatDetails: ILayerCompatDetails | undefined,
118
+ maybeDataStoreCompatDetailsForRuntime: ILayerCompatDetails | undefined,
126
119
  disposeFn: () => void,
120
+ logger: ITelemetryLoggerExt,
127
121
  ): void {
128
- const layerCheckResult = checkLayerCompatibility(
122
+ validateLayerCompatibility(
123
+ "runtime",
124
+ "dataStore",
125
+ runtimeCompatDetailsForDataStore,
129
126
  dataStoreSupportRequirementsForRuntime,
130
- maybeDataStoreCompatDetails,
127
+ maybeDataStoreCompatDetailsForRuntime,
128
+ disposeFn,
129
+ logger,
131
130
  );
132
- if (!layerCheckResult.isCompatible) {
133
- const error = new UsageError("Runtime is not compatible with DataStore", {
134
- errorDetails: JSON.stringify({
135
- runtimeVersion: runtimeCoreCompatDetails.pkgVersion,
136
- dataStoreVersion: maybeDataStoreCompatDetails?.pkgVersion,
137
- runtimeGeneration: runtimeCoreCompatDetails.generation,
138
- dataStoreGeneration: maybeDataStoreCompatDetails?.generation,
139
- minSupportedGeneration: dataStoreSupportRequirementsForRuntime.minSupportedGeneration,
140
- isGenerationCompatible: layerCheckResult.isGenerationCompatible,
141
- unsupportedFeatures: layerCheckResult.unsupportedFeatures,
142
- }),
143
- });
144
- disposeFn();
145
- throw error;
146
- }
147
131
  }
@@ -3,20 +3,7 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import type {
7
- FetchSource,
8
- ICreateBlobResponse,
9
- IDocumentStorageServicePolicies,
10
- ISnapshot,
11
- ISnapshotFetchOptions,
12
- ISnapshotTree,
13
- ISummaryContext,
14
- ISummaryHandle,
15
- ISummaryTree,
16
- IVersion,
17
- } from "@fluidframework/driver-definitions/internal";
18
6
  import type { IRuntimeStorageService } from "@fluidframework/runtime-definitions/internal";
19
- import { UsageError } from "@fluidframework/telemetry-utils/internal";
20
7
 
21
8
  /**
22
9
  * IRuntimeStorageService proxy which intercepts requests if they can be satisfied by the blobs received in the
@@ -28,14 +15,6 @@ export class StorageServiceWithAttachBlobs implements IRuntimeStorageService {
28
15
  private readonly attachBlobs: Map<string, ArrayBufferLike>,
29
16
  ) {}
30
17
 
31
- /**
32
- * {@link IRuntimeStorageService.policies}.
33
- * @deprecated This will be removed in a future release. The DataStore layer does not need this.
34
- */
35
- public get policies(): IDocumentStorageServicePolicies | undefined {
36
- return this.internalStorageService.policies;
37
- }
38
-
39
18
  public async readBlob(id: string): Promise<ArrayBufferLike> {
40
19
  const blob = this.attachBlobs.get(id);
41
20
  if (blob !== undefined) {
@@ -46,75 +25,4 @@ export class StorageServiceWithAttachBlobs implements IRuntimeStorageService {
46
25
  // IRuntimeStorageService to cache appropriately, no need to double-cache.
47
26
  return this.internalStorageService.readBlob(id);
48
27
  }
49
-
50
- /**
51
- * {@link IRuntimeStorageService.getSnapshotTree}.
52
- * @deprecated This will be removed in a future release. The DataStore layer does not need this.
53
- */
54
- public async getSnapshotTree(
55
- version?: IVersion,
56
- scenarioName?: string,
57
- // eslint-disable-next-line @rushstack/no-new-null
58
- ): Promise<ISnapshotTree | null> {
59
- return this.internalStorageService.getSnapshotTree(version, scenarioName);
60
- }
61
-
62
- /**
63
- * {@link IRuntimeStorageService.getSnapshot}.
64
- * @deprecated This will be removed in a future release. The DataStore layer does not need this.
65
- */
66
- public async getSnapshot(snapshotFetchOptions?: ISnapshotFetchOptions): Promise<ISnapshot> {
67
- if (this.internalStorageService.getSnapshot !== undefined) {
68
- return this.internalStorageService.getSnapshot(snapshotFetchOptions);
69
- }
70
- throw new UsageError(
71
- "getSnapshot api should exist on internal storage in documentStorageServiceProxy class",
72
- );
73
- }
74
-
75
- /**
76
- * {@link IRuntimeStorageService.getVersions}.
77
- * @deprecated This will be removed in a future release. The DataStore layer does not need this.
78
- */
79
- public async getVersions(
80
- // eslint-disable-next-line @rushstack/no-new-null
81
- versionId: string | null,
82
- count: number,
83
- scenarioName?: string,
84
- fetchSource?: FetchSource,
85
- ): Promise<IVersion[]> {
86
- return this.internalStorageService.getVersions(
87
- versionId,
88
- count,
89
- scenarioName,
90
- fetchSource,
91
- );
92
- }
93
-
94
- /**
95
- * {@link IRuntimeStorageService.uploadSummaryWithContext}.
96
- * @deprecated This will be removed in a future release. The DataStore layer does not need this.
97
- */
98
- public async uploadSummaryWithContext(
99
- summary: ISummaryTree,
100
- context: ISummaryContext,
101
- ): Promise<string> {
102
- return this.internalStorageService.uploadSummaryWithContext(summary, context);
103
- }
104
-
105
- /**
106
- * {@link IRuntimeStorageService.createBlob}.
107
- * @deprecated This will be removed in a future release. The DataStore layer does not need this.
108
- */
109
- public async createBlob(file: ArrayBufferLike): Promise<ICreateBlobResponse> {
110
- return this.internalStorageService.createBlob(file);
111
- }
112
-
113
- /**
114
- * {@link IRuntimeStorageService.downloadSummary}.
115
- * @deprecated This will be removed in a future release. The DataStore layer does not need this.
116
- */
117
- public async downloadSummary(handle: ISummaryHandle): Promise<ISummaryTree> {
118
- return this.internalStorageService.downloadSummary(handle);
119
- }
120
28
  }