@fluidframework/container-loader 2.0.0-internal.4.0.6 → 2.0.0-internal.4.1.1
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/README.md +38 -0
- package/dist/connectionManager.d.ts +2 -1
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +16 -6
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionStateHandler.d.ts.map +1 -1
- package/dist/connectionStateHandler.js +7 -0
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container.d.ts +35 -2
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +88 -43
- package/dist/container.js.map +1 -1
- package/dist/containerContext.d.ts +3 -3
- package/dist/containerContext.d.ts.map +1 -1
- package/dist/containerContext.js +5 -4
- package/dist/containerContext.js.map +1 -1
- package/dist/containerStorageAdapter.d.ts +27 -2
- package/dist/containerStorageAdapter.d.ts.map +1 -1
- package/dist/containerStorageAdapter.js +64 -6
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/deltaManager.d.ts +1 -3
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +3 -8
- package/dist/deltaManager.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +4 -1
- package/dist/loader.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/protocol.d.ts +1 -0
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +4 -2
- package/dist/protocol.js.map +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js.map +1 -1
- package/lib/connectionManager.d.ts +2 -1
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +16 -6
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionStateHandler.d.ts.map +1 -1
- package/lib/connectionStateHandler.js +7 -0
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts +35 -2
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +90 -45
- package/lib/container.js.map +1 -1
- package/lib/containerContext.d.ts +3 -3
- package/lib/containerContext.d.ts.map +1 -1
- package/lib/containerContext.js +5 -4
- package/lib/containerContext.js.map +1 -1
- package/lib/containerStorageAdapter.d.ts +27 -2
- package/lib/containerStorageAdapter.d.ts.map +1 -1
- package/lib/containerStorageAdapter.js +62 -6
- package/lib/containerStorageAdapter.js.map +1 -1
- package/lib/deltaManager.d.ts +1 -3
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +3 -8
- package/lib/deltaManager.js.map +1 -1
- package/lib/index.d.ts +3 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js +4 -1
- package/lib/loader.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/protocol.d.ts +1 -0
- package/lib/protocol.d.ts.map +1 -1
- package/lib/protocol.js +3 -1
- package/lib/protocol.js.map +1 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js.map +1 -1
- package/package.json +17 -13
- package/src/connectionManager.ts +17 -7
- package/src/connectionStateHandler.ts +12 -0
- package/src/container.ts +138 -65
- package/src/containerContext.ts +6 -6
- package/src/containerStorageAdapter.ts +88 -5
- package/src/deltaManager.ts +3 -10
- package/src/index.ts +3 -1
- package/src/loader.ts +4 -1
- package/src/packageVersion.ts +1 -1
- package/src/protocol.ts +4 -1
- package/src/utils.ts +3 -1
package/src/containerContext.ts
CHANGED
|
@@ -21,7 +21,6 @@ import {
|
|
|
21
21
|
IProvideFluidCodeDetailsComparer,
|
|
22
22
|
ICodeDetailsLoader,
|
|
23
23
|
IFluidModuleWithDetails,
|
|
24
|
-
ISnapshotTreeWithBlobContents,
|
|
25
24
|
IBatchMessage,
|
|
26
25
|
} from "@fluidframework/container-definitions";
|
|
27
26
|
import { IRequest, IResponse, FluidObject } from "@fluidframework/core-interfaces";
|
|
@@ -221,7 +220,7 @@ export class ContainerContext implements IContainerContext {
|
|
|
221
220
|
public readonly scope: FluidObject,
|
|
222
221
|
private readonly codeLoader: ICodeDetailsLoader,
|
|
223
222
|
private readonly _codeDetails: IFluidCodeDetails,
|
|
224
|
-
private _baseSnapshot: ISnapshotTree | undefined,
|
|
223
|
+
private readonly _baseSnapshot: ISnapshotTree | undefined,
|
|
225
224
|
public readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,
|
|
226
225
|
quorum: IQuorum,
|
|
227
226
|
public readonly loader: ILoader,
|
|
@@ -375,10 +374,8 @@ export class ContainerContext implements IContainerContext {
|
|
|
375
374
|
return true;
|
|
376
375
|
}
|
|
377
376
|
|
|
378
|
-
public
|
|
379
|
-
this.
|
|
380
|
-
this.runtime.notifyAttaching?.(snapshot);
|
|
381
|
-
this.runtime.setAttachState(AttachState.Attaching);
|
|
377
|
+
public async notifyOpReplay(message: ISequencedDocumentMessage): Promise<void> {
|
|
378
|
+
return this.runtime.notifyOpReplay?.(message);
|
|
382
379
|
}
|
|
383
380
|
|
|
384
381
|
// #region private
|
|
@@ -406,6 +403,9 @@ export class ContainerContext implements IContainerContext {
|
|
|
406
403
|
}
|
|
407
404
|
|
|
408
405
|
private attachListener() {
|
|
406
|
+
this.container.once("attaching", () => {
|
|
407
|
+
this.runtime.setAttachState(AttachState.Attaching);
|
|
408
|
+
});
|
|
409
409
|
this.container.once("attached", () => {
|
|
410
410
|
this.runtime.setAttachState(AttachState.Attached);
|
|
411
411
|
});
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { IDisposable, ITelemetryLogger } from "@fluidframework/common-definitions";
|
|
7
|
-
import { assert } from "@fluidframework/common-utils";
|
|
7
|
+
import { assert, bufferToString, stringToBuffer } from "@fluidframework/common-utils";
|
|
8
8
|
import { ISnapshotTreeWithBlobContents } from "@fluidframework/container-definitions";
|
|
9
9
|
import {
|
|
10
10
|
FetchSource,
|
|
@@ -25,12 +25,20 @@ import { IDetachedBlobStorage } from "./loader";
|
|
|
25
25
|
import { ProtocolTreeStorageService } from "./protocolTreeDocumentStorageService";
|
|
26
26
|
import { RetriableDocumentStorageService } from "./retriableDocumentStorageService";
|
|
27
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Stringified blobs from a summary/snapshot tree.
|
|
30
|
+
* @deprecated this is an internal interface and will not longer be exported in future versions
|
|
31
|
+
* @internal
|
|
32
|
+
*/
|
|
33
|
+
export interface ISerializableBlobContents {
|
|
34
|
+
[id: string]: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
28
37
|
/**
|
|
29
38
|
* This class wraps the actual storage and make sure no wrong apis are called according to
|
|
30
39
|
* container attach state.
|
|
31
40
|
*/
|
|
32
41
|
export class ContainerStorageAdapter implements IDocumentStorageService, IDisposable {
|
|
33
|
-
private readonly blobContents: { [id: string]: ArrayBufferLike } = {};
|
|
34
42
|
private _storageService: IDocumentStorageService & Partial<IDisposable>;
|
|
35
43
|
|
|
36
44
|
private _summarizeProtocolTree: boolean | undefined;
|
|
@@ -53,6 +61,10 @@ export class ContainerStorageAdapter implements IDocumentStorageService, IDispos
|
|
|
53
61
|
public constructor(
|
|
54
62
|
detachedBlobStorage: IDetachedBlobStorage | undefined,
|
|
55
63
|
private readonly logger: ITelemetryLogger,
|
|
64
|
+
/**
|
|
65
|
+
* ArrayBufferLikes or utf8 encoded strings, containing blobs from a snapshot
|
|
66
|
+
*/
|
|
67
|
+
private readonly blobContents: { [id: string]: ArrayBufferLike | string } = {},
|
|
56
68
|
private readonly addProtocolSummaryIfMissing: (summaryTree: ISummaryTree) => ISummaryTree,
|
|
57
69
|
forceEnableSummarizeProtocolTree: boolean | undefined,
|
|
58
70
|
) {
|
|
@@ -128,9 +140,13 @@ export class ContainerStorageAdapter implements IDocumentStorageService, IDispos
|
|
|
128
140
|
}
|
|
129
141
|
|
|
130
142
|
public async readBlob(id: string): Promise<ArrayBufferLike> {
|
|
131
|
-
const
|
|
132
|
-
if (
|
|
133
|
-
|
|
143
|
+
const maybeBlob = this.blobContents[id];
|
|
144
|
+
if (maybeBlob !== undefined) {
|
|
145
|
+
if (typeof maybeBlob === "string") {
|
|
146
|
+
const blob = stringToBuffer(maybeBlob, "utf8");
|
|
147
|
+
return blob;
|
|
148
|
+
}
|
|
149
|
+
return maybeBlob;
|
|
134
150
|
}
|
|
135
151
|
return this._storageService.readBlob(id);
|
|
136
152
|
}
|
|
@@ -212,3 +228,70 @@ class BlobOnlyStorage implements IDocumentStorageService {
|
|
|
212
228
|
}
|
|
213
229
|
}
|
|
214
230
|
}
|
|
231
|
+
|
|
232
|
+
// runtime will write a tree to the summary containing only "attachment" type entries
|
|
233
|
+
// which reference attachment blobs by ID. However, some drivers do not support this type
|
|
234
|
+
// and will convert them to "blob" type entries. We want to avoid saving these to reduce
|
|
235
|
+
// the size of stashed change blobs.
|
|
236
|
+
const blobsTreeName = ".blobs";
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Get blob contents of a snapshot tree from storage (or, ideally, cache)
|
|
240
|
+
*/
|
|
241
|
+
export async function getBlobContentsFromTree(
|
|
242
|
+
snapshot: ISnapshotTree,
|
|
243
|
+
storage: IDocumentStorageService,
|
|
244
|
+
): Promise<ISerializableBlobContents> {
|
|
245
|
+
const blobs = {};
|
|
246
|
+
await getBlobContentsFromTreeCore(snapshot, blobs, storage);
|
|
247
|
+
return blobs;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
async function getBlobContentsFromTreeCore(
|
|
251
|
+
tree: ISnapshotTree,
|
|
252
|
+
blobs: ISerializableBlobContents,
|
|
253
|
+
storage: IDocumentStorageService,
|
|
254
|
+
root = true,
|
|
255
|
+
) {
|
|
256
|
+
const treePs: Promise<any>[] = [];
|
|
257
|
+
for (const [key, subTree] of Object.entries(tree.trees)) {
|
|
258
|
+
if (!root || key !== blobsTreeName) {
|
|
259
|
+
treePs.push(getBlobContentsFromTreeCore(subTree, blobs, storage, false));
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
for (const id of Object.values(tree.blobs)) {
|
|
263
|
+
const blob = await storage.readBlob(id);
|
|
264
|
+
// ArrayBufferLike will not survive JSON.stringify()
|
|
265
|
+
blobs[id] = bufferToString(blob, "utf8");
|
|
266
|
+
}
|
|
267
|
+
return Promise.all(treePs);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Extract blob contents from a snapshot tree with blob contents
|
|
272
|
+
*/
|
|
273
|
+
export function getBlobContentsFromTreeWithBlobContents(
|
|
274
|
+
snapshot: ISnapshotTreeWithBlobContents,
|
|
275
|
+
): ISerializableBlobContents {
|
|
276
|
+
const blobs = {};
|
|
277
|
+
getBlobContentsFromTreeWithBlobContentsCore(snapshot, blobs);
|
|
278
|
+
return blobs;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function getBlobContentsFromTreeWithBlobContentsCore(
|
|
282
|
+
tree: ISnapshotTreeWithBlobContents,
|
|
283
|
+
blobs: ISerializableBlobContents,
|
|
284
|
+
root = true,
|
|
285
|
+
) {
|
|
286
|
+
for (const [key, subTree] of Object.entries(tree.trees)) {
|
|
287
|
+
if (!root || key !== blobsTreeName) {
|
|
288
|
+
getBlobContentsFromTreeWithBlobContentsCore(subTree, blobs, false);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
for (const id of Object.values(tree.blobs)) {
|
|
292
|
+
const blob = tree.blobsContents[id];
|
|
293
|
+
assert(blob !== undefined, 0x2ec /* "Blob must be present in blobsContents" */);
|
|
294
|
+
// ArrayBufferLike will not survive JSON.stringify()
|
|
295
|
+
blobs[id] = bufferToString(blob, "utf8");
|
|
296
|
+
}
|
|
297
|
+
}
|
package/src/deltaManager.ts
CHANGED
|
@@ -41,8 +41,9 @@ import {
|
|
|
41
41
|
extractSafePropertiesFromMessage,
|
|
42
42
|
DataProcessingError,
|
|
43
43
|
} from "@fluidframework/container-utils";
|
|
44
|
-
import { DeltaQueue } from "./deltaQueue";
|
|
45
44
|
import { IConnectionManagerFactoryArgs, IConnectionManager } from "./contracts";
|
|
45
|
+
import { DeltaQueue } from "./deltaQueue";
|
|
46
|
+
import { OnlyValidTermValue } from "./protocol";
|
|
46
47
|
|
|
47
48
|
export interface IConnectionArgs {
|
|
48
49
|
mode?: ConnectionMode;
|
|
@@ -123,7 +124,6 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
123
124
|
private lastObservedSeqNumber: number = 0;
|
|
124
125
|
private lastProcessedSequenceNumber: number = 0;
|
|
125
126
|
private lastProcessedMessage: ISequencedDocumentMessage | undefined;
|
|
126
|
-
private baseTerm: number = 0;
|
|
127
127
|
|
|
128
128
|
/** count number of noops sent by the client which may not be acked */
|
|
129
129
|
private noOpCount: number = 0;
|
|
@@ -187,10 +187,6 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
187
187
|
return this.lastObservedSeqNumber;
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
-
public get referenceTerm(): number {
|
|
191
|
-
return this.baseTerm;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
190
|
public get minimumSequenceNumber(): number {
|
|
195
191
|
return this.minSequenceNumber;
|
|
196
192
|
}
|
|
@@ -465,13 +461,11 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
465
461
|
public async attachOpHandler(
|
|
466
462
|
minSequenceNumber: number,
|
|
467
463
|
sequenceNumber: number,
|
|
468
|
-
term: number,
|
|
469
464
|
handler: IDeltaHandlerStrategy,
|
|
470
465
|
prefetchType: "cached" | "all" | "none" = "none",
|
|
471
466
|
) {
|
|
472
467
|
this.initSequenceNumber = sequenceNumber;
|
|
473
468
|
this.lastProcessedSequenceNumber = sequenceNumber;
|
|
474
|
-
this.baseTerm = term;
|
|
475
469
|
this.minSequenceNumber = minSequenceNumber;
|
|
476
470
|
this.lastQueuedSequenceNumber = sequenceNumber;
|
|
477
471
|
this.lastObservedSeqNumber = sequenceNumber;
|
|
@@ -986,9 +980,8 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
986
980
|
|
|
987
981
|
// Back-compat for older server with no term
|
|
988
982
|
if (message.term === undefined) {
|
|
989
|
-
message.term =
|
|
983
|
+
message.term = OnlyValidTermValue;
|
|
990
984
|
}
|
|
991
|
-
this.baseTerm = message.term;
|
|
992
985
|
|
|
993
986
|
if (this.handler === undefined) {
|
|
994
987
|
throw new Error("Attempted to process an inbound message without a handler attached");
|
package/src/index.ts
CHANGED
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
|
|
6
6
|
export { ConnectionState } from "./connectionState";
|
|
7
7
|
export {
|
|
8
|
-
IContainerLoadOptions,
|
|
9
8
|
IContainerConfig,
|
|
9
|
+
IContainerLoadOptions,
|
|
10
10
|
IPendingContainerState,
|
|
11
11
|
waitContainerToCatchUp,
|
|
12
12
|
} from "./container";
|
|
13
|
+
export { ISerializableBlobContents } from "./containerStorageAdapter";
|
|
13
14
|
export {
|
|
14
15
|
ICodeDetailsLoader,
|
|
15
16
|
IDetachedBlobStorage,
|
|
@@ -18,5 +19,6 @@ export {
|
|
|
18
19
|
ILoaderProps,
|
|
19
20
|
ILoaderServices,
|
|
20
21
|
Loader,
|
|
22
|
+
requestResolvedObjectFromContainer,
|
|
21
23
|
} from "./loader";
|
|
22
24
|
export { IProtocolHandler, ProtocolHandlerBuilder } from "./protocol";
|
package/src/loader.ts
CHANGED
|
@@ -273,7 +273,10 @@ export async function requestResolvedObjectFromContainer(
|
|
|
273
273
|
throw new Error(`Invalid URL ${container.resolvedUrl.url}`);
|
|
274
274
|
}
|
|
275
275
|
|
|
276
|
-
|
|
276
|
+
const entryPoint: FluidObject<IFluidRouter> | undefined = await container.getEntryPoint?.();
|
|
277
|
+
const router = entryPoint?.IFluidRouter ?? container.IFluidRouter;
|
|
278
|
+
|
|
279
|
+
return router.request({
|
|
277
280
|
url: `${parsedUrl.path}${parsedUrl.query}`,
|
|
278
281
|
headers,
|
|
279
282
|
});
|
package/src/packageVersion.ts
CHANGED
package/src/protocol.ts
CHANGED
|
@@ -20,6 +20,9 @@ import {
|
|
|
20
20
|
} from "@fluidframework/protocol-definitions";
|
|
21
21
|
import { canBeCoalescedByService } from "@fluidframework/driver-utils";
|
|
22
22
|
|
|
23
|
+
// "term" was an experimental feature that is being removed. The only safe value to use is 1.
|
|
24
|
+
export const OnlyValidTermValue = 1 as const;
|
|
25
|
+
|
|
23
26
|
// ADO: #1986: Start using enum from protocol-base.
|
|
24
27
|
export enum SignalType {
|
|
25
28
|
ClientJoin = "join", // same value as MessageType.ClientJoin,
|
|
@@ -51,7 +54,7 @@ export class ProtocolHandler extends ProtocolOpHandler implements IProtocolHandl
|
|
|
51
54
|
super(
|
|
52
55
|
attributes.minimumSequenceNumber,
|
|
53
56
|
attributes.sequenceNumber,
|
|
54
|
-
|
|
57
|
+
OnlyValidTermValue,
|
|
55
58
|
quorumSnapshot.members,
|
|
56
59
|
quorumSnapshot.proposals,
|
|
57
60
|
quorumSnapshot.values,
|
package/src/utils.ts
CHANGED
|
@@ -126,7 +126,9 @@ export function convertProtocolAndAppSummaryToSnapshotTree(
|
|
|
126
126
|
|
|
127
127
|
// This function converts the snapshot taken in detached container(by serialize api) to snapshotTree with which
|
|
128
128
|
// a detached container can be rehydrated.
|
|
129
|
-
export const getSnapshotTreeFromSerializedContainer = (
|
|
129
|
+
export const getSnapshotTreeFromSerializedContainer = (
|
|
130
|
+
detachedContainerSnapshot: ISummaryTree,
|
|
131
|
+
): ISnapshotTreeWithBlobContents => {
|
|
130
132
|
assert(
|
|
131
133
|
isCombinedAppAndProtocolSummary(detachedContainerSnapshot),
|
|
132
134
|
0x1e0 /* "Protocol and App summary trees should be present" */,
|