@fluidframework/container-runtime 2.51.0-347100 → 2.52.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.
Files changed (96) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/api-report/container-runtime.legacy.alpha.api.md +1 -2
  3. package/container-runtime.test-files.tar +0 -0
  4. package/dist/blobManager/blobManager.d.ts +15 -7
  5. package/dist/blobManager/blobManager.d.ts.map +1 -1
  6. package/dist/blobManager/blobManager.js +72 -186
  7. package/dist/blobManager/blobManager.js.map +1 -1
  8. package/dist/containerCompatibility.d.ts +34 -0
  9. package/dist/containerCompatibility.d.ts.map +1 -0
  10. package/dist/containerCompatibility.js +125 -0
  11. package/dist/containerCompatibility.js.map +1 -0
  12. package/dist/containerRuntime.d.ts +27 -15
  13. package/dist/containerRuntime.d.ts.map +1 -1
  14. package/dist/containerRuntime.js +175 -136
  15. package/dist/containerRuntime.js.map +1 -1
  16. package/dist/dataStoreContext.d.ts +6 -6
  17. package/dist/dataStoreContext.d.ts.map +1 -1
  18. package/dist/dataStoreContext.js.map +1 -1
  19. package/dist/index.d.ts +5 -1
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js.map +1 -1
  22. package/dist/metadata.d.ts +3 -2
  23. package/dist/metadata.d.ts.map +1 -1
  24. package/dist/metadata.js +7 -1
  25. package/dist/metadata.js.map +1 -1
  26. package/dist/packageVersion.d.ts +1 -1
  27. package/dist/packageVersion.d.ts.map +1 -1
  28. package/dist/packageVersion.js +1 -1
  29. package/dist/packageVersion.js.map +1 -1
  30. package/dist/storageServiceWithAttachBlobs.d.ts +40 -5
  31. package/dist/storageServiceWithAttachBlobs.d.ts.map +1 -1
  32. package/dist/storageServiceWithAttachBlobs.js +56 -5
  33. package/dist/storageServiceWithAttachBlobs.js.map +1 -1
  34. package/dist/summary/documentSchema.d.ts +1 -1
  35. package/dist/summary/documentSchema.d.ts.map +1 -1
  36. package/dist/summary/documentSchema.js.map +1 -1
  37. package/dist/summary/summaryFormat.d.ts +3 -3
  38. package/dist/summary/summaryFormat.d.ts.map +1 -1
  39. package/dist/summary/summaryFormat.js.map +1 -1
  40. package/lib/blobManager/blobManager.d.ts +15 -7
  41. package/lib/blobManager/blobManager.d.ts.map +1 -1
  42. package/lib/blobManager/blobManager.js +39 -153
  43. package/lib/blobManager/blobManager.js.map +1 -1
  44. package/lib/containerCompatibility.d.ts +34 -0
  45. package/lib/containerCompatibility.d.ts.map +1 -0
  46. package/lib/containerCompatibility.js +120 -0
  47. package/lib/containerCompatibility.js.map +1 -0
  48. package/lib/containerRuntime.d.ts +27 -15
  49. package/lib/containerRuntime.d.ts.map +1 -1
  50. package/lib/containerRuntime.js +103 -64
  51. package/lib/containerRuntime.js.map +1 -1
  52. package/lib/dataStoreContext.d.ts +6 -6
  53. package/lib/dataStoreContext.d.ts.map +1 -1
  54. package/lib/dataStoreContext.js +1 -1
  55. package/lib/dataStoreContext.js.map +1 -1
  56. package/lib/index.d.ts +5 -1
  57. package/lib/index.d.ts.map +1 -1
  58. package/lib/index.js.map +1 -1
  59. package/lib/metadata.d.ts +3 -2
  60. package/lib/metadata.d.ts.map +1 -1
  61. package/lib/metadata.js +5 -0
  62. package/lib/metadata.js.map +1 -1
  63. package/lib/packageVersion.d.ts +1 -1
  64. package/lib/packageVersion.d.ts.map +1 -1
  65. package/lib/packageVersion.js +1 -1
  66. package/lib/packageVersion.js.map +1 -1
  67. package/lib/storageServiceWithAttachBlobs.d.ts +40 -5
  68. package/lib/storageServiceWithAttachBlobs.d.ts.map +1 -1
  69. package/lib/storageServiceWithAttachBlobs.js +56 -5
  70. package/lib/storageServiceWithAttachBlobs.js.map +1 -1
  71. package/lib/summary/documentSchema.d.ts +1 -1
  72. package/lib/summary/documentSchema.d.ts.map +1 -1
  73. package/lib/summary/documentSchema.js.map +1 -1
  74. package/lib/summary/summaryFormat.d.ts +3 -3
  75. package/lib/summary/summaryFormat.d.ts.map +1 -1
  76. package/lib/summary/summaryFormat.js.map +1 -1
  77. package/package.json +20 -20
  78. package/src/blobManager/blobManager.ts +53 -195
  79. package/src/containerCompatibility.ts +176 -0
  80. package/src/containerRuntime.ts +157 -122
  81. package/src/dataStoreContext.ts +13 -5
  82. package/src/index.ts +6 -1
  83. package/src/metadata.ts +10 -2
  84. package/src/packageVersion.ts +1 -1
  85. package/src/storageServiceWithAttachBlobs.ts +92 -10
  86. package/src/summary/documentSchema.ts +1 -1
  87. package/src/summary/summaryFormat.ts +2 -2
  88. package/dist/compatUtils.d.ts +0 -106
  89. package/dist/compatUtils.d.ts.map +0 -1
  90. package/dist/compatUtils.js +0 -251
  91. package/dist/compatUtils.js.map +0 -1
  92. package/lib/compatUtils.d.ts +0 -106
  93. package/lib/compatUtils.d.ts.map +0 -1
  94. package/lib/compatUtils.js +0 -242
  95. package/lib/compatUtils.js.map +0 -1
  96. package/src/compatUtils.ts +0 -365
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @fluidframework/container-runtime
2
2
 
