@fluidframework/container-loader 2.0.0-dev-rc.5.0.0.263932 → 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 +3 -2
- 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 +4 -3
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +7 -8
- 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 +25 -15
- 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 +86 -69
- 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 +6 -5
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +15 -16
- package/dist/deltaManager.js.map +1 -1
- package/dist/deltaQueue.js.map +1 -1
- package/dist/disposal.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/location-redirection-utilities/resolveWithLocationRedirection.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 +4 -3
- 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 +6 -2
- 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 +3 -2
- 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 +4 -3
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +5 -6
- 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 +26 -16
- 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 +28 -11
- 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 +6 -5
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +8 -9
- package/lib/deltaManager.js.map +1 -1
- package/lib/deltaQueue.js.map +1 -1
- package/lib/disposal.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/location-redirection-utilities/resolveWithLocationRedirection.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 +4 -3
- 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 +6 -2
- 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 +16 -26
- package/src/attachment.ts +3 -1
- package/src/audience.ts +3 -6
- package/src/catchUpMonitor.ts +1 -1
- package/src/connectionManager.ts +18 -21
- package/src/connectionStateHandler.ts +35 -23
- 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 +8 -8
- 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 +14 -9
- package/src/utils.ts +6 -7
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
import { IDeltaManager } from "@fluidframework/container-definitions/internal";
|
|
7
7
|
import { ITelemetryBaseProperties } from "@fluidframework/core-interfaces";
|
|
8
8
|
import { assert, Timer } from "@fluidframework/core-utils/internal";
|
|
9
|
+
import { IClient, ISequencedClient } from "@fluidframework/driver-definitions";
|
|
9
10
|
import { IAnyDriverError } from "@fluidframework/driver-definitions/internal";
|
|
10
|
-
import { IClient, ISequencedClient } from "@fluidframework/protocol-definitions";
|
|
11
11
|
import {
|
|
12
12
|
type TelemetryEventCategory,
|
|
13
13
|
ITelemetryLoggerExt,
|
|
14
|
+
MonitoringContext,
|
|
14
15
|
PerformanceEvent,
|
|
15
|
-
loggerToMonitoringContext,
|
|
16
16
|
} from "@fluidframework/telemetry-utils/internal";
|
|
17
17
|
|
|
18
18
|
import { CatchUpMonitor, ICatchUpMonitor } from "./catchUpMonitor.js";
|
|
@@ -31,6 +31,7 @@ const JoinSignalTimeoutMs = 10000;
|
|
|
31
31
|
/** Constructor parameter type for passing in dependencies needed by the ConnectionStateHandler */
|
|
32
32
|
export interface IConnectionStateHandlerInputs {
|
|
33
33
|
logger: ITelemetryLoggerExt;
|
|
34
|
+
mc: MonitoringContext;
|
|
34
35
|
/** Log to telemetry any change in state, included to Connecting */
|
|
35
36
|
connectionStateChanged: (
|
|
36
37
|
value: ConnectionState,
|
|
@@ -92,10 +93,10 @@ export function createConnectionStateHandler(
|
|
|
92
93
|
deltaManager: IDeltaManager<any, any>,
|
|
93
94
|
clientId?: string,
|
|
94
95
|
) {
|
|
95
|
-
const
|
|
96
|
+
const config = inputs.mc.config;
|
|
96
97
|
return createConnectionStateHandlerCore(
|
|
97
|
-
|
|
98
|
-
|
|
98
|
+
config.getBoolean("Fluid.Container.DisableCatchUpBeforeDeclaringConnected") !== true, // connectedRaisedWhenCaughtUp
|
|
99
|
+
config.getBoolean("Fluid.Container.DisableJoinSignalWait") !== true, // readClientsWaitForJoinSignal
|
|
99
100
|
inputs,
|
|
100
101
|
deltaManager,
|
|
101
102
|
clientId,
|
|
@@ -189,6 +190,9 @@ class ConnectionStateHandlerPassThrough
|
|
|
189
190
|
public get logger() {
|
|
190
191
|
return this.inputs.logger;
|
|
191
192
|
}
|
|
193
|
+
public get mc() {
|
|
194
|
+
return this.inputs.mc;
|
|
195
|
+
}
|
|
192
196
|
public connectionStateChanged(
|
|
193
197
|
value: ConnectionState,
|
|
194
198
|
oldState: ConnectionState,
|
|
@@ -469,18 +473,6 @@ class ConnectionStateHandler implements IConnectionStateHandler {
|
|
|
469
473
|
});
|
|
470
474
|
}
|
|
471
475
|
this.applyForConnectedState("addMemberEvent");
|
|
472
|
-
} else if (clientId === this.clientId) {
|
|
473
|
-
// If we see our clientId and it's not also our pending ID, it's our own join op
|
|
474
|
-
// being replayed, so start the timer in case our previous client is still in quorum
|
|
475
|
-
assert(
|
|
476
|
-
!this.waitingForLeaveOp,
|
|
477
|
-
0x5d2 /* Unexpected join op with current clientId while waiting */,
|
|
478
|
-
);
|
|
479
|
-
assert(
|
|
480
|
-
this.connectionState !== ConnectionState.Connected,
|
|
481
|
-
0x5d3 /* Unexpected join op with current clientId while connected */,
|
|
482
|
-
);
|
|
483
|
-
this.prevClientLeftTimer.restart();
|
|
484
476
|
}
|
|
485
477
|
}
|
|
486
478
|
|
|
@@ -528,7 +520,7 @@ class ConnectionStateHandler implements IConnectionStateHandler {
|
|
|
528
520
|
|
|
529
521
|
private receivedRemoveMemberEvent(clientId: string) {
|
|
530
522
|
// If the client which has left was us, then finish the timer.
|
|
531
|
-
if (this.clientId === clientId) {
|
|
523
|
+
if (this.clientId === clientId && this.waitingForLeaveOp) {
|
|
532
524
|
this.prevClientLeftTimer.clear();
|
|
533
525
|
this.applyForConnectedState("removeMemberEvent");
|
|
534
526
|
}
|
|
@@ -660,9 +652,6 @@ class ConnectionStateHandler implements IConnectionStateHandler {
|
|
|
660
652
|
}
|
|
661
653
|
this._clientId = this.pendingClientId;
|
|
662
654
|
} else if (value === ConnectionState.Disconnected) {
|
|
663
|
-
// Clear pending state immediately to prepare for reconnect
|
|
664
|
-
this._pendingClientId = undefined;
|
|
665
|
-
|
|
666
655
|
if (this.joinTimer.hasTimer) {
|
|
667
656
|
this.stopjoinTimer();
|
|
668
657
|
}
|
|
@@ -691,8 +680,15 @@ class ConnectionStateHandler implements IConnectionStateHandler {
|
|
|
691
680
|
}
|
|
692
681
|
}
|
|
693
682
|
|
|
694
|
-
// Report transition
|
|
683
|
+
// Report transition
|
|
695
684
|
this.handler.connectionStateChanged(this._connectionState, oldState, reason);
|
|
685
|
+
|
|
686
|
+
// Clear pending state immediately to prepare for reconnect
|
|
687
|
+
// Do it after calling connectionStateChanged() above, such that our telemetry contains pendingClientId on disconnect events
|
|
688
|
+
// and we can pair attempts to connect with disconnects (that's the only ID we have if connection did not move far enough before being disconnected)
|
|
689
|
+
if (value === ConnectionState.Disconnected) {
|
|
690
|
+
this._pendingClientId = undefined;
|
|
691
|
+
}
|
|
696
692
|
}
|
|
697
693
|
|
|
698
694
|
protected get membership(): IMembership | undefined {
|
|
@@ -737,8 +733,24 @@ class ConnectionStateHandler implements IConnectionStateHandler {
|
|
|
737
733
|
this.receivedAddMemberEvent(this.pendingClientId!);
|
|
738
734
|
}
|
|
739
735
|
|
|
736
|
+
assert(
|
|
737
|
+
!this.waitingForLeaveOp,
|
|
738
|
+
"leave timer can't be set as we have not had access to quorum",
|
|
739
|
+
);
|
|
740
|
+
|
|
741
|
+
// This check is required for scenario of loading container from pending state, and ensuring there is no way
|
|
742
|
+
// old clientId is still in the quorum (very unlikely, but you never know)
|
|
740
743
|
// if we have a clientId from a previous container we need to wait for its leave message
|
|
741
|
-
|
|
744
|
+
// This mimicks check in setConnectionState()
|
|
745
|
+
// Note that we are not consulting this.handler.shouldClientJoinWrite() here
|
|
746
|
+
// It could produce wrong results for stashed ops were never sent to Loader yet, and if this check
|
|
747
|
+
// makes determination only on that (and not uses "dirty" events), then it can produce wrong result.
|
|
748
|
+
// In most cases it does not matter, as this client already left quorum. But in really unfortunate case,
|
|
749
|
+
// we might wait even if we could avoid such wait.
|
|
750
|
+
if (
|
|
751
|
+
this._clientId !== undefined &&
|
|
752
|
+
protocol.quorum?.getMember(this._clientId) !== undefined
|
|
753
|
+
) {
|
|
742
754
|
this.prevClientLeftTimer.restart();
|
|
743
755
|
}
|
|
744
756
|
}
|
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
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { ICriticalContainerError } from "@fluidframework/container-definitions";
|
|
6
7
|
import {
|
|
7
|
-
ICriticalContainerError,
|
|
8
8
|
IDeltaManager,
|
|
9
9
|
IDeltaManagerEvents,
|
|
10
10
|
IDeltaQueue,
|
|
@@ -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,
|