@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/lib/channelCollection.js
CHANGED
|
@@ -25,9 +25,11 @@ import { nonDataStorePaths, rootHasIsolatedChannels, } from "./summary/index.js"
|
|
|
25
25
|
*/
|
|
26
26
|
export const AllowTombstoneRequestHeaderKey = "allowTombstone"; // Belongs in the enum above, but avoiding the breaking change
|
|
27
27
|
/**
|
|
28
|
-
* Creates a shallow wrapper of {@link
|
|
28
|
+
* Creates a shallow wrapper of {@link IFluidParentContextPrivate} or
|
|
29
|
+
* {@link IFluidRootParentContextPrivate} with `submitMessage` and `submitSignal`
|
|
30
|
+
* methods replaced with the provided overrides.
|
|
29
31
|
*/
|
|
30
|
-
export function
|
|
32
|
+
export function formParentContext(context, overrides) {
|
|
31
33
|
return {
|
|
32
34
|
get IFluidDataStoreRegistry() {
|
|
33
35
|
return context.IFluidDataStoreRegistry;
|
|
@@ -67,12 +69,8 @@ export function wrapContext(context) {
|
|
|
67
69
|
getAudience: (...args) => {
|
|
68
70
|
return context.getAudience(...args);
|
|
69
71
|
},
|
|
70
|
-
submitMessage: (
|
|
71
|
-
|
|
72
|
-
},
|
|
73
|
-
submitSignal: (...args) => {
|
|
74
|
-
return context.submitSignal(...args);
|
|
75
|
-
},
|
|
72
|
+
submitMessage: overrides.submitMessage.bind(overrides),
|
|
73
|
+
submitSignal: overrides.submitSignal,
|
|
76
74
|
makeLocallyVisible: (...args) => {
|
|
77
75
|
return context.makeLocallyVisible(...args);
|
|
78
76
|
},
|
|
@@ -92,36 +90,34 @@ export function wrapContext(context) {
|
|
|
92
90
|
return context.setChannelDirty(address);
|
|
93
91
|
},
|
|
94
92
|
minVersionForCollab: context.minVersionForCollab,
|
|
93
|
+
getExtension: context.getExtension.bind(context),
|
|
95
94
|
};
|
|
96
95
|
}
|
|
97
96
|
/**
|
|
98
|
-
* Creates a wrapper of a {@link
|
|
97
|
+
* Creates a wrapper of a {@link IFluidRootParentContextPrivate} to be provided to the inner datastore channels.
|
|
99
98
|
* The wrapper will have the submit methods overwritten with the appropriate id as the destination address.
|
|
100
99
|
*
|
|
101
100
|
* @param id - the id of the channel
|
|
102
|
-
* @param parentContext - the {@link
|
|
101
|
+
* @param parentContext - the {@link IFluidRootParentContextPrivate} to wrap
|
|
103
102
|
* @returns A wrapped {@link IFluidParentContext}
|
|
104
103
|
*/
|
|
105
104
|
function wrapContextForInnerChannel(id, parentContext) {
|
|
106
|
-
const context =
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
};
|
|
123
|
-
parentContext.submitSignal(type, envelope, targetClientId);
|
|
124
|
-
};
|
|
105
|
+
const context = formParentContext(parentContext, {
|
|
106
|
+
submitMessage: (type, content, localOpMetadata) => {
|
|
107
|
+
const fluidDataStoreContent = {
|
|
108
|
+
content,
|
|
109
|
+
type,
|
|
110
|
+
};
|
|
111
|
+
const envelope = {
|
|
112
|
+
address: id,
|
|
113
|
+
contents: fluidDataStoreContent,
|
|
114
|
+
};
|
|
115
|
+
parentContext.submitMessage({ type: ContainerMessageType.FluidDataStoreOp, contents: envelope }, localOpMetadata);
|
|
116
|
+
},
|
|
117
|
+
submitSignal: (type, content, targetClientId) => {
|
|
118
|
+
parentContext.submitSignal({ address: id, contents: { type, content } }, targetClientId);
|
|
119
|
+
},
|
|
120
|
+
});
|
|
125
121
|
return context;
|
|
126
122
|
}
|
|
127
123
|
/**
|
|
@@ -136,7 +132,7 @@ export function getLocalDataStoreType(localDataStore) {
|
|
|
136
132
|
* @internal
|
|
137
133
|
*/
|
|
138
134
|
export class ChannelCollection {
|
|
139
|
-
constructor(baseSnapshot, parentContext, baseLogger, gcNodeUpdated, isDataStoreDeleted, aliasMap
|
|
135
|
+
constructor(baseSnapshot, parentContext, baseLogger, gcNodeUpdated, isDataStoreDeleted, aliasMap) {
|
|
140
136
|
this.baseSnapshot = baseSnapshot;
|
|
141
137
|
this.parentContext = parentContext;
|
|
142
138
|
this.gcNodeUpdated = gcNodeUpdated;
|
|
@@ -153,9 +149,49 @@ export class ChannelCollection {
|
|
|
153
149
|
* For sampling. Only log once per container
|
|
154
150
|
*/
|
|
155
151
|
this.shouldSendAttachLog = true;
|
|
152
|
+
this.reSubmitContainerMessage = (message, localOpMetadata, squash) => {
|
|
153
|
+
switch (message.type) {
|
|
154
|
+
case ContainerMessageType.Attach:
|
|
155
|
+
case ContainerMessageType.Alias: {
|
|
156
|
+
this.parentContext.submitMessage(message, localOpMetadata);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
case ContainerMessageType.FluidDataStoreOp: {
|
|
160
|
+
return this.resubmitDataStoreOp(message.contents, localOpMetadata, squash);
|
|
161
|
+
}
|
|
162
|
+
default: {
|
|
163
|
+
assert(false, 0x907 /* unknown op type */);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
this.resubmitDataStoreOp = (envelope, localOpMetadata, squash) => {
|
|
168
|
+
const context = this.contexts.get(envelope.address);
|
|
169
|
+
// If the data store has been deleted, log an error and throw an error. If there are local changes for a
|
|
170
|
+
// deleted data store, it can otherwise lead to inconsistent state when compared to other clients.
|
|
171
|
+
if (this.checkAndLogIfDeleted(envelope.address, context, "Changed", "resubmitDataStoreOp")) {
|
|
172
|
+
throw new DataCorruptionError("Context is deleted!", {
|
|
173
|
+
callSite: "resubmitDataStoreOp",
|
|
174
|
+
...tagCodeArtifacts({ id: envelope.address }),
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
assert(!!context, 0x160 /* "There should be a store context for the op" */);
|
|
178
|
+
context.reSubmit(envelope.contents, localOpMetadata, squash);
|
|
179
|
+
};
|
|
180
|
+
this.rollbackDataStoreOp = (envelope, localOpMetadata) => {
|
|
181
|
+
const context = this.contexts.get(envelope.address);
|
|
182
|
+
// If the data store has been deleted, log an error and throw an error. If there are local changes for a
|
|
183
|
+
// deleted data store, it can otherwise lead to inconsistent state when compared to other clients.
|
|
184
|
+
if (this.checkAndLogIfDeleted(envelope.address, context, "Changed", "rollbackDataStoreOp")) {
|
|
185
|
+
throw new DataCorruptionError("Context is deleted!", {
|
|
186
|
+
callSite: "rollbackDataStoreOp",
|
|
187
|
+
...tagCodeArtifacts({ id: envelope.address }),
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
assert(!!context, 0x2e8 /* "There should be a store context for the op" */);
|
|
191
|
+
context.rollback(envelope.contents, localOpMetadata);
|
|
192
|
+
};
|
|
156
193
|
this.mc = createChildMonitoringContext({ logger: baseLogger });
|
|
157
194
|
this.contexts = new DataStoreContexts(baseLogger);
|
|
158
|
-
this.entryPoint = new FluidObjectHandle(new LazyPromise(async () => provideEntryPoint(this)), "", this.parentContext.IFluidHandleContext);
|
|
159
195
|
this.aliasedDataStores = new Set(aliasMap.values());
|
|
160
196
|
// Extract stores stored inside the snapshot
|
|
161
197
|
const fluidDataStores = new Map();
|
|
@@ -398,7 +434,7 @@ export class ChannelCollection {
|
|
|
398
434
|
submitAttachChannelOp(localContext) {
|
|
399
435
|
const message = this.generateAttachMessage(localContext);
|
|
400
436
|
this.pendingAttach.set(localContext.id, message);
|
|
401
|
-
this.parentContext.submitMessage(ContainerMessageType.Attach, message, undefined);
|
|
437
|
+
this.parentContext.submitMessage({ type: ContainerMessageType.Attach, contents: message }, undefined);
|
|
402
438
|
this.attachOpFiredForDataStore.add(localContext.id);
|
|
403
439
|
}
|
|
404
440
|
/**
|
|
@@ -472,52 +508,6 @@ export class ChannelCollection {
|
|
|
472
508
|
dispose() {
|
|
473
509
|
return this.disposeOnce.value;
|
|
474
510
|
}
|
|
475
|
-
reSubmit(type, content, localOpMetadata, squash) {
|
|
476
|
-
switch (type) {
|
|
477
|
-
case ContainerMessageType.Attach:
|
|
478
|
-
case ContainerMessageType.Alias: {
|
|
479
|
-
this.parentContext.submitMessage(type, content, localOpMetadata);
|
|
480
|
-
return;
|
|
481
|
-
}
|
|
482
|
-
case ContainerMessageType.FluidDataStoreOp: {
|
|
483
|
-
return this.reSubmitChannelOp(type, content, localOpMetadata, squash);
|
|
484
|
-
}
|
|
485
|
-
default: {
|
|
486
|
-
assert(false, 0x907 /* unknown op type */);
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
reSubmitChannelOp(type, content, localOpMetadata, squash) {
|
|
491
|
-
const envelope = content;
|
|
492
|
-
const context = this.contexts.get(envelope.address);
|
|
493
|
-
// If the data store has been deleted, log an error and throw an error. If there are local changes for a
|
|
494
|
-
// deleted data store, it can otherwise lead to inconsistent state when compared to other clients.
|
|
495
|
-
if (this.checkAndLogIfDeleted(envelope.address, context, "Changed", "resubmitDataStoreOp")) {
|
|
496
|
-
throw new DataCorruptionError("Context is deleted!", {
|
|
497
|
-
callSite: "resubmitDataStoreOp",
|
|
498
|
-
...tagCodeArtifacts({ id: envelope.address }),
|
|
499
|
-
});
|
|
500
|
-
}
|
|
501
|
-
assert(!!context, 0x160 /* "There should be a store context for the op" */);
|
|
502
|
-
const innerContents = envelope.contents;
|
|
503
|
-
context.reSubmit(innerContents.type, innerContents.content, localOpMetadata, squash);
|
|
504
|
-
}
|
|
505
|
-
rollback(type, content, localOpMetadata) {
|
|
506
|
-
assert(type === ContainerMessageType.FluidDataStoreOp, 0x8e8 /* type */);
|
|
507
|
-
const envelope = content;
|
|
508
|
-
const context = this.contexts.get(envelope.address);
|
|
509
|
-
// If the data store has been deleted, log an error and throw an error. If there are local changes for a
|
|
510
|
-
// deleted data store, it can otherwise lead to inconsistent state when compared to other clients.
|
|
511
|
-
if (this.checkAndLogIfDeleted(envelope.address, context, "Changed", "rollbackDataStoreOp")) {
|
|
512
|
-
throw new DataCorruptionError("Context is deleted!", {
|
|
513
|
-
callSite: "rollbackDataStoreOp",
|
|
514
|
-
...tagCodeArtifacts({ id: envelope.address }),
|
|
515
|
-
});
|
|
516
|
-
}
|
|
517
|
-
assert(!!context, 0x2e8 /* "There should be a store context for the op" */);
|
|
518
|
-
const innerContents = envelope.contents;
|
|
519
|
-
context.rollback(innerContents.type, innerContents.content, localOpMetadata);
|
|
520
|
-
}
|
|
521
511
|
async applyStashedOp(content) {
|
|
522
512
|
const opContents = content;
|
|
523
513
|
switch (opContents.type) {
|
|
@@ -1229,7 +1219,50 @@ export function detectOutboundReferences(address, contents, addedOutboundReferen
|
|
|
1229
1219
|
addedOutboundReference(fromPath, toPath);
|
|
1230
1220
|
}
|
|
1231
1221
|
}
|
|
1222
|
+
// #region Experimentation
|
|
1223
|
+
// The code below here is for experimentation (and one test) only.
|
|
1232
1224
|
/**
|
|
1225
|
+
* @privateRemarks This class is only used for experimentation/testing.
|
|
1226
|
+
*/
|
|
1227
|
+
export class ComposableChannelCollection extends ChannelCollection {
|
|
1228
|
+
constructor(baseSnapshot, parentContext, baseLogger, gcNodeUpdated, isDataStoreDeleted, aliasMap, provideEntryPoint) {
|
|
1229
|
+
super(baseSnapshot,
|
|
1230
|
+
/* [root] parentContext */
|
|
1231
|
+
formParentContext(parentContext, {
|
|
1232
|
+
submitMessage: (containerRuntimeMessage, localOpMetadata) => {
|
|
1233
|
+
// Note that here our message format is reconfigured.
|
|
1234
|
+
// While `ContainerRuntime*Message`s use `contents`
|
|
1235
|
+
// as `FluidDataStoreMessage`s, the content is
|
|
1236
|
+
// stored in `content`.
|
|
1237
|
+
parentContext.submitMessage(containerRuntimeMessage.type, containerRuntimeMessage.contents, localOpMetadata);
|
|
1238
|
+
},
|
|
1239
|
+
submitSignal: (envelope, targetClientId) => {
|
|
1240
|
+
parentContext.submitSignal(envelope.contents.type, {
|
|
1241
|
+
address: envelope.address,
|
|
1242
|
+
contents: envelope.contents.content,
|
|
1243
|
+
}, targetClientId);
|
|
1244
|
+
},
|
|
1245
|
+
}), baseLogger, gcNodeUpdated, isDataStoreDeleted, aliasMap);
|
|
1246
|
+
this.entryPoint = new FluidObjectHandle(new LazyPromise(async () => provideEntryPoint(this)), "", this.parentContext.IFluidHandleContext);
|
|
1247
|
+
}
|
|
1248
|
+
reSubmit(type, content, localOpMetadata, squash) {
|
|
1249
|
+
// If the cast is incorrect and type is not one of the three supported,
|
|
1250
|
+
// reSubmitContainerMessage will assert.
|
|
1251
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Need to force conversion
|
|
1252
|
+
const message = {
|
|
1253
|
+
type,
|
|
1254
|
+
contents: content,
|
|
1255
|
+
};
|
|
1256
|
+
this.reSubmitContainerMessage(message, localOpMetadata, squash);
|
|
1257
|
+
}
|
|
1258
|
+
rollback(type, content, localOpMetadata) {
|
|
1259
|
+
assert(type === ContainerMessageType.FluidDataStoreOp, 0x8e8 /* type */);
|
|
1260
|
+
this.rollbackDataStoreOp(content, localOpMetadata);
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
/**
|
|
1264
|
+
* @privateRemarks This factory is only used for experimentation/testing.
|
|
1265
|
+
*
|
|
1233
1266
|
* @internal
|
|
1234
1267
|
*/
|
|
1235
1268
|
export class ChannelCollectionFactory {
|
|
@@ -1254,10 +1287,10 @@ export class ChannelCollectionFactory {
|
|
|
1254
1287
|
// this factory and the container runtime are
|
|
1255
1288
|
// from the same package.
|
|
1256
1289
|
assert(context instanceof FluidDataStoreContext, 0xb8f /* we don't support the layer boundary here today */);
|
|
1257
|
-
const runtime = new
|
|
1258
|
-
|
|
1259
|
-
(
|
|
1260
|
-
new Map(), // aliasMap
|
|
1290
|
+
const runtime = new ComposableChannelCollection(context.baseSnapshot,
|
|
1291
|
+
/* parentContext */ context, context.baseLogger,
|
|
1292
|
+
/* gcNodeUpdated */ () => { },
|
|
1293
|
+
/* isDataStoreDeleted */ (_nodePath) => false, new Map(), // aliasMap
|
|
1261
1294
|
this.provideEntryPoint);
|
|
1262
1295
|
return runtime;
|
|
1263
1296
|
}
|