@fluidframework/container-loader 2.0.0-dev.5.2.0.169897 → 2.0.0-dev.6.4.0.191258
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 +162 -0
- package/README.md +10 -6
- package/dist/audience.d.ts +1 -0
- package/dist/audience.d.ts.map +1 -1
- package/dist/audience.js +5 -3
- package/dist/audience.js.map +1 -1
- package/dist/catchUpMonitor.d.ts +1 -1
- package/dist/catchUpMonitor.d.ts.map +1 -1
- package/dist/catchUpMonitor.js +2 -2
- package/dist/catchUpMonitor.js.map +1 -1
- package/dist/connectionManager.d.ts +6 -6
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +97 -93
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionStateHandler.d.ts +19 -15
- package/dist/connectionStateHandler.d.ts.map +1 -1
- package/dist/connectionStateHandler.js +59 -59
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container.d.ts +48 -38
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +447 -325
- package/dist/container.js.map +1 -1
- package/dist/containerContext.d.ts +22 -70
- package/dist/containerContext.d.ts.map +1 -1
- package/dist/containerContext.js +24 -221
- package/dist/containerContext.js.map +1 -1
- package/dist/containerStorageAdapter.d.ts +1 -1
- package/dist/containerStorageAdapter.d.ts.map +1 -1
- package/dist/containerStorageAdapter.js +47 -16
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/contracts.d.ts +21 -10
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +3 -3
- package/dist/contracts.js.map +1 -1
- package/dist/debugLogger.d.ts +30 -0
- package/dist/debugLogger.d.ts.map +1 -0
- package/dist/debugLogger.js +95 -0
- package/dist/debugLogger.js.map +1 -0
- package/dist/deltaManager.d.ts +21 -9
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +114 -66
- package/dist/deltaManager.js.map +1 -1
- package/dist/deltaQueue.d.ts +1 -1
- package/dist/deltaQueue.d.ts.map +1 -1
- package/dist/deltaQueue.js +10 -10
- package/dist/deltaQueue.js.map +1 -1
- package/dist/disposal.d.ts +13 -0
- package/dist/disposal.d.ts.map +1 -0
- package/dist/disposal.js +25 -0
- package/dist/disposal.js.map +1 -0
- package/dist/error.d.ts +23 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +32 -0
- package/dist/error.js.map +1 -0
- package/dist/loader.d.ts +23 -5
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +82 -51
- package/dist/loader.js.map +1 -1
- package/dist/noopHeuristic.d.ts +23 -0
- package/dist/noopHeuristic.d.ts.map +1 -0
- package/dist/noopHeuristic.js +90 -0
- package/dist/noopHeuristic.js.map +1 -0
- 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 +9 -12
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +26 -7
- package/dist/protocol.js.map +1 -1
- package/dist/protocolTreeDocumentStorageService.d.ts +1 -1
- package/dist/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/dist/protocolTreeDocumentStorageService.js.map +1 -1
- package/dist/quorum.d.ts +1 -14
- package/dist/quorum.d.ts.map +1 -1
- package/dist/quorum.js +1 -29
- package/dist/quorum.js.map +1 -1
- package/dist/retriableDocumentStorageService.d.ts +1 -1
- package/dist/retriableDocumentStorageService.d.ts.map +1 -1
- package/dist/retriableDocumentStorageService.js +4 -4
- package/dist/retriableDocumentStorageService.js.map +1 -1
- package/dist/utils.d.ts +8 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +30 -11
- package/dist/utils.js.map +1 -1
- package/lib/audience.d.ts +1 -0
- package/lib/audience.d.ts.map +1 -1
- package/lib/audience.js +4 -2
- package/lib/audience.js.map +1 -1
- package/lib/catchUpMonitor.d.ts +1 -1
- package/lib/catchUpMonitor.d.ts.map +1 -1
- package/lib/catchUpMonitor.js +1 -1
- package/lib/catchUpMonitor.js.map +1 -1
- package/lib/connectionManager.d.ts +6 -6
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +74 -67
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionStateHandler.d.ts +19 -15
- package/lib/connectionStateHandler.d.ts.map +1 -1
- package/lib/connectionStateHandler.js +36 -36
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts +48 -38
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +414 -292
- package/lib/container.js.map +1 -1
- package/lib/containerContext.d.ts +22 -70
- package/lib/containerContext.d.ts.map +1 -1
- package/lib/containerContext.js +24 -221
- package/lib/containerContext.js.map +1 -1
- package/lib/containerStorageAdapter.d.ts +1 -1
- package/lib/containerStorageAdapter.d.ts.map +1 -1
- package/lib/containerStorageAdapter.js +43 -12
- package/lib/containerStorageAdapter.js.map +1 -1
- package/lib/contracts.d.ts +21 -10
- package/lib/contracts.d.ts.map +1 -1
- package/lib/contracts.js +3 -3
- package/lib/contracts.js.map +1 -1
- package/lib/debugLogger.d.ts +30 -0
- package/lib/debugLogger.d.ts.map +1 -0
- package/lib/debugLogger.js +91 -0
- package/lib/debugLogger.js.map +1 -0
- package/lib/deltaManager.d.ts +21 -9
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +88 -37
- package/lib/deltaManager.js.map +1 -1
- package/lib/deltaQueue.d.ts +1 -1
- package/lib/deltaQueue.d.ts.map +1 -1
- package/lib/deltaQueue.js +3 -3
- package/lib/deltaQueue.js.map +1 -1
- package/lib/disposal.d.ts +13 -0
- package/lib/disposal.d.ts.map +1 -0
- package/lib/disposal.js +21 -0
- package/lib/disposal.js.map +1 -0
- package/lib/error.d.ts +23 -0
- package/lib/error.d.ts.map +1 -0
- package/lib/error.js +28 -0
- package/lib/error.js.map +1 -0
- package/lib/loader.d.ts +23 -5
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js +82 -51
- package/lib/loader.js.map +1 -1
- package/lib/noopHeuristic.d.ts +23 -0
- package/lib/noopHeuristic.d.ts.map +1 -0
- package/lib/{collabWindowTracker.js → noopHeuristic.js} +31 -42
- package/lib/noopHeuristic.js.map +1 -0
- 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 +9 -12
- package/lib/protocol.d.ts.map +1 -1
- package/lib/protocol.js +24 -6
- package/lib/protocol.js.map +1 -1
- package/lib/protocolTreeDocumentStorageService.d.ts +1 -1
- package/lib/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/lib/protocolTreeDocumentStorageService.js.map +1 -1
- package/lib/quorum.d.ts +1 -14
- package/lib/quorum.d.ts.map +1 -1
- package/lib/quorum.js +0 -26
- package/lib/quorum.js.map +1 -1
- package/lib/retriableDocumentStorageService.d.ts +1 -1
- package/lib/retriableDocumentStorageService.d.ts.map +1 -1
- package/lib/retriableDocumentStorageService.js +2 -2
- package/lib/retriableDocumentStorageService.js.map +1 -1
- package/lib/utils.d.ts +8 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +25 -7
- package/lib/utils.js.map +1 -1
- package/package.json +26 -28
- package/src/audience.ts +7 -1
- package/src/catchUpMonitor.ts +2 -2
- package/src/connectionManager.ts +76 -52
- package/src/connectionStateHandler.ts +46 -48
- package/src/container.ts +561 -326
- package/src/containerContext.ts +31 -349
- package/src/containerStorageAdapter.ts +49 -6
- package/src/contracts.ts +27 -13
- package/src/debugLogger.ts +113 -0
- package/src/deltaManager.ts +93 -36
- package/src/deltaQueue.ts +2 -1
- package/src/disposal.ts +25 -0
- package/src/error.ts +44 -0
- package/src/loader.ts +84 -36
- package/src/{collabWindowTracker.ts → noopHeuristic.ts} +38 -47
- package/src/packageVersion.ts +1 -1
- package/src/protocol.ts +26 -16
- package/src/protocolTreeDocumentStorageService.ts +1 -1
- package/src/quorum.ts +1 -40
- package/src/retriableDocumentStorageService.ts +3 -4
- package/src/utils.ts +33 -8
- package/dist/collabWindowTracker.d.ts +0 -19
- package/dist/collabWindowTracker.d.ts.map +0 -1
- package/dist/collabWindowTracker.js +0 -101
- package/dist/collabWindowTracker.js.map +0 -1
- package/dist/deltaManagerProxy.d.ts +0 -42
- package/dist/deltaManagerProxy.d.ts.map +0 -1
- package/dist/deltaManagerProxy.js +0 -79
- package/dist/deltaManagerProxy.js.map +0 -1
- package/lib/collabWindowTracker.d.ts +0 -19
- package/lib/collabWindowTracker.d.ts.map +0 -1
- package/lib/collabWindowTracker.js.map +0 -1
- package/lib/deltaManagerProxy.d.ts +0 -42
- package/lib/deltaManagerProxy.d.ts.map +0 -1
- package/lib/deltaManagerProxy.js +0 -74
- package/lib/deltaManagerProxy.js.map +0 -1
- package/src/deltaManagerProxy.ts +0 -109
package/src/containerContext.ts
CHANGED
|
@@ -3,220 +3,72 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { ITelemetryLoggerExt
|
|
7
|
-
import { assert, LazyPromise, TypedEventEmitter } from "@fluidframework/common-utils";
|
|
6
|
+
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
|
|
8
7
|
import {
|
|
9
8
|
IAudience,
|
|
10
9
|
IContainerContext,
|
|
11
10
|
IDeltaManager,
|
|
12
11
|
ILoader,
|
|
13
|
-
IRuntime,
|
|
14
12
|
ICriticalContainerError,
|
|
15
13
|
AttachState,
|
|
16
14
|
ILoaderOptions,
|
|
17
|
-
IRuntimeFactory,
|
|
18
|
-
IProvideRuntimeFactory,
|
|
19
15
|
IFluidCodeDetails,
|
|
20
|
-
IFluidCodeDetailsComparer,
|
|
21
|
-
IProvideFluidCodeDetailsComparer,
|
|
22
|
-
ICodeDetailsLoader,
|
|
23
|
-
IFluidModuleWithDetails,
|
|
24
16
|
IBatchMessage,
|
|
25
17
|
} from "@fluidframework/container-definitions";
|
|
26
|
-
import {
|
|
18
|
+
import { FluidObject } from "@fluidframework/core-interfaces";
|
|
27
19
|
import { IDocumentStorageService } from "@fluidframework/driver-definitions";
|
|
28
20
|
import {
|
|
29
|
-
IClientConfiguration,
|
|
30
21
|
IClientDetails,
|
|
31
22
|
IDocumentMessage,
|
|
32
|
-
IQuorum,
|
|
33
23
|
IQuorumClients,
|
|
34
24
|
ISequencedDocumentMessage,
|
|
35
|
-
ISignalMessage,
|
|
36
25
|
ISnapshotTree,
|
|
37
|
-
ISummaryTree,
|
|
38
26
|
IVersion,
|
|
39
27
|
MessageType,
|
|
40
28
|
ISummaryContent,
|
|
41
29
|
} from "@fluidframework/protocol-definitions";
|
|
42
|
-
import { UsageError } from "@fluidframework/container-utils";
|
|
43
|
-
import { Container } from "./container";
|
|
44
|
-
|
|
45
|
-
const PackageNotFactoryError = "Code package does not implement IRuntimeFactory";
|
|
46
30
|
|
|
47
31
|
/**
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* "runtimeInstantiated" - When an {@link @fluidframework/container-definitions#IRuntime} has been instantiated (by
|
|
51
|
-
* calling instantiateRuntime() on the runtime factory), and this._runtime is set.
|
|
52
|
-
*
|
|
53
|
-
* "disposed" - When its dispose() method is called. The {@link ContainerContext} is no longer usable at that point.
|
|
32
|
+
* {@inheritDoc @fluidframework/container-definitions#IContainerContext}
|
|
54
33
|
*/
|
|
55
|
-
type ContextLifecycleEvents = "runtimeInstantiated" | "disposed";
|
|
56
|
-
|
|
57
34
|
export class ContainerContext implements IContainerContext {
|
|
58
|
-
public
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
loader: ILoader,
|
|
67
|
-
submitFn: (type: MessageType, contents: any, batch: boolean, appData: any) => number,
|
|
68
|
-
submitSummaryFn: (summaryOp: ISummaryContent, referenceSequenceNumber?: number) => number,
|
|
69
|
-
submitBatchFn: (batch: IBatchMessage[], referenceSequenceNumber?: number) => number,
|
|
70
|
-
submitSignalFn: (contents: any) => void,
|
|
71
|
-
disposeFn: (error?: ICriticalContainerError) => void,
|
|
72
|
-
closeFn: (error?: ICriticalContainerError) => void,
|
|
73
|
-
version: string,
|
|
74
|
-
updateDirtyContainerState: (dirty: boolean) => void,
|
|
75
|
-
existing: boolean,
|
|
76
|
-
pendingLocalState?: unknown,
|
|
77
|
-
): Promise<ContainerContext> {
|
|
78
|
-
const context = new ContainerContext(
|
|
79
|
-
container,
|
|
80
|
-
scope,
|
|
81
|
-
codeLoader,
|
|
82
|
-
codeDetails,
|
|
83
|
-
baseSnapshot,
|
|
84
|
-
deltaManager,
|
|
85
|
-
quorum,
|
|
86
|
-
loader,
|
|
87
|
-
submitFn,
|
|
88
|
-
submitSummaryFn,
|
|
89
|
-
submitBatchFn,
|
|
90
|
-
submitSignalFn,
|
|
91
|
-
disposeFn,
|
|
92
|
-
closeFn,
|
|
93
|
-
version,
|
|
94
|
-
updateDirtyContainerState,
|
|
95
|
-
existing,
|
|
96
|
-
pendingLocalState,
|
|
97
|
-
);
|
|
98
|
-
await context.instantiateRuntime(existing);
|
|
99
|
-
return context;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
public readonly taggedLogger: ITelemetryLoggerExt;
|
|
103
|
-
public readonly supportedFeatures: ReadonlyMap<string, unknown>;
|
|
35
|
+
public readonly supportedFeatures: ReadonlyMap<string, unknown> = new Map([
|
|
36
|
+
/**
|
|
37
|
+
* This version of the loader accepts `referenceSequenceNumber`, provided by the container runtime,
|
|
38
|
+
* as a parameter to the `submitBatchFn` and `submitSummaryFn` functions.
|
|
39
|
+
* This is then used to set the reference sequence numbers of the submitted ops in the DeltaManager.
|
|
40
|
+
*/
|
|
41
|
+
["referenceSequenceNumbers", true],
|
|
42
|
+
]);
|
|
104
43
|
|
|
105
44
|
public get clientId(): string | undefined {
|
|
106
|
-
return this.
|
|
45
|
+
return this._getClientId();
|
|
107
46
|
}
|
|
108
47
|
|
|
109
48
|
/**
|
|
110
49
|
* DISCLAIMER: this id is only for telemetry purposes. Not suitable for any other usages.
|
|
111
50
|
*/
|
|
112
51
|
public get id(): string {
|
|
113
|
-
return this.
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
public get clientDetails(): IClientDetails {
|
|
117
|
-
return this.container.clientDetails;
|
|
52
|
+
return this._getContainerDiagnosticId() ?? "";
|
|
118
53
|
}
|
|
119
54
|
|
|
120
|
-
private _connected: boolean;
|
|
121
55
|
/**
|
|
122
56
|
* When true, ops are free to flow
|
|
123
57
|
* When false, ops should be kept as pending or rejected
|
|
124
58
|
*/
|
|
125
59
|
public get connected(): boolean {
|
|
126
|
-
return this.
|
|
60
|
+
return this._getConnected();
|
|
127
61
|
}
|
|
128
62
|
|
|
129
|
-
public get canSummarize(): boolean {
|
|
130
|
-
return "summarize" in this.runtime;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
public get serviceConfiguration(): IClientConfiguration | undefined {
|
|
134
|
-
return this.container.serviceConfiguration;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
public get audience(): IAudience {
|
|
138
|
-
return this.container.audience;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
public get options(): ILoaderOptions {
|
|
142
|
-
return this.container.options;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
public get baseSnapshot() {
|
|
146
|
-
return this._baseSnapshot;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
public get storage(): IDocumentStorageService {
|
|
150
|
-
return this.container.storage;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
private _runtime: IRuntime | undefined;
|
|
154
|
-
private get runtime() {
|
|
155
|
-
if (this._runtime === undefined) {
|
|
156
|
-
throw new Error("Attempted to access runtime before it was defined");
|
|
157
|
-
}
|
|
158
|
-
return this._runtime;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
private _disposed = false;
|
|
162
|
-
|
|
163
|
-
public get disposed() {
|
|
164
|
-
return this._disposed;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
public get codeDetails() {
|
|
168
|
-
return this._codeDetails;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
private readonly _quorum: IQuorum;
|
|
172
|
-
public get quorum(): IQuorumClients {
|
|
173
|
-
return this._quorum;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
private readonly _fluidModuleP: Promise<IFluidModuleWithDetails>;
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* {@inheritDoc @fluidframework/container-definitions#IContainerContext.getEntryPoint}
|
|
180
|
-
*/
|
|
181
|
-
public async getEntryPoint?(): Promise<FluidObject | undefined> {
|
|
182
|
-
if (this._disposed) {
|
|
183
|
-
throw new UsageError("The context is already disposed");
|
|
184
|
-
}
|
|
185
|
-
if (this._runtime !== undefined) {
|
|
186
|
-
return this._runtime?.getEntryPoint?.();
|
|
187
|
-
}
|
|
188
|
-
return new Promise<FluidObject | undefined>((resolve, reject) => {
|
|
189
|
-
const runtimeInstantiatedHandler = () => {
|
|
190
|
-
assert(
|
|
191
|
-
this._runtime !== undefined,
|
|
192
|
-
0x5a3 /* runtimeInstantiated fired but runtime is still undefined */,
|
|
193
|
-
);
|
|
194
|
-
resolve(this._runtime.getEntryPoint?.());
|
|
195
|
-
this.lifecycleEvents.off("disposed", disposedHandler);
|
|
196
|
-
};
|
|
197
|
-
const disposedHandler = () => {
|
|
198
|
-
reject(new Error("ContainerContext was disposed"));
|
|
199
|
-
this.lifecycleEvents.off("runtimeInstantiated", runtimeInstantiatedHandler);
|
|
200
|
-
};
|
|
201
|
-
this.lifecycleEvents.once("runtimeInstantiated", runtimeInstantiatedHandler);
|
|
202
|
-
this.lifecycleEvents.once("disposed", disposedHandler);
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* Emits events about the container context's lifecycle.
|
|
208
|
-
* Use it to coordinate things inside the ContainerContext class.
|
|
209
|
-
*/
|
|
210
|
-
private readonly lifecycleEvents = new TypedEventEmitter<ContextLifecycleEvents>();
|
|
211
|
-
|
|
212
63
|
constructor(
|
|
213
|
-
|
|
64
|
+
public readonly options: ILoaderOptions,
|
|
214
65
|
public readonly scope: FluidObject,
|
|
215
|
-
|
|
216
|
-
private readonly
|
|
217
|
-
private readonly _baseSnapshot: ISnapshotTree | undefined,
|
|
66
|
+
public readonly baseSnapshot: ISnapshotTree | undefined,
|
|
67
|
+
private readonly _version: IVersion | undefined,
|
|
218
68
|
public readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,
|
|
219
|
-
|
|
69
|
+
public readonly storage: IDocumentStorageService,
|
|
70
|
+
public readonly quorum: IQuorumClients,
|
|
71
|
+
public readonly audience: IAudience,
|
|
220
72
|
public readonly loader: ILoader,
|
|
221
73
|
public readonly submitFn: (
|
|
222
74
|
type: MessageType,
|
|
@@ -236,194 +88,24 @@ export class ContainerContext implements IContainerContext {
|
|
|
236
88
|
public readonly submitSignalFn: (contents: any) => void,
|
|
237
89
|
public readonly disposeFn: (error?: ICriticalContainerError) => void,
|
|
238
90
|
public readonly closeFn: (error?: ICriticalContainerError) => void,
|
|
239
|
-
public readonly version: string,
|
|
240
91
|
public readonly updateDirtyContainerState: (dirty: boolean) => void,
|
|
92
|
+
public readonly getAbsoluteUrl: (relativeUrl: string) => Promise<string | undefined>,
|
|
93
|
+
private readonly _getContainerDiagnosticId: () => string | undefined,
|
|
94
|
+
private readonly _getClientId: () => string | undefined,
|
|
95
|
+
private readonly _getAttachState: () => AttachState,
|
|
96
|
+
private readonly _getConnected: () => boolean,
|
|
97
|
+
public readonly getSpecifiedCodeDetails: () => IFluidCodeDetails | undefined,
|
|
98
|
+
public readonly clientDetails: IClientDetails,
|
|
241
99
|
public readonly existing: boolean,
|
|
100
|
+
public readonly taggedLogger: ITelemetryLoggerExt,
|
|
242
101
|
public readonly pendingLocalState?: unknown,
|
|
243
|
-
) {
|
|
244
|
-
this._connected = this.container.connected;
|
|
245
|
-
this._quorum = quorum;
|
|
246
|
-
this.taggedLogger = container.subLogger;
|
|
247
|
-
this._fluidModuleP = new LazyPromise<IFluidModuleWithDetails>(async () =>
|
|
248
|
-
this.loadCodeModule(_codeDetails),
|
|
249
|
-
);
|
|
250
|
-
|
|
251
|
-
this.supportedFeatures = new Map([
|
|
252
|
-
/**
|
|
253
|
-
* This version of the loader accepts `referenceSequenceNumber`, provided by the container runtime,
|
|
254
|
-
* as a parameter to the `submitBatchFn` and `submitSummaryFn` functions.
|
|
255
|
-
* This is then used to set the reference sequence numbers of the submitted ops in the DeltaManager.
|
|
256
|
-
*/
|
|
257
|
-
["referenceSequenceNumbers", true],
|
|
258
|
-
]);
|
|
259
|
-
this.attachListener();
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* @deprecated Temporary migratory API, to be removed when customers no longer need it.
|
|
264
|
-
* When removed, `ContainerContext` should only take an {@link @fluidframework/container-definitions#IQuorumClients}
|
|
265
|
-
* rather than an {@link @fluidframework/protocol-definitions#IQuorum}.
|
|
266
|
-
* See {@link @fluidframework/container-definitions#IContainerContext} for more details.
|
|
267
|
-
*/
|
|
268
|
-
public getSpecifiedCodeDetails(): IFluidCodeDetails | undefined {
|
|
269
|
-
return (this._quorum.get("code") ?? this._quorum.get("code2")) as
|
|
270
|
-
| IFluidCodeDetails
|
|
271
|
-
| undefined;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
public dispose(error?: Error): void {
|
|
275
|
-
if (this._disposed) {
|
|
276
|
-
return;
|
|
277
|
-
}
|
|
278
|
-
this._disposed = true;
|
|
279
|
-
|
|
280
|
-
this.lifecycleEvents.emit("disposed");
|
|
281
|
-
this.runtime.dispose(error);
|
|
282
|
-
this._quorum.dispose();
|
|
283
|
-
this.deltaManager.dispose();
|
|
284
|
-
}
|
|
102
|
+
) {}
|
|
285
103
|
|
|
286
104
|
public getLoadedFromVersion(): IVersion | undefined {
|
|
287
|
-
return this.
|
|
105
|
+
return this._version;
|
|
288
106
|
}
|
|
289
107
|
|
|
290
108
|
public get attachState(): AttachState {
|
|
291
|
-
return this.
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* Create a summary. Used when attaching or serializing a detached container.
|
|
296
|
-
*
|
|
297
|
-
* @param blobRedirectTable - A table passed during the attach process. While detached, blob upload is supported
|
|
298
|
-
* using IDs generated locally. After attach, these IDs cannot be used, so this table maps the old local IDs to the
|
|
299
|
-
* new storage IDs so requests can be redirected.
|
|
300
|
-
*/
|
|
301
|
-
public createSummary(blobRedirectTable?: Map<string, string>): ISummaryTree {
|
|
302
|
-
return this.runtime.createSummary(blobRedirectTable);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
public setConnectionState(connected: boolean, clientId?: string) {
|
|
306
|
-
const runtime = this.runtime;
|
|
307
|
-
this._connected = connected;
|
|
308
|
-
runtime.setConnectionState(connected, clientId);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
public process(message: ISequencedDocumentMessage, local: boolean) {
|
|
312
|
-
this.runtime.process(message, local);
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
public processSignal(message: ISignalMessage, local: boolean) {
|
|
316
|
-
this.runtime.processSignal(message, local);
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
public async request(path: IRequest): Promise<IResponse> {
|
|
320
|
-
return this.runtime.request(path);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
public async getAbsoluteUrl(relativeUrl: string): Promise<string | undefined> {
|
|
324
|
-
return this.container.getAbsoluteUrl(relativeUrl);
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
public getPendingLocalState(): unknown {
|
|
328
|
-
return this.runtime.getPendingLocalState();
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
/**
|
|
332
|
-
* Determines if the current code details of the context
|
|
333
|
-
* satisfy the incoming constraint code details
|
|
334
|
-
*/
|
|
335
|
-
public async satisfies(constraintCodeDetails: IFluidCodeDetails) {
|
|
336
|
-
const comparers: IFluidCodeDetailsComparer[] = [];
|
|
337
|
-
|
|
338
|
-
const maybeCompareCodeLoader = this.codeLoader;
|
|
339
|
-
if (maybeCompareCodeLoader.IFluidCodeDetailsComparer !== undefined) {
|
|
340
|
-
comparers.push(maybeCompareCodeLoader.IFluidCodeDetailsComparer);
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
const moduleWithDetails = await this._fluidModuleP;
|
|
344
|
-
const maybeCompareExport: Partial<IProvideFluidCodeDetailsComparer> | undefined =
|
|
345
|
-
moduleWithDetails.module?.fluidExport;
|
|
346
|
-
if (maybeCompareExport?.IFluidCodeDetailsComparer !== undefined) {
|
|
347
|
-
comparers.push(maybeCompareExport.IFluidCodeDetailsComparer);
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
// if there are not comparers it is not possible to know
|
|
351
|
-
// if the current satisfy the incoming, so return false,
|
|
352
|
-
// as assuming they do not satisfy is safer .e.g we will
|
|
353
|
-
// reload, rather than potentially running with
|
|
354
|
-
// incompatible code
|
|
355
|
-
if (comparers.length === 0) {
|
|
356
|
-
return false;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
for (const comparer of comparers) {
|
|
360
|
-
const satisfies = await comparer.satisfies(
|
|
361
|
-
moduleWithDetails.details,
|
|
362
|
-
constraintCodeDetails,
|
|
363
|
-
);
|
|
364
|
-
if (satisfies === false) {
|
|
365
|
-
return false;
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
return true;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
public async notifyOpReplay(message: ISequencedDocumentMessage): Promise<void> {
|
|
372
|
-
return this.runtime.notifyOpReplay?.(message);
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
// #region private
|
|
376
|
-
|
|
377
|
-
private async getRuntimeFactory(): Promise<IRuntimeFactory> {
|
|
378
|
-
const fluidExport: FluidObject<IProvideRuntimeFactory> | undefined = (
|
|
379
|
-
await this._fluidModuleP
|
|
380
|
-
).module?.fluidExport;
|
|
381
|
-
const runtimeFactory = fluidExport?.IRuntimeFactory;
|
|
382
|
-
if (runtimeFactory === undefined) {
|
|
383
|
-
throw new Error(PackageNotFactoryError);
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
return runtimeFactory;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
private async instantiateRuntime(existing: boolean) {
|
|
390
|
-
const runtimeFactory = await this.getRuntimeFactory();
|
|
391
|
-
this._runtime = await PerformanceEvent.timedExecAsync(
|
|
392
|
-
this.taggedLogger,
|
|
393
|
-
{ eventName: "InstantiateRuntime" },
|
|
394
|
-
async () => runtimeFactory.instantiateRuntime(this, existing),
|
|
395
|
-
);
|
|
396
|
-
this.lifecycleEvents.emit("runtimeInstantiated");
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
private attachListener() {
|
|
400
|
-
this.container.once("attaching", () => {
|
|
401
|
-
this.runtime.setAttachState(AttachState.Attaching);
|
|
402
|
-
});
|
|
403
|
-
this.container.once("attached", () => {
|
|
404
|
-
this.runtime.setAttachState(AttachState.Attached);
|
|
405
|
-
});
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
private async loadCodeModule(codeDetails: IFluidCodeDetails): Promise<IFluidModuleWithDetails> {
|
|
409
|
-
const loadCodeResult = await PerformanceEvent.timedExecAsync(
|
|
410
|
-
this.taggedLogger,
|
|
411
|
-
{ eventName: "CodeLoad" },
|
|
412
|
-
async () => this.codeLoader.load(codeDetails),
|
|
413
|
-
);
|
|
414
|
-
|
|
415
|
-
if ("module" in loadCodeResult) {
|
|
416
|
-
const { module, details } = loadCodeResult;
|
|
417
|
-
return {
|
|
418
|
-
module,
|
|
419
|
-
details: details ?? codeDetails,
|
|
420
|
-
};
|
|
421
|
-
} else {
|
|
422
|
-
// If "module" is not in the result, we are using a legacy ICodeLoader. Fix the result up with details.
|
|
423
|
-
// Once usage drops to 0 we can remove this compat path.
|
|
424
|
-
this.taggedLogger.sendTelemetryEvent({ eventName: "LegacyCodeLoader" });
|
|
425
|
-
return loadCodeResult;
|
|
426
|
-
}
|
|
109
|
+
return this._getAttachState();
|
|
427
110
|
}
|
|
428
|
-
// #endregion
|
|
429
111
|
}
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { IDisposable } from "@fluidframework/
|
|
6
|
+
import { IDisposable } from "@fluidframework/core-interfaces";
|
|
7
7
|
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
|
|
8
|
-
import {
|
|
8
|
+
import { bufferToString, stringToBuffer } from "@fluid-internal/client-utils";
|
|
9
|
+
import { assert } from "@fluidframework/core-utils";
|
|
9
10
|
import { ISnapshotTreeWithBlobContents } from "@fluidframework/container-definitions";
|
|
10
11
|
import {
|
|
11
12
|
FetchSource,
|
|
@@ -229,6 +230,14 @@ class BlobOnlyStorage implements IDocumentStorageService {
|
|
|
229
230
|
}
|
|
230
231
|
}
|
|
231
232
|
|
|
233
|
+
// runtime will write a tree to the summary containing "attachment" type entries
|
|
234
|
+
// which reference attachment blobs by ID, along with a blob containing the blob redirect table.
|
|
235
|
+
// However, some drivers do not support the "attachment" type and will convert them to "blob" type
|
|
236
|
+
// entries. We want to avoid saving these to reduce the size of stashed change blobs, but we
|
|
237
|
+
// need to make sure the blob redirect table is saved.
|
|
238
|
+
const blobsTreeName = ".blobs";
|
|
239
|
+
const redirectTableBlobName = ".redirectTable";
|
|
240
|
+
|
|
232
241
|
/**
|
|
233
242
|
* Get blob contents of a snapshot tree from storage (or, ideally, cache)
|
|
234
243
|
*/
|
|
@@ -245,10 +254,15 @@ async function getBlobContentsFromTreeCore(
|
|
|
245
254
|
tree: ISnapshotTree,
|
|
246
255
|
blobs: ISerializableBlobContents,
|
|
247
256
|
storage: IDocumentStorageService,
|
|
257
|
+
root = true,
|
|
248
258
|
) {
|
|
249
259
|
const treePs: Promise<any>[] = [];
|
|
250
|
-
for (const subTree of Object.
|
|
251
|
-
|
|
260
|
+
for (const [key, subTree] of Object.entries(tree.trees)) {
|
|
261
|
+
if (root && key === blobsTreeName) {
|
|
262
|
+
treePs.push(getBlobManagerTreeFromTree(subTree, blobs, storage));
|
|
263
|
+
} else {
|
|
264
|
+
treePs.push(getBlobContentsFromTreeCore(subTree, blobs, storage, false));
|
|
265
|
+
}
|
|
252
266
|
}
|
|
253
267
|
for (const id of Object.values(tree.blobs)) {
|
|
254
268
|
const blob = await storage.readBlob(id);
|
|
@@ -258,6 +272,18 @@ async function getBlobContentsFromTreeCore(
|
|
|
258
272
|
return Promise.all(treePs);
|
|
259
273
|
}
|
|
260
274
|
|
|
275
|
+
// save redirect table from .blobs tree but nothing else
|
|
276
|
+
async function getBlobManagerTreeFromTree(
|
|
277
|
+
tree: ISnapshotTree,
|
|
278
|
+
blobs: ISerializableBlobContents,
|
|
279
|
+
storage: IDocumentStorageService,
|
|
280
|
+
) {
|
|
281
|
+
const id = tree.blobs[redirectTableBlobName];
|
|
282
|
+
const blob = await storage.readBlob(id);
|
|
283
|
+
// ArrayBufferLike will not survive JSON.stringify()
|
|
284
|
+
blobs[id] = bufferToString(blob, "utf8");
|
|
285
|
+
}
|
|
286
|
+
|
|
261
287
|
/**
|
|
262
288
|
* Extract blob contents from a snapshot tree with blob contents
|
|
263
289
|
*/
|
|
@@ -272,9 +298,14 @@ export function getBlobContentsFromTreeWithBlobContents(
|
|
|
272
298
|
function getBlobContentsFromTreeWithBlobContentsCore(
|
|
273
299
|
tree: ISnapshotTreeWithBlobContents,
|
|
274
300
|
blobs: ISerializableBlobContents,
|
|
301
|
+
root = true,
|
|
275
302
|
) {
|
|
276
|
-
for (const subTree of Object.
|
|
277
|
-
|
|
303
|
+
for (const [key, subTree] of Object.entries(tree.trees)) {
|
|
304
|
+
if (root && key === blobsTreeName) {
|
|
305
|
+
getBlobManagerTreeFromTreeWithBlobContents(subTree, blobs);
|
|
306
|
+
} else {
|
|
307
|
+
getBlobContentsFromTreeWithBlobContentsCore(subTree, blobs, false);
|
|
308
|
+
}
|
|
278
309
|
}
|
|
279
310
|
for (const id of Object.values(tree.blobs)) {
|
|
280
311
|
const blob = tree.blobsContents[id];
|
|
@@ -283,3 +314,15 @@ function getBlobContentsFromTreeWithBlobContentsCore(
|
|
|
283
314
|
blobs[id] = bufferToString(blob, "utf8");
|
|
284
315
|
}
|
|
285
316
|
}
|
|
317
|
+
|
|
318
|
+
// save redirect table from .blobs tree but nothing else
|
|
319
|
+
function getBlobManagerTreeFromTreeWithBlobContents(
|
|
320
|
+
tree: ISnapshotTreeWithBlobContents,
|
|
321
|
+
blobs: ISerializableBlobContents,
|
|
322
|
+
) {
|
|
323
|
+
const id = tree.blobs[redirectTableBlobName];
|
|
324
|
+
const blob = tree.blobsContents[id];
|
|
325
|
+
assert(blob !== undefined, 0x70f /* Blob must be present in blobsContents */);
|
|
326
|
+
// ArrayBufferLike will not survive JSON.stringify()
|
|
327
|
+
blobs[id] = bufferToString(blob, "utf8");
|
|
328
|
+
}
|
package/src/contracts.ts
CHANGED
|
@@ -3,24 +3,25 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { ITelemetryProperties } from "@fluidframework/
|
|
6
|
+
import { IErrorBase, ITelemetryProperties } from "@fluidframework/core-interfaces";
|
|
7
7
|
import {
|
|
8
|
-
|
|
9
|
-
ReadOnlyInfo,
|
|
10
|
-
IConnectionDetailsInternal,
|
|
8
|
+
IConnectionDetails,
|
|
11
9
|
ICriticalContainerError,
|
|
10
|
+
IDeltaQueue,
|
|
12
11
|
IFluidCodeDetails,
|
|
13
12
|
isFluidPackage,
|
|
13
|
+
ReadOnlyInfo,
|
|
14
14
|
} from "@fluidframework/container-definitions";
|
|
15
15
|
import {
|
|
16
16
|
ConnectionMode,
|
|
17
|
-
IDocumentMessage,
|
|
18
|
-
ISequencedDocumentMessage,
|
|
19
17
|
IClientConfiguration,
|
|
20
18
|
IClientDetails,
|
|
19
|
+
IDocumentMessage,
|
|
20
|
+
ISequencedDocumentMessage,
|
|
21
|
+
ISignalClient,
|
|
21
22
|
ISignalMessage,
|
|
22
23
|
} from "@fluidframework/protocol-definitions";
|
|
23
|
-
import {
|
|
24
|
+
import { IContainerPackageInfo } from "@fluidframework/driver-definitions";
|
|
24
25
|
|
|
25
26
|
export enum ReconnectMode {
|
|
26
27
|
Never = "Never",
|
|
@@ -28,6 +29,21 @@ export enum ReconnectMode {
|
|
|
28
29
|
Enabled = "Enabled",
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
export interface IConnectionStateChangeReason<T extends IErrorBase = IErrorBase> {
|
|
33
|
+
text: string;
|
|
34
|
+
error?: T;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Internal version of IConnectionDetails with props are only exposed internally
|
|
39
|
+
*/
|
|
40
|
+
export interface IConnectionDetailsInternal extends IConnectionDetails {
|
|
41
|
+
mode: ConnectionMode;
|
|
42
|
+
version: string;
|
|
43
|
+
initialClients: ISignalClient[];
|
|
44
|
+
reason: IConnectionStateChangeReason;
|
|
45
|
+
}
|
|
46
|
+
|
|
31
47
|
/**
|
|
32
48
|
* Connection manager (implements this interface) is responsible for maintaining connection
|
|
33
49
|
* to relay service.
|
|
@@ -95,7 +111,7 @@ export interface IConnectionManager {
|
|
|
95
111
|
/**
|
|
96
112
|
* Initiates connection to relay service (noop if already connected).
|
|
97
113
|
*/
|
|
98
|
-
connect(reason:
|
|
114
|
+
connect(reason: IConnectionStateChangeReason, connectionMode?: ConnectionMode): void;
|
|
99
115
|
|
|
100
116
|
/**
|
|
101
117
|
* Disposed connection manager
|
|
@@ -139,7 +155,7 @@ export interface IConnectionManagerFactoryArgs {
|
|
|
139
155
|
/**
|
|
140
156
|
* Called whenever connection to relay service is lost.
|
|
141
157
|
*/
|
|
142
|
-
readonly disconnectHandler: (reason:
|
|
158
|
+
readonly disconnectHandler: (reason: IConnectionStateChangeReason) => void;
|
|
143
159
|
|
|
144
160
|
/**
|
|
145
161
|
* Called whenever new connection to rely service is established
|
|
@@ -148,8 +164,6 @@ export interface IConnectionManagerFactoryArgs {
|
|
|
148
164
|
|
|
149
165
|
/**
|
|
150
166
|
* Called whenever ping/pong messages are roundtripped on connection.
|
|
151
|
-
*
|
|
152
|
-
* @deprecated No replacement API intended.
|
|
153
167
|
*/
|
|
154
168
|
readonly pongHandler: (latency: number) => void;
|
|
155
169
|
|
|
@@ -171,12 +185,12 @@ export interface IConnectionManagerFactoryArgs {
|
|
|
171
185
|
/**
|
|
172
186
|
* Called whenever we try to start establishing a new connection.
|
|
173
187
|
*/
|
|
174
|
-
readonly establishConnectionHandler: (reason:
|
|
188
|
+
readonly establishConnectionHandler: (reason: IConnectionStateChangeReason) => void;
|
|
175
189
|
|
|
176
190
|
/**
|
|
177
191
|
* Called whenever we cancel the connection in progress.
|
|
178
192
|
*/
|
|
179
|
-
readonly cancelConnectionHandler: (reason:
|
|
193
|
+
readonly cancelConnectionHandler: (reason: IConnectionStateChangeReason) => void;
|
|
180
194
|
}
|
|
181
195
|
|
|
182
196
|
/**
|