3
+ ## 2.52.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Moved MinimumVersionForCollab to @fluidframework/runtime-definitions ([#25059](https://github.com/microsoft/FluidFramework/pull/25059)) [4a7b370667](https://github.com/microsoft/FluidFramework/commit/4a7b3706675139af6d8aaae707b96b74081f1fc8)
8
+
9
+ MinimumVersionForCollab has been moved from @fluidframework/container-runtime to @fluidframework/runtime-definitions.
10
+ The export in @fluidframework/container-runtime is now deprecated and will be removed in a future version.
11
+ Consumers should import it from @fluidframework/runtime-definitions going forward.
12
+
13
+ ## 2.51.0
14
+
15
+ Dependency updates only.
16
+
3
17
  ## 2.50.0
4
18
 
5
19
  Dependency updates only.
@@ -346,8 +346,7 @@ export interface LoadContainerRuntimeParams {
346
346
  runtimeOptions?: IContainerRuntimeOptions;
347
347
  }
348
348
 
349
- // @alpha @legacy
350
- export type MinimumVersionForCollab = `${1 | 2}.${bigint}.${bigint}` | `${1 | 2}.${bigint}.${bigint}-${string}`;
349
+ export { MinimumVersionForCollab }
351
350
 
352
351
  // @alpha @deprecated @legacy (undocumented)
353
352
  export type OmitAttributesVersions<T> = Omit<T, "snapshotFormatVersion" | "summaryFormatVersion">;
Binary file
@@ -2,9 +2,9 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
+ import { type IContainerStorageService } from "@fluidframework/container-definitions/internal";
5
6
  import { IContainerRuntime, IContainerRuntimeEvents } from "@fluidframework/container-runtime-definitions/internal";
6
7
  import type { IEventProvider, IFluidHandleContext, IFluidHandleInternalPayloadPending, ILocalFluidHandle, ILocalFluidHandleEvents, Listenable, PayloadState } from "@fluidframework/core-interfaces/internal";
7
- import { IDocumentStorageService, ICreateBlobResponse } from "@fluidframework/driver-definitions/internal";
8
8
  import { IGarbageCollectionData, ISummaryTreeWithStats, ITelemetryContext, type ISequencedMessageEnvelope } from "@fluidframework/runtime-definitions/internal";
9
9
  import { FluidHandleBase } from "@fluidframework/runtime-utils/internal";
10
10
  import { type IBlobManagerLoadInfo } from "./blobManagerSnapSum.js";
