@fluidframework/container-runtime 2.70.0-361788 → 2.71.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.cjs +5 -1
- package/CHANGELOG.md +14 -0
- package/container-runtime.test-files.tar +0 -0
- package/dist/channelCollection.d.ts +66 -17
- package/dist/channelCollection.d.ts.map +1 -1
- package/dist/channelCollection.js +118 -84
- package/dist/channelCollection.js.map +1 -1
- package/dist/containerRuntime.d.ts +19 -11
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +146 -52
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts +3 -1
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js +8 -9
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +6 -5
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +7 -4
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/messageTypes.d.ts +17 -4
- package/dist/messageTypes.d.ts.map +1 -1
- package/dist/messageTypes.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/runtimeLayerCompatState.d.ts +2 -2
- package/dist/runtimeLayerCompatState.d.ts.map +1 -1
- package/dist/runtimeLayerCompatState.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +3 -1
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/channelCollection.d.ts +66 -17
- package/lib/channelCollection.d.ts.map +1 -1
- package/lib/channelCollection.js +115 -82
- package/lib/channelCollection.js.map +1 -1
- package/lib/containerRuntime.d.ts +19 -11
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +148 -53
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.d.ts +3 -1
- package/lib/dataStore.d.ts.map +1 -1
- package/lib/dataStore.js +3 -4
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +6 -5
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +8 -5
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/index.d.ts +3 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/messageTypes.d.ts +17 -4
- package/lib/messageTypes.d.ts.map +1 -1
- package/lib/messageTypes.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/runtimeLayerCompatState.d.ts +2 -2
- package/lib/runtimeLayerCompatState.d.ts.map +1 -1
- package/lib/runtimeLayerCompatState.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js +3 -1
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/package.json +22 -30
- package/src/channelCollection.ts +255 -109
- package/src/containerRuntime.ts +262 -92
- package/src/dataStore.ts +12 -10
- package/src/dataStoreContext.ts +45 -39
- package/src/index.ts +8 -3
- package/src/messageTypes.ts +17 -2
- package/src/packageVersion.ts +1 -1
- package/src/runtimeLayerCompatState.ts +1 -1
- package/src/summary/summarizerNode/summarizerNode.ts +1 -0
package/src/channelCollection.ts
CHANGED
|
@@ -11,7 +11,10 @@ import type {
|
|
|
11
11
|
IResponse,
|
|
12
12
|
ITelemetryBaseLogger,
|
|
13
13
|
} from "@fluidframework/core-interfaces";
|
|
14
|
-
import type {
|
|
14
|
+
import type {
|
|
15
|
+
IFluidHandleInternal,
|
|
16
|
+
ISignalEnvelope,
|
|
17
|
+
} from "@fluidframework/core-interfaces/internal";
|
|
15
18
|
import { assert, Lazy, LazyPromise } from "@fluidframework/core-utils/internal";
|
|
16
19
|
import { FluidObjectHandle } from "@fluidframework/datastore/internal";
|
|
17
20
|
import type {
|
|
@@ -24,29 +27,33 @@ import {
|
|
|
24
27
|
getSnapshotTree,
|
|
25
28
|
isInstanceOfISnapshot,
|
|
26
29
|
} from "@fluidframework/driver-utils/internal";
|
|
30
|
+
import type {
|
|
31
|
+
AliasResult,
|
|
32
|
+
ContainerExtensionProvider,
|
|
33
|
+
FluidDataStoreMessage,
|
|
34
|
+
IAttachMessage,
|
|
35
|
+
IEnvelope,
|
|
36
|
+
IFluidDataStoreChannel,
|
|
37
|
+
IFluidDataStoreContext,
|
|
38
|
+
IFluidDataStoreContextDetached,
|
|
39
|
+
IFluidDataStoreFactory,
|
|
40
|
+
IFluidDataStoreRegistry,
|
|
41
|
+
IFluidParentContext,
|
|
42
|
+
IGarbageCollectionData,
|
|
43
|
+
IInboundSignalMessage,
|
|
44
|
+
InboundAttachMessage,
|
|
45
|
+
IRuntimeMessageCollection,
|
|
46
|
+
IRuntimeMessagesContent,
|
|
47
|
+
ISummarizeResult,
|
|
48
|
+
ISummaryTreeWithStats,
|
|
49
|
+
ITelemetryContext,
|
|
50
|
+
MinimumVersionForCollab,
|
|
51
|
+
NamedFluidDataStoreRegistryEntries,
|
|
52
|
+
} from "@fluidframework/runtime-definitions/internal";
|
|
27
53
|
import {
|
|
28
|
-
type ISummaryTreeWithStats,
|
|
29
|
-
type ITelemetryContext,
|
|
30
|
-
type IGarbageCollectionData,
|
|
31
|
-
type AliasResult,
|
|
32
54
|
CreateSummarizerNodeSource,
|
|
33
|
-
type IAttachMessage,
|
|
34
|
-
type IEnvelope,
|
|
35
|
-
type IFluidDataStoreChannel,
|
|
36
|
-
type IFluidDataStoreContext,
|
|
37
|
-
type IFluidDataStoreContextDetached,
|
|
38
|
-
type IFluidDataStoreFactory,
|
|
39
|
-
type IFluidDataStoreRegistry,
|
|
40
|
-
type IFluidParentContext,
|
|
41
|
-
type ISummarizeResult,
|
|
42
|
-
type NamedFluidDataStoreRegistryEntries,
|
|
43
55
|
channelsTreeName,
|
|
44
|
-
type IInboundSignalMessage,
|
|
45
56
|
gcDataBlobKey,
|
|
46
|
-
type IRuntimeMessagesContent,
|
|
47
|
-
type InboundAttachMessage,
|
|
48
|
-
type IRuntimeMessageCollection,
|
|
49
|
-
type MinimumVersionForCollab,
|
|
50
57
|
} from "@fluidframework/runtime-definitions/internal";
|
|
51
58
|
import {
|
|
52
59
|
GCDataBuilder,
|
|
@@ -89,7 +96,7 @@ import {
|
|
|
89
96
|
} from "./dataStore.js";
|
|
90
97
|
import {
|
|
91
98
|
FluidDataStoreContext,
|
|
92
|
-
type
|
|
99
|
+
type IFluidDataStoreContextPrivate,
|
|
93
100
|
type ILocalDetachedFluidDataStoreContextProps,
|
|
94
101
|
LocalDetachedFluidDataStoreContext,
|
|
95
102
|
LocalFluidDataStoreContext,
|
|
@@ -99,6 +106,11 @@ import {
|
|
|
99
106
|
import { DataStoreContexts } from "./dataStoreContexts.js";
|
|
100
107
|
import { FluidDataStoreRegistry } from "./dataStoreRegistry.js";
|
|
101
108
|
import { GCNodeType, type IGCNodeUpdatedProps, urlToGCNodePath } from "./gc/index.js";
|
|
109
|
+
import type {
|
|
110
|
+
ContainerRuntimeAliasMessage,
|
|
111
|
+
ContainerRuntimeDataStoreOpMessage,
|
|
112
|
+
OutboundContainerRuntimeAttachMessage,
|
|
113
|
+
} from "./messageTypes.js";
|
|
102
114
|
import { ContainerMessageType, type LocalContainerRuntimeMessage } from "./messageTypes.js";
|
|
103
115
|
import { StorageServiceWithAttachBlobs } from "./storageServiceWithAttachBlobs.js";
|
|
104
116
|
import {
|
|
@@ -115,10 +127,16 @@ export const AllowTombstoneRequestHeaderKey = "allowTombstone"; // Belongs in th
|
|
|
115
127
|
|
|
116
128
|
type PendingAliasResolve = (success: boolean) => void;
|
|
117
129
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
130
|
+
/**
|
|
131
|
+
* Envelope for signals not intended for the container.
|
|
132
|
+
*
|
|
133
|
+
* @privateRemarks
|
|
134
|
+
* `clientBroadcastSignalSequenceNumber` might be added to the envelope by the container runtime.
|
|
135
|
+
* But it should not be provided to start with.
|
|
136
|
+
*
|
|
137
|
+
* Equivalent to `Required<Omit<ISignalEnvelope, "clientBroadcastSignalSequenceNumber">>`.
|
|
138
|
+
*/
|
|
139
|
+
export type AddressedUnsequencedSignalEnvelope = IEnvelope<ISignalEnvelope["contents"]>;
|
|
122
140
|
|
|
123
141
|
/**
|
|
124
142
|
* This version of the interface is private to this the package. It should never be exported under any tag.
|
|
@@ -129,19 +147,64 @@ interface FluidDataStoreMessage {
|
|
|
129
147
|
* to ease interactions within this package.
|
|
130
148
|
*/
|
|
131
149
|
export interface IFluidParentContextPrivate
|
|
132
|
-
extends
|
|
150
|
+
extends IFluidParentContext,
|
|
151
|
+
ContainerExtensionProvider {
|
|
133
152
|
readonly isReadOnly: () => boolean;
|
|
153
|
+
readonly minVersionForCollab: MinimumVersionForCollab;
|
|
154
|
+
}
|
|
134
155
|
|
|
156
|
+
/**
|
|
157
|
+
* Kin of {@link @fluidframework/runtime-definitions#IFluidParentContext} with alternate
|
|
158
|
+
* `submitMessage` and `submitSignal` methods that are typed specifically for the
|
|
159
|
+
* root context (aka {@link ContainerRuntime} provided context).
|
|
160
|
+
*
|
|
161
|
+
* @privateRemarks
|
|
162
|
+
* These replacements might be able to get cleaned up if the future suggestions
|
|
163
|
+
* found in {@link @fluidframework/runtime-definitions#FluidDataStoreMessage}
|
|
164
|
+
* `@privateRemarks` section are implemented.
|
|
165
|
+
*/
|
|
166
|
+
export interface IFluidRootParentContextPrivate
|
|
167
|
+
extends Omit<IFluidParentContextPrivate, "submitMessage" | "submitSignal"> {
|
|
135
168
|
/**
|
|
136
|
-
*
|
|
169
|
+
* Submits the message to be sent to other clients.
|
|
170
|
+
* @param containerRuntimeMessage - The message.
|
|
171
|
+
* @param localOpMetadata - The local metadata associated with the message.
|
|
172
|
+
* This is kept locally and not sent to the server. This will be sent back
|
|
173
|
+
* when this message is received back from the server. This is also sent if
|
|
174
|
+
* we are asked to resubmit the message.
|
|
137
175
|
*/
|
|
138
|
-
readonly
|
|
176
|
+
readonly submitMessage: (
|
|
177
|
+
containerRuntimeMessage:
|
|
178
|
+
| ContainerRuntimeDataStoreOpMessage
|
|
179
|
+
| OutboundContainerRuntimeAttachMessage
|
|
180
|
+
| ContainerRuntimeAliasMessage,
|
|
181
|
+
localOpMetadata: unknown,
|
|
182
|
+
) => void;
|
|
183
|
+
/**
|
|
184
|
+
* Submits the signal to be sent to other clients.
|
|
185
|
+
* @param envelope - {@link IEnvelope} containing the signal address and contents.
|
|
186
|
+
* @param targetClientId - When specified, the signal is only sent to the provided client id.
|
|
187
|
+
*/
|
|
188
|
+
readonly submitSignal: (
|
|
189
|
+
envelope: AddressedUnsequencedSignalEnvelope,
|
|
190
|
+
targetClientId?: string,
|
|
191
|
+
) => void;
|
|
139
192
|
}
|
|
140
193
|
|
|
194
|
+
type SubmitKeys = "submitMessage" | "submitSignal";
|
|
195
|
+
|
|
141
196
|
/**
|
|
142
|
-
* Creates a shallow wrapper of {@link
|
|
197
|
+
* Creates a shallow wrapper of {@link IFluidParentContextPrivate} or
|
|
198
|
+
* {@link IFluidRootParentContextPrivate} with `submitMessage` and `submitSignal`
|
|
199
|
+
* methods replaced with the provided overrides.
|
|
143
200
|
*/
|
|
144
|
-
export function
|
|
201
|
+
export function formParentContext<
|
|
202
|
+
T extends IFluidParentContextPrivate | IFluidRootParentContextPrivate,
|
|
203
|
+
>(
|
|
204
|
+
context: Omit<IFluidParentContextPrivate & IFluidRootParentContextPrivate, SubmitKeys>,
|
|
205
|
+
overrides: Pick<T, SubmitKeys>,
|
|
206
|
+
): Omit<IFluidParentContextPrivate & IFluidRootParentContextPrivate, SubmitKeys> &
|
|
207
|
+
Pick<T, SubmitKeys> {
|
|
145
208
|
return {
|
|
146
209
|
get IFluidDataStoreRegistry() {
|
|
147
210
|
return context.IFluidDataStoreRegistry;
|
|
@@ -181,12 +244,8 @@ export function wrapContext(context: IFluidParentContextPrivate): IFluidParentCo
|
|
|
181
244
|
getAudience: (...args) => {
|
|
182
245
|
return context.getAudience(...args);
|
|
183
246
|
},
|
|
184
|
-
submitMessage: (
|
|
185
|
-
|
|
186
|
-
},
|
|
187
|
-
submitSignal: (...args) => {
|
|
188
|
-
return context.submitSignal(...args);
|
|
189
|
-
},
|
|
247
|
+
submitMessage: overrides.submitMessage.bind(overrides),
|
|
248
|
+
submitSignal: overrides.submitSignal,
|
|
190
249
|
makeLocallyVisible: (...args) => {
|
|
191
250
|
return context.makeLocallyVisible(...args);
|
|
192
251
|
},
|
|
@@ -206,46 +265,41 @@ export function wrapContext(context: IFluidParentContextPrivate): IFluidParentCo
|
|
|
206
265
|
return context.setChannelDirty(address);
|
|
207
266
|
},
|
|
208
267
|
minVersionForCollab: context.minVersionForCollab,
|
|
268
|
+
getExtension: context.getExtension.bind(context),
|
|
209
269
|
};
|
|
210
270
|
}
|
|
211
271
|
|
|
212
272
|
/**
|
|
213
|
-
* Creates a wrapper of a {@link
|
|
273
|
+
* Creates a wrapper of a {@link IFluidRootParentContextPrivate} to be provided to the inner datastore channels.
|
|
214
274
|
* The wrapper will have the submit methods overwritten with the appropriate id as the destination address.
|
|
215
275
|
*
|
|
216
276
|
* @param id - the id of the channel
|
|
217
|
-
* @param parentContext - the {@link
|
|
277
|
+
* @param parentContext - the {@link IFluidRootParentContextPrivate} to wrap
|
|
218
278
|
* @returns A wrapped {@link IFluidParentContext}
|
|
219
279
|
*/
|
|
220
280
|
function wrapContextForInnerChannel(
|
|
221
281
|
id: string,
|
|
222
|
-
parentContext:
|
|
282
|
+
parentContext: IFluidRootParentContextPrivate,
|
|
223
283
|
): IFluidParentContextPrivate {
|
|
224
|
-
const context =
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
)
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
const envelope: IEnvelope = {
|
|
244
|
-
address: id,
|
|
245
|
-
contents,
|
|
246
|
-
};
|
|
247
|
-
parentContext.submitSignal(type, envelope, targetClientId);
|
|
248
|
-
};
|
|
284
|
+
const context = formParentContext<IFluidParentContextPrivate>(parentContext, {
|
|
285
|
+
submitMessage: (type: string, content: unknown, localOpMetadata: unknown) => {
|
|
286
|
+
const fluidDataStoreContent: FluidDataStoreMessage = {
|
|
287
|
+
content,
|
|
288
|
+
type,
|
|
289
|
+
};
|
|
290
|
+
const envelope = {
|
|
291
|
+
address: id,
|
|
292
|
+
contents: fluidDataStoreContent,
|
|
293
|
+
};
|
|
294
|
+
parentContext.submitMessage(
|
|
295
|
+
{ type: ContainerMessageType.FluidDataStoreOp, contents: envelope },
|
|
296
|
+
localOpMetadata,
|
|
297
|
+
);
|
|
298
|
+
},
|
|
299
|
+
submitSignal: (type: string, content: unknown, targetClientId?: string) => {
|
|
300
|
+
parentContext.submitSignal({ address: id, contents: { type, content } }, targetClientId);
|
|
301
|
+
},
|
|
302
|
+
});
|
|
249
303
|
|
|
250
304
|
return context;
|
|
251
305
|
}
|
|
@@ -262,7 +316,9 @@ export function getLocalDataStoreType(localDataStore: LocalFluidDataStoreContext
|
|
|
262
316
|
* but eventually could be hosted on any channel once we formalize the channel api boundary.
|
|
263
317
|
* @internal
|
|
264
318
|
*/
|
|
265
|
-
export class ChannelCollection
|
|
319
|
+
export class ChannelCollection
|
|
320
|
+
implements Omit<IFluidDataStoreChannel, "entryPoint" | "reSubmit" | "rollback">, IDisposable
|
|
321
|
+
{
|
|
266
322
|
// Stores tracked by the Domain
|
|
267
323
|
private readonly pendingAttach = new Map<string, IAttachMessage>();
|
|
268
324
|
// 0.24 back-compat attachingBeforeSummary
|
|
@@ -273,8 +329,6 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable {
|
|
|
273
329
|
// eslint-disable-next-line unicorn/consistent-function-scoping -- Property is defined once; no need to extract inner lambda
|
|
274
330
|
private readonly disposeOnce = new Lazy<void>(() => this.contexts.dispose());
|
|
275
331
|
|
|
276
|
-
public readonly entryPoint: IFluidHandleInternal<FluidObject>;
|
|
277
|
-
|
|
278
332
|
public readonly containerLoadStats: {
|
|
279
333
|
// number of dataStores during loadContainer
|
|
280
334
|
readonly containerLoadDataStoreCount: number;
|
|
@@ -292,20 +346,14 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable {
|
|
|
292
346
|
|
|
293
347
|
constructor(
|
|
294
348
|
protected readonly baseSnapshot: ISnapshotTree | ISnapshot | undefined,
|
|
295
|
-
public readonly parentContext:
|
|
349
|
+
public readonly parentContext: IFluidRootParentContextPrivate,
|
|
296
350
|
baseLogger: ITelemetryBaseLogger,
|
|
297
351
|
private readonly gcNodeUpdated: (props: IGCNodeUpdatedProps) => void,
|
|
298
352
|
private readonly isDataStoreDeleted: (nodePath: string) => boolean,
|
|
299
353
|
private readonly aliasMap: Map<string, string>,
|
|
300
|
-
provideEntryPoint: (runtime: ChannelCollection) => Promise<FluidObject>,
|
|
301
354
|
) {
|
|
302
355
|
this.mc = createChildMonitoringContext({ logger: baseLogger });
|
|
303
356
|
this.contexts = new DataStoreContexts(baseLogger);
|
|
304
|
-
this.entryPoint = new FluidObjectHandle<FluidObject>(
|
|
305
|
-
new LazyPromise(async () => provideEntryPoint(this)),
|
|
306
|
-
"",
|
|
307
|
-
this.parentContext.IFluidHandleContext,
|
|
308
|
-
);
|
|
309
357
|
this.aliasedDataStores = new Set(aliasMap.values());
|
|
310
358
|
|
|
311
359
|
// Extract stores stored inside the snapshot
|
|
@@ -605,7 +653,10 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable {
|
|
|
605
653
|
protected submitAttachChannelOp(localContext: LocalFluidDataStoreContext): void {
|
|
606
654
|
const message = this.generateAttachMessage(localContext);
|
|
607
655
|
this.pendingAttach.set(localContext.id, message);
|
|
608
|
-
this.parentContext.submitMessage(
|
|
656
|
+
this.parentContext.submitMessage(
|
|
657
|
+
{ type: ContainerMessageType.Attach, contents: message },
|
|
658
|
+
undefined,
|
|
659
|
+
);
|
|
609
660
|
this.attachOpFiredForDataStore.add(localContext.id);
|
|
610
661
|
}
|
|
611
662
|
|
|
@@ -664,7 +715,7 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable {
|
|
|
664
715
|
public createDataStoreContext(
|
|
665
716
|
pkg: readonly string[],
|
|
666
717
|
loadingGroupId?: string,
|
|
667
|
-
):
|
|
718
|
+
): IFluidDataStoreContextPrivate {
|
|
668
719
|
return this.createContext(
|
|
669
720
|
this.createDataStoreId(),
|
|
670
721
|
pkg,
|
|
@@ -712,34 +763,34 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable {
|
|
|
712
763
|
return this.disposeOnce.value;
|
|
713
764
|
}
|
|
714
765
|
|
|
715
|
-
public
|
|
716
|
-
|
|
717
|
-
|
|
766
|
+
public readonly reSubmitContainerMessage = (
|
|
767
|
+
message:
|
|
768
|
+
| ContainerRuntimeDataStoreOpMessage
|
|
769
|
+
| OutboundContainerRuntimeAttachMessage
|
|
770
|
+
| ContainerRuntimeAliasMessage,
|
|
718
771
|
localOpMetadata: unknown,
|
|
719
|
-
squash: boolean,
|
|
720
|
-
): void {
|
|
721
|
-
switch (type) {
|
|
772
|
+
squash: boolean | undefined,
|
|
773
|
+
): void => {
|
|
774
|
+
switch (message.type) {
|
|
722
775
|
case ContainerMessageType.Attach:
|
|
723
776
|
case ContainerMessageType.Alias: {
|
|
724
|
-
this.parentContext.submitMessage(
|
|
777
|
+
this.parentContext.submitMessage(message, localOpMetadata);
|
|
725
778
|
return;
|
|
726
779
|
}
|
|
727
780
|
case ContainerMessageType.FluidDataStoreOp: {
|
|
728
|
-
return this.
|
|
781
|
+
return this.resubmitDataStoreOp(message.contents, localOpMetadata, squash);
|
|
729
782
|
}
|
|
730
783
|
default: {
|
|
731
784
|
assert(false, 0x907 /* unknown op type */);
|
|
732
785
|
}
|
|
733
786
|
}
|
|
734
|
-
}
|
|
787
|
+
};
|
|
735
788
|
|
|
736
|
-
protected
|
|
737
|
-
|
|
738
|
-
content: unknown,
|
|
789
|
+
protected readonly resubmitDataStoreOp = (
|
|
790
|
+
envelope: IEnvelope<FluidDataStoreMessage>,
|
|
739
791
|
localOpMetadata: unknown,
|
|
740
|
-
squash: boolean,
|
|
741
|
-
): void {
|
|
742
|
-
const envelope = content as IEnvelope;
|
|
792
|
+
squash: boolean | undefined,
|
|
793
|
+
): void => {
|
|
743
794
|
const context = this.contexts.get(envelope.address);
|
|
744
795
|
// If the data store has been deleted, log an error and throw an error. If there are local changes for a
|
|
745
796
|
// deleted data store, it can otherwise lead to inconsistent state when compared to other clients.
|
|
@@ -752,13 +803,13 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable {
|
|
|
752
803
|
});
|
|
753
804
|
}
|
|
754
805
|
assert(!!context, 0x160 /* "There should be a store context for the op" */);
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
}
|
|
806
|
+
context.reSubmit(envelope.contents, localOpMetadata, squash);
|
|
807
|
+
};
|
|
758
808
|
|
|
759
|
-
public
|
|
760
|
-
|
|
761
|
-
|
|
809
|
+
public readonly rollbackDataStoreOp = (
|
|
810
|
+
envelope: IEnvelope<FluidDataStoreMessage>,
|
|
811
|
+
localOpMetadata: unknown,
|
|
812
|
+
): void => {
|
|
762
813
|
const context = this.contexts.get(envelope.address);
|
|
763
814
|
// If the data store has been deleted, log an error and throw an error. If there are local changes for a
|
|
764
815
|
// deleted data store, it can otherwise lead to inconsistent state when compared to other clients.
|
|
@@ -771,9 +822,8 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable {
|
|
|
771
822
|
});
|
|
772
823
|
}
|
|
773
824
|
assert(!!context, 0x2e8 /* "There should be a store context for the op" */);
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
}
|
|
825
|
+
context.rollback(envelope.contents, localOpMetadata);
|
|
826
|
+
};
|
|
777
827
|
|
|
778
828
|
public async applyStashedOp(content: unknown): Promise<unknown> {
|
|
779
829
|
const opContents = content as LocalContainerRuntimeMessage;
|
|
@@ -907,7 +957,7 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable {
|
|
|
907
957
|
* like merge tree or shared tree can process ops more efficiently when they are bunched together.
|
|
908
958
|
*/
|
|
909
959
|
for (const { contents, ...restOfMessagesContent } of messagesContent) {
|
|
910
|
-
const contentsEnvelope = contents as IEnvelope
|
|
960
|
+
const contentsEnvelope = contents as IEnvelope<FluidDataStoreMessage>;
|
|
911
961
|
const address = contentsEnvelope.address;
|
|
912
962
|
const context = this.contexts.get(address);
|
|
913
963
|
|
|
@@ -934,8 +984,7 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable {
|
|
|
934
984
|
);
|
|
935
985
|
}
|
|
936
986
|
|
|
937
|
-
const { type: contextType, content: contextContents } =
|
|
938
|
-
contentsEnvelope.contents as FluidDataStoreMessage;
|
|
987
|
+
const { type: contextType, content: contextContents } = contentsEnvelope.contents;
|
|
939
988
|
// If the address or type of the message changes while processing the message, send the current bunch.
|
|
940
989
|
if (
|
|
941
990
|
currentMessageState?.address !== address ||
|
|
@@ -972,7 +1021,7 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable {
|
|
|
972
1021
|
id: string,
|
|
973
1022
|
requestHeaderData: RuntimeHeaderData,
|
|
974
1023
|
originalRequest: IRequest,
|
|
975
|
-
): Promise<
|
|
1024
|
+
): Promise<IFluidDataStoreContextPrivate> {
|
|
976
1025
|
const headerData = { ...defaultRuntimeHeaderData, ...requestHeaderData };
|
|
977
1026
|
if (
|
|
978
1027
|
this.checkAndLogIfDeleted(
|
|
@@ -1008,7 +1057,7 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable {
|
|
|
1008
1057
|
public async getDataStoreIfAvailable(
|
|
1009
1058
|
id: string,
|
|
1010
1059
|
requestHeaderData: RuntimeHeaderData,
|
|
1011
|
-
): Promise<
|
|
1060
|
+
): Promise<IFluidDataStoreContextPrivate | undefined> {
|
|
1012
1061
|
// If the data store has been deleted, log an error and return undefined.
|
|
1013
1062
|
if (
|
|
1014
1063
|
this.checkAndLogIfDeleted(
|
|
@@ -1675,7 +1724,102 @@ export function detectOutboundReferences(
|
|
|
1675
1724
|
}
|
|
1676
1725
|
}
|
|
1677
1726
|
|
|
1727
|
+
// #region Experimentation
|
|
1728
|
+
// The code below here is for experimentation (and one test) only.
|
|
1729
|
+
|
|
1730
|
+
/**
|
|
1731
|
+
* @privateRemarks This class is only used for experimentation/testing.
|
|
1732
|
+
*/
|
|
1733
|
+
export class ComposableChannelCollection
|
|
1734
|
+
extends ChannelCollection
|
|
1735
|
+
implements IFluidDataStoreChannel
|
|
1736
|
+
{
|
|
1737
|
+
public readonly entryPoint: IFluidHandleInternal<FluidObject>;
|
|
1738
|
+
|
|
1739
|
+
public constructor(
|
|
1740
|
+
baseSnapshot: ISnapshotTree | ISnapshot | undefined,
|
|
1741
|
+
parentContext: IFluidParentContextPrivate,
|
|
1742
|
+
baseLogger: ITelemetryBaseLogger,
|
|
1743
|
+
gcNodeUpdated: (props: IGCNodeUpdatedProps) => void,
|
|
1744
|
+
isDataStoreDeleted: (nodePath: string) => boolean,
|
|
1745
|
+
aliasMap: Map<string, string>,
|
|
1746
|
+
provideEntryPoint: (runtime: ComposableChannelCollection) => Promise<FluidObject>,
|
|
1747
|
+
) {
|
|
1748
|
+
super(
|
|
1749
|
+
baseSnapshot,
|
|
1750
|
+
/* [root] parentContext */
|
|
1751
|
+
formParentContext<IFluidRootParentContextPrivate>(parentContext, {
|
|
1752
|
+
submitMessage: (
|
|
1753
|
+
containerRuntimeMessage:
|
|
1754
|
+
| ContainerRuntimeDataStoreOpMessage
|
|
1755
|
+
| OutboundContainerRuntimeAttachMessage
|
|
1756
|
+
| ContainerRuntimeAliasMessage,
|
|
1757
|
+
localOpMetadata: unknown,
|
|
1758
|
+
): void => {
|
|
1759
|
+
// Note that here our message format is reconfigured.
|
|
1760
|
+
// While `ContainerRuntime*Message`s use `contents`
|
|
1761
|
+
// as `FluidDataStoreMessage`s, the content is
|
|
1762
|
+
// stored in `content`.
|
|
1763
|
+
parentContext.submitMessage(
|
|
1764
|
+
containerRuntimeMessage.type,
|
|
1765
|
+
containerRuntimeMessage.contents,
|
|
1766
|
+
localOpMetadata,
|
|
1767
|
+
);
|
|
1768
|
+
},
|
|
1769
|
+
submitSignal: (
|
|
1770
|
+
envelope: AddressedUnsequencedSignalEnvelope,
|
|
1771
|
+
targetClientId?: string,
|
|
1772
|
+
): void => {
|
|
1773
|
+
parentContext.submitSignal(
|
|
1774
|
+
envelope.contents.type,
|
|
1775
|
+
{
|
|
1776
|
+
address: envelope.address,
|
|
1777
|
+
contents: envelope.contents.content,
|
|
1778
|
+
} satisfies IEnvelope<unknown>,
|
|
1779
|
+
targetClientId,
|
|
1780
|
+
);
|
|
1781
|
+
},
|
|
1782
|
+
}),
|
|
1783
|
+
baseLogger,
|
|
1784
|
+
gcNodeUpdated,
|
|
1785
|
+
isDataStoreDeleted,
|
|
1786
|
+
aliasMap,
|
|
1787
|
+
);
|
|
1788
|
+
this.entryPoint = new FluidObjectHandle<FluidObject>(
|
|
1789
|
+
new LazyPromise(async () => provideEntryPoint(this)),
|
|
1790
|
+
"",
|
|
1791
|
+
this.parentContext.IFluidHandleContext,
|
|
1792
|
+
);
|
|
1793
|
+
}
|
|
1794
|
+
|
|
1795
|
+
public reSubmit(
|
|
1796
|
+
type: string,
|
|
1797
|
+
content: unknown,
|
|
1798
|
+
localOpMetadata: unknown,
|
|
1799
|
+
squash?: boolean,
|
|
1800
|
+
): void {
|
|
1801
|
+
// If the cast is incorrect and type is not one of the three supported,
|
|
1802
|
+
// reSubmitContainerMessage will assert.
|
|
1803
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Need to force conversion
|
|
1804
|
+
const message = {
|
|
1805
|
+
type,
|
|
1806
|
+
contents: content,
|
|
1807
|
+
} as
|
|
1808
|
+
| ContainerRuntimeDataStoreOpMessage
|
|
1809
|
+
| OutboundContainerRuntimeAttachMessage
|
|
1810
|
+
| ContainerRuntimeAliasMessage;
|
|
1811
|
+
this.reSubmitContainerMessage(message, localOpMetadata, squash);
|
|
1812
|
+
}
|
|
1813
|
+
|
|
1814
|
+
public rollback(type: string, content: unknown, localOpMetadata: unknown): void {
|
|
1815
|
+
assert(type === ContainerMessageType.FluidDataStoreOp, 0x8e8 /* type */);
|
|
1816
|
+
this.rollbackDataStoreOp(content as IEnvelope<FluidDataStoreMessage>, localOpMetadata);
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1678
1820
|
/**
|
|
1821
|
+
* @privateRemarks This factory is only used for experimentation/testing.
|
|
1822
|
+
*
|
|
1679
1823
|
* @internal
|
|
1680
1824
|
*/
|
|
1681
1825
|
export class ChannelCollectionFactory implements IFluidDataStoreFactory {
|
|
@@ -1715,16 +1859,18 @@ export class ChannelCollectionFactory implements IFluidDataStoreFactory {
|
|
|
1715
1859
|
0xb8f /* we don't support the layer boundary here today */,
|
|
1716
1860
|
);
|
|
1717
1861
|
|
|
1718
|
-
const runtime = new
|
|
1862
|
+
const runtime = new ComposableChannelCollection(
|
|
1719
1863
|
context.baseSnapshot,
|
|
1720
|
-
context,
|
|
1864
|
+
/* parentContext */ context,
|
|
1721
1865
|
context.baseLogger,
|
|
1722
|
-
() => {},
|
|
1723
|
-
(_nodePath: string) => false,
|
|
1866
|
+
/* gcNodeUpdated */ () => {},
|
|
1867
|
+
/* isDataStoreDeleted */ (_nodePath: string) => false,
|
|
1724
1868
|
new Map(), // aliasMap
|
|
1725
1869
|
this.provideEntryPoint,
|
|
1726
1870
|
);
|
|
1727
1871
|
|
|
1728
1872
|
return runtime;
|
|
1729
1873
|
}
|
|
1874
|
+
|
|
1875
|
+
// #endregion Experimentation
|
|
1730
1876
|
}
|