@fluidframework/container-runtime 0.58.3000-61081 → 0.59.1000-61898
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/dist/blobManager.d.ts +13 -1
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +52 -0
- package/dist/blobManager.js.map +1 -1
- package/dist/connectionTelemetry.js +7 -7
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerRuntime.d.ts +27 -3
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +100 -14
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.js +8 -1
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +9 -3
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +22 -6
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStores.d.ts +13 -5
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +39 -18
- package/dist/dataStores.js.map +1 -1
- package/dist/deltaScheduler.d.ts +4 -5
- package/dist/deltaScheduler.d.ts.map +1 -1
- package/dist/deltaScheduler.js +54 -35
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/garbageCollection.d.ts +31 -27
- package/dist/garbageCollection.d.ts.map +1 -1
- package/dist/garbageCollection.js +76 -75
- package/dist/garbageCollection.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/lib/blobManager.d.ts +13 -1
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +52 -0
- package/lib/blobManager.js.map +1 -1
- package/lib/connectionTelemetry.js +7 -7
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerRuntime.d.ts +27 -3
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +101 -15
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.js +8 -1
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +9 -3
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +22 -6
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStores.d.ts +13 -5
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +39 -18
- package/lib/dataStores.js.map +1 -1
- package/lib/deltaScheduler.d.ts +4 -5
- package/lib/deltaScheduler.d.ts.map +1 -1
- package/lib/deltaScheduler.js +54 -35
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/garbageCollection.d.ts +31 -27
- package/lib/garbageCollection.d.ts.map +1 -1
- package/lib/garbageCollection.js +75 -74
- package/lib/garbageCollection.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/package.json +33 -21
- package/src/blobManager.ts +60 -1
- package/src/connectionTelemetry.ts +7 -7
- package/src/containerRuntime.ts +106 -17
- package/src/dataStore.ts +7 -1
- package/src/dataStoreContext.ts +22 -7
- package/src/dataStores.ts +40 -19
- package/src/deltaScheduler.ts +65 -39
- package/src/garbageCollection.ts +92 -78
- package/src/packageVersion.ts +1 -1
package/src/garbageCollection.ts
CHANGED
|
@@ -76,16 +76,33 @@ export interface IGCStats {
|
|
|
76
76
|
nodeCount: number;
|
|
77
77
|
/** The number of data stores in the container. */
|
|
78
78
|
dataStoreCount: number;
|
|
79
|
+
/** The number of attachment blobs in the container. */
|
|
80
|
+
attachmentBlobCount: number;
|
|
79
81
|
/** The number of unreferenced nodes in the container. */
|
|
80
82
|
unrefNodeCount: number;
|
|
81
83
|
/** The number of unreferenced data stores in the container. */
|
|
82
84
|
unrefDataStoreCount: number;
|
|
85
|
+
/** The number of unreferenced attachment blobs in the container. */
|
|
86
|
+
unrefAttachmentBlobCount: number;
|
|
83
87
|
/** The number of nodes whose reference state updated since last GC run. */
|
|
84
88
|
updatedNodeCount: number;
|
|
85
89
|
/** The number of data stores whose reference state updated since last GC run. */
|
|
86
90
|
updatedDataStoreCount: number;
|
|
91
|
+
/** The number of attachment blobs whose reference state updated since last GC run. */
|
|
92
|
+
updatedAttachmentBlobCount: number;
|
|
87
93
|
}
|
|
88
94
|
|
|
95
|
+
/** The types of GC nodes in the GC reference graph. */
|
|
96
|
+
export const GCNodeType = {
|
|
97
|
+
// Nodes that are for data stores.
|
|
98
|
+
DataStore: "DataStore",
|
|
99
|
+
// Nodes that are for attachment blobs, i.e., blobs uploaded via BlobManager.
|
|
100
|
+
Blob: "Blob",
|
|
101
|
+
// Nodes that are neither data store not blobs. For example, root node and DDS nodes.
|
|
102
|
+
Other: "Other",
|
|
103
|
+
};
|
|
104
|
+
export type GCNodeType = typeof GCNodeType[keyof typeof GCNodeType];
|
|
105
|
+
|
|
89
106
|
/** The event that is logged when unreferenced node is used after a certain time. */
|
|
90
107
|
interface IUnreferencedEvent {
|
|
91
108
|
eventName: string;
|
|
@@ -105,6 +122,12 @@ export interface IGarbageCollectionRuntime {
|
|
|
105
122
|
getGCData(fullGC?: boolean): Promise<IGarbageCollectionData>;
|
|
106
123
|
/** After GC has run, called to notify the runtime of routes that are used in it. */
|
|
107
124
|
updateUsedRoutes(usedRoutes: string[], gcTimestamp?: number): void;
|
|
125
|
+
/** After GC has run, called to delete objects in the runtime whose routes are unused. */
|
|
126
|
+
deleteUnusedRoutes(unusedRoutes: string[]): void;
|
|
127
|
+
/** Returns a referenced timestamp to be used to track unreferenced nodes. */
|
|
128
|
+
getCurrentReferenceTimestampMs(): number | undefined;
|
|
129
|
+
/** Returns the type of the GC node. */
|
|
130
|
+
getNodeType(nodePath: string): GCNodeType;
|
|
108
131
|
/** Called when the runtime should close because of an error. */
|
|
109
132
|
closeFn(error?: ICriticalContainerError): void;
|
|
110
133
|
}
|
|
@@ -131,8 +154,8 @@ export interface IGarbageCollector {
|
|
|
131
154
|
): Promise<IGCStats>;
|
|
132
155
|
/** Summarizes the GC data and returns it as a summary tree. */
|
|
133
156
|
summarize(): ISummaryTreeWithStats | undefined;
|
|
134
|
-
/** Returns a map of each
|
|
135
|
-
|
|
157
|
+
/** Returns a map of each node id to its base GC details in the base summary. */
|
|
158
|
+
getBaseGCDetails(): Promise<Map<string, IGarbageCollectionDetailsBase>>;
|
|
136
159
|
/** Called when the latest summary of the system has been refreshed. */
|
|
137
160
|
latestSummaryStateRefreshed(result: RefreshSummaryResult, readAndParseBlob: ReadAndParseBlob): Promise<void>;
|
|
138
161
|
/** Called when a node is updated. Used to detect and log when an inactive node is changed or loaded. */
|
|
@@ -209,9 +232,7 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
209
232
|
public static create(
|
|
210
233
|
provider: IGarbageCollectionRuntime,
|
|
211
234
|
gcOptions: IGCRuntimeOptions,
|
|
212
|
-
|
|
213
|
-
getNodePackagePath: (nodeId: string) => readonly string[] | undefined,
|
|
214
|
-
getCurrentReferenceTimestampMs: () => number | undefined,
|
|
235
|
+
getNodePackagePath: (nodePath: string) => readonly string[] | undefined,
|
|
215
236
|
getLastSummaryTimestampMs: () => number | undefined,
|
|
216
237
|
baseSnapshot: ISnapshotTree | undefined,
|
|
217
238
|
readAndParseBlob: ReadAndParseBlob,
|
|
@@ -222,9 +243,7 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
222
243
|
return new GarbageCollector(
|
|
223
244
|
provider,
|
|
224
245
|
gcOptions,
|
|
225
|
-
deleteUnusedRoutes,
|
|
226
246
|
getNodePackagePath,
|
|
227
|
-
getCurrentReferenceTimestampMs,
|
|
228
247
|
getLastSummaryTimestampMs,
|
|
229
248
|
baseSnapshot,
|
|
230
249
|
readAndParseBlob,
|
|
@@ -309,7 +328,7 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
309
328
|
// Promise when resolved initializes the base state of the nodes from the base summary state.
|
|
310
329
|
private readonly initializeBaseStateP: Promise<void>;
|
|
311
330
|
// The map of data store ids to their GC details in the base summary returned in getDataStoreGCDetails().
|
|
312
|
-
private readonly
|
|
331
|
+
private readonly baseGCDetailsP: Promise<Map<string, IGarbageCollectionDetailsBase>>;
|
|
313
332
|
// The time after which an unreferenced node can be deleted. Currently, we only set the node's state to expired.
|
|
314
333
|
private readonly deleteTimeoutMs: number;
|
|
315
334
|
// Map of node ids to their unreferenced state tracker.
|
|
@@ -324,18 +343,10 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
324
343
|
private readonly pendingEventsQueue: IUnreferencedEvent[] = [];
|
|
325
344
|
|
|
326
345
|
protected constructor(
|
|
327
|
-
private readonly
|
|
346
|
+
private readonly runtime: IGarbageCollectionRuntime,
|
|
328
347
|
private readonly gcOptions: IGCRuntimeOptions,
|
|
329
|
-
/** After GC has run, called to delete objects in the runtime whose routes are unused. */
|
|
330
|
-
private readonly deleteUnusedRoutes: (unusedRoutes: string[]) => void,
|
|
331
348
|
/** For a given node path, returns the node's package path. */
|
|
332
349
|
private readonly getNodePackagePath: (nodePath: string) => readonly string[] | undefined,
|
|
333
|
-
/**
|
|
334
|
-
* Returns a referenced timestamp to be used to track unreferenced nodes. This is a server generated timestamp
|
|
335
|
-
* and may not be available if there aren't any ops processed yet. If so, we skip tracking unreferenced state
|
|
336
|
-
* such as time when node becomes unreferenced or inactive.
|
|
337
|
-
*/
|
|
338
|
-
private readonly getCurrentReferenceTimestampMs: () => number | undefined,
|
|
339
350
|
/** Returns the timestamp of the last summary generated for this container. */
|
|
340
351
|
private readonly getLastSummaryTimestampMs: () => number | undefined,
|
|
341
352
|
baseSnapshot: ISnapshotTree | undefined,
|
|
@@ -357,11 +368,11 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
357
368
|
if (existing) {
|
|
358
369
|
prevSummaryGCVersion = getGCVersion(metadata);
|
|
359
370
|
// Existing documents which did not have metadata blob or had GC disabled have version as 0. For all
|
|
360
|
-
// other
|
|
371
|
+
// other existing documents, GC is enabled.
|
|
361
372
|
this.gcEnabled = prevSummaryGCVersion > 0;
|
|
362
373
|
this.sessionExpiryTimeoutMs = metadata?.sessionExpiryTimeoutMs;
|
|
363
374
|
} else {
|
|
364
|
-
// For new documents, GC has to be
|
|
375
|
+
// For new documents, GC has to be explicitly enabled via the gcAllowed flag in GC options.
|
|
365
376
|
this.gcEnabled = gcOptions.gcAllowed === true;
|
|
366
377
|
// Set the Session Expiry only if the flag is enabled or the test option is set.
|
|
367
378
|
if (this.mc.config.getBoolean(runSessionExpiry) && this.gcEnabled) {
|
|
@@ -374,7 +385,7 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
374
385
|
const timeoutMs = this.sessionExpiryTimeoutMs;
|
|
375
386
|
setLongTimeout(timeoutMs,
|
|
376
387
|
() => {
|
|
377
|
-
this.
|
|
388
|
+
this.runtime.closeFn(new ClientSessionExpiredError(`Client session expired.`, timeoutMs));
|
|
378
389
|
},
|
|
379
390
|
(timer) => {
|
|
380
391
|
this.sessionExpiryTimer = timer;
|
|
@@ -435,10 +446,10 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
435
446
|
// consolidate into IGarbageCollectionState format.
|
|
436
447
|
// Add a node for the root node that is not present in older snapshot format.
|
|
437
448
|
const gcState: IGarbageCollectionState = { gcNodes: { "/": { outboundRoutes: [] } } };
|
|
438
|
-
const
|
|
439
|
-
assert(
|
|
449
|
+
const dataStoreSnapshotTree = getSummaryForDatastores(baseSnapshot, metadata);
|
|
450
|
+
assert(dataStoreSnapshotTree !== undefined,
|
|
440
451
|
0x2a8 /* "Expected data store snapshot tree in base snapshot" */);
|
|
441
|
-
for (const [dsId, dsSnapshotTree] of Object.entries(
|
|
452
|
+
for (const [dsId, dsSnapshotTree] of Object.entries(dataStoreSnapshotTree.trees)) {
|
|
442
453
|
const blobId = dsSnapshotTree.blobs[gcBlobKey];
|
|
443
454
|
if (blobId === undefined) {
|
|
444
455
|
continue;
|
|
@@ -482,7 +493,7 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
482
493
|
* may be out of date. This is fine because the state is updated every time GC runs based on the time then.
|
|
483
494
|
*/
|
|
484
495
|
this.initializeBaseStateP = new LazyPromise<void>(async () => {
|
|
485
|
-
const currentReferenceTimestampMs = this.getCurrentReferenceTimestampMs();
|
|
496
|
+
const currentReferenceTimestampMs = this.runtime.getCurrentReferenceTimestampMs();
|
|
486
497
|
const baseState = await baseSummaryStateP;
|
|
487
498
|
if (baseState === undefined) {
|
|
488
499
|
return;
|
|
@@ -505,9 +516,9 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
505
516
|
this.gcDataFromLastRun = { gcNodes };
|
|
506
517
|
});
|
|
507
518
|
|
|
508
|
-
// Get the GC details for each
|
|
509
|
-
//
|
|
510
|
-
this.
|
|
519
|
+
// Get the GC details for each node from the GC state in the base summary. This is returned in getBaseGCDetails
|
|
520
|
+
// which the caller uses to initialize each node's GC state.
|
|
521
|
+
this.baseGCDetailsP = new LazyPromise<Map<string, IGarbageCollectionDetailsBase>>(async () => {
|
|
511
522
|
const baseState = await baseSummaryStateP;
|
|
512
523
|
if (baseState === undefined) {
|
|
513
524
|
return new Map();
|
|
@@ -526,18 +537,18 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
526
537
|
this.mc.logger,
|
|
527
538
|
).referencedNodeIds;
|
|
528
539
|
|
|
529
|
-
const
|
|
530
|
-
// Currently, the
|
|
540
|
+
const baseGCDetailsMap = unpackChildNodesGCDetails({ gcData: { gcNodes }, usedRoutes });
|
|
541
|
+
// Currently, the nodes may write the GC data. So, we need to update it's base GC details with the
|
|
531
542
|
// unreferenced timestamp. Once we start writing the GC data here, we won't need to do this anymore.
|
|
532
543
|
for (const [nodeId, nodeData] of Object.entries(baseState.gcNodes)) {
|
|
533
544
|
if (nodeData.unreferencedTimestampMs !== undefined) {
|
|
534
|
-
const dataStoreGCDetails =
|
|
545
|
+
const dataStoreGCDetails = baseGCDetailsMap.get(nodeId.slice(1));
|
|
535
546
|
if (dataStoreGCDetails !== undefined) {
|
|
536
547
|
dataStoreGCDetails.unrefTimestamp = nodeData.unreferencedTimestampMs;
|
|
537
548
|
}
|
|
538
549
|
}
|
|
539
550
|
}
|
|
540
|
-
return
|
|
551
|
+
return baseGCDetailsMap;
|
|
541
552
|
});
|
|
542
553
|
|
|
543
554
|
// Initialize the base state. The base GC data is used to detect and log when inactive / deleted objects are
|
|
@@ -561,7 +572,7 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
561
572
|
}
|
|
562
573
|
|
|
563
574
|
/**
|
|
564
|
-
* Runs garbage collection and
|
|
575
|
+
* Runs garbage collection and updates the reference / used state of the nodes in the container.
|
|
565
576
|
* @returns the number of data stores that have been marked as unreferenced.
|
|
566
577
|
*/
|
|
567
578
|
public async collectGarbage(
|
|
@@ -584,10 +595,10 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
584
595
|
await this.initializeBaseStateP;
|
|
585
596
|
|
|
586
597
|
// Let the runtime update its pending state before GC runs.
|
|
587
|
-
await this.
|
|
598
|
+
await this.runtime.updateStateBeforeGC();
|
|
588
599
|
|
|
589
600
|
// Get the runtime's GC data and run GC on the reference graph in it.
|
|
590
|
-
const gcData = await this.
|
|
601
|
+
const gcData = await this.runtime.getGCData(fullGC);
|
|
591
602
|
const gcResult = runGarbageCollection(
|
|
592
603
|
gcData.gcNodes,
|
|
593
604
|
[ "/" ],
|
|
@@ -600,10 +611,10 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
600
611
|
this.updateStateSinceLastRun(gcData);
|
|
601
612
|
|
|
602
613
|
// Update the current state of the system based on the GC run.
|
|
603
|
-
const currentReferenceTimestampMs = this.getCurrentReferenceTimestampMs();
|
|
614
|
+
const currentReferenceTimestampMs = this.runtime.getCurrentReferenceTimestampMs();
|
|
604
615
|
this.updateCurrentState(gcData, gcResult, currentReferenceTimestampMs);
|
|
605
616
|
|
|
606
|
-
this.
|
|
617
|
+
this.runtime.updateUsedRoutes(gcResult.referencedNodeIds, currentReferenceTimestampMs);
|
|
607
618
|
|
|
608
619
|
if (runSweep) {
|
|
609
620
|
// Placeholder for running sweep logic.
|
|
@@ -612,7 +623,7 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
612
623
|
// If we are running in GC test mode, delete objects for unused routes. This enables testing scenarios
|
|
613
624
|
// involving access to deleted data.
|
|
614
625
|
if (this.testMode) {
|
|
615
|
-
this.deleteUnusedRoutes(gcResult.deletedNodeIds);
|
|
626
|
+
this.runtime.deleteUnusedRoutes(gcResult.deletedNodeIds);
|
|
616
627
|
}
|
|
617
628
|
event.end({ ...gcStats });
|
|
618
629
|
return gcStats;
|
|
@@ -644,11 +655,11 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
644
655
|
}
|
|
645
656
|
|
|
646
657
|
/**
|
|
647
|
-
* Returns a map of
|
|
648
|
-
* initialize the GC state of
|
|
658
|
+
* Returns a map of node ids to their base GC details generated from the base summary. This is used by the caller
|
|
659
|
+
* to initialize the GC state of the nodes.
|
|
649
660
|
*/
|
|
650
|
-
public async
|
|
651
|
-
return this.
|
|
661
|
+
public async getBaseGCDetails(): Promise<Map<string, IGarbageCollectionDetailsBase>> {
|
|
662
|
+
return this.baseGCDetailsP;
|
|
652
663
|
}
|
|
653
664
|
|
|
654
665
|
/**
|
|
@@ -905,7 +916,7 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
905
916
|
currentReferences.forEach((route: string) => {
|
|
906
917
|
// Validate references for data stores only. Currently, layers below data stores don't have GC implemented
|
|
907
918
|
// so there is no guarantee their references will be notified.
|
|
908
|
-
if (
|
|
919
|
+
if (this.runtime.getNodeType(route) === GCNodeType.DataStore && !explicitReferences.includes(route)) {
|
|
909
920
|
/**
|
|
910
921
|
* The following log will be enabled once this issue is resolved:
|
|
911
922
|
* https://github.com/microsoft/FluidFramework/issues/8878.
|
|
@@ -922,7 +933,8 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
922
933
|
|
|
923
934
|
/**
|
|
924
935
|
* Generates the stats of a garbage collection run from the given results of the run. Also, logs any pending events
|
|
925
|
-
* in the pendingEventsQueue.
|
|
936
|
+
* in the pendingEventsQueue. This should be called before updating the current state because it generates stats
|
|
937
|
+
* based on previous state of the system.
|
|
926
938
|
* @param gcResult - The result of a GC run.
|
|
927
939
|
* @returns the GC stats of the GC run.
|
|
928
940
|
*/
|
|
@@ -942,44 +954,55 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
942
954
|
const gcStats: IGCStats = {
|
|
943
955
|
nodeCount: 0,
|
|
944
956
|
dataStoreCount: 0,
|
|
957
|
+
attachmentBlobCount: 0,
|
|
945
958
|
unrefNodeCount: 0,
|
|
946
959
|
unrefDataStoreCount: 0,
|
|
960
|
+
unrefAttachmentBlobCount: 0,
|
|
947
961
|
updatedNodeCount: 0,
|
|
948
962
|
updatedDataStoreCount: 0,
|
|
963
|
+
updatedAttachmentBlobCount: 0,
|
|
949
964
|
};
|
|
950
965
|
|
|
951
|
-
|
|
966
|
+
const updateNodeStats = (nodeId: string, referenced: boolean) => {
|
|
952
967
|
gcStats.nodeCount++;
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
if (this.unreferencedNodesState.has(nodeId)) {
|
|
968
|
+
/**
|
|
969
|
+
* `this.unreferencedNodesState` has the previous unreferenced state of all nodes. `referenced` flag passed
|
|
970
|
+
* here is current state of the give node. Check if the reference state of the changed.
|
|
971
|
+
*/
|
|
972
|
+
const stateUpdated = this.unreferencedNodesState.has(nodeId) ? referenced : !referenced;
|
|
973
|
+
if (stateUpdated) {
|
|
960
974
|
gcStats.updatedNodeCount++;
|
|
961
|
-
if (isDataStore) {
|
|
962
|
-
gcStats.updatedDataStoreCount++;
|
|
963
|
-
}
|
|
964
975
|
}
|
|
965
|
-
|
|
976
|
+
if (!referenced) {
|
|
977
|
+
gcStats.unrefNodeCount++;
|
|
978
|
+
}
|
|
966
979
|
|
|
967
|
-
|
|
968
|
-
gcStats.nodeCount++;
|
|
969
|
-
gcStats.unrefNodeCount++;
|
|
970
|
-
const isDataStore = isDataStoreNode(nodeId);
|
|
971
|
-
if (isDataStore) {
|
|
980
|
+
if (this.runtime.getNodeType(nodeId) === GCNodeType.DataStore) {
|
|
972
981
|
gcStats.dataStoreCount++;
|
|
973
|
-
|
|
974
|
-
}
|
|
975
|
-
// If an unreferenced node doesn't an entry in `unreferencedNodesState`, it was previously referenced. So,
|
|
976
|
-
// its reference state updated from the last GC run.
|
|
977
|
-
if (!this.unreferencedNodesState.has(nodeId)) {
|
|
978
|
-
gcStats.updatedNodeCount++;
|
|
979
|
-
if (isDataStore) {
|
|
982
|
+
if (stateUpdated) {
|
|
980
983
|
gcStats.updatedDataStoreCount++;
|
|
981
984
|
}
|
|
985
|
+
if (!referenced) {
|
|
986
|
+
gcStats.unrefDataStoreCount++;
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
if (this.runtime.getNodeType(nodeId) === GCNodeType.Blob) {
|
|
990
|
+
gcStats.attachmentBlobCount++;
|
|
991
|
+
if (stateUpdated) {
|
|
992
|
+
gcStats.updatedAttachmentBlobCount++;
|
|
993
|
+
}
|
|
994
|
+
if (!referenced) {
|
|
995
|
+
gcStats.unrefAttachmentBlobCount++;
|
|
996
|
+
}
|
|
982
997
|
}
|
|
998
|
+
};
|
|
999
|
+
|
|
1000
|
+
for (const nodeId of gcResult.referencedNodeIds) {
|
|
1001
|
+
updateNodeStats(nodeId, true /* referenced */);
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
for (const nodeId of gcResult.deletedNodeIds) {
|
|
1005
|
+
updateNodeStats(nodeId, false /* referenced */);
|
|
983
1006
|
}
|
|
984
1007
|
|
|
985
1008
|
return gcStats;
|
|
@@ -991,7 +1014,7 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
991
1014
|
private logIfInactive(
|
|
992
1015
|
eventSuffix: "Changed" | "Loaded" | "Revived",
|
|
993
1016
|
nodeId: string,
|
|
994
|
-
currentReferenceTimestampMs = this.getCurrentReferenceTimestampMs(),
|
|
1017
|
+
currentReferenceTimestampMs = this.runtime.getCurrentReferenceTimestampMs(),
|
|
995
1018
|
packagePath?: readonly string[],
|
|
996
1019
|
requestHeaders?: IRequestHeader,
|
|
997
1020
|
) {
|
|
@@ -1042,7 +1065,7 @@ async function getGCStateFromSnapshot(
|
|
|
1042
1065
|
): Promise<IGarbageCollectionState> {
|
|
1043
1066
|
let rootGCState: IGarbageCollectionState = { gcNodes: {} };
|
|
1044
1067
|
for (const key of Object.keys(gcSnapshotTree.blobs)) {
|
|
1045
|
-
// Skip blobs that do not
|
|
1068
|
+
// Skip blobs that do not start with the GC prefix.
|
|
1046
1069
|
if (!key.startsWith(gcBlobPrefix)) {
|
|
1047
1070
|
continue;
|
|
1048
1071
|
}
|
|
@@ -1081,12 +1104,3 @@ function setLongTimeout(
|
|
|
1081
1104
|
}
|
|
1082
1105
|
setTimerFn(timer);
|
|
1083
1106
|
}
|
|
1084
|
-
|
|
1085
|
-
/**
|
|
1086
|
-
* Given a GC nodeId, tells whether it belongs to a data store or not.
|
|
1087
|
-
*/
|
|
1088
|
-
function isDataStoreNode(nodeId: string): boolean {
|
|
1089
|
-
const pathParts = nodeId.split("/");
|
|
1090
|
-
// Data store ids are in the format "/dataStoreId".
|
|
1091
|
-
return pathParts.length === 2 && pathParts[1] !== "" ? true : false;
|
|
1092
|
-
}
|
package/src/packageVersion.ts
CHANGED