@fluidframework/container-loader 2.0.0-dev-rc.5.0.0.265721 → 2.0.0-dev-rc.5.0.0.267932
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/api-report/container-loader.api.md +6 -4
- package/dist/attachment.d.ts +1 -1
- package/dist/attachment.d.ts.map +1 -1
- package/dist/attachment.js.map +1 -1
- package/dist/audience.d.ts +1 -1
- package/dist/audience.d.ts.map +1 -1
- package/dist/audience.js.map +1 -1
- package/dist/catchUpMonitor.js.map +1 -1
- package/dist/connectionManager.d.ts +2 -2
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +3 -4
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionStateHandler.d.ts +4 -2
- package/dist/connectionStateHandler.d.ts.map +1 -1
- package/dist/connectionStateHandler.js +18 -12
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container.d.ts +2 -2
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +84 -67
- package/dist/container.js.map +1 -1
- package/dist/containerContext.d.ts +2 -2
- package/dist/containerContext.d.ts.map +1 -1
- package/dist/containerContext.js.map +1 -1
- package/dist/containerStorageAdapter.d.ts +2 -2
- package/dist/containerStorageAdapter.d.ts.map +1 -1
- package/dist/containerStorageAdapter.js +7 -2
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/contracts.d.ts +2 -2
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/debugLogger.d.ts.map +1 -1
- package/dist/debugLogger.js.map +1 -1
- package/dist/deltaManager.d.ts +4 -4
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +8 -9
- package/dist/deltaManager.js.map +1 -1
- package/dist/loadPaused.js.map +1 -1
- package/dist/loader.d.ts +8 -1
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js.map +1 -1
- package/dist/memoryBlobStorage.d.ts +9 -0
- package/dist/memoryBlobStorage.d.ts.map +1 -0
- package/dist/memoryBlobStorage.js +58 -0
- package/dist/memoryBlobStorage.js.map +1 -0
- package/dist/noopHeuristic.d.ts +1 -1
- package/dist/noopHeuristic.d.ts.map +1 -1
- package/dist/noopHeuristic.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 +2 -1
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +4 -4
- package/dist/protocol.js.map +1 -1
- package/dist/protocolTreeDocumentStorageService.d.ts +5 -5
- package/dist/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/dist/protocolTreeDocumentStorageService.js.map +1 -1
- package/dist/quorum.d.ts +1 -1
- package/dist/quorum.d.ts.map +1 -1
- package/dist/quorum.js.map +1 -1
- package/dist/retriableDocumentStorageService.d.ts +2 -2
- package/dist/retriableDocumentStorageService.d.ts.map +1 -1
- package/dist/retriableDocumentStorageService.js.map +1 -1
- package/dist/serializedStateManager.d.ts +5 -3
- package/dist/serializedStateManager.d.ts.map +1 -1
- package/dist/serializedStateManager.js.map +1 -1
- package/dist/utils.d.ts +2 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +7 -7
- package/dist/utils.js.map +1 -1
- package/lib/attachment.d.ts +1 -1
- package/lib/attachment.d.ts.map +1 -1
- package/lib/attachment.js.map +1 -1
- package/lib/audience.d.ts +1 -1
- package/lib/audience.d.ts.map +1 -1
- package/lib/audience.js.map +1 -1
- package/lib/catchUpMonitor.js.map +1 -1
- package/lib/connectionManager.d.ts +2 -2
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +1 -2
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionStateHandler.d.ts +4 -2
- package/lib/connectionStateHandler.d.ts.map +1 -1
- package/lib/connectionStateHandler.js +19 -13
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts +2 -2
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +26 -9
- package/lib/container.js.map +1 -1
- package/lib/containerContext.d.ts +2 -2
- package/lib/containerContext.d.ts.map +1 -1
- package/lib/containerContext.js.map +1 -1
- package/lib/containerStorageAdapter.d.ts +2 -2
- package/lib/containerStorageAdapter.d.ts.map +1 -1
- package/lib/containerStorageAdapter.js +7 -2
- package/lib/containerStorageAdapter.js.map +1 -1
- package/lib/contracts.d.ts +2 -2
- package/lib/contracts.d.ts.map +1 -1
- package/lib/contracts.js.map +1 -1
- package/lib/debugLogger.d.ts.map +1 -1
- package/lib/debugLogger.js.map +1 -1
- package/lib/deltaManager.d.ts +4 -4
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +1 -2
- package/lib/deltaManager.js.map +1 -1
- package/lib/loadPaused.js.map +1 -1
- package/lib/loader.d.ts +8 -1
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js.map +1 -1
- package/lib/memoryBlobStorage.d.ts +9 -0
- package/lib/memoryBlobStorage.d.ts.map +1 -0
- package/lib/memoryBlobStorage.js +52 -0
- package/lib/memoryBlobStorage.js.map +1 -0
- package/lib/noopHeuristic.d.ts +1 -1
- package/lib/noopHeuristic.d.ts.map +1 -1
- package/lib/noopHeuristic.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 +2 -1
- package/lib/protocol.d.ts.map +1 -1
- package/lib/protocol.js +1 -1
- package/lib/protocol.js.map +1 -1
- package/lib/protocolTreeDocumentStorageService.d.ts +5 -5
- package/lib/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/lib/protocolTreeDocumentStorageService.js.map +1 -1
- package/lib/quorum.d.ts +1 -1
- package/lib/quorum.d.ts.map +1 -1
- package/lib/quorum.js.map +1 -1
- package/lib/retriableDocumentStorageService.d.ts +2 -2
- package/lib/retriableDocumentStorageService.d.ts.map +1 -1
- package/lib/retriableDocumentStorageService.js.map +1 -1
- package/lib/serializedStateManager.d.ts +5 -3
- package/lib/serializedStateManager.d.ts.map +1 -1
- package/lib/serializedStateManager.js.map +1 -1
- package/lib/tsdoc-metadata.json +1 -1
- package/lib/utils.d.ts +2 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +2 -2
- package/lib/utils.js.map +1 -1
- package/package.json +12 -13
- package/src/attachment.ts +3 -1
- package/src/audience.ts +1 -1
- package/src/catchUpMonitor.ts +1 -1
- package/src/connectionManager.ts +16 -16
- package/src/connectionStateHandler.ts +27 -19
- package/src/container.ts +51 -27
- package/src/containerContext.ts +6 -3
- package/src/containerStorageAdapter.ts +7 -6
- package/src/contracts.ts +7 -5
- package/src/debugLogger.ts +2 -3
- package/src/deltaManager.ts +7 -7
- package/src/loadPaused.ts +1 -1
- package/src/loader.ts +9 -1
- package/src/memoryBlobStorage.ts +80 -0
- package/src/noopHeuristic.ts +1 -1
- package/src/packageVersion.ts +1 -1
- package/src/protocol.ts +7 -8
- package/src/protocolTreeDocumentStorageService.ts +1 -1
- package/src/quorum.ts +1 -1
- package/src/retriableDocumentStorageService.ts +3 -6
- package/src/serializedStateManager.ts +8 -7
- package/src/utils.ts +6 -7
package/src/container.ts
CHANGED
|
@@ -37,6 +37,16 @@ import {
|
|
|
37
37
|
} from "@fluidframework/core-interfaces";
|
|
38
38
|
import { type ISignalEnvelope } from "@fluidframework/core-interfaces/internal";
|
|
39
39
|
import { assert, isPromiseLike, unreachableCase } from "@fluidframework/core-utils/internal";
|
|
40
|
+
import {
|
|
41
|
+
IClient,
|
|
42
|
+
IClientDetails,
|
|
43
|
+
IQuorumClients,
|
|
44
|
+
ISequencedClient,
|
|
45
|
+
ISequencedDocumentMessage,
|
|
46
|
+
ISignalMessage,
|
|
47
|
+
ISummaryTree,
|
|
48
|
+
SummaryType,
|
|
49
|
+
} from "@fluidframework/driver-definitions";
|
|
40
50
|
import {
|
|
41
51
|
IDocumentService,
|
|
42
52
|
IDocumentServiceFactory,
|
|
@@ -45,6 +55,15 @@ import {
|
|
|
45
55
|
ISnapshot,
|
|
46
56
|
IThrottlingWarning,
|
|
47
57
|
IUrlResolver,
|
|
58
|
+
ICommittedProposal,
|
|
59
|
+
IDocumentAttributes,
|
|
60
|
+
IDocumentMessage,
|
|
61
|
+
IQuorumProposals,
|
|
62
|
+
ISequencedProposal,
|
|
63
|
+
ISnapshotTree,
|
|
64
|
+
ISummaryContent,
|
|
65
|
+
IVersion,
|
|
66
|
+
MessageType,
|
|
48
67
|
} from "@fluidframework/driver-definitions/internal";
|
|
49
68
|
import {
|
|
50
69
|
getSnapshotTree,
|
|
@@ -57,25 +76,6 @@ import {
|
|
|
57
76
|
runWithRetry,
|
|
58
77
|
} from "@fluidframework/driver-utils/internal";
|
|
59
78
|
import { IQuorumSnapshot } from "@fluidframework/protocol-base";
|
|
60
|
-
import {
|
|
61
|
-
IClient,
|
|
62
|
-
IClientDetails,
|
|
63
|
-
ICommittedProposal,
|
|
64
|
-
IDocumentAttributes,
|
|
65
|
-
IDocumentMessage,
|
|
66
|
-
IQuorumClients,
|
|
67
|
-
IQuorumProposals,
|
|
68
|
-
ISequencedClient,
|
|
69
|
-
ISequencedDocumentMessage,
|
|
70
|
-
ISequencedProposal,
|
|
71
|
-
ISignalMessage,
|
|
72
|
-
ISnapshotTree,
|
|
73
|
-
ISummaryContent,
|
|
74
|
-
ISummaryTree,
|
|
75
|
-
IVersion,
|
|
76
|
-
MessageType,
|
|
77
|
-
SummaryType,
|
|
78
|
-
} from "@fluidframework/protocol-definitions";
|
|
79
79
|
import {
|
|
80
80
|
type TelemetryEventCategory,
|
|
81
81
|
ITelemetryLoggerExt,
|
|
@@ -92,6 +92,7 @@ import {
|
|
|
92
92
|
normalizeError,
|
|
93
93
|
raiseConnectedEvent,
|
|
94
94
|
wrapError,
|
|
95
|
+
loggerToMonitoringContext,
|
|
95
96
|
} from "@fluidframework/telemetry-utils/internal";
|
|
96
97
|
import structuredClone from "@ungap/structured-clone";
|
|
97
98
|
import { v4 as uuid } from "uuid";
|
|
@@ -111,7 +112,13 @@ import {
|
|
|
111
112
|
getPackageName,
|
|
112
113
|
} from "./contracts.js";
|
|
113
114
|
import { DeltaManager, IConnectionArgs } from "./deltaManager.js";
|
|
115
|
+
// eslint-disable-next-line import/no-deprecated
|
|
114
116
|
import { IDetachedBlobStorage, ILoaderOptions, RelativeLoader } from "./loader.js";
|
|
117
|
+
import {
|
|
118
|
+
serializeMemoryDetachedBlobStorage,
|
|
119
|
+
createMemoryDetachedBlobStorage,
|
|
120
|
+
tryInitializeMemoryDetachedBlobStorage,
|
|
121
|
+
} from "./memoryBlobStorage.js";
|
|
115
122
|
import { NoopHeuristic } from "./noopHeuristic.js";
|
|
116
123
|
import { pkgVersion } from "./packageVersion.js";
|
|
117
124
|
import {
|
|
@@ -218,6 +225,7 @@ export interface IContainerCreateProps {
|
|
|
218
225
|
/**
|
|
219
226
|
* Blobs storage for detached containers.
|
|
220
227
|
*/
|
|
228
|
+
// eslint-disable-next-line import/no-deprecated
|
|
221
229
|
readonly detachedBlobStorage?: IDetachedBlobStorage;
|
|
222
230
|
|
|
223
231
|
/**
|
|
@@ -465,7 +473,8 @@ export class Container
|
|
|
465
473
|
private readonly options: ILoaderOptions;
|
|
466
474
|
private readonly scope: FluidObject;
|
|
467
475
|
private readonly subLogger: ITelemetryLoggerExt;
|
|
468
|
-
|
|
476
|
+
// eslint-disable-next-line import/no-deprecated
|
|
477
|
+
private readonly detachedBlobStorage: IDetachedBlobStorage;
|
|
469
478
|
private readonly protocolHandlerBuilder: ProtocolHandlerBuilder;
|
|
470
479
|
private readonly client: IClient;
|
|
471
480
|
|
|
@@ -517,6 +526,15 @@ export class Container
|
|
|
517
526
|
0x969 /* not connected yet */,
|
|
518
527
|
);
|
|
519
528
|
|
|
529
|
+
// Track membership changes and update connection state accordingly
|
|
530
|
+
// We do this call here, instead of doing it in initializeProtocolState() due to pendingLocalState.
|
|
531
|
+
// When we load from stashed state, we let connectionStateHandler know about clientId from previous container instance.
|
|
532
|
+
// But we will play trailing ops from snapshot, including potentially playing join & leave ops for that same clientId!
|
|
533
|
+
// In other words, if connectionStateHandler has access to Quorum early in load sequence, it will see events (in stashed ops mode)
|
|
534
|
+
// in the order that is not possible in real life, that it may not expect.
|
|
535
|
+
// Ideally, we should supply pendingLocalState?.clientId here as well, not in constructor, but it does not matter (at least today)
|
|
536
|
+
this.connectionStateHandler.initProtocol(this.protocolHandler);
|
|
537
|
+
|
|
520
538
|
// Propagate current connection state through the system.
|
|
521
539
|
const readonly = this.readOnlyInfo.readonly ?? false;
|
|
522
540
|
// This call does not look like needed any more, with delaying all connection-related events past loaded phase.
|
|
@@ -767,7 +785,7 @@ export class Container
|
|
|
767
785
|
// Tracking alternative ways to handle this in AB#4129.
|
|
768
786
|
this.options = { ...options };
|
|
769
787
|
this.scope = scope;
|
|
770
|
-
this.detachedBlobStorage = detachedBlobStorage;
|
|
788
|
+
this.detachedBlobStorage = detachedBlobStorage ?? createMemoryDetachedBlobStorage();
|
|
771
789
|
this.protocolHandlerBuilder =
|
|
772
790
|
protocolHandlerBuilder ??
|
|
773
791
|
((
|
|
@@ -856,6 +874,9 @@ export class Container
|
|
|
856
874
|
this.connectionStateHandler = createConnectionStateHandler(
|
|
857
875
|
{
|
|
858
876
|
logger: this.mc.logger,
|
|
877
|
+
// WARNING: logger on this context should not including getters like containerConnectionState above (on this.subLogger),
|
|
878
|
+
// as that will result in attempt to dereference this.connectionStateHandler from this call while it's still undefined.
|
|
879
|
+
mc: loggerToMonitoringContext(subLogger),
|
|
859
880
|
connectionStateChanged: (value, oldState, reason) => {
|
|
860
881
|
this.logConnectionStateChangeTelemetry(value, oldState, reason);
|
|
861
882
|
if (this.loaded) {
|
|
@@ -944,7 +965,7 @@ export class Container
|
|
|
944
965
|
options.summarizeProtocolTree;
|
|
945
966
|
|
|
946
967
|
this.storageAdapter = new ContainerStorageAdapter(
|
|
947
|
-
detachedBlobStorage,
|
|
968
|
+
this.detachedBlobStorage,
|
|
948
969
|
this.mc.logger,
|
|
949
970
|
pendingLocalState?.snapshotBlobs,
|
|
950
971
|
pendingLocalState?.loadedGroupIdSnapshots,
|
|
@@ -1208,7 +1229,8 @@ export class Container
|
|
|
1208
1229
|
baseSnapshot,
|
|
1209
1230
|
snapshotBlobs,
|
|
1210
1231
|
pendingRuntimeState,
|
|
1211
|
-
hasAttachmentBlobs:
|
|
1232
|
+
hasAttachmentBlobs: this.detachedBlobStorage.size > 0,
|
|
1233
|
+
attachmentBlobs: serializeMemoryDetachedBlobStorage(this.detachedBlobStorage),
|
|
1212
1234
|
};
|
|
1213
1235
|
return JSON.stringify(detachedContainerState);
|
|
1214
1236
|
}
|
|
@@ -1328,6 +1350,7 @@ export class Container
|
|
|
1328
1350
|
this.serializedStateManager.setInitialSnapshot(snapshotWithBlobs);
|
|
1329
1351
|
|
|
1330
1352
|
if (!this.closed) {
|
|
1353
|
+
this.detachedBlobStorage.dispose?.();
|
|
1331
1354
|
this.handleDeltaConnectionArg(attachProps?.deltaConnection, {
|
|
1332
1355
|
fetchOpsFromStorage: false,
|
|
1333
1356
|
reason: { text: "createDetached" },
|
|
@@ -1760,11 +1783,15 @@ export class Container
|
|
|
1760
1783
|
baseSnapshot,
|
|
1761
1784
|
snapshotBlobs,
|
|
1762
1785
|
hasAttachmentBlobs,
|
|
1786
|
+
attachmentBlobs,
|
|
1763
1787
|
pendingRuntimeState,
|
|
1764
1788
|
}: IPendingDetachedContainerState) {
|
|
1765
1789
|
if (hasAttachmentBlobs) {
|
|
1790
|
+
if (attachmentBlobs !== undefined) {
|
|
1791
|
+
tryInitializeMemoryDetachedBlobStorage(this.detachedBlobStorage, attachmentBlobs);
|
|
1792
|
+
}
|
|
1766
1793
|
assert(
|
|
1767
|
-
|
|
1794
|
+
this.detachedBlobStorage.size > 0,
|
|
1768
1795
|
0x250 /* "serialized container with attachment blobs must be rehydrated with detached blob storage" */,
|
|
1769
1796
|
);
|
|
1770
1797
|
}
|
|
@@ -1853,9 +1880,6 @@ export class Container
|
|
|
1853
1880
|
protocolLogger.sendErrorEvent(error);
|
|
1854
1881
|
});
|
|
1855
1882
|
|
|
1856
|
-
// Track membership changes and update connection state accordingly
|
|
1857
|
-
this.connectionStateHandler.initProtocol(protocol);
|
|
1858
|
-
|
|
1859
1883
|
protocol.quorum.on("addProposal", (proposal: ISequencedProposal) => {
|
|
1860
1884
|
if (proposal.key === "code" || proposal.key === "code2") {
|
|
1861
1885
|
this.emit("codeDetailsProposed", proposal.value, proposal);
|
package/src/containerContext.ts
CHANGED
|
@@ -17,17 +17,20 @@ import {
|
|
|
17
17
|
} from "@fluidframework/container-definitions/internal";
|
|
18
18
|
import { type FluidObject } from "@fluidframework/core-interfaces";
|
|
19
19
|
import { type ISignalEnvelope } from "@fluidframework/core-interfaces/internal";
|
|
20
|
-
import { IDocumentStorageService, ISnapshot } from "@fluidframework/driver-definitions/internal";
|
|
21
20
|
import {
|
|
22
21
|
IClientDetails,
|
|
23
|
-
IDocumentMessage,
|
|
24
22
|
IQuorumClients,
|
|
25
23
|
ISequencedDocumentMessage,
|
|
24
|
+
} from "@fluidframework/driver-definitions";
|
|
25
|
+
import {
|
|
26
|
+
IDocumentStorageService,
|
|
27
|
+
ISnapshot,
|
|
28
|
+
IDocumentMessage,
|
|
26
29
|
ISnapshotTree,
|
|
27
30
|
ISummaryContent,
|
|
28
31
|
IVersion,
|
|
29
32
|
MessageType,
|
|
30
|
-
} from "@fluidframework/
|
|
33
|
+
} from "@fluidframework/driver-definitions/internal";
|
|
31
34
|
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils/internal";
|
|
32
35
|
|
|
33
36
|
/**
|
|
@@ -7,6 +7,7 @@ import { bufferToString, stringToBuffer } from "@fluid-internal/client-utils";
|
|
|
7
7
|
import { ISnapshotTreeWithBlobContents } from "@fluidframework/container-definitions/internal";
|
|
8
8
|
import { IDisposable } from "@fluidframework/core-interfaces";
|
|
9
9
|
import { assert } from "@fluidframework/core-utils/internal";
|
|
10
|
+
import { ISummaryHandle, ISummaryTree } from "@fluidframework/driver-definitions";
|
|
10
11
|
import {
|
|
11
12
|
FetchSource,
|
|
12
13
|
IDocumentService,
|
|
@@ -15,17 +16,14 @@ import {
|
|
|
15
16
|
ISnapshot,
|
|
16
17
|
ISnapshotFetchOptions,
|
|
17
18
|
ISummaryContext,
|
|
18
|
-
} from "@fluidframework/driver-definitions/internal";
|
|
19
|
-
import { UsageError } from "@fluidframework/driver-utils/internal";
|
|
20
|
-
import {
|
|
21
19
|
ICreateBlobResponse,
|
|
22
20
|
ISnapshotTree,
|
|
23
|
-
ISummaryHandle,
|
|
24
|
-
ISummaryTree,
|
|
25
21
|
IVersion,
|
|
26
|
-
} from "@fluidframework/
|
|
22
|
+
} from "@fluidframework/driver-definitions/internal";
|
|
23
|
+
import { UsageError } from "@fluidframework/driver-utils/internal";
|
|
27
24
|
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils/internal";
|
|
28
25
|
|
|
26
|
+
// eslint-disable-next-line import/no-deprecated
|
|
29
27
|
import { IDetachedBlobStorage } from "./loader.js";
|
|
30
28
|
import { ProtocolTreeStorageService } from "./protocolTreeDocumentStorageService.js";
|
|
31
29
|
import { RetriableDocumentStorageService } from "./retriableDocumentStorageService.js";
|
|
@@ -79,6 +77,7 @@ export class ContainerStorageAdapter
|
|
|
79
77
|
* @param forceEnableSummarizeProtocolTree - Enforce uploading a protocol summary regardless of the service's policy
|
|
80
78
|
*/
|
|
81
79
|
public constructor(
|
|
80
|
+
// eslint-disable-next-line import/no-deprecated
|
|
82
81
|
detachedBlobStorage: IDetachedBlobStorage | undefined,
|
|
83
82
|
private readonly logger: ITelemetryLoggerExt,
|
|
84
83
|
/**
|
|
@@ -233,6 +232,7 @@ export class ContainerStorageAdapter
|
|
|
233
232
|
*/
|
|
234
233
|
class BlobOnlyStorage implements IDocumentStorageService {
|
|
235
234
|
constructor(
|
|
235
|
+
// eslint-disable-next-line import/no-deprecated
|
|
236
236
|
private readonly detachedStorage: IDetachedBlobStorage | undefined,
|
|
237
237
|
private readonly logger: ITelemetryLoggerExt,
|
|
238
238
|
) {}
|
|
@@ -245,6 +245,7 @@ class BlobOnlyStorage implements IDocumentStorageService {
|
|
|
245
245
|
return this.verifyStorage().readBlob(blobId);
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
+
// eslint-disable-next-line import/no-deprecated
|
|
248
249
|
private verifyStorage(): IDetachedBlobStorage {
|
|
249
250
|
if (this.detachedStorage === undefined) {
|
|
250
251
|
throw new UsageError("Real storage calls not allowed in Unattached container");
|
package/src/contracts.ts
CHANGED
|
@@ -12,16 +12,18 @@ import {
|
|
|
12
12
|
IConnectionDetails,
|
|
13
13
|
} from "@fluidframework/container-definitions/internal";
|
|
14
14
|
import { IErrorBase, ITelemetryBaseProperties } from "@fluidframework/core-interfaces";
|
|
15
|
-
import { IContainerPackageInfo } from "@fluidframework/driver-definitions/internal";
|
|
16
15
|
import {
|
|
17
16
|
ConnectionMode,
|
|
18
|
-
IClientConfiguration,
|
|
19
17
|
IClientDetails,
|
|
20
|
-
IDocumentMessage,
|
|
21
18
|
ISequencedDocumentMessage,
|
|
22
|
-
ISignalClient,
|
|
23
19
|
ISignalMessage,
|
|
24
|
-
} from "@fluidframework/
|
|
20
|
+
} from "@fluidframework/driver-definitions";
|
|
21
|
+
import {
|
|
22
|
+
IContainerPackageInfo,
|
|
23
|
+
IClientConfiguration,
|
|
24
|
+
IDocumentMessage,
|
|
25
|
+
ISignalClient,
|
|
26
|
+
} from "@fluidframework/driver-definitions/internal";
|
|
25
27
|
|
|
26
28
|
export enum ReconnectMode {
|
|
27
29
|
Never = "Never",
|
package/src/debugLogger.ts
CHANGED
|
@@ -16,13 +16,12 @@ import {
|
|
|
16
16
|
eventNamespaceSeparator,
|
|
17
17
|
formatTick,
|
|
18
18
|
} from "@fluidframework/telemetry-utils/internal";
|
|
19
|
-
|
|
20
19
|
// This import style is necessary to ensure the emitted JS code works in both CJS and ESM.
|
|
21
20
|
import debugPkg from "debug";
|
|
22
|
-
const { debug: registerDebug } = debugPkg;
|
|
23
|
-
|
|
24
21
|
import type { IDebugger } from "debug";
|
|
25
22
|
|
|
23
|
+
const { debug: registerDebug } = debugPkg;
|
|
24
|
+
|
|
26
25
|
/**
|
|
27
26
|
* Implementation of debug logger
|
|
28
27
|
*/
|
package/src/deltaManager.ts
CHANGED
|
@@ -16,23 +16,23 @@ import {
|
|
|
16
16
|
} from "@fluidframework/core-interfaces";
|
|
17
17
|
import { IThrottlingWarning } from "@fluidframework/core-interfaces/internal";
|
|
18
18
|
import { assert } from "@fluidframework/core-utils/internal";
|
|
19
|
+
import {
|
|
20
|
+
ConnectionMode,
|
|
21
|
+
ISequencedDocumentMessage,
|
|
22
|
+
ISignalMessage,
|
|
23
|
+
} from "@fluidframework/driver-definitions";
|
|
19
24
|
import {
|
|
20
25
|
IDocumentDeltaStorageService,
|
|
21
26
|
IDocumentService,
|
|
22
27
|
DriverErrorTypes,
|
|
28
|
+
IDocumentMessage,
|
|
29
|
+
MessageType,
|
|
23
30
|
} from "@fluidframework/driver-definitions/internal";
|
|
24
31
|
import {
|
|
25
32
|
MessageType2,
|
|
26
33
|
NonRetryableError,
|
|
27
34
|
isRuntimeMessage,
|
|
28
35
|
} from "@fluidframework/driver-utils/internal";
|
|
29
|
-
import {
|
|
30
|
-
ConnectionMode,
|
|
31
|
-
IDocumentMessage,
|
|
32
|
-
ISequencedDocumentMessage,
|
|
33
|
-
ISignalMessage,
|
|
34
|
-
MessageType,
|
|
35
|
-
} from "@fluidframework/protocol-definitions";
|
|
36
36
|
import {
|
|
37
37
|
type ITelemetryErrorEventExt,
|
|
38
38
|
type ITelemetryGenericEventExt,
|
package/src/loadPaused.ts
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
import { ILoader, LoaderHeader } from "@fluidframework/container-definitions/internal";
|
|
7
7
|
import { IRequest } from "@fluidframework/core-interfaces";
|
|
8
|
-
import { GenericError } from "@fluidframework/telemetry-utils/internal";
|
|
9
8
|
import type { IErrorBase } from "@fluidframework/core-interfaces";
|
|
9
|
+
import { GenericError } from "@fluidframework/telemetry-utils/internal";
|
|
10
10
|
|
|
11
11
|
/* eslint-disable jsdoc/check-indentation */
|
|
12
12
|
|
package/src/loader.ts
CHANGED
|
@@ -19,13 +19,13 @@ import {
|
|
|
19
19
|
IRequest,
|
|
20
20
|
ITelemetryBaseLogger,
|
|
21
21
|
} from "@fluidframework/core-interfaces";
|
|
22
|
+
import { IClientDetails } from "@fluidframework/driver-definitions";
|
|
22
23
|
import {
|
|
23
24
|
IDocumentServiceFactory,
|
|
24
25
|
IDocumentStorageService,
|
|
25
26
|
IResolvedUrl,
|
|
26
27
|
IUrlResolver,
|
|
27
28
|
} from "@fluidframework/driver-definitions/internal";
|
|
28
|
-
import { IClientDetails } from "@fluidframework/protocol-definitions";
|
|
29
29
|
import {
|
|
30
30
|
ITelemetryLoggerExt,
|
|
31
31
|
MonitoringContext,
|
|
@@ -227,6 +227,7 @@ export interface ILoaderServices {
|
|
|
227
227
|
|
|
228
228
|
/**
|
|
229
229
|
* Blobs storage for detached containers.
|
|
230
|
+
* @deprecated - IDetachedBlobStorage will be removed in a future release without a replacement. Blobs created while detached will be stored in memory to align with attached container behavior. AB#8049
|
|
230
231
|
*/
|
|
231
232
|
readonly detachedBlobStorage?: IDetachedBlobStorage;
|
|
232
233
|
|
|
@@ -241,6 +242,8 @@ export interface ILoaderServices {
|
|
|
241
242
|
* Subset of IDocumentStorageService which only supports createBlob() and readBlob(). This is used to support
|
|
242
243
|
* blobs in detached containers.
|
|
243
244
|
* @alpha
|
|
245
|
+
*
|
|
246
|
+
* @deprecated - IDetachedBlobStorage will be removed in a future release without a replacement. Blobs created while detached will be stored in memory to align with attached container behavior. AB#8049
|
|
244
247
|
*/
|
|
245
248
|
export type IDetachedBlobStorage = Pick<IDocumentStorageService, "createBlob" | "readBlob"> & {
|
|
246
249
|
size: number;
|
|
@@ -248,6 +251,11 @@ export type IDetachedBlobStorage = Pick<IDocumentStorageService, "createBlob" |
|
|
|
248
251
|
* Return an array of all blob IDs present in storage
|
|
249
252
|
*/
|
|
250
253
|
getBlobIds(): string[];
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* After the container is attached, the detached blob storage is no longer needed and will be disposed.
|
|
257
|
+
*/
|
|
258
|
+
dispose?(): void;
|
|
251
259
|
};
|
|
252
260
|
|
|
253
261
|
/**
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { bufferToString, stringToBuffer } from "@fluid-internal/client-utils";
|
|
7
|
+
import { assert, isObject } from "@fluidframework/core-utils/internal";
|
|
8
|
+
import type { ICreateBlobResponse } from "@fluidframework/driver-definitions/internal";
|
|
9
|
+
|
|
10
|
+
// eslint-disable-next-line import/no-deprecated
|
|
11
|
+
import type { IDetachedBlobStorage } from "./loader.js";
|
|
12
|
+
|
|
13
|
+
const MemoryDetachedBlobStorageIdentifier = Symbol();
|
|
14
|
+
|
|
15
|
+
// eslint-disable-next-line import/no-deprecated
|
|
16
|
+
interface MemoryDetachedBlobStorage extends IDetachedBlobStorage {
|
|
17
|
+
[MemoryDetachedBlobStorageIdentifier]: typeof MemoryDetachedBlobStorageIdentifier;
|
|
18
|
+
initialize(attachmentBlobs: string[]): void;
|
|
19
|
+
serialize(): string | undefined;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function isMemoryDetachedBlobStorage(
|
|
23
|
+
// eslint-disable-next-line import/no-deprecated
|
|
24
|
+
detachedStorage: IDetachedBlobStorage,
|
|
25
|
+
): detachedStorage is MemoryDetachedBlobStorage {
|
|
26
|
+
return (
|
|
27
|
+
isObject(detachedStorage) &&
|
|
28
|
+
MemoryDetachedBlobStorageIdentifier in detachedStorage &&
|
|
29
|
+
detachedStorage[MemoryDetachedBlobStorageIdentifier] === MemoryDetachedBlobStorageIdentifier
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function serializeMemoryDetachedBlobStorage(
|
|
34
|
+
// eslint-disable-next-line import/no-deprecated
|
|
35
|
+
detachedStorage: IDetachedBlobStorage,
|
|
36
|
+
): string | undefined {
|
|
37
|
+
if (detachedStorage.size > 0 && isMemoryDetachedBlobStorage(detachedStorage)) {
|
|
38
|
+
return detachedStorage.serialize();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function tryInitializeMemoryDetachedBlobStorage(
|
|
43
|
+
// eslint-disable-next-line import/no-deprecated
|
|
44
|
+
detachedStorage: IDetachedBlobStorage,
|
|
45
|
+
attachmentBlobs: string,
|
|
46
|
+
) {
|
|
47
|
+
if (!isMemoryDetachedBlobStorage(detachedStorage)) {
|
|
48
|
+
throw new Error(
|
|
49
|
+
"DetachedBlobStorage was not provided to the loader during serialize so cannot be provided during rehydrate.",
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
assert(detachedStorage.size === 0, "Blob storage already initialized");
|
|
54
|
+
const maybeAttachmentBlobs = JSON.parse(attachmentBlobs);
|
|
55
|
+
assert(Array.isArray(maybeAttachmentBlobs), "Invalid attachmentBlobs");
|
|
56
|
+
|
|
57
|
+
detachedStorage.initialize(maybeAttachmentBlobs);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// eslint-disable-next-line import/no-deprecated
|
|
61
|
+
export function createMemoryDetachedBlobStorage(): IDetachedBlobStorage {
|
|
62
|
+
const blobs: ArrayBufferLike[] = [];
|
|
63
|
+
const storage: MemoryDetachedBlobStorage = {
|
|
64
|
+
[MemoryDetachedBlobStorageIdentifier]: MemoryDetachedBlobStorageIdentifier,
|
|
65
|
+
createBlob: async (file: ArrayBufferLike): Promise<ICreateBlobResponse> => ({
|
|
66
|
+
id: `${blobs.push(file) - 1}`,
|
|
67
|
+
}),
|
|
68
|
+
readBlob: async (id: string): Promise<ArrayBufferLike> =>
|
|
69
|
+
blobs[Number(id)] ?? Promise.reject(new Error(`Blob not found: ${id}`)),
|
|
70
|
+
get size() {
|
|
71
|
+
return blobs.length;
|
|
72
|
+
},
|
|
73
|
+
getBlobIds: (): string[] => blobs.map((_, i) => `${i}`),
|
|
74
|
+
dispose: () => blobs.splice(0),
|
|
75
|
+
serialize: () => JSON.stringify(blobs.map((b) => bufferToString(b, "utf-8"))),
|
|
76
|
+
initialize: (attachmentBlobs: string[]) =>
|
|
77
|
+
blobs.push(...attachmentBlobs.map((maybeBlob) => stringToBuffer(maybeBlob, "utf-8"))),
|
|
78
|
+
};
|
|
79
|
+
return storage;
|
|
80
|
+
}
|
package/src/noopHeuristic.ts
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
import { TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
7
7
|
import { IEvent } from "@fluidframework/core-interfaces";
|
|
8
8
|
import { assert, Timer } from "@fluidframework/core-utils/internal";
|
|
9
|
+
import { ISequencedDocumentMessage } from "@fluidframework/driver-definitions";
|
|
9
10
|
import { isRuntimeMessage } from "@fluidframework/driver-utils/internal";
|
|
10
|
-
import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
|
|
11
11
|
|
|
12
12
|
const defaultNoopTimeFrequency = 2000;
|
|
13
13
|
const defaultNoopCountFrequency = 50;
|
package/src/packageVersion.ts
CHANGED
package/src/protocol.ts
CHANGED
|
@@ -4,20 +4,19 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { IAudienceOwner } from "@fluidframework/container-definitions/internal";
|
|
7
|
+
import { ISequencedDocumentMessage, ISignalMessage } from "@fluidframework/driver-definitions";
|
|
8
|
+
import {
|
|
9
|
+
IDocumentAttributes,
|
|
10
|
+
IProcessMessageResult,
|
|
11
|
+
ISignalClient,
|
|
12
|
+
MessageType,
|
|
13
|
+
} from "@fluidframework/driver-definitions/internal";
|
|
7
14
|
import { canBeCoalescedByService } from "@fluidframework/driver-utils/internal";
|
|
8
15
|
import {
|
|
9
16
|
IProtocolHandler as IBaseProtocolHandler,
|
|
10
17
|
IQuorumSnapshot,
|
|
11
18
|
ProtocolOpHandler,
|
|
12
19
|
} from "@fluidframework/protocol-base";
|
|
13
|
-
import {
|
|
14
|
-
IDocumentAttributes,
|
|
15
|
-
IProcessMessageResult,
|
|
16
|
-
ISequencedDocumentMessage,
|
|
17
|
-
ISignalClient,
|
|
18
|
-
ISignalMessage,
|
|
19
|
-
MessageType,
|
|
20
|
-
} from "@fluidframework/protocol-definitions";
|
|
21
20
|
|
|
22
21
|
// ADO: #1986: Start using enum from protocol-base.
|
|
23
22
|
export enum SignalType {
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { IDisposable } from "@fluidframework/core-interfaces";
|
|
7
|
+
import { ISummaryTree } from "@fluidframework/driver-definitions";
|
|
7
8
|
import {
|
|
8
9
|
IDocumentStorageService,
|
|
9
10
|
ISummaryContext,
|
|
10
11
|
} from "@fluidframework/driver-definitions/internal";
|
|
11
|
-
import { ISummaryTree } from "@fluidframework/protocol-definitions";
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* A storage service wrapper whose sole job is to intercept calls to uploadSummaryWithContext and ensure they include
|
package/src/quorum.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { IFluidCodeDetails } from "@fluidframework/container-definitions/internal";
|
|
7
|
-
import { ICommittedProposal } from "@fluidframework/
|
|
7
|
+
import { ICommittedProposal } from "@fluidframework/driver-definitions/internal";
|
|
8
8
|
|
|
9
9
|
export function initQuorumValuesFromCodeDetails(
|
|
10
10
|
source: IFluidCodeDetails,
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { IDisposable } from "@fluidframework/core-interfaces";
|
|
7
7
|
import { assert } from "@fluidframework/core-utils/internal";
|
|
8
|
+
import { ISummaryHandle, ISummaryTree } from "@fluidframework/driver-definitions";
|
|
8
9
|
import {
|
|
9
10
|
FetchSource,
|
|
10
11
|
IDocumentStorageService,
|
|
@@ -12,15 +13,11 @@ import {
|
|
|
12
13
|
ISnapshot,
|
|
13
14
|
ISnapshotFetchOptions,
|
|
14
15
|
ISummaryContext,
|
|
15
|
-
} from "@fluidframework/driver-definitions/internal";
|
|
16
|
-
import { runWithRetry } from "@fluidframework/driver-utils/internal";
|
|
17
|
-
import {
|
|
18
16
|
ICreateBlobResponse,
|
|
19
17
|
ISnapshotTree,
|
|
20
|
-
ISummaryHandle,
|
|
21
|
-
ISummaryTree,
|
|
22
18
|
IVersion,
|
|
23
|
-
} from "@fluidframework/
|
|
19
|
+
} from "@fluidframework/driver-definitions/internal";
|
|
20
|
+
import { runWithRetry } from "@fluidframework/driver-utils/internal";
|
|
24
21
|
import {
|
|
25
22
|
ITelemetryLoggerExt,
|
|
26
23
|
GenericError,
|
|
@@ -3,32 +3,31 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { stringToBuffer } from "@fluid-internal/client-utils";
|
|
6
7
|
import {
|
|
7
8
|
IGetPendingLocalStateProps,
|
|
8
9
|
IRuntime,
|
|
9
10
|
} from "@fluidframework/container-definitions/internal";
|
|
10
|
-
import {
|
|
11
|
+
import type { IEventProvider, IEvent, ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
|
|
11
12
|
import { assert } from "@fluidframework/core-utils/internal";
|
|
13
|
+
import { ISequencedDocumentMessage } from "@fluidframework/driver-definitions";
|
|
12
14
|
import {
|
|
13
15
|
FetchSource,
|
|
14
16
|
IDocumentStorageService,
|
|
15
17
|
IResolvedUrl,
|
|
16
18
|
ISnapshot,
|
|
17
|
-
} from "@fluidframework/driver-definitions/internal";
|
|
18
|
-
import { getSnapshotTree } from "@fluidframework/driver-utils/internal";
|
|
19
|
-
import {
|
|
20
19
|
type IDocumentAttributes,
|
|
21
|
-
ISequencedDocumentMessage,
|
|
22
20
|
ISnapshotTree,
|
|
23
21
|
IVersion,
|
|
24
|
-
} from "@fluidframework/
|
|
22
|
+
} from "@fluidframework/driver-definitions/internal";
|
|
23
|
+
import { getSnapshotTree } from "@fluidframework/driver-utils/internal";
|
|
25
24
|
import {
|
|
26
25
|
MonitoringContext,
|
|
27
26
|
PerformanceEvent,
|
|
28
27
|
UsageError,
|
|
29
28
|
createChildMonitoringContext,
|
|
30
29
|
} from "@fluidframework/telemetry-utils/internal";
|
|
31
|
-
|
|
30
|
+
|
|
32
31
|
import { ISerializableBlobContents, getBlobContentsFromTree } from "./containerStorageAdapter.js";
|
|
33
32
|
import { convertSnapshotToSnapshotInfo, getDocumentAttributes } from "./utils.js";
|
|
34
33
|
|
|
@@ -93,6 +92,8 @@ export interface IPendingDetachedContainerState extends SnapshotWithBlobs {
|
|
|
93
92
|
attached: false;
|
|
94
93
|
/** Indicates whether we expect the rehydrated container to have non-empty Detached Blob Storage */
|
|
95
94
|
hasAttachmentBlobs: boolean;
|
|
95
|
+
/** Used by the memory blob storage to persisted attachment blobs */
|
|
96
|
+
attachmentBlobs?: string;
|
|
96
97
|
/**
|
|
97
98
|
* Runtime-specific state that will be needed to properly rehydrate
|
|
98
99
|
* (it's included in ContainerContext passed to instantiateRuntime)
|
package/src/utils.ts
CHANGED
|
@@ -5,7 +5,12 @@
|
|
|
5
5
|
|
|
6
6
|
import { Uint8ArrayToString, bufferToString, stringToBuffer } from "@fluid-internal/client-utils";
|
|
7
7
|
import { assert, compareArrays, unreachableCase } from "@fluidframework/core-utils/internal";
|
|
8
|
-
import {
|
|
8
|
+
import { ISummaryTree, SummaryType } from "@fluidframework/driver-definitions";
|
|
9
|
+
import {
|
|
10
|
+
DriverErrorTypes,
|
|
11
|
+
IDocumentAttributes,
|
|
12
|
+
ISnapshotTree,
|
|
13
|
+
} from "@fluidframework/driver-definitions/internal";
|
|
9
14
|
import {
|
|
10
15
|
IDocumentStorageService,
|
|
11
16
|
type ISnapshot,
|
|
@@ -16,12 +21,6 @@ import {
|
|
|
16
21
|
isCombinedAppAndProtocolSummary,
|
|
17
22
|
readAndParse,
|
|
18
23
|
} from "@fluidframework/driver-utils/internal";
|
|
19
|
-
import {
|
|
20
|
-
IDocumentAttributes,
|
|
21
|
-
ISnapshotTree,
|
|
22
|
-
ISummaryTree,
|
|
23
|
-
SummaryType,
|
|
24
|
-
} from "@fluidframework/protocol-definitions";
|
|
25
24
|
import { LoggingError, UsageError } from "@fluidframework/telemetry-utils/internal";
|
|
26
25
|
import { v4 as uuid } from "uuid";
|
|
27
26
|
|