@@ -77,20 +77,17 @@ export declare class BlobManager {
77
77
  */
78
78
  private readonly opsInFlight;
79
79
  private readonly sendBlobAttachOp;
80
- private stopAttaching;
81
80
  private readonly routeContext;
82
81
  private readonly storage;
83
82
  private readonly blobRequested;
84
83
  private readonly isBlobDeleted;
85
84
  private readonly runtime;
86
85
  private readonly localBlobIdGenerator;
87
- private readonly pendingStashedBlobs;
88
- readonly stashedBlobsUploadP: Promise<(void | ICreateBlobResponse)[]>;
89
86
  private readonly createBlobPayloadPending;
90
87
  constructor(props: {
91
88
  readonly routeContext: IFluidHandleContext;
92
89
  blobManagerLoadInfo: IBlobManagerLoadInfo;
93
- readonly storage: IDocumentStorageService;
90
+ readonly storage: Pick<IContainerStorageService, "createBlob" | "readBlob">;
94
91
  /**
95
92
  * Submit a BlobAttach op. When a blob is uploaded, there is a short grace period before which the blob is
96
93
  * deleted. The BlobAttach op notifies the server that blob is in use. The server will then not delete the
@@ -101,7 +98,7 @@ export declare class BlobManager {
101
98
  * knowledge of which they cannot request the blob from storage. It's important that this op is sequenced
102
99
  * before any ops that reference the local ID, otherwise, an invalid handle could be added to the document.
103
100
  */
104
- sendBlobAttachOp: (localId: string, storageId?: string) => void;
101
+ sendBlobAttachOp: (localId: string, storageId: string) => void;
105
102
  readonly blobRequested: (blobPath: string) => void;
106
103
  readonly isBlobDeleted: (blobPath: string) => boolean;
107
104
  readonly runtime: IBlobManagerRuntime;
@@ -112,7 +109,6 @@ export declare class BlobManager {
112
109
  get allBlobsAttached(): boolean;
113
110
  get hasPendingBlobs(): boolean;
114
111
  private createAbortError;
115
- hasPendingStashedUploads(): boolean;
116
112
  hasBlob(blobId: string): boolean;
117
113
  /**
118
114
  * Retrieve the blob with the given local blob id.
@@ -179,6 +175,18 @@ export declare class BlobManager {
179
175
  */
180
176
  private verifyBlobNotDeleted;
181
177
  setRedirectTable(table: Map<string, string>): void;
178
+ /**
179
+ * To be used in getPendingLocalState flow. Get a serializable record of the blobs that are
180
+ * pending upload and/or their BlobAttach op, which can be given to a new BlobManager to
181
+ * resume work.
182
+ *
183
+ * @privateRemarks
184
+ * For now, we don't track any pending blobs since the getPendingBlobs flow doesn't enable
185
+ * restoring to a state where an accessible handle has been stored by the customer (and we'll
186
+ * just drop any BlobAttach ops on the ground during reSubmit). However, once we add support
187
+ * for payload-pending handles, this will return the blobs associated with those handles.
188
+ */
189
+ getPendingBlobs(): IPendingBlobs | undefined;
182
190
  /**
183
191
  * Part of container serialization when imminent closure is enabled (Currently when calling closeAndGetPendingLocalState).
184
192
  * This asynchronous function resolves all pending createBlob calls and waits for each blob
@@ -1 +1 @@
1
- {"version":3,"file":"blobManager.d.ts","sourceRoot":"","sources":["../../src/blobManager/blobManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"blobManager.d.ts","sourceRoot":"","sources":["../../src/blobManager/blobManager.ts"],"names":[],"mappings":"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"}
@@ -6,12 +6,13 @@
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.isBlobPath = exports.BlobManager = exports.blobManagerBasePath = exports.BlobHandle = void 0;
8
8
  const client_utils_1 = require("@fluid-internal/client-utils");
9
- const container_definitions_1 = require("@fluidframework/container-definitions");
10
- const internal_1 = require("@fluidframework/core-utils/internal");
11
- const internal_2 = require("@fluidframework/driver-utils/internal");
12
- const internal_3 = require("@fluidframework/runtime-utils/internal");
13
- const internal_4 = require("@fluidframework/telemetry-utils/internal");
9
+ const internal_1 = require("@fluidframework/container-definitions/internal");
10
+ const internal_2 = require("@fluidframework/core-utils/internal");
11
+ const internal_3 = require("@fluidframework/driver-utils/internal");
12
+ const internal_4 = require("@fluidframework/runtime-utils/internal");
13
+ const internal_5 = require("@fluidframework/telemetry-utils/internal");
14
14
  const uuid_1 = require("uuid");
15
+ const metadata_js_1 = require("../metadata.js");
15
16
  const blobManagerSnapSum_js_1 = require("./blobManagerSnapSum.js");
16
17
  /**
17
18
  * This class represents blob (long string)
@@ -20,7 +21,7 @@ const blobManagerSnapSum_js_1 = require("./blobManagerSnapSum.js");
20
21
  * DataObject.request() recognizes requests in the form of `/blobs/<id>`
21
22
  * and loads blob.
22
23
  */
23
- class BlobHandle extends internal_3.FluidHandleBase {
24
+ class BlobHandle extends internal_4.FluidHandleBase {
24
25
  get isAttached() {
25
26
  return this.routeContext.isAttached && this.attached;
26
27
  }
@@ -50,7 +51,7 @@ class BlobHandle extends internal_3.FluidHandleBase {
50
51
  this._payloadShareError = error;
51
52
  this._events?.emit("payloadShareFailed", error);
52
53
  };
53
- this.absolutePath = (0, internal_3.generateHandleContextPath)(path, this.routeContext);
54
+ this.absolutePath = (0, internal_4.generateHandleContextPath)(path, this.routeContext);
54
55
  }
55
56
  attachGraph() {
56
57
  if (!this.attached) {
@@ -60,12 +61,6 @@ class BlobHandle extends internal_3.FluidHandleBase {
60
61
  }
61
62
  }
62
63
  exports.BlobHandle = BlobHandle;
63
- const stashedPendingBlobOverrides = {
64
- stashedUpload: true,
65
- storageId: undefined,
66
- minTTLInSeconds: undefined,
67
- uploadTime: undefined,
68
- };
69
64
  exports.blobManagerBasePath = "_blobs";
70
65
  class BlobManager {
71
66
  get events() {
@@ -84,9 +79,7 @@ class BlobManager {
84
79
  * because we know that the server will not delete the blob corresponding to that storage ID.
85
80
  */
86
81
  this.opsInFlight = new Map();
87
- this.stopAttaching = false;
88
- this.pendingStashedBlobs = new Map();
89
- const { routeContext, blobManagerLoadInfo, storage, sendBlobAttachOp, blobRequested, isBlobDeleted, runtime, stashedBlobs, localBlobIdGenerator, createBlobPayloadPending, } = props;
82
+ const { routeContext, blobManagerLoadInfo, storage, sendBlobAttachOp, blobRequested, isBlobDeleted, runtime, localBlobIdGenerator, createBlobPayloadPending, } = props;
90
83
  this.routeContext = routeContext;
91
84
  this.storage = storage;
92
85
  this.blobRequested = blobRequested;
@@ -94,47 +87,14 @@ class BlobManager {
94
87
  this.runtime = runtime;
95
88
  this.localBlobIdGenerator = localBlobIdGenerator ?? uuid_1.v4;
96
89
  this.createBlobPayloadPending = createBlobPayloadPending;
97
- this.mc = (0, internal_4.createChildMonitoringContext)({
90
+ this.mc = (0, internal_5.createChildMonitoringContext)({
98
91
  logger: this.runtime.baseLogger,
99
92
  namespace: "BlobManager",
100
93
  });
101
94
  this.redirectTable = (0, blobManagerSnapSum_js_1.toRedirectTable)(blobManagerLoadInfo, this.mc.logger, this.runtime.attachState);
102
- // Begin uploading stashed blobs from previous container instance
103
- for (const [localId, entry] of Object.entries(stashedBlobs ?? {})) {
104
- const { acked, storageId, minTTLInSeconds, uploadTime } = entry;
105
- const blob = (0, client_utils_1.stringToBuffer)(entry.blob, "base64");
106
- const pendingEntry = {
107
- blob,
108
- opsent: true,
109
- handleP: new internal_1.Deferred(),
110
- storageId,
111
- uploadP: undefined,
112
- uploadTime,
113
- minTTLInSeconds,
114
- attached: true,
115
- acked,
116
- };
117
- this.pendingBlobs.set(localId, pendingEntry);
118
- if (storageId !== undefined && minTTLInSeconds && uploadTime) {
119
- const timeLapseSinceLocalUpload = (Date.now() - uploadTime) / 1000;
120
- // stashed entries with more than half-life in storage will not be reuploaded
121
- if (minTTLInSeconds - timeLapseSinceLocalUpload > minTTLInSeconds / 2) {
122
- continue;
123
- }
124
- }
125
- this.pendingStashedBlobs.set(localId, this.uploadBlob(localId, blob));
126
- this.pendingBlobs.set(localId, {
127
- ...pendingEntry,
128
- ...stashedPendingBlobOverrides,
129
- uploadP: this.pendingStashedBlobs.get(localId),
130
- });
131
- }
132
- this.stashedBlobsUploadP = internal_4.PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "BlobUploadProcessStashedChanges", count: this.pendingStashedBlobs.size }, async () => Promise.all(this.pendingStashedBlobs.values()), { start: true, end: true }).finally(() => {
133
- this.pendingStashedBlobs.clear();
134
- });
135
95
  this.sendBlobAttachOp = (localId, blobId) => {
136
96
  const pendingEntry = this.pendingBlobs.get(localId);
137
- (0, internal_1.assert)(pendingEntry !== undefined, 0x725 /* Must have pending blob entry for upcoming op */);
97
+ (0, internal_2.assert)(pendingEntry !== undefined, 0x725 /* Must have pending blob entry for upcoming op */);
138
98
  if (pendingEntry?.uploadTime && pendingEntry?.minTTLInSeconds) {
139
99
  const secondsSinceUpload = (Date.now() - pendingEntry.uploadTime) / 1000;
140
100
  const expired = pendingEntry.minTTLInSeconds - secondsSinceUpload < 0;
@@ -170,18 +130,15 @@ class BlobManager {
170
130
  return true;
171
131
  }
172
132
  get hasPendingBlobs() {
173
- return ((this.runtime.attachState !== container_definitions_1.AttachState.Attached && this.redirectTable.size > 0) ||
133
+ return ((this.runtime.attachState !== internal_1.AttachState.Attached && this.redirectTable.size > 0) ||
174
134
  this.pendingBlobs.size > 0);
175
135
  }
176
136
  createAbortError(pending) {
177
- return new internal_4.LoggingError("uploadBlob aborted", {
137
+ return new internal_5.LoggingError("uploadBlob aborted", {
178
138
  acked: pending?.acked,
179
139
  uploadTime: pending?.uploadTime,
180
140
  });
181
141
  }
182
- hasPendingStashedUploads() {
183
- return [...this.pendingBlobs.values()].some((e) => e.stashedUpload === true);
184
- }
185
142
  hasBlob(blobId) {
186
143
  return this.redirectTable.get(blobId) !== undefined;
187
144
  }
@@ -204,10 +161,10 @@ class BlobManager {
204
161
  return pending.blob;
205
162
  }
206
163
  let storageId;
207
- if (this.runtime.attachState === container_definitions_1.AttachState.Detached) {
208
- (0, internal_1.assert)(this.redirectTable.has(blobId), 0x383 /* requesting unknown blobs */);
164
+ if (this.runtime.attachState === internal_1.AttachState.Detached) {
165
+ (0, internal_2.assert)(this.redirectTable.has(blobId), 0x383 /* requesting unknown blobs */);
209
166
  // Blobs created while the container is detached are stored in IDetachedBlobStorage.
210
- // The 'IDocumentStorageService.readBlob()' call below will retrieve these via localId.
167
+ // The 'IContainerStorageService.readBlob()' call below will retrieve these via localId.
211
168
  storageId = blobId;
212
169
  }
213
170
  else {
@@ -215,7 +172,7 @@ class BlobManager {
215
172
  if (!payloadPending) {
216
173
  // Only blob handles explicitly marked with pending payload are permitted to exist without
217
174
  // yet knowing their storage id. Otherwise they must already be associated with a storage id.
218
- (0, internal_1.assert)(attachedStorageId !== undefined, 0x11f /* "requesting unknown blobs" */);
175
+ (0, internal_2.assert)(attachedStorageId !== undefined, 0x11f /* "requesting unknown blobs" */);
219
176
  }
220
177
  // If we didn't find it in the redirectTable, assume the attach op is coming eventually and wait.
221
178
  // We do this even if the local client doesn't have the blob payloadPending flag enabled, in case a
@@ -233,7 +190,7 @@ class BlobManager {
233
190
  this.internalEvents.on("processedBlobAttach", onProcessBlobAttach);
234
191
  }));
235
192
  }
236
- return internal_4.PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "AttachmentReadBlob", id: storageId }, async (event) => {
193
+ return internal_5.PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "AttachmentReadBlob", id: storageId }, async (event) => {
237
194
  return this.storage.readBlob(storageId).catch((error) => {
238
195
  if (this.runtime.disposed) {
239
196
  // If the runtime is disposed, this is not an error we care to track, it's expected behavior.
@@ -244,7 +201,7 @@ class BlobManager {
244
201
  }, { end: true, cancel: "error" });
245
202
  }
246
203
  getBlobHandle(localId) {
247
- (0, internal_1.assert)(this.redirectTable.has(localId) || this.pendingBlobs.has(localId), 0x384 /* requesting handle for unknown blob */);
204
+ (0, internal_2.assert)(this.redirectTable.has(localId) || this.pendingBlobs.has(localId), 0x384 /* requesting handle for unknown blob */);
248
205
  const pending = this.pendingBlobs.get(localId);
249
206
  // Create a callback function for once the handle has been attached
250
207
  const callback = pending
@@ -260,21 +217,21 @@ class BlobManager {
260
217
  }
261
218
  async createBlobDetached(blob) {
262
219
  // Blobs created while the container is detached are stored in IDetachedBlobStorage.
263
- // The 'IDocumentStorageService.createBlob()' call below will respond with a localId.
220
+ // The 'IContainerStorageService.createBlob()' call below will respond with a localId.
264
221
  const response = await this.storage.createBlob(blob);
265
222
  this.setRedirection(response.id, undefined);
266
223
  return this.getBlobHandle(response.id);
267
224
  }
268
225
  async createBlob(blob, signal) {
269
- if (this.runtime.attachState === container_definitions_1.AttachState.Detached) {
226
+ if (this.runtime.attachState === internal_1.AttachState.Detached) {
270
227
  return this.createBlobDetached(blob);
271
228
  }
272
- if (this.runtime.attachState === container_definitions_1.AttachState.Attaching) {
229
+ if (this.runtime.attachState === internal_1.AttachState.Attaching) {
273
230
  // blob upload is not supported in "Attaching" state
274
231
  this.mc.logger.sendTelemetryEvent({ eventName: "CreateBlobWhileAttaching" });
275
232
  await new Promise((resolve) => this.runtime.once("attached", resolve));
276
233
  }
277
- (0, internal_1.assert)(this.runtime.attachState === container_definitions_1.AttachState.Attached, 0x385 /* For clarity and paranoid defense against adding future attachment states */);
234
+ (0, internal_2.assert)(this.runtime.attachState === internal_1.AttachState.Attached, 0x385 /* For clarity and paranoid defense against adding future attachment states */);
278
235
  return this.createBlobPayloadPending
279
236
  ? this.createBlobWithPayloadPending(blob)
280
237
  : this.createBlobLegacy(blob, signal);
@@ -288,7 +245,7 @@ class BlobManager {
288
245
  const localId = this.localBlobIdGenerator();
289
246
  const pendingEntry = {
290
247
  blob,
291
- handleP: new internal_1.Deferred(),
248
+ handleP: new internal_2.Deferred(),
292
249
  uploadP: this.uploadBlob(localId, blob),
293
250
  attached: false,
294
251
  acked: false,
@@ -312,7 +269,7 @@ class BlobManager {
312
269
  () => {
313
270
  const pendingEntry = {
314
271
  blob,
315
- handleP: new internal_1.Deferred(),
272
+ handleP: new internal_2.Deferred(),
316
273
  uploadP: this.uploadBlob(localId, blob),
317
274
  attached: true,
318
275
  acked: false,
@@ -337,15 +294,15 @@ class BlobManager {
337
294
  return blobHandle;
338
295
  }
339
296
  async uploadBlob(localId, blob) {
340
- return (0, internal_2.runWithRetry)(async () => {
297
+ return (0, internal_3.runWithRetry)(async () => {
341
298
  try {
342
299
  return await this.storage.createBlob(blob);
343
300
  }
344
301
  catch (error) {
345
302
  const entry = this.pendingBlobs.get(localId);
346
- (0, internal_1.assert)(!!entry, 0x387 /* Must have pending blob entry for blob which failed to upload */);
347
- if (entry.opsent && !(0, internal_2.canRetryOnError)(error)) {
348
- throw (0, internal_4.wrapError)(error, () => new internal_4.LoggingError(`uploadBlob error`, { canRetry: true }));
303
+ (0, internal_2.assert)(!!entry, 0x387 /* Must have pending blob entry for blob which failed to upload */);
304
+ if (entry.opsent && !(0, internal_3.canRetryOnError)(error)) {
305
+ throw (0, internal_5.wrapError)(error, () => new internal_5.LoggingError(`uploadBlob error`, { canRetry: true }));
349
306
  }
350
307
  throw error;
351
308
  }
@@ -389,17 +346,8 @@ class BlobManager {
389
346
  }
390
347
  onUploadResolve(localId, response) {
391
348
  const entry = this.pendingBlobs.get(localId);
392
- if (entry === undefined && this.pendingStashedBlobs.has(localId)) {
393
- // The blob was already processed and deleted. This can happen if the blob was reuploaded by
394
- // the stashing process and the original upload was processed before the stashed upload.
395
- this.mc.logger.sendTelemetryEvent({
396
- eventName: "StashedBlobAlreadyProcessed",
397
- localId,
398
- });
399
- return;
400
- }
401
- (0, internal_1.assert)(entry !== undefined, 0x6c8 /* pending blob entry not found for uploaded blob */);
402
- if ((entry.abortSignal?.aborted === true && !entry.opsent) || this.stopAttaching) {
349
+ (0, internal_2.assert)(entry !== undefined, 0x6c8 /* pending blob entry not found for uploaded blob */);
350
+ if (entry.abortSignal?.aborted === true && !entry.opsent) {
403
351
  this.mc.logger.sendTelemetryEvent({
404
352
  eventName: "BlobAborted",
405
353
  localId,
@@ -407,8 +355,7 @@ class BlobManager {
407
355
  this.deletePendingBlob(localId);
408
356
  return;
409
357
  }
410
- (0, internal_1.assert)(entry.storageId === undefined, 0x386 /* Must have pending blob entry for uploaded blob */);
411
- entry.stashedUpload = undefined;
358
+ (0, internal_2.assert)(entry.storageId === undefined, 0x386 /* Must have pending blob entry for uploaded blob */);
412
359
  entry.storageId = response.id;
413
360
  entry.uploadTime = Date.now();
414
361
  entry.minTTLInSeconds = response.minTTLInSeconds;
@@ -452,38 +399,29 @@ class BlobManager {
452
399
  * @param metadata - op metadata containing storage and/or local IDs
453
400
  */
454
401
  reSubmit(metadata) {
455
- (0, internal_1.assert)(!!metadata, 0x38b /* Resubmitted ops must have metadata */);
402
+ (0, internal_2.assert)((0, metadata_js_1.isBlobMetadata)(metadata), 0xc01 /* Expected blob metadata for a BlobAttach op */);
456
403
  const { localId, blobId } = metadata;
457
- (0, internal_1.assert)(localId !== undefined, 0x50d /* local ID not available on reSubmit */);
458
- const pendingEntry = this.pendingBlobs.get(localId);
459
- if (!blobId) {
460
- // We submitted this op while offline. The blob should have been uploaded by now.
461
- (0, internal_1.assert)(pendingEntry?.opsent === true && !!pendingEntry?.storageId, 0x38d /* blob must be uploaded before resubmitting BlobAttach op */);
462
- return this.sendBlobAttachOp(localId, pendingEntry?.storageId);
404
+ // Any blob that we're actively trying to advance to attached state must have a
405
+ // pendingBlobs entry. Decline to resubmit for anything else.
406
+ // For example, we might be asked to resubmit stashed ops for blobs that never had
407
+ // their handle attached - these won't have a pendingBlobs entry and we shouldn't
408
+ // try to attach them since they won't be accessible to the customer and would just
409
+ // be considered garbage immediately.
410
+ if (this.pendingBlobs.has(localId)) {
411
+ this.sendBlobAttachOp(localId, blobId);
463
412
  }
464
- return this.sendBlobAttachOp(localId, blobId);
465
413
  }
466
414
  processBlobAttachMessage(message, local) {
467
- const localId = message.metadata?.localId;
468
- const blobId = message.metadata?.blobId;
469
- if (localId) {
470
- const pendingEntry = this.pendingBlobs.get(localId);
471
- if (pendingEntry?.abortSignal?.aborted) {
472
- this.deletePendingBlob(localId);
473
- return;
474
- }
475
- }
476
- (0, internal_1.assert)(blobId !== undefined, 0x12a /* "Missing blob id on metadata" */);
477
- // Set up a mapping from local ID to storage ID. This is crucial since without this the blob cannot be
478
- // requested from the server.
479
- // Note: The check for undefined is needed for back-compat when localId was not part of the BlobAttach op that
480
- // was sent when online.
481
- if (localId !== undefined) {
482
- this.setRedirection(localId, blobId);
415
+ (0, internal_2.assert)((0, metadata_js_1.isBlobMetadata)(message.metadata), 0xc02 /* Expected blob metadata for a BlobAttach op */);
416
+ const { localId, blobId } = message.metadata;
417
+ const pendingEntry = this.pendingBlobs.get(localId);
418
+ if (pendingEntry?.abortSignal?.aborted) {
419
+ this.deletePendingBlob(localId);
420
+ return;
483
421
  }
422
+ this.setRedirection(localId, blobId);
484
423
  // set identity (id -> id) entry
485
424
  this.setRedirection(blobId, blobId);
486
- (0, internal_1.assert)(localId !== undefined, 0x50e /* local ID not present in blob attach message */);
487
425
  if (local) {
488
426
  const waitingBlobs = this.opsInFlight.get(blobId);
489
427
  if (waitingBlobs !== undefined) {
@@ -492,7 +430,7 @@ class BlobManager {
492
430
  // storage ID is already in flight and any op containing this local ID will be sequenced after that.
493
431
  for (const pendingLocalId of waitingBlobs) {
494
432
  const entry = this.pendingBlobs.get(pendingLocalId);
495
- (0, internal_1.assert)(entry !== undefined, 0x38f /* local online BlobAttach op with no pending blob entry */);
433
+ (0, internal_2.assert)(entry !== undefined, 0x38f /* local online BlobAttach op with no pending blob entry */);
496
434
  this.setRedirection(pendingLocalId, blobId);
497
435
  entry.acked = true;
498
436
  const blobHandle = this.getBlobHandle(pendingLocalId);
@@ -525,7 +463,7 @@ class BlobManager {
525
463
  getGCData(fullGC = false) {
526
464
  const gcData = { gcNodes: {} };
527
465
  for (const [localId, storageId] of this.redirectTable) {
528
- (0, internal_1.assert)(!!storageId, 0x390 /* Must be attached to get GC data */);
466
+ (0, internal_2.assert)(!!storageId, 0x390 /* Must be attached to get GC data */);
529
467
  // Only return local ids as GC nodes because a blob can only be referenced via its local id. The storage
530
468
  // id entries have the same key and value, ignore them.
531
469
  // The outbound routes are empty because a blob node cannot reference other nodes. It can only be referenced
@@ -584,14 +522,14 @@ class BlobManager {
584
522
  continue;
585
523
  }
586
524
  const storageId = this.redirectTable.get(blobId);
587
- (0, internal_1.assert)(!!storageId, 0x5bb /* Must be attached to run GC */);
525
+ (0, internal_2.assert)(!!storageId, 0x5bb /* Must be attached to run GC */);
588
526
  maybeUnusedStorageIds.add(storageId);
589
527
  this.redirectTable.delete(blobId);
590
528
  }
591
529
  // Find out storage ids that are in-use and remove them from maybeUnusedStorageIds. A storage id is in-use if
592
530
  // the redirect table has a local id -> storage id entry for it.
593
531
  for (const [localId, storageId] of this.redirectTable.entries()) {
594
- (0, internal_1.assert)(!!storageId, 0x5bc /* Must be attached to run GC */);
532
+ (0, internal_2.assert)(!!storageId, 0x5bc /* Must be attached to run GC */);
595
533
  // For every storage id, the redirect table has a id -> id entry. These do not make the storage id in-use.
596
534
  if (maybeUnusedStorageIds.has(storageId) && localId !== storageId) {
597
535
  maybeUnusedStorageIds.delete(storageId);
@@ -612,7 +550,7 @@ class BlobManager {
612
550
  return;
613
551
  }
614
552
  const request = { url: blobId };
615
- const error = (0, internal_3.responseToException)((0, internal_3.createResponseError)(404, `Blob was deleted`, request), request);
553
+ const error = (0, internal_4.responseToException)((0, internal_4.createResponseError)(404, `Blob was deleted`, request), request);
616
554
  // Only log deleted events. Tombstone events are logged by garbage collector.
617
555
  this.mc.logger.sendErrorEvent({
618
556
  eventName: "GC_Deleted_Blob_Requested",
@@ -621,15 +559,29 @@ class BlobManager {
621
559
  throw error;
622
560
  }
623
561
  setRedirectTable(table) {
624
- (0, internal_1.assert)(this.runtime.attachState === container_definitions_1.AttachState.Detached, 0x252 /* "redirect table can only be set in detached container" */);
625
- (0, internal_1.assert)(this.redirectTable.size === table.size, 0x391 /* Redirect table size must match BlobManager's local ID count */);
562
+ (0, internal_2.assert)(this.runtime.attachState === internal_1.AttachState.Detached, 0x252 /* "redirect table can only be set in detached container" */);
563
+ (0, internal_2.assert)(this.redirectTable.size === table.size, 0x391 /* Redirect table size must match BlobManager's local ID count */);
626
564
  for (const [localId, storageId] of table) {
627
- (0, internal_1.assert)(this.redirectTable.has(localId), 0x254 /* "unrecognized id in redirect table" */);
565
+ (0, internal_2.assert)(this.redirectTable.has(localId), 0x254 /* "unrecognized id in redirect table" */);
628
566
  this.setRedirection(localId, storageId);
629
567
  // set identity (id -> id) entry
630
568
  this.setRedirection(storageId, storageId);
631
569
  }
632
570
  }
571
+ /**
572
+ * To be used in getPendingLocalState flow. Get a serializable record of the blobs that are
573
+ * pending upload and/or their BlobAttach op, which can be given to a new BlobManager to
574
+ * resume work.
575
+ *
576
+ * @privateRemarks
577
+ * For now, we don't track any pending blobs since the getPendingBlobs flow doesn't enable
578
+ * restoring to a state where an accessible handle has been stored by the customer (and we'll
579
+ * just drop any BlobAttach ops on the ground during reSubmit). However, once we add support
580
+ * for payload-pending handles, this will return the blobs associated with those handles.
581
+ */
582
+ getPendingBlobs() {
583
+ return undefined;
584
+ }
633
585
  /**
634
586
  * Part of container serialization when imminent closure is enabled (Currently when calling closeAndGetPendingLocalState).
635
587
  * This asynchronous function resolves all pending createBlob calls and waits for each blob
@@ -641,73 +593,7 @@ class BlobManager {
641
593
  * or undefined if no blobs were processed.
642
594
  */
643
595
  async attachAndGetPendingBlobs(stopBlobAttachingSignal) {
644
- return internal_4.PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "GetPendingBlobs" }, async () => {
645
- if (this.pendingBlobs.size === 0) {
646
- return;
647
- }
648
- const blobs = {};
649
- const localBlobs = new Set();
650
- // This while is used to stash blobs created while attaching and getting blobs
651
- while (localBlobs.size < this.pendingBlobs.size) {
652
- const attachHandlesP = [];
653
- for (const [localId, entry] of this.pendingBlobs) {
654
- if (!localBlobs.has(entry)) {
655
- localBlobs.add(entry);
656
- // In order to follow natural blob creation flow we need to:
657
- // 1 send the blob attach op
658
- // 2 resolve the blob handle
659
- // 3 wait for op referencing the blob
660
- if (!entry.opsent) {
661
- this.sendBlobAttachOp(localId, entry.storageId);
662
- }
663
- // Resolving the blob handle to let hosts continue with their operations (it will resolve
664
- // original createBlob call) and let them attach the blob. This is a lie we told since the upload
665
- // hasn't finished yet, but it's fine since we will retry on rehydration.
666
- entry.handleP.resolve(this.getBlobHandle(localId));
667
- // Array of promises that will resolve when handles get attached.
668
- attachHandlesP.push(new Promise((resolve, reject) => {
669
- stopBlobAttachingSignal?.addEventListener("abort", () => {
670
- this.stopAttaching = true;
671
- reject(new Error("Operation aborted"));
672
- }, { once: true });
673
- const onHandleAttached = (attachedEntry) => {
674
- if (attachedEntry === entry) {
675
- this.internalEvents.off("handleAttached", onHandleAttached);
676
- resolve();
677
- }
678
- };
679
- if (entry.attached) {
680
- resolve();
681
- }
682
- else {
683
- this.internalEvents.on("handleAttached", onHandleAttached);
684
- }
685
- }));
686
- }
687
- }
688
- // Wait for all blobs to be attached. This is important, otherwise serialized container
689
- // could send the blobAttach op without any op that references the blob, making it useless.
690
- await Promise.allSettled(attachHandlesP);
691
- }
692
- for (const [localId, entry] of this.pendingBlobs) {
693
- if (stopBlobAttachingSignal?.aborted && !entry.attached) {
694
- this.mc.logger.sendTelemetryEvent({
695
- eventName: "UnableToStashBlob",
696
- id: localId,
697
- });
698
- continue;
699
- }
700
- (0, internal_1.assert)(entry.attached === true, 0x790 /* stashed blob should be attached */);
701
- blobs[localId] = {
702
- blob: (0, client_utils_1.bufferToString)(entry.blob, "base64"),
703
- storageId: entry.storageId,
704
- acked: entry.acked,
705
- minTTLInSeconds: entry.minTTLInSeconds,
706
- uploadTime: entry.uploadTime,
707
- };
708
- }
709
- return Object.keys(blobs).length > 0 ? blobs : undefined;
710
- });
596
+ throw new internal_5.UsageError("attachAndGetPendingBlobs is no longer supported");
711
597
  }
712
598
  }
713
599
  exports.BlobManager = BlobManager;
@@ -722,7 +608,7 @@ const getGCNodePathFromBlobId = (blobId) => `/${exports.blobManagerBasePath}/${b
722
608
  */
723
609
  const getBlobIdFromGCNodePath = (nodePath) => {
724
610
  const pathParts = nodePath.split("/");
725
- (0, internal_1.assert)(areBlobPathParts(pathParts), 0x5bd /* Invalid blob node path */);
611
+ (0, internal_2.assert)(areBlobPathParts(pathParts), 0x5bd /* Invalid blob node path */);
726
612
  return pathParts[2];
727
613
  };
728
614
  /**