@fluidframework/container-runtime 2.0.0-internal.7.3.0 → 2.0.0-internal.8.0.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/CHANGELOG.md +50 -0
- package/api-extractor-lint.json +13 -0
- package/api-extractor.json +9 -1
- package/api-report/container-runtime.api.md +123 -123
- package/dist/blobManager.d.ts +4 -4
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js.map +1 -1
- package/dist/container-runtime-alpha.d.ts +1444 -0
- package/dist/container-runtime-beta.d.ts +292 -0
- package/dist/container-runtime-public.d.ts +292 -0
- package/dist/container-runtime-untrimmed.d.ts +1792 -0
- package/dist/containerRuntime.d.ts +36 -66
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +68 -104
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.js +0 -12
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreRegistry.d.ts +1 -1
- package/dist/dataStoreRegistry.js +1 -1
- package/dist/dataStoreRegistry.js.map +1 -1
- package/dist/dataStores.d.ts +10 -15
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +77 -40
- package/dist/dataStores.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +41 -13
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +215 -78
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.d.ts.map +1 -1
- package/dist/gc/gcConfigs.js +34 -37
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +121 -46
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js +26 -18
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcHelpers.d.ts +18 -25
- package/dist/gc/gcHelpers.d.ts.map +1 -1
- package/dist/gc/gcHelpers.js +29 -45
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts +0 -5
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js +14 -42
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/gc/gcUnreferencedStateTracker.d.ts +11 -5
- package/dist/gc/gcUnreferencedStateTracker.d.ts.map +1 -1
- package/dist/gc/gcUnreferencedStateTracker.js +43 -19
- package/dist/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/dist/gc/index.d.ts +1 -1
- package/dist/gc/index.d.ts.map +1 -1
- package/dist/gc/index.js +4 -5
- package/dist/gc/index.js.map +1 -1
- package/dist/index.d.ts +15 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -6
- package/dist/index.js.map +1 -1
- package/dist/messageTypes.d.ts +15 -7
- package/dist/messageTypes.d.ts.map +1 -1
- package/dist/messageTypes.js +6 -1
- package/dist/messageTypes.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts +1 -1
- package/dist/opLifecycle/definitions.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/pendingStateManager.d.ts +1 -0
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +1 -0
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/summary/orderedClientElection.d.ts +1 -1
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.d.ts +2 -2
- package/dist/summary/runWhileConnectedCoordinator.js +1 -1
- package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/summary/summarizer.d.ts +1 -13
- package/dist/summary/summarizer.d.ts.map +1 -1
- package/dist/summary/summarizer.js +1 -47
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +30 -30
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/dist/summary/summaryCollection.d.ts +10 -10
- package/dist/summary/summaryCollection.js +1 -1
- package/dist/summary/summaryCollection.js.map +1 -1
- package/dist/summary/summaryFormat.d.ts +3 -3
- package/dist/summary/summaryFormat.js.map +1 -1
- package/lib/blobManager.d.ts +4 -4
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js.map +1 -1
- package/lib/container-runtime-alpha.d.ts +1444 -0
- package/lib/container-runtime-beta.d.ts +292 -0
- package/lib/container-runtime-public.d.ts +292 -0
- package/lib/container-runtime-untrimmed.d.ts +1792 -0
- package/lib/containerRuntime.d.ts +36 -66
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +69 -104
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.js +0 -12
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreRegistry.d.ts +1 -1
- package/lib/dataStoreRegistry.js +1 -1
- package/lib/dataStoreRegistry.js.map +1 -1
- package/lib/dataStores.d.ts +10 -15
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +80 -43
- package/lib/dataStores.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts +41 -13
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +217 -80
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcConfigs.d.ts.map +1 -1
- package/lib/gc/gcConfigs.js +37 -40
- package/lib/gc/gcConfigs.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +121 -46
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js +25 -17
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/gc/gcHelpers.d.ts +18 -25
- package/lib/gc/gcHelpers.d.ts.map +1 -1
- package/lib/gc/gcHelpers.js +27 -43
- package/lib/gc/gcHelpers.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts +0 -5
- package/lib/gc/gcTelemetry.d.ts.map +1 -1
- package/lib/gc/gcTelemetry.js +15 -43
- package/lib/gc/gcTelemetry.js.map +1 -1
- package/lib/gc/gcUnreferencedStateTracker.d.ts +11 -5
- package/lib/gc/gcUnreferencedStateTracker.d.ts.map +1 -1
- package/lib/gc/gcUnreferencedStateTracker.js +43 -19
- package/lib/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/lib/gc/index.d.ts +1 -1
- package/lib/gc/index.d.ts.map +1 -1
- package/lib/gc/index.js +1 -1
- package/lib/gc/index.js.map +1 -1
- package/lib/index.d.ts +15 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +16 -2
- package/lib/index.js.map +1 -1
- package/lib/messageTypes.d.ts +15 -7
- package/lib/messageTypes.d.ts.map +1 -1
- package/lib/messageTypes.js +6 -1
- package/lib/messageTypes.js.map +1 -1
- package/lib/opLifecycle/definitions.d.ts +1 -1
- package/lib/opLifecycle/definitions.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/pendingStateManager.d.ts +1 -0
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +1 -0
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/summary/orderedClientElection.d.ts +1 -1
- package/lib/summary/orderedClientElection.js.map +1 -1
- package/lib/summary/runWhileConnectedCoordinator.d.ts +2 -2
- package/lib/summary/runWhileConnectedCoordinator.js +1 -1
- package/lib/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/lib/summary/summarizer.d.ts +1 -13
- package/lib/summary/summarizer.d.ts.map +1 -1
- package/lib/summary/summarizer.js +1 -47
- package/lib/summary/summarizer.js.map +1 -1
- package/lib/summary/summarizerTypes.d.ts +30 -30
- package/lib/summary/summarizerTypes.js.map +1 -1
- package/lib/summary/summaryCollection.d.ts +10 -10
- package/lib/summary/summaryCollection.js +1 -1
- package/lib/summary/summaryCollection.js.map +1 -1
- package/lib/summary/summaryFormat.d.ts +3 -3
- package/lib/summary/summaryFormat.js.map +1 -1
- package/package.json +46 -19
- package/src/blobManager.ts +5 -5
- package/src/containerRuntime.ts +93 -141
- package/src/dataStore.ts +1 -15
- package/src/dataStoreRegistry.ts +1 -1
- package/src/dataStores.ts +140 -69
- package/src/gc/garbageCollection.md +14 -15
- package/src/gc/garbageCollection.ts +256 -96
- package/src/gc/gcConfigs.ts +50 -52
- package/src/gc/gcDefinitions.ts +137 -52
- package/src/gc/gcHelpers.ts +31 -52
- package/src/gc/gcTelemetry.ts +16 -57
- package/src/gc/gcUnreferencedStateTracker.ts +61 -22
- package/src/gc/index.ts +6 -4
- package/src/index.ts +19 -2
- package/src/messageTypes.ts +19 -4
- package/src/opLifecycle/definitions.ts +1 -1
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +1 -0
- package/src/summary/orderedClientElection.ts +1 -1
- package/src/summary/runWhileConnectedCoordinator.ts +2 -2
- package/src/summary/summarizer.ts +2 -51
- package/src/summary/summarizerTypes.ts +30 -30
- package/src/summary/summaryCollection.ts +10 -10
- package/src/summary/summaryFormat.ts +3 -3
- package/dist/id-compressor/appendOnlySortedMap.d.ts +0 -124
- package/dist/id-compressor/appendOnlySortedMap.d.ts.map +0 -1
- package/dist/id-compressor/appendOnlySortedMap.js +0 -318
- package/dist/id-compressor/appendOnlySortedMap.js.map +0 -1
- package/dist/id-compressor/finalSpace.d.ts +0 -29
- package/dist/id-compressor/finalSpace.d.ts.map +0 -1
- package/dist/id-compressor/finalSpace.js +0 -62
- package/dist/id-compressor/finalSpace.js.map +0 -1
- package/dist/id-compressor/idCompressor.d.ts +0 -54
- package/dist/id-compressor/idCompressor.d.ts.map +0 -1
- package/dist/id-compressor/idCompressor.js +0 -495
- package/dist/id-compressor/idCompressor.js.map +0 -1
- package/dist/id-compressor/identifiers.d.ts +0 -32
- package/dist/id-compressor/identifiers.d.ts.map +0 -1
- package/dist/id-compressor/identifiers.js +0 -15
- package/dist/id-compressor/identifiers.js.map +0 -1
- package/dist/id-compressor/index.d.ts +0 -13
- package/dist/id-compressor/index.d.ts.map +0 -1
- package/dist/id-compressor/index.js +0 -32
- package/dist/id-compressor/index.js.map +0 -1
- package/dist/id-compressor/persistanceUtilities.d.ts +0 -22
- package/dist/id-compressor/persistanceUtilities.d.ts.map +0 -1
- package/dist/id-compressor/persistanceUtilities.js +0 -43
- package/dist/id-compressor/persistanceUtilities.js.map +0 -1
- package/dist/id-compressor/sessionSpaceNormalizer.d.ts +0 -46
- package/dist/id-compressor/sessionSpaceNormalizer.d.ts.map +0 -1
- package/dist/id-compressor/sessionSpaceNormalizer.js +0 -80
- package/dist/id-compressor/sessionSpaceNormalizer.js.map +0 -1
- package/dist/id-compressor/sessions.d.ts +0 -115
- package/dist/id-compressor/sessions.d.ts.map +0 -1
- package/dist/id-compressor/sessions.js +0 -305
- package/dist/id-compressor/sessions.js.map +0 -1
- package/dist/id-compressor/utilities.d.ts +0 -52
- package/dist/id-compressor/utilities.d.ts.map +0 -1
- package/dist/id-compressor/utilities.js +0 -169
- package/dist/id-compressor/utilities.js.map +0 -1
- package/lib/id-compressor/appendOnlySortedMap.d.ts +0 -124
- package/lib/id-compressor/appendOnlySortedMap.d.ts.map +0 -1
- package/lib/id-compressor/appendOnlySortedMap.js +0 -314
- package/lib/id-compressor/appendOnlySortedMap.js.map +0 -1
- package/lib/id-compressor/finalSpace.d.ts +0 -29
- package/lib/id-compressor/finalSpace.d.ts.map +0 -1
- package/lib/id-compressor/finalSpace.js +0 -58
- package/lib/id-compressor/finalSpace.js.map +0 -1
- package/lib/id-compressor/idCompressor.d.ts +0 -54
- package/lib/id-compressor/idCompressor.d.ts.map +0 -1
- package/lib/id-compressor/idCompressor.js +0 -491
- package/lib/id-compressor/idCompressor.js.map +0 -1
- package/lib/id-compressor/identifiers.d.ts +0 -32
- package/lib/id-compressor/identifiers.d.ts.map +0 -1
- package/lib/id-compressor/identifiers.js +0 -11
- package/lib/id-compressor/identifiers.js.map +0 -1
- package/lib/id-compressor/index.d.ts +0 -13
- package/lib/id-compressor/index.d.ts.map +0 -1
- package/lib/id-compressor/index.js +0 -13
- package/lib/id-compressor/index.js.map +0 -1
- package/lib/id-compressor/persistanceUtilities.d.ts +0 -22
- package/lib/id-compressor/persistanceUtilities.d.ts.map +0 -1
- package/lib/id-compressor/persistanceUtilities.js +0 -34
- package/lib/id-compressor/persistanceUtilities.js.map +0 -1
- package/lib/id-compressor/sessionSpaceNormalizer.d.ts +0 -46
- package/lib/id-compressor/sessionSpaceNormalizer.d.ts.map +0 -1
- package/lib/id-compressor/sessionSpaceNormalizer.js +0 -76
- package/lib/id-compressor/sessionSpaceNormalizer.js.map +0 -1
- package/lib/id-compressor/sessions.d.ts +0 -115
- package/lib/id-compressor/sessions.d.ts.map +0 -1
- package/lib/id-compressor/sessions.js +0 -290
- package/lib/id-compressor/sessions.js.map +0 -1
- package/lib/id-compressor/utilities.d.ts +0 -52
- package/lib/id-compressor/utilities.d.ts.map +0 -1
- package/lib/id-compressor/utilities.js +0 -151
- package/lib/id-compressor/utilities.js.map +0 -1
- package/src/id-compressor/README.md +0 -3
- package/src/id-compressor/appendOnlySortedMap.ts +0 -366
- package/src/id-compressor/finalSpace.ts +0 -67
- package/src/id-compressor/idCompressor.ts +0 -630
- package/src/id-compressor/identifiers.ts +0 -42
- package/src/id-compressor/index.ts +0 -26
- package/src/id-compressor/persistanceUtilities.ts +0 -58
- package/src/id-compressor/sessionSpaceNormalizer.ts +0 -83
- package/src/id-compressor/sessions.ts +0 -405
- package/src/id-compressor/utilities.ts +0 -190
package/src/dataStores.ts
CHANGED
|
@@ -40,6 +40,7 @@ import {
|
|
|
40
40
|
import {
|
|
41
41
|
createChildMonitoringContext,
|
|
42
42
|
DataCorruptionError,
|
|
43
|
+
DataProcessingError,
|
|
43
44
|
extractSafePropertiesFromMessage,
|
|
44
45
|
LoggingError,
|
|
45
46
|
MonitoringContext,
|
|
@@ -60,13 +61,8 @@ import {
|
|
|
60
61
|
} from "./dataStoreContext";
|
|
61
62
|
import { StorageServiceWithAttachBlobs } from "./storageServiceWithAttachBlobs";
|
|
62
63
|
import { IDataStoreAliasMessage, isDataStoreAliasMessage } from "./dataStore";
|
|
63
|
-
import { GCNodeType, disableDatastoreSweepKey
|
|
64
|
-
import {
|
|
65
|
-
summarizerClientType,
|
|
66
|
-
IContainerRuntimeMetadata,
|
|
67
|
-
nonDataStorePaths,
|
|
68
|
-
rootHasIsolatedChannels,
|
|
69
|
-
} from "./summary";
|
|
64
|
+
import { GCNodeType, disableDatastoreSweepKey } from "./gc";
|
|
65
|
+
import { IContainerRuntimeMetadata, nonDataStorePaths, rootHasIsolatedChannels } from "./summary";
|
|
70
66
|
|
|
71
67
|
type PendingAliasResolve = (success: boolean) => void;
|
|
72
68
|
|
|
@@ -280,6 +276,19 @@ export class DataStores implements IDisposable {
|
|
|
280
276
|
}
|
|
281
277
|
|
|
282
278
|
const context = this.contexts.get(aliasMessage.internalId);
|
|
279
|
+
// If the data store has been deleted, log an error and ignore this message. This helps prevent document
|
|
280
|
+
// corruption in case a deleted data store accidentally submitted a signal.
|
|
281
|
+
if (
|
|
282
|
+
this.checkAndLogIfDeleted(
|
|
283
|
+
aliasMessage.internalId,
|
|
284
|
+
context,
|
|
285
|
+
"Changed",
|
|
286
|
+
"processAliasMessageCore",
|
|
287
|
+
)
|
|
288
|
+
) {
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
|
|
283
292
|
if (context === undefined) {
|
|
284
293
|
this.mc.logger.sendErrorEvent({
|
|
285
294
|
eventName: "AliasFluidDataStoreNotFound",
|
|
@@ -381,18 +390,43 @@ export class DataStores implements IDisposable {
|
|
|
381
390
|
|
|
382
391
|
public resubmitDataStoreOp(envelope: IEnvelope, localOpMetadata: unknown) {
|
|
383
392
|
const context = this.contexts.get(envelope.address);
|
|
393
|
+
// If the data store has been deleted, log an error and throw an error. If there are local changes for a
|
|
394
|
+
// deleted data store, it can otherwise lead to inconsistent state when compared to other clients.
|
|
395
|
+
if (
|
|
396
|
+
this.checkAndLogIfDeleted(envelope.address, context, "Changed", "resubmitDataStoreOp")
|
|
397
|
+
) {
|
|
398
|
+
throw new DataCorruptionError("Context is deleted!", {
|
|
399
|
+
callSite: "resubmitDataStoreOp",
|
|
400
|
+
...tagCodeArtifacts({ id: envelope.address }),
|
|
401
|
+
});
|
|
402
|
+
}
|
|
384
403
|
assert(!!context, 0x160 /* "There should be a store context for the op" */);
|
|
385
404
|
context.reSubmit(envelope.contents, localOpMetadata);
|
|
386
405
|
}
|
|
387
406
|
|
|
388
407
|
public rollbackDataStoreOp(envelope: IEnvelope, localOpMetadata: unknown) {
|
|
389
408
|
const context = this.contexts.get(envelope.address);
|
|
409
|
+
// If the data store has been deleted, log an error and throw an error. If there are local changes for a
|
|
410
|
+
// deleted data store, it can otherwise lead to inconsistent state when compared to other clients.
|
|
411
|
+
if (
|
|
412
|
+
this.checkAndLogIfDeleted(envelope.address, context, "Changed", "rollbackDataStoreOp")
|
|
413
|
+
) {
|
|
414
|
+
throw new DataCorruptionError("Context is deleted!", {
|
|
415
|
+
callSite: "rollbackDataStoreOp",
|
|
416
|
+
...tagCodeArtifacts({ id: envelope.address }),
|
|
417
|
+
});
|
|
418
|
+
}
|
|
390
419
|
assert(!!context, 0x2e8 /* "There should be a store context for the op" */);
|
|
391
420
|
context.rollback(envelope.contents, localOpMetadata);
|
|
392
421
|
}
|
|
393
422
|
|
|
394
423
|
public async applyStashedOp(envelope: IEnvelope): Promise<unknown> {
|
|
395
424
|
const context = this.contexts.get(envelope.address);
|
|
425
|
+
// If the data store has been deleted, log an error and ignore this message. This helps prevent document
|
|
426
|
+
// corruption in case the data store that stashed the op is deleted.
|
|
427
|
+
if (this.checkAndLogIfDeleted(envelope.address, context, "Changed", "applyStashedOp")) {
|
|
428
|
+
return undefined;
|
|
429
|
+
}
|
|
396
430
|
assert(!!context, 0x161 /* "There should be a store context for the op" */);
|
|
397
431
|
return context.applyStashedOp(envelope.contents);
|
|
398
432
|
}
|
|
@@ -410,8 +444,21 @@ export class DataStores implements IDisposable {
|
|
|
410
444
|
) {
|
|
411
445
|
const envelope = message.contents as IEnvelope;
|
|
412
446
|
const transformed = { ...message, contents: envelope.contents };
|
|
413
|
-
this.validateNotDeleted(envelope.address);
|
|
414
447
|
const context = this.contexts.get(envelope.address);
|
|
448
|
+
|
|
449
|
+
// If the data store has been deleted, log an error and ignore this message. This helps prevent document
|
|
450
|
+
// corruption in case a deleted data store accidentally submitted an op.
|
|
451
|
+
if (
|
|
452
|
+
this.checkAndLogIfDeleted(
|
|
453
|
+
envelope.address,
|
|
454
|
+
context,
|
|
455
|
+
"Changed",
|
|
456
|
+
"processFluidDataStoreOp",
|
|
457
|
+
)
|
|
458
|
+
) {
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
|
|
415
462
|
assert(!!context, 0x162 /* "There should be a store context for the op" */);
|
|
416
463
|
context.process(transformed, local, localMessageMetadata);
|
|
417
464
|
|
|
@@ -429,7 +476,22 @@ export class DataStores implements IDisposable {
|
|
|
429
476
|
requestHeaderData: RuntimeHeaderData,
|
|
430
477
|
): Promise<FluidDataStoreContext> {
|
|
431
478
|
const headerData = { ...defaultRuntimeHeaderData, ...requestHeaderData };
|
|
432
|
-
|
|
479
|
+
if (
|
|
480
|
+
this.checkAndLogIfDeleted(
|
|
481
|
+
id,
|
|
482
|
+
this.contexts.get(id),
|
|
483
|
+
"Requested",
|
|
484
|
+
"getDataStore",
|
|
485
|
+
requestHeaderData,
|
|
486
|
+
)
|
|
487
|
+
) {
|
|
488
|
+
// The requested data store has been deleted by gc. Create a 404 response exception.
|
|
489
|
+
const request: IRequest = { url: id };
|
|
490
|
+
throw responseToException(
|
|
491
|
+
createResponseError(404, "DataStore was deleted", request),
|
|
492
|
+
request,
|
|
493
|
+
);
|
|
494
|
+
}
|
|
433
495
|
|
|
434
496
|
const context = await this.contexts.getBoundOrRemoted(id, headerData.wait);
|
|
435
497
|
if (context === undefined) {
|
|
@@ -447,8 +509,16 @@ export class DataStores implements IDisposable {
|
|
|
447
509
|
id: string,
|
|
448
510
|
requestHeaderData: RuntimeHeaderData,
|
|
449
511
|
): Promise<FluidDataStoreContext | undefined> {
|
|
450
|
-
// If the data store has been deleted, return undefined.
|
|
451
|
-
if (
|
|
512
|
+
// If the data store has been deleted, log an error and return undefined.
|
|
513
|
+
if (
|
|
514
|
+
this.checkAndLogIfDeleted(
|
|
515
|
+
id,
|
|
516
|
+
this.contexts.get(id),
|
|
517
|
+
"Requested",
|
|
518
|
+
"getDataStoreIfAvailable",
|
|
519
|
+
requestHeaderData,
|
|
520
|
+
)
|
|
521
|
+
) {
|
|
452
522
|
return undefined;
|
|
453
523
|
}
|
|
454
524
|
const headerData = { ...defaultRuntimeHeaderData, ...requestHeaderData };
|
|
@@ -460,55 +530,43 @@ export class DataStores implements IDisposable {
|
|
|
460
530
|
}
|
|
461
531
|
|
|
462
532
|
/**
|
|
463
|
-
* Checks if the data store has been deleted by GC.
|
|
464
|
-
* @param id - data store id
|
|
465
|
-
* @param
|
|
466
|
-
* @param
|
|
533
|
+
* Checks if the data store has been deleted by GC. If so, log an error.
|
|
534
|
+
* @param id - The data store's id.
|
|
535
|
+
* @param context - The data store context.
|
|
536
|
+
* @param callSite - The function name this is called from.
|
|
537
|
+
* @param requestHeaderData - The request header information to log if the data store is deleted.
|
|
467
538
|
* @returns true if the data store is deleted. Otherwise, returns false.
|
|
468
539
|
*/
|
|
469
|
-
private
|
|
540
|
+
private checkAndLogIfDeleted(
|
|
541
|
+
id: string,
|
|
542
|
+
context: FluidDataStoreContext | undefined,
|
|
543
|
+
deletedLogSuffix: string,
|
|
544
|
+
callSite: string,
|
|
545
|
+
requestHeaderData?: RuntimeHeaderData,
|
|
546
|
+
) {
|
|
470
547
|
const dataStoreNodePath = `/${id}`;
|
|
471
548
|
if (!this.isDataStoreDeleted(dataStoreNodePath)) {
|
|
472
549
|
return false;
|
|
473
550
|
}
|
|
474
|
-
assert(
|
|
475
|
-
!this.contexts.has(id),
|
|
476
|
-
0x570 /* Inconsistent state! GC says the data store is deleted, but the data store is not deleted from the runtime. */,
|
|
477
|
-
);
|
|
478
|
-
sendGCUnexpectedUsageEvent(
|
|
479
|
-
this.mc,
|
|
480
|
-
{
|
|
481
|
-
eventName: "GC_Deleted_DataStore_Requested",
|
|
482
|
-
category: "error",
|
|
483
|
-
isSummarizerClient: this.runtime.clientDetails.type === summarizerClientType,
|
|
484
|
-
id,
|
|
485
|
-
headers: JSON.stringify(requestHeaderData),
|
|
486
|
-
gcTombstoneEnforcementAllowed: this.runtime.gcTombstoneEnforcementAllowed,
|
|
487
|
-
},
|
|
488
|
-
undefined /* packagePath */,
|
|
489
|
-
);
|
|
490
|
-
return true;
|
|
491
|
-
}
|
|
492
551
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
const request: IRequest = { url: id };
|
|
502
|
-
throw responseToException(
|
|
503
|
-
createResponseError(404, "DataStore was deleted", request),
|
|
504
|
-
request,
|
|
505
|
-
);
|
|
506
|
-
}
|
|
552
|
+
this.mc.logger.sendErrorEvent({
|
|
553
|
+
eventName: `GC_Deleted_DataStore_${deletedLogSuffix}`,
|
|
554
|
+
...tagCodeArtifacts({ id }),
|
|
555
|
+
callSite,
|
|
556
|
+
headers: JSON.stringify(requestHeaderData),
|
|
557
|
+
exists: context !== undefined,
|
|
558
|
+
});
|
|
559
|
+
return true;
|
|
507
560
|
}
|
|
508
561
|
|
|
509
562
|
public processSignal(fluidDataStoreId: string, message: IInboundSignalMessage, local: boolean) {
|
|
510
|
-
this.validateNotDeleted(fluidDataStoreId);
|
|
511
563
|
const context = this.contexts.get(fluidDataStoreId);
|
|
564
|
+
// If the data store has been deleted, log an error and ignore this message. This helps prevent document
|
|
565
|
+
// corruption in case a deleted data store accidentally submitted a signal.
|
|
566
|
+
if (this.checkAndLogIfDeleted(fluidDataStoreId, context, "Changed", "processSignal")) {
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
569
|
+
|
|
512
570
|
if (!context) {
|
|
513
571
|
// Attach message may not have been processed yet
|
|
514
572
|
assert(!local, 0x163 /* "Missing datastore for local signal" */);
|
|
@@ -573,11 +631,16 @@ export class DataStores implements IDisposable {
|
|
|
573
631
|
Array.from(this.contexts)
|
|
574
632
|
.filter(([_, context]) => {
|
|
575
633
|
// Summarizer works only with clients with no local changes. A data store in attaching
|
|
576
|
-
// state indicates an op was sent to attach a local data store
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
634
|
+
// state indicates an op was sent to attach a local data store, and the the attach op
|
|
635
|
+
// had not yet round tripped back to the client.
|
|
636
|
+
if (context.attachState === AttachState.Attaching) {
|
|
637
|
+
// Formerly assert 0x588
|
|
638
|
+
const error = DataProcessingError.create(
|
|
639
|
+
"Local data store detected in attaching state during summarize",
|
|
640
|
+
"summarize",
|
|
641
|
+
);
|
|
642
|
+
throw error;
|
|
643
|
+
}
|
|
581
644
|
return context.attachState === AttachState.Attached;
|
|
582
645
|
})
|
|
583
646
|
.map(async ([contextId, context]) => {
|
|
@@ -675,11 +738,17 @@ export class DataStores implements IDisposable {
|
|
|
675
738
|
Array.from(this.contexts)
|
|
676
739
|
.filter(([_, context]) => {
|
|
677
740
|
// Summarizer client and hence GC works only with clients with no local changes. A data store in
|
|
678
|
-
// attaching state indicates an op was sent to attach a local data store
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
741
|
+
// attaching state indicates an op was sent to attach a local data store, and the the attach op
|
|
742
|
+
// had not yet round tripped back to the client.
|
|
743
|
+
// Formerly assert 0x589
|
|
744
|
+
if (context.attachState === AttachState.Attaching) {
|
|
745
|
+
const error = DataProcessingError.create(
|
|
746
|
+
"Local data store detected in attaching state while running GC",
|
|
747
|
+
"getGCData",
|
|
748
|
+
);
|
|
749
|
+
throw error;
|
|
750
|
+
}
|
|
751
|
+
|
|
683
752
|
return context.attachState === AttachState.Attached;
|
|
684
753
|
})
|
|
685
754
|
.map(async ([contextId, context]) => {
|
|
@@ -699,7 +768,7 @@ export class DataStores implements IDisposable {
|
|
|
699
768
|
* After GC has run, called to notify this Container's data stores of routes that are used in it.
|
|
700
769
|
* @param usedRoutes - The routes that are used in all data stores in this Container.
|
|
701
770
|
*/
|
|
702
|
-
public updateUsedRoutes(usedRoutes: string[]) {
|
|
771
|
+
public updateUsedRoutes(usedRoutes: readonly string[]) {
|
|
703
772
|
// Get a map of data store ids to routes used in it.
|
|
704
773
|
const usedDataStoreRoutes = unpackChildNodesUsedRoutes(usedRoutes);
|
|
705
774
|
|
|
@@ -721,7 +790,7 @@ export class DataStores implements IDisposable {
|
|
|
721
790
|
* This is called to update objects whose routes are unused. The unused objects are deleted.
|
|
722
791
|
* @param unusedRoutes - The routes that are unused in all data stores in this Container.
|
|
723
792
|
*/
|
|
724
|
-
public updateUnusedRoutes(unusedRoutes: string[]) {
|
|
793
|
+
public updateUnusedRoutes(unusedRoutes: readonly string[]) {
|
|
725
794
|
for (const route of unusedRoutes) {
|
|
726
795
|
const pathParts = route.split("/");
|
|
727
796
|
// Delete data store only if its route (/datastoreId) is in unusedRoutes. We don't want to delete a data
|
|
@@ -744,7 +813,7 @@ export class DataStores implements IDisposable {
|
|
|
744
813
|
* be deleted.
|
|
745
814
|
* @returns The routes of data stores and its objects that were deleted.
|
|
746
815
|
*/
|
|
747
|
-
public deleteSweepReadyNodes(sweepReadyDataStoreRoutes: string[]): string[] {
|
|
816
|
+
public deleteSweepReadyNodes(sweepReadyDataStoreRoutes: readonly string[]): readonly string[] {
|
|
748
817
|
// If sweep for data stores is not enabled, return empty list indicating nothing is deleted.
|
|
749
818
|
if (this.mc.config.getBoolean(disableDatastoreSweepKey) === true) {
|
|
750
819
|
return [];
|
|
@@ -753,23 +822,25 @@ export class DataStores implements IDisposable {
|
|
|
753
822
|
const pathParts = route.split("/");
|
|
754
823
|
const dataStoreId = pathParts[1];
|
|
755
824
|
|
|
756
|
-
// TODO: GC:Validation - Skip any routes already deleted
|
|
757
825
|
// Ignore sub-data store routes because a data store and its sub-routes are deleted together, so, we only
|
|
758
826
|
// need to delete the data store.
|
|
759
827
|
if (pathParts.length > 2) {
|
|
760
828
|
continue;
|
|
761
829
|
}
|
|
762
830
|
|
|
763
|
-
|
|
831
|
+
const dataStoreContext = this.contexts.get(dataStoreId);
|
|
832
|
+
if (dataStoreContext === undefined) {
|
|
764
833
|
this.mc.logger.sendErrorEvent({
|
|
765
834
|
eventName: "DeletedDataStoreNotFound",
|
|
766
|
-
dataStoreId,
|
|
835
|
+
...tagCodeArtifacts({ id: dataStoreId }),
|
|
836
|
+
details: {
|
|
837
|
+
alreadyDeleted: this.isDataStoreDeleted(dataStoreId),
|
|
838
|
+
},
|
|
767
839
|
});
|
|
840
|
+
continue;
|
|
768
841
|
}
|
|
769
842
|
|
|
770
|
-
|
|
771
|
-
assert(dataStore !== undefined, 0x571 /* Attempting to delete unknown dataStore */);
|
|
772
|
-
dataStore.delete();
|
|
843
|
+
dataStoreContext.delete();
|
|
773
844
|
|
|
774
845
|
// Delete the contexts of sweep ready data stores.
|
|
775
846
|
this.contexts.delete(dataStoreId);
|
|
@@ -784,7 +855,7 @@ export class DataStores implements IDisposable {
|
|
|
784
855
|
* scenarios with accessing deleted content without actually deleting content from summaries.
|
|
785
856
|
* @param tombstonedRoutes - The routes that are tombstones in all data stores in this Container.
|
|
786
857
|
*/
|
|
787
|
-
public updateTombstonedRoutes(tombstonedRoutes: string[]) {
|
|
858
|
+
public updateTombstonedRoutes(tombstonedRoutes: readonly string[]) {
|
|
788
859
|
const tombstonedDataStoresSet: Set<string> = new Set();
|
|
789
860
|
for (const route of tombstonedRoutes) {
|
|
790
861
|
const pathParts = route.split("/");
|
|
@@ -50,16 +50,19 @@ Mark phase is enabled by default for a container. It is enabled during creation
|
|
|
50
50
|
|
|
51
51
|
### Sweep phase
|
|
52
52
|
|
|
53
|
-
In this phase, the GC algorithm
|
|
54
|
-
|
|
55
|
-
The Fluid Runtime enforces a maximum session length (configurable) in order to guarantee
|
|
53
|
+
In this phase, the GC algorithm deletes any Fluid object that has been unreferenced for a sufficient time to guarantee
|
|
54
|
+
they could never be referenced again by any active clients, i.e., clients that have the object in memory and could reference it again.
|
|
55
|
+
The Fluid Runtime enforces a maximum session length (configurable) in order to guarantee all in-memory objects are cleared before
|
|
56
|
+
it concludes an object is safe to delete.
|
|
56
57
|
|
|
57
|
-
GC sweep phase
|
|
58
|
-
as part of the Mark Phase when Sweep is disabled. In this mode, any object that GC determines is ready to be deleted is
|
|
59
|
-
marked as a "Tombstone", which triggers certain logging events and/or behavior changes if/when that Tombstoned object is
|
|
60
|
-
accessed by the application.
|
|
58
|
+
GC sweep phase runs in two stages:
|
|
61
59
|
|
|
62
|
-
|
|
60
|
+
- The first stage is the "Tombstone" stage, where objects are marked as Tombstones, meaning GC believes they will
|
|
61
|
+
never be referenced again and are safe to delete. They are not yet deleted at this point, but any attempt to
|
|
62
|
+
load them will fail. This way, there's a chance to recover a Tombstoned object in case we detect it's still being used.
|
|
63
|
+
- The second stage is the "Sweep" or "Delete" stage, where the objects are fully deleted.
|
|
64
|
+
This occurs after a configurable delay called the "Sweep Grace Period", to give time for application teams
|
|
65
|
+
to monitor for Tombstone-related errors and react before delete occurs.
|
|
63
66
|
|
|
64
67
|
## GC Configuration
|
|
65
68
|
|
|
@@ -67,7 +70,8 @@ The default configuration for GC today is:
|
|
|
67
70
|
|
|
68
71
|
- GC Mark Phase is **enabled**, including Tombstone Mode
|
|
69
72
|
- Session Expiry is **enabled**
|
|
70
|
-
-
|
|
73
|
+
- The "Tombstone" stage of Sweep Phase is **enabled** (attempting to load a tombstoned object will fail)
|
|
74
|
+
- The "Delete" stage of Sweep Phase is **disabled**
|
|
71
75
|
- Note: Once enabled, Sweep will only run for documents created from that point forward
|
|
72
76
|
|
|
73
77
|
### Techniques used for configuration
|
|
@@ -94,12 +98,7 @@ covered in the [Advanced Configuration](./gcEarlyAdoption.md#more-advanced-confi
|
|
|
94
98
|
|
|
95
99
|
### Enabling Sweep Phase
|
|
96
100
|
|
|
97
|
-
To enable Sweep Phase for new documents, you must set the `
|
|
98
|
-
The full semantics of this GC Option are discussed [here](./gcEarlyAdoption.md#more-about-gcsweepgeneration-and-gctombstonegeneration).
|
|
99
|
-
Note that this will disabled Tombstone Mode.
|
|
100
|
-
|
|
101
|
-
A full treatment of Tombstone and Sweep configuration can be found in
|
|
102
|
-
[this companion document geared towards early adopters of GC](./gcEarlyAdoption.md).
|
|
101
|
+
To enable the Sweep Phase for new documents, you must set the `enableGCSweep` GC Option to true.
|
|
103
102
|
|
|
104
103
|
### More Advanced Configuration
|
|
105
104
|
|