@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.
- package/CHANGELOG.md +14 -0
- package/api-report/container-runtime.legacy.alpha.api.md +1 -2
- package/container-runtime.test-files.tar +0 -0
- package/dist/blobManager/blobManager.d.ts +15 -7
- package/dist/blobManager/blobManager.d.ts.map +1 -1
- package/dist/blobManager/blobManager.js +72 -186
- package/dist/blobManager/blobManager.js.map +1 -1
- package/dist/containerCompatibility.d.ts +34 -0
- package/dist/containerCompatibility.d.ts.map +1 -0
- package/dist/containerCompatibility.js +125 -0
- package/dist/containerCompatibility.js.map +1 -0
- package/dist/containerRuntime.d.ts +27 -15
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +175 -136
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.d.ts +6 -6
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/metadata.d.ts +3 -2
- package/dist/metadata.d.ts.map +1 -1
- package/dist/metadata.js +7 -1
- package/dist/metadata.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/storageServiceWithAttachBlobs.d.ts +40 -5
- package/dist/storageServiceWithAttachBlobs.d.ts.map +1 -1
- package/dist/storageServiceWithAttachBlobs.js +56 -5
- package/dist/storageServiceWithAttachBlobs.js.map +1 -1
- package/dist/summary/documentSchema.d.ts +1 -1
- package/dist/summary/documentSchema.d.ts.map +1 -1
- package/dist/summary/documentSchema.js.map +1 -1
- package/dist/summary/summaryFormat.d.ts +3 -3
- package/dist/summary/summaryFormat.d.ts.map +1 -1
- package/dist/summary/summaryFormat.js.map +1 -1
- package/lib/blobManager/blobManager.d.ts +15 -7
- package/lib/blobManager/blobManager.d.ts.map +1 -1
- package/lib/blobManager/blobManager.js +39 -153
- package/lib/blobManager/blobManager.js.map +1 -1
- package/lib/containerCompatibility.d.ts +34 -0
- package/lib/containerCompatibility.d.ts.map +1 -0
- package/lib/containerCompatibility.js +120 -0
- package/lib/containerCompatibility.js.map +1 -0
- package/lib/containerRuntime.d.ts +27 -15
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +103 -64
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.d.ts +6 -6
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +1 -1
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/index.d.ts +5 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/metadata.d.ts +3 -2
- package/lib/metadata.d.ts.map +1 -1
- package/lib/metadata.js +5 -0
- package/lib/metadata.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/storageServiceWithAttachBlobs.d.ts +40 -5
- package/lib/storageServiceWithAttachBlobs.d.ts.map +1 -1
- package/lib/storageServiceWithAttachBlobs.js +56 -5
- package/lib/storageServiceWithAttachBlobs.js.map +1 -1
- package/lib/summary/documentSchema.d.ts +1 -1
- package/lib/summary/documentSchema.d.ts.map +1 -1
- package/lib/summary/documentSchema.js.map +1 -1
- package/lib/summary/summaryFormat.d.ts +3 -3
- package/lib/summary/summaryFormat.d.ts.map +1 -1
- package/lib/summary/summaryFormat.js.map +1 -1
- package/package.json +20 -20
- package/src/blobManager/blobManager.ts +53 -195
- package/src/containerCompatibility.ts +176 -0
- package/src/containerRuntime.ts +157 -122
- package/src/dataStoreContext.ts +13 -5
- package/src/index.ts +6 -1
- package/src/metadata.ts +10 -2
- package/src/packageVersion.ts +1 -1
- package/src/storageServiceWithAttachBlobs.ts +92 -10
- package/src/summary/documentSchema.ts +1 -1
- package/src/summary/summaryFormat.ts +2 -2
- package/dist/compatUtils.d.ts +0 -106
- package/dist/compatUtils.d.ts.map +0 -1
- package/dist/compatUtils.js +0 -251
- package/dist/compatUtils.js.map +0 -1
- package/lib/compatUtils.d.ts +0 -106
- package/lib/compatUtils.d.ts.map +0 -1
- package/lib/compatUtils.js +0 -242
- package/lib/compatUtils.js.map +0 -1
- 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
|
-
|
|
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:
|
|
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
|
|
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":"AAAA;;;GAGG;
|
|
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
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
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
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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 !==
|
|
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
|
|
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 ===
|
|
208
|
-
(0,
|
|
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 '
|
|
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,
|
|
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
|
|
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,
|
|
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 '
|
|
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 ===
|
|
226
|
+
if (this.runtime.attachState === internal_1.AttachState.Detached) {
|
|
270
227
|
return this.createBlobDetached(blob);
|
|
271
228
|
}
|
|
272
|
-
if (this.runtime.attachState ===
|
|
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,
|
|
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
|
|
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
|
|
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,
|
|
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,
|
|
347
|
-
if (entry.opsent && !(0,
|
|
348
|
-
throw (0,
|
|
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
|
-
|
|
393
|
-
|
|
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,
|
|
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,
|
|
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
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
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
|
-
|
|
468
|
-
const blobId = message.metadata
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
625
|
-
(0,
|
|
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,
|
|
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
|
-
|
|
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,
|
|
611
|
+
(0, internal_2.assert)(areBlobPathParts(pathParts), 0x5bd /* Invalid blob node path */);
|
|
726
612
|
return pathParts[2];
|
|
727
613
|
};
|
|
728
614
|
/**
|