@fluidframework/container-runtime 2.0.0-internal.6.4.0 → 2.0.0-internal.7.0.1
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 +103 -0
- package/dist/blobManager.d.ts +3 -6
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +23 -48
- package/dist/blobManager.js.map +1 -1
- package/dist/containerHandleContext.js +3 -3
- package/dist/containerHandleContext.js.map +1 -1
- package/dist/containerRuntime.d.ts +13 -14
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +253 -237
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.js +9 -9
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +2 -3
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +88 -87
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreRegistry.js +3 -3
- package/dist/dataStoreRegistry.js.map +1 -1
- package/dist/dataStores.d.ts +0 -16
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +0 -48
- package/dist/dataStores.js.map +1 -1
- package/dist/deltaManagerProxyBase.js +4 -4
- package/dist/deltaManagerProxyBase.js.map +1 -1
- package/dist/deltaManagerSummarizerProxy.js +6 -6
- package/dist/deltaManagerSummarizerProxy.js.map +1 -1
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +12 -3
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +54 -31
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.d.ts +1 -0
- package/dist/gc/gcConfigs.d.ts.map +1 -1
- package/dist/gc/gcConfigs.js +12 -2
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +25 -22
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts +13 -7
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js +74 -42
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/gc/gcUnreferencedStateTracker.js +3 -3
- package/dist/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/dist/gc/index.d.ts +2 -2
- package/dist/gc/index.d.ts.map +1 -1
- package/dist/gc/index.js +1 -5
- package/dist/gc/index.js.map +1 -1
- package/dist/id-compressor/appendOnlySortedMap.js.map +1 -1
- package/dist/id-compressor/idCompressor.js.map +1 -1
- package/dist/id-compressor/identifiers.d.ts +3 -3
- package/dist/id-compressor/identifiers.d.ts.map +1 -1
- package/dist/messageTypes.d.ts +17 -17
- package/dist/messageTypes.d.ts.map +1 -1
- package/dist/messageTypes.js +1 -1
- package/dist/messageTypes.js.map +1 -1
- package/dist/opLifecycle/batchManager.js +6 -6
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts +2 -2
- package/dist/opLifecycle/definitions.d.ts.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 +3 -19
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +20 -39
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/summary/orderedClientElection.d.ts +3 -3
- package/dist/summary/orderedClientElection.d.ts.map +1 -1
- package/dist/summary/orderedClientElection.js +54 -54
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.js +6 -6
- package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/summary/runningSummarizer.js +37 -37
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.d.ts.map +1 -1
- package/dist/summary/summarizer.js +8 -6
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerClientElection.js +6 -6
- package/dist/summary/summarizerClientElection.js.map +1 -1
- package/dist/summary/summarizerHeuristics.js +9 -9
- package/dist/summary/summarizerHeuristics.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +7 -7
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.js +3 -3
- package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +2 -2
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +12 -12
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summaryCollection.d.ts +2 -2
- package/dist/summary/summaryCollection.d.ts.map +1 -1
- package/dist/summary/summaryCollection.js +21 -21
- package/dist/summary/summaryCollection.js.map +1 -1
- package/dist/summary/summaryFormat.d.ts +5 -5
- package/dist/summary/summaryFormat.d.ts.map +1 -1
- package/dist/summary/summaryGenerator.d.ts +3 -3
- package/dist/summary/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryManager.js +7 -7
- package/dist/summary/summaryManager.js.map +1 -1
- package/dist/throttler.js +16 -16
- package/dist/throttler.js.map +1 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/lib/blobManager.d.ts +3 -6
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +24 -49
- package/lib/blobManager.js.map +1 -1
- package/lib/containerHandleContext.js +3 -3
- package/lib/containerHandleContext.js.map +1 -1
- package/lib/containerRuntime.d.ts +13 -14
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +249 -235
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.js +9 -9
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +2 -3
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +89 -88
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreRegistry.js +3 -3
- package/lib/dataStoreRegistry.js.map +1 -1
- package/lib/dataStores.d.ts +0 -16
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +2 -50
- package/lib/dataStores.js.map +1 -1
- package/lib/deltaManagerProxyBase.js +4 -4
- package/lib/deltaManagerProxyBase.js.map +1 -1
- package/lib/deltaManagerSummarizerProxy.js +6 -6
- package/lib/deltaManagerSummarizerProxy.js.map +1 -1
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts +12 -3
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +55 -32
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcConfigs.d.ts +1 -0
- package/lib/gc/gcConfigs.d.ts.map +1 -1
- package/lib/gc/gcConfigs.js +14 -4
- package/lib/gc/gcConfigs.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +25 -22
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts +13 -7
- package/lib/gc/gcTelemetry.d.ts.map +1 -1
- package/lib/gc/gcTelemetry.js +74 -42
- package/lib/gc/gcTelemetry.js.map +1 -1
- package/lib/gc/gcUnreferencedStateTracker.js +3 -3
- package/lib/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/lib/gc/index.d.ts +2 -2
- package/lib/gc/index.d.ts.map +1 -1
- package/lib/gc/index.js +2 -2
- package/lib/gc/index.js.map +1 -1
- package/lib/id-compressor/appendOnlySortedMap.js.map +1 -1
- package/lib/id-compressor/idCompressor.js.map +1 -1
- package/lib/id-compressor/identifiers.d.ts +3 -3
- package/lib/id-compressor/identifiers.d.ts.map +1 -1
- package/lib/messageTypes.d.ts +17 -17
- package/lib/messageTypes.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.js +6 -6
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/definitions.d.ts +2 -2
- package/lib/opLifecycle/definitions.d.ts.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 +3 -19
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +20 -39
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/summary/orderedClientElection.d.ts +3 -3
- package/lib/summary/orderedClientElection.d.ts.map +1 -1
- package/lib/summary/orderedClientElection.js +54 -54
- package/lib/summary/orderedClientElection.js.map +1 -1
- package/lib/summary/runWhileConnectedCoordinator.js +6 -6
- package/lib/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/lib/summary/runningSummarizer.js +37 -37
- package/lib/summary/runningSummarizer.js.map +1 -1
- package/lib/summary/summarizer.d.ts.map +1 -1
- package/lib/summary/summarizer.js +8 -6
- package/lib/summary/summarizer.js.map +1 -1
- package/lib/summary/summarizerClientElection.js +6 -6
- package/lib/summary/summarizerClientElection.js.map +1 -1
- package/lib/summary/summarizerHeuristics.js +9 -9
- package/lib/summary/summarizerHeuristics.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js +7 -7
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.js +3 -3
- package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +2 -2
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.d.ts +12 -12
- package/lib/summary/summarizerTypes.d.ts.map +1 -1
- package/lib/summary/summaryCollection.d.ts +2 -2
- package/lib/summary/summaryCollection.d.ts.map +1 -1
- package/lib/summary/summaryCollection.js +21 -21
- package/lib/summary/summaryCollection.js.map +1 -1
- package/lib/summary/summaryFormat.d.ts +5 -5
- package/lib/summary/summaryFormat.d.ts.map +1 -1
- package/lib/summary/summaryGenerator.d.ts +3 -3
- package/lib/summary/summaryGenerator.d.ts.map +1 -1
- package/lib/summary/summaryManager.js +6 -6
- package/lib/summary/summaryManager.js.map +1 -1
- package/lib/throttler.js +16 -16
- package/lib/throttler.js.map +1 -1
- package/package.json +53 -21
- package/src/blobManager.ts +18 -58
- package/src/containerRuntime.ts +68 -49
- package/src/dataStore.ts +1 -1
- package/src/dataStoreContext.ts +18 -14
- package/src/dataStores.ts +2 -80
- package/src/gc/garbageCollection.ts +53 -24
- package/src/gc/gcConfigs.ts +22 -4
- package/src/gc/gcDefinitions.ts +23 -20
- package/src/gc/gcEarlyAdoption.md +1 -1
- package/src/gc/gcTelemetry.ts +103 -56
- package/src/gc/index.ts +0 -4
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +7 -46
- package/src/summary/summarizer.ts +3 -1
package/src/dataStores.ts
CHANGED
|
@@ -50,12 +50,7 @@ import { buildSnapshotTree } from "@fluidframework/driver-utils";
|
|
|
50
50
|
import { assert, Lazy } from "@fluidframework/core-utils";
|
|
51
51
|
import { v4 as uuid } from "uuid";
|
|
52
52
|
import { DataStoreContexts } from "./dataStoreContexts";
|
|
53
|
-
import {
|
|
54
|
-
ContainerRuntime,
|
|
55
|
-
defaultRuntimeHeaderData,
|
|
56
|
-
RuntimeHeaderData,
|
|
57
|
-
TombstoneResponseHeaderKey,
|
|
58
|
-
} from "./containerRuntime";
|
|
53
|
+
import { ContainerRuntime, defaultRuntimeHeaderData, RuntimeHeaderData } from "./containerRuntime";
|
|
59
54
|
import {
|
|
60
55
|
FluidDataStoreContext,
|
|
61
56
|
RemoteFluidDataStoreContext,
|
|
@@ -65,12 +60,7 @@ import {
|
|
|
65
60
|
} from "./dataStoreContext";
|
|
66
61
|
import { StorageServiceWithAttachBlobs } from "./storageServiceWithAttachBlobs";
|
|
67
62
|
import { IDataStoreAliasMessage, isDataStoreAliasMessage } from "./dataStore";
|
|
68
|
-
import {
|
|
69
|
-
GCNodeType,
|
|
70
|
-
disableDatastoreSweepKey,
|
|
71
|
-
throwOnTombstoneLoadKey,
|
|
72
|
-
sendGCUnexpectedUsageEvent,
|
|
73
|
-
} from "./gc";
|
|
63
|
+
import { GCNodeType, disableDatastoreSweepKey, sendGCUnexpectedUsageEvent } from "./gc";
|
|
74
64
|
import {
|
|
75
65
|
summarizerClientType,
|
|
76
66
|
IContainerRuntimeMetadata,
|
|
@@ -104,8 +94,6 @@ export class DataStores implements IDisposable {
|
|
|
104
94
|
// Stores the ids of new data stores between two GC runs. This is used to notify the garbage collector of new
|
|
105
95
|
// root data stores that are added.
|
|
106
96
|
private dataStoresSinceLastGC: string[] = [];
|
|
107
|
-
/** If true, throw an error when a tombstone data store is retrieved. */
|
|
108
|
-
private readonly throwOnTombstoneLoad: boolean;
|
|
109
97
|
// The handle to the container runtime. This is used mainly for GC purposes to represent outbound reference from
|
|
110
98
|
// the container runtime to other nodes.
|
|
111
99
|
private readonly containerRuntimeHandle: IFluidHandle;
|
|
@@ -140,12 +128,6 @@ export class DataStores implements IDisposable {
|
|
|
140
128
|
this.runtime.IFluidHandleContext,
|
|
141
129
|
);
|
|
142
130
|
|
|
143
|
-
// Tombstone should only throw when the feature flag is enabled and the client isn't a summarizer
|
|
144
|
-
this.throwOnTombstoneLoad =
|
|
145
|
-
this.mc.config.getBoolean(throwOnTombstoneLoadKey) === true &&
|
|
146
|
-
this.runtime.gcTombstoneEnforcementAllowed &&
|
|
147
|
-
this.runtime.clientDetails.type !== summarizerClientType;
|
|
148
|
-
|
|
149
131
|
// Extract stores stored inside the snapshot
|
|
150
132
|
const fluidDataStores = new Map<string, ISnapshotTree>();
|
|
151
133
|
if (baseSnapshot) {
|
|
@@ -455,9 +437,6 @@ export class DataStores implements IDisposable {
|
|
|
455
437
|
const request: IRequest = { url: id };
|
|
456
438
|
throw responseToException(create404Response(request), request);
|
|
457
439
|
}
|
|
458
|
-
|
|
459
|
-
this.validateNotTombstoned(context, requestHeaderData);
|
|
460
|
-
|
|
461
440
|
return context;
|
|
462
441
|
}
|
|
463
442
|
|
|
@@ -477,8 +456,6 @@ export class DataStores implements IDisposable {
|
|
|
477
456
|
if (context === undefined) {
|
|
478
457
|
return undefined;
|
|
479
458
|
}
|
|
480
|
-
// Check if the data store is tombstoned. If so, we want to log a telemetry event.
|
|
481
|
-
this.checkIfTombstoned(context, requestHeaderData);
|
|
482
459
|
return context;
|
|
483
460
|
}
|
|
484
461
|
|
|
@@ -529,61 +506,6 @@ export class DataStores implements IDisposable {
|
|
|
529
506
|
}
|
|
530
507
|
}
|
|
531
508
|
|
|
532
|
-
/**
|
|
533
|
-
* Checks if the data store has not been marked as tombstone by GC or not.
|
|
534
|
-
* @param context - the data store context in question
|
|
535
|
-
* @param requestHeaderData - the request header information to log if the validation detects the data store has been tombstoned
|
|
536
|
-
* @returns true if the data store is tombstoned. Otherwise, returns false.
|
|
537
|
-
*/
|
|
538
|
-
private checkIfTombstoned(
|
|
539
|
-
context: FluidDataStoreContext,
|
|
540
|
-
requestHeaderData: RuntimeHeaderData,
|
|
541
|
-
) {
|
|
542
|
-
if (!context.tombstoned) {
|
|
543
|
-
return false;
|
|
544
|
-
}
|
|
545
|
-
const logErrorEvent = this.throwOnTombstoneLoad && !requestHeaderData.allowTombstone;
|
|
546
|
-
sendGCUnexpectedUsageEvent(
|
|
547
|
-
this.mc,
|
|
548
|
-
{
|
|
549
|
-
eventName: "GC_Tombstone_DataStore_Requested",
|
|
550
|
-
category: logErrorEvent ? "error" : "generic",
|
|
551
|
-
isSummarizerClient: this.runtime.clientDetails.type === summarizerClientType,
|
|
552
|
-
id: context.id,
|
|
553
|
-
headers: JSON.stringify(requestHeaderData),
|
|
554
|
-
gcTombstoneEnforcementAllowed: this.runtime.gcTombstoneEnforcementAllowed,
|
|
555
|
-
},
|
|
556
|
-
context.isLoaded ? context.packagePath : undefined,
|
|
557
|
-
);
|
|
558
|
-
return true;
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
/**
|
|
562
|
-
* Validates that the data store context requested has not been marked as tombstone by GC.
|
|
563
|
-
* @param context - the data store context in question
|
|
564
|
-
* @param request - the request information to log if the validation detects the data store has been tombstoned
|
|
565
|
-
* @param requestHeaderData - the request header information to log if the validation detects the data store has been tombstoned
|
|
566
|
-
*/
|
|
567
|
-
private validateNotTombstoned(
|
|
568
|
-
context: FluidDataStoreContext,
|
|
569
|
-
requestHeaderData: RuntimeHeaderData,
|
|
570
|
-
) {
|
|
571
|
-
if (this.checkIfTombstoned(context, requestHeaderData)) {
|
|
572
|
-
// The requested data store is removed by gc. Create a 404 gc response exception.
|
|
573
|
-
const request: IRequest = { url: context.id };
|
|
574
|
-
const error = responseToException(
|
|
575
|
-
createResponseError(404, "DataStore was deleted", request, {
|
|
576
|
-
[TombstoneResponseHeaderKey]: true,
|
|
577
|
-
}),
|
|
578
|
-
request,
|
|
579
|
-
);
|
|
580
|
-
// Throw an error if configured via options and via request headers.
|
|
581
|
-
if (this.throwOnTombstoneLoad && !requestHeaderData.allowTombstone) {
|
|
582
|
-
throw error;
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
|
|
587
509
|
public processSignal(fluidDataStoreId: string, message: IInboundSignalMessage, local: boolean) {
|
|
588
510
|
this.validateNotDeleted(fluidDataStoreId);
|
|
589
511
|
const context = this.contexts.get(fluidDataStoreId);
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { LazyPromise, Timer } from "@fluidframework/core-utils";
|
|
7
|
-
import { IRequest
|
|
7
|
+
import { IRequest } from "@fluidframework/core-interfaces";
|
|
8
8
|
import {
|
|
9
9
|
gcTreeKey,
|
|
10
10
|
IGarbageCollectionData,
|
|
@@ -23,9 +23,9 @@ import {
|
|
|
23
23
|
} from "@fluidframework/telemetry-utils";
|
|
24
24
|
|
|
25
25
|
import {
|
|
26
|
-
AllowInactiveRequestHeaderKey,
|
|
27
26
|
InactiveResponseHeaderKey,
|
|
28
|
-
|
|
27
|
+
RuntimeHeaderData,
|
|
28
|
+
TombstoneResponseHeaderKey,
|
|
29
29
|
} from "../containerRuntime";
|
|
30
30
|
import { ClientSessionExpiredError } from "../error";
|
|
31
31
|
import { IRefreshSummaryResult } from "../summary";
|
|
@@ -113,6 +113,19 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
113
113
|
private readonly summaryStateTracker: GCSummaryStateTracker;
|
|
114
114
|
private readonly telemetryTracker: GCTelemetryTracker;
|
|
115
115
|
|
|
116
|
+
/** If false, loading or using a Tombstoned object should merely log, not fail */
|
|
117
|
+
public get tombstoneEnforcementAllowed(): boolean {
|
|
118
|
+
return this.configs.tombstoneEnforcementAllowed;
|
|
119
|
+
}
|
|
120
|
+
/** If true, throw an error when a tombstone data store is retrieved */
|
|
121
|
+
public get throwOnTombstoneLoad(): boolean {
|
|
122
|
+
return this.configs.throwOnTombstoneLoad;
|
|
123
|
+
}
|
|
124
|
+
/** If true, throw an error when a tombstone data store is used */
|
|
125
|
+
public get throwOnTombstoneUsage(): boolean {
|
|
126
|
+
return this.configs.throwOnTombstoneUsage;
|
|
127
|
+
}
|
|
128
|
+
|
|
116
129
|
/** For a given node path, returns the node's package path. */
|
|
117
130
|
private readonly getNodePackagePath: (
|
|
118
131
|
nodePath: string,
|
|
@@ -176,7 +189,6 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
176
189
|
this.mc,
|
|
177
190
|
this.configs,
|
|
178
191
|
this.isSummarizerClient,
|
|
179
|
-
this.runtime.gcTombstoneEnforcementAllowed,
|
|
180
192
|
createParams.createContainerMetadata,
|
|
181
193
|
(nodeId: string) => this.runtime.getNodeType(nodeId),
|
|
182
194
|
(nodeId: string) => this.unreferencedNodesState.get(nodeId),
|
|
@@ -850,11 +862,13 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
850
862
|
}
|
|
851
863
|
|
|
852
864
|
/**
|
|
853
|
-
* Called when a node with the given id is updated. If the node is inactive, log an error
|
|
865
|
+
* Called when a node with the given id is updated. If the node is inactive or tombstoned, this will log an error
|
|
866
|
+
* or throw an error if failing on incorrect usage is configured.
|
|
854
867
|
* @param nodePath - The path of the node that changed.
|
|
855
868
|
* @param reason - Whether the node was loaded or changed.
|
|
856
869
|
* @param timestampMs - The timestamp when the node changed.
|
|
857
870
|
* @param packagePath - The package path of the node. This may not be available if the node hasn't been loaded yet.
|
|
871
|
+
* @param request - The original request for loads to preserve it in telemetry.
|
|
858
872
|
* @param requestHeaders - If the node was loaded via request path, the headers in the request.
|
|
859
873
|
*/
|
|
860
874
|
public nodeUpdated(
|
|
@@ -862,12 +876,15 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
862
876
|
reason: "Loaded" | "Changed",
|
|
863
877
|
timestampMs?: number,
|
|
864
878
|
packagePath?: readonly string[],
|
|
865
|
-
|
|
879
|
+
request?: IRequest,
|
|
880
|
+
headerData?: RuntimeHeaderData,
|
|
866
881
|
) {
|
|
867
882
|
if (!this.configs.shouldRunGC) {
|
|
868
883
|
return;
|
|
869
884
|
}
|
|
870
885
|
|
|
886
|
+
const isTombstoned = this.tombstones.includes(nodePath);
|
|
887
|
+
|
|
871
888
|
// This will log if appropriate
|
|
872
889
|
this.telemetryTracker.nodeUsed({
|
|
873
890
|
id: nodePath,
|
|
@@ -876,32 +893,44 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
876
893
|
timestampMs ?? this.runtime.getCurrentReferenceTimestampMs(),
|
|
877
894
|
packagePath,
|
|
878
895
|
completedGCRuns: this.completedRuns,
|
|
879
|
-
isTombstoned
|
|
896
|
+
isTombstoned,
|
|
880
897
|
lastSummaryTime: this.getLastSummaryTimestampMs(),
|
|
881
|
-
|
|
898
|
+
headers: headerData,
|
|
882
899
|
});
|
|
883
900
|
|
|
884
|
-
|
|
885
|
-
|
|
901
|
+
const nodeType = this.runtime.getNodeType(nodePath);
|
|
902
|
+
|
|
903
|
+
// Unless this is a Loaded event for a Blob or DataStore, we're done after telemetry tracking
|
|
904
|
+
if (reason !== "Loaded" || ![GCNodeType.Blob, GCNodeType.DataStore].includes(nodeType)) {
|
|
886
905
|
return;
|
|
887
906
|
}
|
|
888
907
|
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
if (shouldThrowOnInactiveLoad && state === "Inactive") {
|
|
897
|
-
const request: IRequest = { url: nodePath };
|
|
898
|
-
const error = responseToException(
|
|
899
|
-
createResponseError(404, "Object is inactive", request, {
|
|
900
|
-
[InactiveResponseHeaderKey]: true,
|
|
908
|
+
const errorRequest: IRequest = request ?? { url: nodePath };
|
|
909
|
+
// If the object is tombstoned and tombstone enforcement is configured, throw an error.
|
|
910
|
+
if (isTombstoned && this.throwOnTombstoneLoad && headerData?.allowTombstone !== true) {
|
|
911
|
+
// The requested data store is removed by gc. Create a 404 gc response exception.
|
|
912
|
+
throw responseToException(
|
|
913
|
+
createResponseError(404, `${nodeType} was tombstoned`, errorRequest, {
|
|
914
|
+
[TombstoneResponseHeaderKey]: true,
|
|
901
915
|
}),
|
|
902
|
-
|
|
916
|
+
errorRequest,
|
|
903
917
|
);
|
|
904
|
-
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
// If the object is inactive and inactive enforcement is configured, throw an error.
|
|
921
|
+
if (this.unreferencedNodesState.get(nodePath)?.state === "Inactive") {
|
|
922
|
+
const shouldThrowOnInactiveLoad =
|
|
923
|
+
!this.isSummarizerClient &&
|
|
924
|
+
this.configs.throwOnInactiveLoad === true &&
|
|
925
|
+
headerData?.allowInactive !== true;
|
|
926
|
+
if (shouldThrowOnInactiveLoad) {
|
|
927
|
+
throw responseToException(
|
|
928
|
+
createResponseError(404, `${nodeType} is inactive`, errorRequest, {
|
|
929
|
+
[InactiveResponseHeaderKey]: true,
|
|
930
|
+
}),
|
|
931
|
+
errorRequest,
|
|
932
|
+
);
|
|
933
|
+
}
|
|
905
934
|
}
|
|
906
935
|
}
|
|
907
936
|
|
package/src/gc/gcConfigs.ts
CHANGED
|
@@ -24,8 +24,10 @@ import {
|
|
|
24
24
|
runSessionExpiryKey,
|
|
25
25
|
runSweepKey,
|
|
26
26
|
stableGCVersion,
|
|
27
|
+
throwOnTombstoneLoadKey,
|
|
28
|
+
throwOnTombstoneUsageKey,
|
|
27
29
|
} from "./gcDefinitions";
|
|
28
|
-
import { getGCVersion, shouldAllowGcSweep } from "./gcHelpers";
|
|
30
|
+
import { getGCVersion, shouldAllowGcSweep, shouldAllowGcTombstoneEnforcement } from "./gcHelpers";
|
|
29
31
|
|
|
30
32
|
/**
|
|
31
33
|
* Generates configurations for the Garbage Collector that it uses to determine what to run and how.
|
|
@@ -42,6 +44,7 @@ export function generateGCConfigs(
|
|
|
42
44
|
gcOptions: IGCRuntimeOptions;
|
|
43
45
|
metadata: IContainerRuntimeMetadata | undefined;
|
|
44
46
|
existing: boolean;
|
|
47
|
+
isSummarizerClient: boolean;
|
|
45
48
|
},
|
|
46
49
|
): IGarbageCollectorConfigs {
|
|
47
50
|
let gcEnabled: boolean;
|
|
@@ -152,8 +155,6 @@ export function generateGCConfigs(
|
|
|
152
155
|
throw new UsageError("inactive timeout should not be greater than the sweep timeout");
|
|
153
156
|
}
|
|
154
157
|
|
|
155
|
-
const throwOnInactiveLoad: boolean | undefined = createParams.gcOptions.throwOnInactiveLoad;
|
|
156
|
-
|
|
157
158
|
// Whether we are running in test mode. In this mode, unreferenced nodes are immediately deleted.
|
|
158
159
|
const testMode =
|
|
159
160
|
mc.config.getBoolean(gcTestModeKey) ?? createParams.gcOptions.runGCInTestMode === true;
|
|
@@ -162,6 +163,20 @@ export function generateGCConfigs(
|
|
|
162
163
|
const tombstoneMode = !shouldRunSweep && mc.config.getBoolean(disableTombstoneKey) !== true;
|
|
163
164
|
const runFullGC = createParams.gcOptions.runFullGC;
|
|
164
165
|
|
|
166
|
+
const throwOnInactiveLoad: boolean | undefined = createParams.gcOptions.throwOnInactiveLoad;
|
|
167
|
+
const tombstoneEnforcementAllowed = shouldAllowGcTombstoneEnforcement(
|
|
168
|
+
createParams.metadata?.gcFeatureMatrix?.tombstoneGeneration /* persisted */,
|
|
169
|
+
createParams.gcOptions[gcTombstoneGenerationOptionName] /* current */,
|
|
170
|
+
);
|
|
171
|
+
const throwOnTombstoneLoad =
|
|
172
|
+
mc.config.getBoolean(throwOnTombstoneLoadKey) === true &&
|
|
173
|
+
tombstoneEnforcementAllowed &&
|
|
174
|
+
!createParams.isSummarizerClient;
|
|
175
|
+
const throwOnTombstoneUsage =
|
|
176
|
+
mc.config.getBoolean(throwOnTombstoneUsageKey) === true &&
|
|
177
|
+
tombstoneEnforcementAllowed &&
|
|
178
|
+
!createParams.isSummarizerClient;
|
|
179
|
+
|
|
165
180
|
return {
|
|
166
181
|
gcEnabled,
|
|
167
182
|
sweepEnabled,
|
|
@@ -173,10 +188,13 @@ export function generateGCConfigs(
|
|
|
173
188
|
sessionExpiryTimeoutMs,
|
|
174
189
|
sweepTimeoutMs,
|
|
175
190
|
inactiveTimeoutMs,
|
|
176
|
-
throwOnInactiveLoad,
|
|
177
191
|
persistedGcFeatureMatrix,
|
|
178
192
|
gcVersionInBaseSnapshot,
|
|
179
193
|
gcVersionInEffect,
|
|
194
|
+
throwOnInactiveLoad,
|
|
195
|
+
tombstoneEnforcementAllowed,
|
|
196
|
+
throwOnTombstoneLoad,
|
|
197
|
+
throwOnTombstoneUsage,
|
|
180
198
|
};
|
|
181
199
|
}
|
|
182
200
|
|
package/src/gc/gcDefinitions.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { ICriticalContainerError } from "@fluidframework/container-definitions";
|
|
7
|
-
import {
|
|
7
|
+
import { IRequest } from "@fluidframework/core-interfaces";
|
|
8
8
|
import { ISnapshotTree } from "@fluidframework/protocol-definitions";
|
|
9
9
|
import {
|
|
10
10
|
IGarbageCollectionData,
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
ICreateContainerMetadata,
|
|
20
20
|
IRefreshSummaryResult,
|
|
21
21
|
} from "../summary";
|
|
22
|
+
import { RuntimeHeaderData } from "../containerRuntime";
|
|
22
23
|
|
|
23
24
|
export type GCVersion = number;
|
|
24
25
|
|
|
@@ -193,8 +194,6 @@ export interface IGarbageCollectionRuntime {
|
|
|
193
194
|
getNodeType(nodePath: string): GCNodeType;
|
|
194
195
|
/** Called when the runtime should close because of an error. */
|
|
195
196
|
closeFn: (error?: ICriticalContainerError) => void;
|
|
196
|
-
/** If false, loading or using a Tombstoned object should merely log, not fail */
|
|
197
|
-
gcTombstoneEnforcementAllowed: boolean;
|
|
198
197
|
}
|
|
199
198
|
|
|
200
199
|
/** Defines the contract for the garbage collector. */
|
|
@@ -205,6 +204,12 @@ export interface IGarbageCollector {
|
|
|
205
204
|
readonly summaryStateNeedsReset: boolean;
|
|
206
205
|
/** The count of data stores whose GC state updated since the last summary. */
|
|
207
206
|
readonly updatedDSCountSinceLastSummary: number;
|
|
207
|
+
/** Tells whether tombstone feature is enabled and enforced. */
|
|
208
|
+
readonly tombstoneEnforcementAllowed: boolean;
|
|
209
|
+
/** Tells whether loading a tombstone object should fail or merely log. */
|
|
210
|
+
readonly throwOnTombstoneLoad: boolean;
|
|
211
|
+
/** Tells whether using a tombstone object should fail or merely log. */
|
|
212
|
+
readonly throwOnTombstoneUsage: boolean;
|
|
208
213
|
/** Initialize the state from the base snapshot after its creation. */
|
|
209
214
|
initializeBaseState(): Promise<void>;
|
|
210
215
|
/** Run garbage collection and update the reference / used state of the system. */
|
|
@@ -228,13 +233,17 @@ export interface IGarbageCollector {
|
|
|
228
233
|
getBaseGCDetails(): Promise<IGarbageCollectionDetailsBase>;
|
|
229
234
|
/** Called when the latest summary of the system has been refreshed. */
|
|
230
235
|
refreshLatestSummary(result: IRefreshSummaryResult): Promise<void>;
|
|
231
|
-
/**
|
|
236
|
+
/**
|
|
237
|
+
* Called when a node with the given path is updated. If the node is inactive or tombstoned, this will log an error
|
|
238
|
+
* or throw an error if failing on incorrect usage is configured.
|
|
239
|
+
*/
|
|
232
240
|
nodeUpdated(
|
|
233
241
|
nodePath: string,
|
|
234
242
|
reason: "Loaded" | "Changed",
|
|
235
243
|
timestampMs?: number,
|
|
236
244
|
packagePath?: readonly string[],
|
|
237
|
-
|
|
245
|
+
request?: IRequest,
|
|
246
|
+
headerData?: RuntimeHeaderData,
|
|
238
247
|
): void;
|
|
239
248
|
/** Called when a reference is added to a node. Used to identify nodes that were referenced between summaries. */
|
|
240
249
|
addedOutboundReference(fromNodePath: string, toNodePath: string): void;
|
|
@@ -267,24 +276,12 @@ export interface IGCRuntimeOptions {
|
|
|
267
276
|
* GC has mark phase and sweep phase. In mark phase, unreferenced objects are identified
|
|
268
277
|
* and marked as such in the summary. This option enables the mark phase.
|
|
269
278
|
* In sweep phase, unreferenced objects are eventually deleted from the container if they meet certain conditions.
|
|
270
|
-
* Sweep phase can be enabled
|
|
279
|
+
* Sweep phase can be enabled using the "gcSweepGeneration" option.
|
|
271
280
|
*
|
|
272
281
|
* Note: This setting is persisted in the container's summary and cannot be changed.
|
|
273
282
|
*/
|
|
274
283
|
gcAllowed?: boolean;
|
|
275
284
|
|
|
276
|
-
/**
|
|
277
|
-
* @deprecated - @see gcSweepGenerationOptionName and @see GCFeatureMatrix.sweepGeneration
|
|
278
|
-
*
|
|
279
|
-
* Flag that if true, enables GC's sweep phase for a new container.
|
|
280
|
-
*
|
|
281
|
-
* This will allow GC to eventually delete unreferenced objects from the container.
|
|
282
|
-
* This flag should only be set to true if "gcAllowed" is true.
|
|
283
|
-
*
|
|
284
|
-
* Note: This setting is persisted in the container's summary and cannot be changed.
|
|
285
|
-
*/
|
|
286
|
-
sweepAllowed?: boolean;
|
|
287
|
-
|
|
288
285
|
/**
|
|
289
286
|
* Flag that if true, will disable garbage collection for the session.
|
|
290
287
|
* Can be used to disable running GC on containers where it is allowed via the gcAllowed option.
|
|
@@ -344,8 +341,6 @@ export interface IGarbageCollectorConfigs {
|
|
|
344
341
|
readonly sweepTimeoutMs: number | undefined;
|
|
345
342
|
/** The time after which an unreferenced node is inactive. */
|
|
346
343
|
readonly inactiveTimeoutMs: number;
|
|
347
|
-
/** It is easier for users to diagnose InactiveObject usage if we throw on load, which this option enables */
|
|
348
|
-
readonly throwOnInactiveLoad: boolean | undefined;
|
|
349
344
|
/** Tracks whether GC should run in test mode. In this mode, unreferenced objects are deleted immediately. */
|
|
350
345
|
readonly testMode: boolean;
|
|
351
346
|
/**
|
|
@@ -361,6 +356,14 @@ export interface IGarbageCollectorConfigs {
|
|
|
361
356
|
readonly gcVersionInBaseSnapshot: GCVersion | undefined;
|
|
362
357
|
/** The current version of GC data in the running code */
|
|
363
358
|
readonly gcVersionInEffect: GCVersion;
|
|
359
|
+
/** It is easier for users to diagnose InactiveObject usage if we throw on load, which this option enables */
|
|
360
|
+
readonly throwOnInactiveLoad: boolean | undefined;
|
|
361
|
+
/** If false, loading or using a Tombstoned object should merely log, not fail */
|
|
362
|
+
readonly tombstoneEnforcementAllowed: boolean;
|
|
363
|
+
/** If true, throw an error when a tombstone data store is retrieved */
|
|
364
|
+
readonly throwOnTombstoneLoad: boolean;
|
|
365
|
+
/** If true, throw an error when a tombstone data store is used. */
|
|
366
|
+
readonly throwOnTombstoneUsage: boolean;
|
|
364
367
|
}
|
|
365
368
|
|
|
366
369
|
/** The state of node that is unreferenced. */
|
|
@@ -78,7 +78,7 @@ For this to work, you must disable the `Fluid.GarbageCollection.ThrowOnTombstone
|
|
|
78
78
|
|
|
79
79
|
When a Tombstoned object (via `handle.get()`) fails to load, the 404 response error object has an `underlyingResponseHeaders` with the
|
|
80
80
|
`isTombstoned` flag set to true: i.e. `error.underlyingResponseHeaders?.isTombstoned === true`. In this case,
|
|
81
|
-
you may turn around and use `
|
|
81
|
+
you may turn around and use `IContainerRuntimeWithResolveHandle_Deprecated.resolveHandle` with `allowTombstone: true` in `IRequest.headers` to request
|
|
82
82
|
the object again - this time it will succeed.
|
|
83
83
|
|
|
84
84
|
To be very clear once again - This path uses deprecated APIs (`resolveHandle`) and comes with no guarantees of support.
|