@fluidframework/container-runtime 2.0.0-dev-rc.3.0.0.254866 → 2.0.0-dev-rc.5.0.0.263932
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 +69 -0
- package/api-report/container-runtime.api.md +93 -39
- package/dist/batchTracker.d.ts +1 -1
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +7 -7
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +2 -4
- package/dist/blobManager.js.map +1 -1
- package/dist/channelCollection.d.ts +10 -6
- package/dist/channelCollection.d.ts.map +1 -1
- package/dist/channelCollection.js +85 -22
- package/dist/channelCollection.js.map +1 -1
- package/dist/connectionTelemetry.d.ts +2 -2
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +54 -5
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerRuntime.d.ts +22 -35
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +232 -174
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts +1 -1
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +9 -6
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +19 -5
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.d.ts +2 -0
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js +7 -0
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/deltaManagerProxies.d.ts +81 -0
- package/dist/deltaManagerProxies.d.ts.map +1 -0
- package/dist/{deltaManagerSummarizerProxy.js → deltaManagerProxies.js} +75 -20
- package/dist/deltaManagerProxies.js.map +1 -0
- package/dist/deltaScheduler.d.ts +2 -2
- package/dist/deltaScheduler.d.ts.map +1 -1
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +5 -12
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +45 -29
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +27 -6
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcHelpers.d.ts +5 -4
- package/dist/gc/gcHelpers.d.ts.map +1 -1
- package/dist/gc/gcHelpers.js +14 -2
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts +14 -4
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js +24 -21
- package/dist/gc/gcTelemetry.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 +2 -2
- package/dist/gc/index.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/{alpha.d.ts → legacy.d.ts} +8 -1
- package/dist/messageTypes.d.ts +5 -2
- package/dist/messageTypes.d.ts.map +1 -1
- package/dist/messageTypes.js.map +1 -1
- package/dist/metadata.d.ts +2 -2
- package/dist/metadata.d.ts.map +1 -1
- package/dist/metadata.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts +4 -1
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js +0 -10
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +6 -6
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +2 -2
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSplitter.js +1 -1
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +0 -4
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +7 -38
- package/dist/opLifecycle/outbox.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 +9 -2
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +26 -10
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/public.d.ts +3 -0
- package/dist/scheduleManager.d.ts +2 -2
- package/dist/scheduleManager.d.ts.map +1 -1
- package/dist/scheduleManager.js.map +1 -1
- package/dist/summary/documentSchema.d.ts +3 -1
- package/dist/summary/documentSchema.d.ts.map +1 -1
- package/dist/summary/documentSchema.js +34 -16
- package/dist/summary/documentSchema.js.map +1 -1
- package/dist/summary/index.d.ts +1 -1
- package/dist/summary/index.d.ts.map +1 -1
- package/dist/summary/index.js.map +1 -1
- package/dist/summary/orderedClientElection.d.ts +2 -2
- package/dist/summary/orderedClientElection.d.ts.map +1 -1
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/runningSummarizer.js +10 -10
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.d.ts +1 -2
- package/dist/summary/summarizer.d.ts.map +1 -1
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerClientElection.d.ts +1 -1
- package/dist/summary/summarizerClientElection.d.ts.map +1 -1
- package/dist/summary/summarizerClientElection.js.map +1 -1
- package/dist/summary/summarizerHeuristics.d.ts +1 -1
- package/dist/summary/summarizerHeuristics.d.ts.map +1 -1
- package/dist/summary/summarizerHeuristics.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.d.ts +4 -3
- package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +4 -10
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +2 -3
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +1 -2
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +2 -9
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +3 -5
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.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.map +1 -1
- package/dist/summary/summaryFormat.d.ts +25 -5
- package/dist/summary/summaryFormat.d.ts.map +1 -1
- package/dist/summary/summaryFormat.js.map +1 -1
- package/dist/summary/summaryGenerator.d.ts +1 -2
- package/dist/summary/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryGenerator.js +12 -11
- package/dist/summary/summaryGenerator.js.map +1 -1
- package/dist/summary/summaryManager.d.ts.map +1 -1
- package/dist/summary/summaryManager.js +5 -5
- package/dist/summary/summaryManager.js.map +1 -1
- package/{lib/beta.d.ts → internal.d.ts} +2 -0
- package/{dist/beta.d.ts → legacy.d.ts} +2 -0
- package/lib/batchTracker.d.ts +1 -1
- package/lib/batchTracker.d.ts.map +1 -1
- package/lib/batchTracker.js.map +1 -1
- package/lib/blobManager.d.ts +7 -7
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +3 -5
- package/lib/blobManager.js.map +1 -1
- package/lib/channelCollection.d.ts +10 -6
- package/lib/channelCollection.d.ts.map +1 -1
- package/lib/channelCollection.js +88 -25
- package/lib/channelCollection.js.map +1 -1
- package/lib/connectionTelemetry.d.ts +2 -2
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +49 -0
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerRuntime.d.ts +22 -35
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +232 -174
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.d.ts +1 -1
- package/lib/dataStore.d.ts.map +1 -1
- package/lib/dataStore.js +1 -1
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +9 -6
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +21 -7
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreContexts.d.ts +2 -0
- package/lib/dataStoreContexts.d.ts.map +1 -1
- package/lib/dataStoreContexts.js +7 -0
- package/lib/dataStoreContexts.js.map +1 -1
- package/lib/deltaManagerProxies.d.ts +81 -0
- package/lib/deltaManagerProxies.d.ts.map +1 -0
- package/lib/{deltaManagerSummarizerProxy.js → deltaManagerProxies.js} +72 -19
- package/lib/deltaManagerProxies.js.map +1 -0
- package/lib/deltaScheduler.d.ts +2 -2
- package/lib/deltaScheduler.d.ts.map +1 -1
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts +5 -12
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +47 -31
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +27 -6
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/gc/gcHelpers.d.ts +5 -4
- package/lib/gc/gcHelpers.d.ts.map +1 -1
- package/lib/gc/gcHelpers.js +12 -1
- package/lib/gc/gcHelpers.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts +14 -4
- package/lib/gc/gcTelemetry.d.ts.map +1 -1
- package/lib/gc/gcTelemetry.js +24 -21
- package/lib/gc/gcTelemetry.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 +1 -1
- package/lib/gc/index.js.map +1 -1
- package/lib/index.d.ts +3 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/{alpha.d.ts → legacy.d.ts} +8 -1
- package/lib/messageTypes.d.ts +5 -2
- package/lib/messageTypes.d.ts.map +1 -1
- package/lib/messageTypes.js.map +1 -1
- package/lib/metadata.d.ts +2 -2
- package/lib/metadata.d.ts.map +1 -1
- package/lib/metadata.js.map +1 -1
- package/lib/opLifecycle/batchManager.d.ts +4 -1
- package/lib/opLifecycle/batchManager.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.js +0 -10
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +6 -6
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.js +2 -2
- package/lib/opLifecycle/opGroupingManager.js.map +1 -1
- package/lib/opLifecycle/opSplitter.js +1 -1
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts +0 -4
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +7 -38
- package/lib/opLifecycle/outbox.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 +9 -2
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +27 -11
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/public.d.ts +3 -0
- package/lib/scheduleManager.d.ts +2 -2
- package/lib/scheduleManager.d.ts.map +1 -1
- package/lib/scheduleManager.js.map +1 -1
- package/lib/summary/documentSchema.d.ts +3 -1
- package/lib/summary/documentSchema.d.ts.map +1 -1
- package/lib/summary/documentSchema.js +34 -16
- package/lib/summary/documentSchema.js.map +1 -1
- package/lib/summary/index.d.ts +1 -1
- package/lib/summary/index.d.ts.map +1 -1
- package/lib/summary/index.js.map +1 -1
- package/lib/summary/orderedClientElection.d.ts +2 -2
- package/lib/summary/orderedClientElection.d.ts.map +1 -1
- package/lib/summary/orderedClientElection.js +1 -1
- package/lib/summary/orderedClientElection.js.map +1 -1
- package/lib/summary/runningSummarizer.js +1 -1
- package/lib/summary/runningSummarizer.js.map +1 -1
- package/lib/summary/summarizer.d.ts +1 -2
- package/lib/summary/summarizer.d.ts.map +1 -1
- package/lib/summary/summarizer.js.map +1 -1
- package/lib/summary/summarizerClientElection.d.ts +1 -1
- package/lib/summary/summarizerClientElection.d.ts.map +1 -1
- package/lib/summary/summarizerClientElection.js.map +1 -1
- package/lib/summary/summarizerHeuristics.d.ts +1 -1
- package/lib/summary/summarizerHeuristics.d.ts.map +1 -1
- package/lib/summary/summarizerHeuristics.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.d.ts +4 -3
- package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js +4 -10
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts +2 -3
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +1 -2
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js +2 -9
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/lib/summary/summarizerTypes.d.ts +3 -5
- package/lib/summary/summarizerTypes.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.js.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.map +1 -1
- package/lib/summary/summaryFormat.d.ts +25 -5
- package/lib/summary/summaryFormat.d.ts.map +1 -1
- package/lib/summary/summaryFormat.js.map +1 -1
- package/lib/summary/summaryGenerator.d.ts +1 -2
- package/lib/summary/summaryGenerator.d.ts.map +1 -1
- package/lib/summary/summaryGenerator.js +5 -4
- package/lib/summary/summaryGenerator.js.map +1 -1
- package/lib/summary/summaryManager.d.ts.map +1 -1
- package/lib/summary/summaryManager.js +2 -2
- package/lib/summary/summaryManager.js.map +1 -1
- package/lib/tsdoc-metadata.json +1 -1
- package/package.json +37 -59
- package/src/batchTracker.ts +1 -2
- package/src/blobManager.ts +11 -10
- package/src/channelCollection.ts +115 -47
- package/src/connectionTelemetry.ts +59 -4
- package/src/containerRuntime.ts +302 -270
- package/src/dataStore.ts +7 -4
- package/src/dataStoreContext.ts +57 -16
- package/src/dataStoreContexts.ts +13 -2
- package/src/{deltaManagerSummarizerProxy.ts → deltaManagerProxies.ts} +98 -24
- package/src/deltaScheduler.ts +2 -3
- package/src/gc/garbageCollection.ts +64 -42
- package/src/gc/gcDefinitions.ts +22 -10
- package/src/gc/gcHelpers.ts +14 -1
- package/src/gc/gcTelemetry.ts +57 -50
- package/src/gc/index.ts +2 -1
- package/src/index.ts +7 -0
- package/src/messageTypes.ts +4 -2
- package/src/metadata.ts +2 -2
- package/src/opLifecycle/README.md +4 -4
- package/src/opLifecycle/batchManager.ts +5 -14
- package/src/opLifecycle/opDecompressor.ts +12 -6
- package/src/opLifecycle/opGroupingManager.ts +2 -2
- package/src/opLifecycle/opSplitter.ts +1 -1
- package/src/opLifecycle/outbox.ts +7 -53
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +38 -15
- package/src/scheduleManager.ts +2 -2
- package/src/summary/documentSchema.ts +52 -18
- package/src/summary/index.ts +4 -0
- package/src/summary/orderedClientElection.ts +6 -3
- package/src/summary/runningSummarizer.ts +1 -1
- package/src/summary/summarizer.ts +1 -1
- package/src/summary/summarizerClientElection.ts +1 -1
- package/src/summary/summarizerHeuristics.ts +1 -1
- package/src/summary/summarizerNode/summarizerNode.ts +3 -12
- package/src/summary/summarizerNode/summarizerNodeUtils.ts +2 -3
- package/src/summary/summarizerNode/summarizerNodeWithGc.ts +1 -10
- package/src/summary/summarizerTypes.ts +6 -5
- package/src/summary/summaryCollection.ts +2 -2
- package/src/summary/summaryFormat.ts +30 -4
- package/src/summary/summaryGenerator.ts +20 -9
- package/src/summary/summaryManager.ts +6 -3
- package/dist/deltaManagerSummarizerProxy.d.ts +0 -44
- package/dist/deltaManagerSummarizerProxy.d.ts.map +0 -1
- package/dist/deltaManagerSummarizerProxy.js.map +0 -1
- package/lib/deltaManagerSummarizerProxy.d.ts +0 -44
- package/lib/deltaManagerSummarizerProxy.d.ts.map +0 -1
- package/lib/deltaManagerSummarizerProxy.js.map +0 -1
package/src/dataStore.ts
CHANGED
|
@@ -4,15 +4,18 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { AttachState } from "@fluidframework/container-definitions";
|
|
7
|
-
import { FluidObject,
|
|
7
|
+
import { FluidObject, type IFluidHandleInternal } from "@fluidframework/core-interfaces/internal";
|
|
8
8
|
import { assert, unreachableCase } from "@fluidframework/core-utils/internal";
|
|
9
9
|
import {
|
|
10
10
|
AliasResult,
|
|
11
11
|
IDataStore,
|
|
12
12
|
IFluidDataStoreChannel,
|
|
13
13
|
} from "@fluidframework/runtime-definitions/internal";
|
|
14
|
-
import {
|
|
15
|
-
|
|
14
|
+
import {
|
|
15
|
+
ITelemetryLoggerExt,
|
|
16
|
+
TelemetryDataTag,
|
|
17
|
+
UsageError,
|
|
18
|
+
} from "@fluidframework/telemetry-utils/internal";
|
|
16
19
|
|
|
17
20
|
import { ChannelCollection } from "./channelCollection.js";
|
|
18
21
|
import { ContainerMessageType } from "./messageTypes.js";
|
|
@@ -166,7 +169,7 @@ class DataStore implements IDataStore {
|
|
|
166
169
|
/**
|
|
167
170
|
* {@inheritDoc @fluidframework/runtime-definitions#IDataStore.entryPoint}
|
|
168
171
|
*/
|
|
169
|
-
get entryPoint():
|
|
172
|
+
get entryPoint(): IFluidHandleInternal<FluidObject> {
|
|
170
173
|
return this.fluidDataStoreChannel.entryPoint;
|
|
171
174
|
}
|
|
172
175
|
|
package/src/dataStoreContext.ts
CHANGED
|
@@ -4,19 +4,26 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
7
|
-
import { AttachState, IAudience
|
|
7
|
+
import { AttachState, IAudience } from "@fluidframework/container-definitions";
|
|
8
|
+
import { IDeltaManager } from "@fluidframework/container-definitions/internal";
|
|
8
9
|
import {
|
|
9
10
|
FluidObject,
|
|
10
11
|
IDisposable,
|
|
11
|
-
IEvent,
|
|
12
|
-
IFluidHandle,
|
|
13
12
|
IRequest,
|
|
14
13
|
IResponse,
|
|
15
14
|
ITelemetryBaseProperties,
|
|
16
15
|
} from "@fluidframework/core-interfaces";
|
|
16
|
+
import { type IEvent, type IFluidHandleInternal } from "@fluidframework/core-interfaces/internal";
|
|
17
17
|
import { assert, LazyPromise, unreachableCase } from "@fluidframework/core-utils/internal";
|
|
18
|
-
import {
|
|
19
|
-
|
|
18
|
+
import {
|
|
19
|
+
IDocumentStorageService,
|
|
20
|
+
type ISnapshot,
|
|
21
|
+
} from "@fluidframework/driver-definitions/internal";
|
|
22
|
+
import {
|
|
23
|
+
BlobTreeEntry,
|
|
24
|
+
isInstanceOfISnapshot,
|
|
25
|
+
readAndParse,
|
|
26
|
+
} from "@fluidframework/driver-utils/internal";
|
|
20
27
|
import type { IIdCompressor } from "@fluidframework/id-compressor";
|
|
21
28
|
import {
|
|
22
29
|
IClientDetails,
|
|
@@ -52,7 +59,11 @@ import {
|
|
|
52
59
|
channelsTreeName,
|
|
53
60
|
gcDataBlobKey,
|
|
54
61
|
} from "@fluidframework/runtime-definitions/internal";
|
|
55
|
-
import {
|
|
62
|
+
import {
|
|
63
|
+
addBlobToSummary,
|
|
64
|
+
isSnapshotFetchRequiredForLoadingGroupId,
|
|
65
|
+
toFluidHandleInternal,
|
|
66
|
+
} from "@fluidframework/runtime-utils/internal";
|
|
56
67
|
import {
|
|
57
68
|
DataCorruptionError,
|
|
58
69
|
DataProcessingError,
|
|
@@ -67,6 +78,7 @@ import {
|
|
|
67
78
|
|
|
68
79
|
import { detectOutboundRoutesViaDDSKey, sendGCUnexpectedUsageEvent } from "./gc/index.js";
|
|
69
80
|
import {
|
|
81
|
+
// eslint-disable-next-line import/no-deprecated
|
|
70
82
|
ReadFluidDataStoreAttributes,
|
|
71
83
|
WriteFluidDataStoreAttributes,
|
|
72
84
|
dataStoreAttributesBlobName,
|
|
@@ -164,7 +176,7 @@ export interface ILocalDetachedFluidDataStoreContextProps extends ILocalFluidDat
|
|
|
164
176
|
* @internal
|
|
165
177
|
*/
|
|
166
178
|
export interface IRemoteFluidDataStoreContextProps extends IFluidDataStoreContextProps {
|
|
167
|
-
readonly
|
|
179
|
+
readonly snapshot: ISnapshotTree | ISnapshot | undefined;
|
|
168
180
|
}
|
|
169
181
|
|
|
170
182
|
// back-compat: To be removed in the future.
|
|
@@ -219,6 +231,7 @@ export abstract class FluidDataStoreContext
|
|
|
219
231
|
return this._containerRuntime;
|
|
220
232
|
}
|
|
221
233
|
|
|
234
|
+
// back-compat, to be removed in 2.0
|
|
222
235
|
public ensureNoDataModelChanges<T>(callback: () => T): T {
|
|
223
236
|
return this.parentContext.ensureNoDataModelChanges(callback);
|
|
224
237
|
}
|
|
@@ -721,11 +734,17 @@ export abstract class FluidDataStoreContext
|
|
|
721
734
|
* @param srcHandle - The handle of the node that added the reference.
|
|
722
735
|
* @param outboundHandle - The handle of the outbound node that is referenced.
|
|
723
736
|
*/
|
|
724
|
-
public addedGCOutboundReference(
|
|
737
|
+
public addedGCOutboundReference(
|
|
738
|
+
srcHandle: IFluidHandleInternal,
|
|
739
|
+
outboundHandle: IFluidHandleInternal,
|
|
740
|
+
): void {
|
|
725
741
|
// By default, skip this call since the ContainerRuntime will detect the outbound route directly.
|
|
726
742
|
if (this.mc.config.getBoolean(detectOutboundRoutesViaDDSKey) === true) {
|
|
727
743
|
// Note: The ContainerRuntime code will check this same setting to avoid double counting.
|
|
728
|
-
this.parentContext.addedGCOutboundReference?.(
|
|
744
|
+
this.parentContext.addedGCOutboundReference?.(
|
|
745
|
+
toFluidHandleInternal(srcHandle),
|
|
746
|
+
toFluidHandleInternal(outboundHandle),
|
|
747
|
+
);
|
|
729
748
|
}
|
|
730
749
|
}
|
|
731
750
|
|
|
@@ -1053,7 +1072,7 @@ export abstract class FluidDataStoreContext
|
|
|
1053
1072
|
public async uploadBlob(
|
|
1054
1073
|
blob: ArrayBufferLike,
|
|
1055
1074
|
signal?: AbortSignal,
|
|
1056
|
-
): Promise<
|
|
1075
|
+
): Promise<IFluidHandleInternal<ArrayBufferLike>> {
|
|
1057
1076
|
return this.parentContext.uploadBlob(blob, signal);
|
|
1058
1077
|
}
|
|
1059
1078
|
}
|
|
@@ -1061,23 +1080,28 @@ export abstract class FluidDataStoreContext
|
|
|
1061
1080
|
/** @internal */
|
|
1062
1081
|
export class RemoteFluidDataStoreContext extends FluidDataStoreContext {
|
|
1063
1082
|
// Tells whether we need to fetch the snapshot before use. This is to support Data Virtualization.
|
|
1064
|
-
private snapshotFetchRequired: boolean;
|
|
1083
|
+
private snapshotFetchRequired: boolean | undefined;
|
|
1065
1084
|
private readonly runtime: IContainerRuntimeBase;
|
|
1085
|
+
private readonly blobContents: Map<string, ArrayBuffer> | undefined;
|
|
1066
1086
|
|
|
1067
1087
|
constructor(props: IRemoteFluidDataStoreContextProps) {
|
|
1068
1088
|
super(props, true /* existing */, false /* isLocalDataStore */, () => {
|
|
1069
1089
|
throw new Error("Already attached");
|
|
1070
1090
|
});
|
|
1071
1091
|
|
|
1072
|
-
this._baseSnapshot = props.snapshotTree;
|
|
1073
|
-
this.snapshotFetchRequired = !!props.snapshotTree?.omitted;
|
|
1074
1092
|
this.runtime = props.parentContext.containerRuntime;
|
|
1075
|
-
if (props.
|
|
1076
|
-
this.
|
|
1093
|
+
if (isInstanceOfISnapshot(props.snapshot)) {
|
|
1094
|
+
this.blobContents = props.snapshot.blobContents;
|
|
1095
|
+
this._baseSnapshot = props.snapshot.snapshotTree;
|
|
1096
|
+
} else {
|
|
1097
|
+
this._baseSnapshot = props.snapshot;
|
|
1098
|
+
}
|
|
1099
|
+
if (this._baseSnapshot !== undefined) {
|
|
1100
|
+
this.summarizerNode.updateBaseSummaryState(this._baseSnapshot);
|
|
1077
1101
|
}
|
|
1078
1102
|
}
|
|
1079
1103
|
|
|
1080
|
-
/*
|
|
1104
|
+
/*
|
|
1081
1105
|
This API should not be called for RemoteFluidDataStoreContext. But here is one scenario where it's not the case:
|
|
1082
1106
|
The scenario (hit by stashedOps.spec.ts, "resends attach op" UT is the following (as far as I understand):
|
|
1083
1107
|
1. data store is being attached in attached container
|
|
@@ -1092,6 +1116,21 @@ export class RemoteFluidDataStoreContext extends FluidDataStoreContext {
|
|
|
1092
1116
|
private readonly initialSnapshotDetailsP = new LazyPromise<ISnapshotDetails>(async () => {
|
|
1093
1117
|
// Sequence number of the snapshot.
|
|
1094
1118
|
let sequenceNumber: number | undefined;
|
|
1119
|
+
// Check whether we need to fetch the snapshot first to load.
|
|
1120
|
+
if (this.snapshotFetchRequired === undefined && this._baseSnapshot?.groupId !== undefined) {
|
|
1121
|
+
assert(
|
|
1122
|
+
this.blobContents !== undefined,
|
|
1123
|
+
0x97a /* Blob contents should be present to evaluate */,
|
|
1124
|
+
);
|
|
1125
|
+
assert(
|
|
1126
|
+
this._baseSnapshot !== undefined,
|
|
1127
|
+
0x97b /* snapshotTree should be present to evaluate */,
|
|
1128
|
+
);
|
|
1129
|
+
this.snapshotFetchRequired = isSnapshotFetchRequiredForLoadingGroupId(
|
|
1130
|
+
this._baseSnapshot,
|
|
1131
|
+
this.blobContents,
|
|
1132
|
+
);
|
|
1133
|
+
}
|
|
1095
1134
|
if (this.snapshotFetchRequired) {
|
|
1096
1135
|
assert(
|
|
1097
1136
|
this.loadingGroupId !== undefined,
|
|
@@ -1110,6 +1149,7 @@ export class RemoteFluidDataStoreContext extends FluidDataStoreContext {
|
|
|
1110
1149
|
|
|
1111
1150
|
if (!!tree && tree.blobs[dataStoreAttributesBlobName] !== undefined) {
|
|
1112
1151
|
// Need to get through snapshot and use that to populate extraBlobs
|
|
1152
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1113
1153
|
const attributes = await readAndParse<ReadFluidDataStoreAttributes>(
|
|
1114
1154
|
this.storage,
|
|
1115
1155
|
tree.blobs[dataStoreAttributesBlobName],
|
|
@@ -1286,6 +1326,7 @@ export class LocalFluidDataStoreContextBase extends FluidDataStoreContext {
|
|
|
1286
1326
|
|
|
1287
1327
|
private readonly initialSnapshotDetailsP = new LazyPromise<ISnapshotDetails>(async () => {
|
|
1288
1328
|
let snapshot = this.snapshotTree;
|
|
1329
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1289
1330
|
let attributes: ReadFluidDataStoreAttributes;
|
|
1290
1331
|
let isRootDataStore = false;
|
|
1291
1332
|
if (snapshot !== undefined) {
|
package/src/dataStoreContexts.ts
CHANGED
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { IDisposable, ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
|
|
7
7
|
import { assert, Deferred, Lazy } from "@fluidframework/core-utils/internal";
|
|
8
|
-
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
|
|
9
|
-
import { createChildLogger } from "@fluidframework/telemetry-utils/internal";
|
|
8
|
+
import { ITelemetryLoggerExt, createChildLogger } from "@fluidframework/telemetry-utils/internal";
|
|
10
9
|
|
|
11
10
|
import { FluidDataStoreContext, LocalFluidDataStoreContext } from "./dataStoreContext.js";
|
|
12
11
|
|
|
@@ -83,9 +82,21 @@ export class DataStoreContexts implements Iterable<[string, FluidDataStoreContex
|
|
|
83
82
|
public delete(id: string): boolean {
|
|
84
83
|
this.deferredContexts.delete(id);
|
|
85
84
|
this.notBoundContexts.delete(id);
|
|
85
|
+
|
|
86
|
+
// Stash the context here in case it's requested in this session, we can log some details about it
|
|
87
|
+
const context = this._contexts.get(id);
|
|
88
|
+
this._recentlyDeletedContexts.set(id, context);
|
|
89
|
+
|
|
86
90
|
return this._contexts.delete(id);
|
|
87
91
|
}
|
|
88
92
|
|
|
93
|
+
private readonly _recentlyDeletedContexts: Map<string, FluidDataStoreContext | undefined> =
|
|
94
|
+
new Map();
|
|
95
|
+
|
|
96
|
+
public getRecentlyDeletedContext(id: string) {
|
|
97
|
+
return this._recentlyDeletedContexts.get(id);
|
|
98
|
+
}
|
|
99
|
+
|
|
89
100
|
/**
|
|
90
101
|
* Return the unbound local context with the given id,
|
|
91
102
|
* or undefined if it's not found or not unbound.
|
|
@@ -11,9 +11,9 @@ import type {
|
|
|
11
11
|
IDeltaQueue,
|
|
12
12
|
IDeltaSender,
|
|
13
13
|
ReadOnlyInfo,
|
|
14
|
-
} from "@fluidframework/container-definitions";
|
|
14
|
+
} from "@fluidframework/container-definitions/internal";
|
|
15
15
|
import type { IErrorBase } from "@fluidframework/core-interfaces";
|
|
16
|
-
import type { IAnyDriverError } from "@fluidframework/driver-definitions";
|
|
16
|
+
import type { IAnyDriverError } from "@fluidframework/driver-definitions/internal";
|
|
17
17
|
import {
|
|
18
18
|
IClientConfiguration,
|
|
19
19
|
IClientDetails,
|
|
@@ -23,13 +23,15 @@ import {
|
|
|
23
23
|
} from "@fluidframework/protocol-definitions";
|
|
24
24
|
|
|
25
25
|
import { summarizerClientType } from "./summary/index.js";
|
|
26
|
+
import type { PendingStateManager } from "./pendingStateManager.js";
|
|
26
27
|
|
|
27
28
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
29
|
+
* Base class for DeltaManager proxy that proxy's access to the real DeltaManager.
|
|
30
|
+
*
|
|
31
|
+
* This class allows us to build proxy functionality without actually having to implement all the methods
|
|
32
|
+
* of the DeltaManager.
|
|
31
33
|
*/
|
|
32
|
-
export class
|
|
34
|
+
export abstract class BaseDeltaManagerProxy
|
|
33
35
|
extends TypedEventEmitter<IDeltaManagerEvents>
|
|
34
36
|
implements IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>
|
|
35
37
|
{
|
|
@@ -90,35 +92,20 @@ export class DeltaManagerSummarizerProxy
|
|
|
90
92
|
}
|
|
91
93
|
|
|
92
94
|
public get active(): boolean {
|
|
93
|
-
|
|
94
|
-
// except for the SummarizeOp which is generated by the runtime.
|
|
95
|
-
return !this.isSummarizerClient && this.deltaManager.active;
|
|
95
|
+
return this.deltaManager.active;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
public get readOnlyInfo(): ReadOnlyInfo {
|
|
99
|
-
// Summarizer clients should be read-only as far as the runtime and layers below are concerned. There shouldn't
|
|
100
|
-
// be any local changes (writes) in the summarizer except for the summarize op which is generated by the runtime.
|
|
101
|
-
if (this.isSummarizerClient) {
|
|
102
|
-
return {
|
|
103
|
-
readonly: true,
|
|
104
|
-
forced: false,
|
|
105
|
-
permissions: undefined,
|
|
106
|
-
storageOnly: false,
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
99
|
return this.deltaManager.readOnlyInfo;
|
|
110
100
|
}
|
|
111
101
|
|
|
112
|
-
private readonly isSummarizerClient: boolean;
|
|
113
|
-
|
|
114
102
|
constructor(
|
|
115
|
-
|
|
103
|
+
protected readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,
|
|
116
104
|
) {
|
|
117
105
|
super();
|
|
118
106
|
|
|
119
107
|
// We are expecting this class to have many listeners, so we suppress noisy "MaxListenersExceededWarning" logging.
|
|
120
108
|
super.setMaxListeners(0);
|
|
121
|
-
this.isSummarizerClient = this.deltaManager.clientDetails.type === summarizerClientType;
|
|
122
109
|
|
|
123
110
|
this.deltaManager.on("prepareSend", this.onPrepareSend);
|
|
124
111
|
this.deltaManager.on("submitOp", this.onSubmitOp);
|
|
@@ -153,7 +140,10 @@ export class DeltaManagerSummarizerProxy
|
|
|
153
140
|
private readonly onSubmitOp = (message: IDocumentMessage): void => {
|
|
154
141
|
this.emit("submitOp", message);
|
|
155
142
|
};
|
|
156
|
-
|
|
143
|
+
protected readonly onOp = (
|
|
144
|
+
message: ISequencedDocumentMessage,
|
|
145
|
+
processingTime: number,
|
|
146
|
+
): void => {
|
|
157
147
|
this.emit("op", message, processingTime);
|
|
158
148
|
};
|
|
159
149
|
private readonly onPong = (latency: number): void => {
|
|
@@ -172,3 +162,87 @@ export class DeltaManagerSummarizerProxy
|
|
|
172
162
|
this.emit("readonly", readonly, readonlyConnectionReason);
|
|
173
163
|
};
|
|
174
164
|
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Proxy to the real IDeltaManager for restricting certain access to layers below container runtime in summarizer clients:
|
|
168
|
+
* - Summarizer client should be read-only to layers below the container runtime to restrict local changes.
|
|
169
|
+
* - Summarizer client should not be active to layers below the container runtime to restrict local changes.
|
|
170
|
+
*/
|
|
171
|
+
export class DeltaManagerSummarizerProxy extends BaseDeltaManagerProxy {
|
|
172
|
+
public get active(): boolean {
|
|
173
|
+
// Summarize clients should not be active. There shouldn't be any local changes (writes) in the summarizer
|
|
174
|
+
// except for the SummarizeOp which is generated by the runtime.
|
|
175
|
+
return !this.isSummarizerClient && this.deltaManager.active;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
public get readOnlyInfo(): ReadOnlyInfo {
|
|
179
|
+
// Summarizer clients should be read-only as far as the runtime and layers below are concerned. There shouldn't
|
|
180
|
+
// be any local changes (writes) in the summarizer except for the summarize op which is generated by the runtime.
|
|
181
|
+
if (this.isSummarizerClient) {
|
|
182
|
+
return {
|
|
183
|
+
readonly: true,
|
|
184
|
+
forced: false,
|
|
185
|
+
permissions: undefined,
|
|
186
|
+
storageOnly: false,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
return this.deltaManager.readOnlyInfo;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
private readonly isSummarizerClient: boolean;
|
|
193
|
+
|
|
194
|
+
constructor(
|
|
195
|
+
protected readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,
|
|
196
|
+
) {
|
|
197
|
+
super(deltaManager);
|
|
198
|
+
this.isSummarizerClient = this.deltaManager.clientDetails.type === summarizerClientType;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export class DeltaManagerPendingOpsProxy extends BaseDeltaManagerProxy {
|
|
203
|
+
public get minimumSequenceNumber(): number {
|
|
204
|
+
const minPendingSeqNum = this.pendingStateManager.minimumPendingMessageSequenceNumber;
|
|
205
|
+
// There is a chance that minPendingSeqNum is greater than minimum sequence number.
|
|
206
|
+
// minPendingSeqNum is based on the pending ops, so it's based on ref seq number.
|
|
207
|
+
// Imagine an op has just be sent while there's another client that has been lagging behind,
|
|
208
|
+
// it will likely have a ref seq number greater than the minimum seq number.
|
|
209
|
+
if (
|
|
210
|
+
minPendingSeqNum !== undefined &&
|
|
211
|
+
minPendingSeqNum < this.deltaManager.minimumSequenceNumber
|
|
212
|
+
) {
|
|
213
|
+
return minPendingSeqNum;
|
|
214
|
+
}
|
|
215
|
+
return this.deltaManager.minimumSequenceNumber;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
public get lastMessage() {
|
|
219
|
+
if (this.deltaManager.lastMessage === undefined) {
|
|
220
|
+
return this.deltaManager.lastMessage;
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
...this.deltaManager.lastMessage,
|
|
224
|
+
minimumSequenceNumber: this.minimumSequenceNumber,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
protected readonly onOp = (
|
|
229
|
+
message: ISequencedDocumentMessage,
|
|
230
|
+
processingTime: number,
|
|
231
|
+
): void => {
|
|
232
|
+
const messageIntercept = {
|
|
233
|
+
...message,
|
|
234
|
+
minimumSequenceNumber: this.minimumSequenceNumber,
|
|
235
|
+
};
|
|
236
|
+
this.emit("op", messageIntercept, processingTime);
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
constructor(
|
|
240
|
+
protected readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,
|
|
241
|
+
private readonly pendingStateManager: Pick<
|
|
242
|
+
PendingStateManager,
|
|
243
|
+
"minimumPendingMessageSequenceNumber"
|
|
244
|
+
>,
|
|
245
|
+
) {
|
|
246
|
+
super(deltaManager);
|
|
247
|
+
}
|
|
248
|
+
}
|
package/src/deltaScheduler.ts
CHANGED
|
@@ -4,10 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { performance } from "@fluid-internal/client-utils";
|
|
7
|
-
import { IDeltaManager } from "@fluidframework/container-definitions";
|
|
7
|
+
import { IDeltaManager } from "@fluidframework/container-definitions/internal";
|
|
8
8
|
import { IDocumentMessage, ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
|
|
9
|
-
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
|
|
10
|
-
import { formatTick } from "@fluidframework/telemetry-utils/internal";
|
|
9
|
+
import { ITelemetryLoggerExt, formatTick } from "@fluidframework/telemetry-utils/internal";
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
12
|
* DeltaScheduler is responsible for the scheduling of inbound delta queue in cases where there
|
|
@@ -12,8 +12,8 @@ import {
|
|
|
12
12
|
gcTreeKey,
|
|
13
13
|
} from "@fluidframework/runtime-definitions/internal";
|
|
14
14
|
import { createResponseError, responseToException } from "@fluidframework/runtime-utils/internal";
|
|
15
|
-
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
|
|
16
15
|
import {
|
|
16
|
+
ITelemetryLoggerExt,
|
|
17
17
|
DataProcessingError,
|
|
18
18
|
MonitoringContext,
|
|
19
19
|
PerformanceEvent,
|
|
@@ -23,11 +23,7 @@ import {
|
|
|
23
23
|
} from "@fluidframework/telemetry-utils/internal";
|
|
24
24
|
|
|
25
25
|
import { BlobManager } from "../blobManager.js";
|
|
26
|
-
import {
|
|
27
|
-
InactiveResponseHeaderKey,
|
|
28
|
-
RuntimeHeaderData,
|
|
29
|
-
TombstoneResponseHeaderKey,
|
|
30
|
-
} from "../containerRuntime.js";
|
|
26
|
+
import { InactiveResponseHeaderKey, TombstoneResponseHeaderKey } from "../containerRuntime.js";
|
|
31
27
|
import { ClientSessionExpiredError } from "../error.js";
|
|
32
28
|
import { ContainerMessageType, ContainerRuntimeGCMessage } from "../messageTypes.js";
|
|
33
29
|
import { IRefreshSummaryResult } from "../summary/index.js";
|
|
@@ -48,12 +44,15 @@ import {
|
|
|
48
44
|
ISweepPhaseStats,
|
|
49
45
|
UnreferencedState,
|
|
50
46
|
disableAutoRecoveryKey,
|
|
47
|
+
type IGCNodeUpdatedProps,
|
|
51
48
|
} from "./gcDefinitions.js";
|
|
52
49
|
import {
|
|
53
50
|
cloneGCData,
|
|
54
51
|
compatBehaviorAllowsGCMessageType,
|
|
55
52
|
concatGarbageCollectionData,
|
|
53
|
+
dataStoreNodePathOnly,
|
|
56
54
|
getGCDataFromSnapshot,
|
|
55
|
+
urlToGCNodePath,
|
|
57
56
|
} from "./gcHelpers.js";
|
|
58
57
|
import { runGarbageCollection } from "./gcReferenceGraphAlgorithm.js";
|
|
59
58
|
import { IGarbageCollectionSnapshotData, IGarbageCollectionState } from "./gcSummaryDefinitions.js";
|
|
@@ -401,17 +400,27 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
401
400
|
return;
|
|
402
401
|
}
|
|
403
402
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
403
|
+
const initialized = this.gcDataFromLastRun !== undefined;
|
|
404
|
+
await PerformanceEvent.timedExecAsync(
|
|
405
|
+
this.mc.logger,
|
|
406
|
+
{
|
|
407
|
+
eventName: "InitializeOrUpdateGCState",
|
|
408
|
+
details: { initialized, unrefNodeCount: this.unreferencedNodesState.size },
|
|
409
|
+
},
|
|
410
|
+
async () => {
|
|
411
|
+
// If the GC state hasn't been initialized yet, initialize it and return.
|
|
412
|
+
if (!initialized) {
|
|
413
|
+
await this.initializeGCStateFromBaseSnapshotP;
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
409
416
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
417
|
+
// If the GC state has been initialized, update the tracking of unreferenced nodes as per the current
|
|
418
|
+
// reference timestamp.
|
|
419
|
+
for (const [, nodeStateTracker] of this.unreferencedNodesState) {
|
|
420
|
+
nodeStateTracker.updateTracking(currentReferenceTimestampMs);
|
|
421
|
+
}
|
|
422
|
+
},
|
|
423
|
+
);
|
|
415
424
|
}
|
|
416
425
|
|
|
417
426
|
/**
|
|
@@ -978,30 +987,30 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
978
987
|
/**
|
|
979
988
|
* Called when a node with the given id is updated. If the node is inactive or tombstoned, this will log an error
|
|
980
989
|
* or throw an error if failing on incorrect usage is configured.
|
|
981
|
-
* @param
|
|
982
|
-
* @param reason - Whether the node was loaded or changed.
|
|
983
|
-
* @param timestampMs - The timestamp when the node changed.
|
|
984
|
-
* @param packagePath - The package path of the node. This may not be available if the node hasn't been loaded yet.
|
|
985
|
-
* @param request - The original request for loads to preserve it in telemetry.
|
|
986
|
-
* @param requestHeaders - If the node was loaded via request path, the headers in the request.
|
|
990
|
+
* @param IGCNodeUpdatedProps - Details about the node and how it was updated
|
|
987
991
|
*/
|
|
988
|
-
public nodeUpdated(
|
|
989
|
-
|
|
990
|
-
reason
|
|
991
|
-
timestampMs
|
|
992
|
-
packagePath
|
|
993
|
-
request
|
|
994
|
-
headerData
|
|
995
|
-
) {
|
|
992
|
+
public nodeUpdated({
|
|
993
|
+
node,
|
|
994
|
+
reason,
|
|
995
|
+
timestampMs,
|
|
996
|
+
packagePath,
|
|
997
|
+
request,
|
|
998
|
+
headerData,
|
|
999
|
+
}: IGCNodeUpdatedProps) {
|
|
996
1000
|
if (!this.configs.shouldRunGC) {
|
|
997
1001
|
return;
|
|
998
1002
|
}
|
|
999
1003
|
|
|
1000
|
-
|
|
1004
|
+
// trackedId will be either DataStore or Blob ID (not sub-DataStore ID, since some of those are unrecognized by GC)
|
|
1005
|
+
const trackedId = node.path;
|
|
1006
|
+
const isTombstoned = this.tombstones.includes(trackedId);
|
|
1007
|
+
const isInactive = this.unreferencedNodesState.get(trackedId)?.state === "Inactive";
|
|
1008
|
+
|
|
1009
|
+
const fullPath = request !== undefined ? urlToGCNodePath(request.url) : trackedId;
|
|
1001
1010
|
|
|
1002
1011
|
// This will log if appropriate
|
|
1003
|
-
this.telemetryTracker.nodeUsed({
|
|
1004
|
-
id:
|
|
1012
|
+
this.telemetryTracker.nodeUsed(trackedId, {
|
|
1013
|
+
id: fullPath,
|
|
1005
1014
|
usageType: reason,
|
|
1006
1015
|
currentReferenceTimestampMs:
|
|
1007
1016
|
timestampMs ?? this.runtime.getCurrentReferenceTimestampMs(),
|
|
@@ -1010,6 +1019,8 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
1010
1019
|
isTombstoned,
|
|
1011
1020
|
lastSummaryTime: this.getLastSummaryTimestampMs(),
|
|
1012
1021
|
headers: headerData,
|
|
1022
|
+
requestUrl: request?.url,
|
|
1023
|
+
requestHeaders: JSON.stringify(request?.headers),
|
|
1013
1024
|
});
|
|
1014
1025
|
|
|
1015
1026
|
// Any time we log a Tombstone Loaded error (via Telemetry Tracker),
|
|
@@ -1018,17 +1029,20 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
1018
1029
|
// to be loaded by the Summarizer, and auto-recovery will be triggered then.
|
|
1019
1030
|
if (isTombstoned && reason === "Loaded") {
|
|
1020
1031
|
// Note that when a DataStore and its DDS are all loaded, each will trigger AutoRecovery for itself.
|
|
1021
|
-
this.triggerAutoRecovery(
|
|
1032
|
+
this.triggerAutoRecovery(fullPath);
|
|
1022
1033
|
}
|
|
1023
1034
|
|
|
1024
|
-
const nodeType = this.runtime.getNodeType(
|
|
1035
|
+
const nodeType = this.runtime.getNodeType(fullPath);
|
|
1025
1036
|
|
|
1026
1037
|
// Unless this is a Loaded event for a Blob or DataStore, we're done after telemetry tracking
|
|
1027
|
-
|
|
1038
|
+
const loadedBlobOrDataStore =
|
|
1039
|
+
reason === "Loaded" &&
|
|
1040
|
+
(nodeType === GCNodeType.Blob || nodeType === GCNodeType.DataStore);
|
|
1041
|
+
if (!loadedBlobOrDataStore) {
|
|
1028
1042
|
return;
|
|
1029
1043
|
}
|
|
1030
1044
|
|
|
1031
|
-
const errorRequest: IRequest = request ?? { url:
|
|
1045
|
+
const errorRequest: IRequest = request ?? { url: fullPath };
|
|
1032
1046
|
if (isTombstoned && this.throwOnTombstoneLoad && headerData?.allowTombstone !== true) {
|
|
1033
1047
|
// The requested data store is removed by gc. Create a 404 gc response exception.
|
|
1034
1048
|
throw responseToException(
|
|
@@ -1040,7 +1054,7 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
1040
1054
|
}
|
|
1041
1055
|
|
|
1042
1056
|
// If the object is inactive and inactive enforcement is configured, throw an error.
|
|
1043
|
-
if (
|
|
1057
|
+
if (isInactive) {
|
|
1044
1058
|
const shouldThrowOnInactiveLoad =
|
|
1045
1059
|
!this.isSummarizerClient &&
|
|
1046
1060
|
this.configs.throwOnInactiveLoad === true &&
|
|
@@ -1112,22 +1126,30 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
1112
1126
|
outboundRoutes.push(toNodePath);
|
|
1113
1127
|
this.newReferencesSinceLastRun.set(fromNodePath, outboundRoutes);
|
|
1114
1128
|
|
|
1115
|
-
|
|
1129
|
+
// GC won't recognize some subDataStore paths that we encounter (e.g. a path suited for a custom request handler)
|
|
1130
|
+
// So for subDataStore paths we need to check the parent dataStore for current tombstone/inactive status.
|
|
1131
|
+
const trackedId =
|
|
1132
|
+
this.runtime.getNodeType(toNodePath) === "SubDataStore"
|
|
1133
|
+
? dataStoreNodePathOnly(toNodePath)
|
|
1134
|
+
: toNodePath;
|
|
1135
|
+
this.telemetryTracker.nodeUsed(trackedId, {
|
|
1116
1136
|
id: toNodePath,
|
|
1137
|
+
fromId: fromNodePath,
|
|
1117
1138
|
usageType: "Revived",
|
|
1118
1139
|
currentReferenceTimestampMs: this.runtime.getCurrentReferenceTimestampMs(),
|
|
1119
1140
|
packagePath: undefined,
|
|
1120
1141
|
completedGCRuns: this.completedRuns,
|
|
1121
|
-
isTombstoned: this.tombstones.includes(
|
|
1142
|
+
isTombstoned: this.tombstones.includes(trackedId),
|
|
1122
1143
|
lastSummaryTime: this.getLastSummaryTimestampMs(),
|
|
1123
|
-
fromId: fromNodePath,
|
|
1124
1144
|
autorecovery,
|
|
1125
1145
|
});
|
|
1126
1146
|
|
|
1127
|
-
// This node is referenced - Clear its unreferenced state
|
|
1147
|
+
// This node is referenced - Clear its unreferenced state if present
|
|
1128
1148
|
// But don't delete the node id from the map yet.
|
|
1129
1149
|
// When generating GC stats, the set of nodes in here is used as the baseline for
|
|
1130
1150
|
// what was unreferenced in the last GC run.
|
|
1151
|
+
// NOTE: We use toNodePath not trackedId even though it may be an unrecognized subDataStore route (hence no-op),
|
|
1152
|
+
// because a reference to such a path is not sufficient to consider the DataStore referenced.
|
|
1131
1153
|
this.unreferencedNodesState.get(toNodePath)?.stopTracking();
|
|
1132
1154
|
}
|
|
1133
1155
|
|
package/src/gc/gcDefinitions.ts
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
ISummarizeResult,
|
|
13
13
|
} from "@fluidframework/runtime-definitions/internal";
|
|
14
14
|
import { ReadAndParseBlob } from "@fluidframework/runtime-utils/internal";
|
|
15
|
-
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
|
|
15
|
+
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils/internal";
|
|
16
16
|
|
|
17
17
|
import { RuntimeHeaderData } from "../containerRuntime.js";
|
|
18
18
|
import { ContainerRuntimeGCMessage } from "../messageTypes.js";
|
|
@@ -245,7 +245,7 @@ export const GCNodeType = {
|
|
|
245
245
|
Blob: "Blob",
|
|
246
246
|
// Nodes that are neither of the above. For example, root node.
|
|
247
247
|
Other: "Other",
|
|
248
|
-
};
|
|
248
|
+
} as const;
|
|
249
249
|
|
|
250
250
|
/**
|
|
251
251
|
* @alpha
|
|
@@ -370,14 +370,7 @@ export interface IGarbageCollector {
|
|
|
370
370
|
* Called when a node with the given path is updated. If the node is inactive or tombstoned, this will log an error
|
|
371
371
|
* or throw an error if failing on incorrect usage is configured.
|
|
372
372
|
*/
|
|
373
|
-
nodeUpdated(
|
|
374
|
-
nodePath: string,
|
|
375
|
-
reason: "Loaded" | "Changed",
|
|
376
|
-
timestampMs?: number,
|
|
377
|
-
packagePath?: readonly string[],
|
|
378
|
-
request?: IRequest,
|
|
379
|
-
headerData?: RuntimeHeaderData,
|
|
380
|
-
): void;
|
|
373
|
+
nodeUpdated(props: IGCNodeUpdatedProps): void;
|
|
381
374
|
/** Called when a reference is added to a node. Used to identify nodes that were referenced between summaries. */
|
|
382
375
|
addedOutboundReference(fromNodePath: string, toNodePath: string, autorecovery?: true): void;
|
|
383
376
|
/** Called to process a garbage collection message. */
|
|
@@ -388,6 +381,25 @@ export interface IGarbageCollector {
|
|
|
388
381
|
dispose(): void;
|
|
389
382
|
}
|
|
390
383
|
|
|
384
|
+
/**
|
|
385
|
+
* Info needed by GC when notified that a node was updated (loaded or changed)
|
|
386
|
+
* @internal
|
|
387
|
+
*/
|
|
388
|
+
export interface IGCNodeUpdatedProps {
|
|
389
|
+
/** Type and path of the updated node */
|
|
390
|
+
node: { type: (typeof GCNodeType)["DataStore" | "Blob"]; path: string };
|
|
391
|
+
/** Whether the node (or a subpath) was loaded or changed. */
|
|
392
|
+
reason: "Loaded" | "Changed";
|
|
393
|
+
/** The op-based timestamp when the node changed, if applicable */
|
|
394
|
+
timestampMs?: number;
|
|
395
|
+
/** The package path of the node. This may not be available if the node hasn't been loaded yet */
|
|
396
|
+
packagePath?: readonly string[];
|
|
397
|
+
/** The original request for loads to preserve it in telemetry */
|
|
398
|
+
request?: IRequest;
|
|
399
|
+
/** If the node was loaded via request path, the header data. May be modified from the original request */
|
|
400
|
+
headerData?: RuntimeHeaderData;
|
|
401
|
+
}
|
|
402
|
+
|
|
391
403
|
/** Parameters necessary for creating a GarbageCollector. */
|
|
392
404
|
export interface IGarbageCollectorCreateParams {
|
|
393
405
|
readonly runtime: IGarbageCollectionRuntime;
|