@fluidframework/container-runtime 0.57.0-51086 → 0.58.0-55561

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.
Files changed (114) hide show
  1. package/dist/batchTracker.d.ts +26 -0
  2. package/dist/batchTracker.d.ts.map +1 -0
  3. package/dist/batchTracker.js +59 -0
  4. package/dist/batchTracker.js.map +1 -0
  5. package/dist/containerRuntime.d.ts +12 -7
  6. package/dist/containerRuntime.d.ts.map +1 -1
  7. package/dist/containerRuntime.js +125 -55
  8. package/dist/containerRuntime.js.map +1 -1
  9. package/dist/dataStore.d.ts +1 -36
  10. package/dist/dataStore.d.ts.map +1 -1
  11. package/dist/dataStore.js +5 -27
  12. package/dist/dataStore.js.map +1 -1
  13. package/dist/dataStoreContext.d.ts +5 -7
  14. package/dist/dataStoreContext.d.ts.map +1 -1
  15. package/dist/dataStoreContext.js +12 -7
  16. package/dist/dataStoreContext.js.map +1 -1
  17. package/dist/dataStores.d.ts +1 -1
  18. package/dist/dataStores.d.ts.map +1 -1
  19. package/dist/dataStores.js +3 -3
  20. package/dist/dataStores.js.map +1 -1
  21. package/dist/garbageCollection.d.ts +25 -11
  22. package/dist/garbageCollection.d.ts.map +1 -1
  23. package/dist/garbageCollection.js +100 -57
  24. package/dist/garbageCollection.js.map +1 -1
  25. package/dist/index.d.ts +0 -1
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +1 -3
  28. package/dist/index.js.map +1 -1
  29. package/dist/packageVersion.d.ts +1 -1
  30. package/dist/packageVersion.js +1 -1
  31. package/dist/packageVersion.js.map +1 -1
  32. package/dist/pendingStateManager.d.ts.map +1 -1
  33. package/dist/pendingStateManager.js +1 -6
  34. package/dist/pendingStateManager.js.map +1 -1
  35. package/dist/runningSummarizer.d.ts +1 -1
  36. package/dist/runningSummarizer.d.ts.map +1 -1
  37. package/dist/runningSummarizer.js +1 -1
  38. package/dist/runningSummarizer.js.map +1 -1
  39. package/dist/summarizer.d.ts +3 -4
  40. package/dist/summarizer.d.ts.map +1 -1
  41. package/dist/summarizer.js +8 -9
  42. package/dist/summarizer.js.map +1 -1
  43. package/dist/summaryGenerator.d.ts +1 -1
  44. package/dist/summaryGenerator.d.ts.map +1 -1
  45. package/dist/summaryGenerator.js +1 -1
  46. package/dist/summaryGenerator.js.map +1 -1
  47. package/dist/summaryManager.d.ts +2 -6
  48. package/dist/summaryManager.d.ts.map +1 -1
  49. package/dist/summaryManager.js +4 -10
  50. package/dist/summaryManager.js.map +1 -1
  51. package/lib/batchTracker.d.ts +26 -0
  52. package/lib/batchTracker.d.ts.map +1 -0
  53. package/lib/batchTracker.js +54 -0
  54. package/lib/batchTracker.js.map +1 -0
  55. package/lib/containerRuntime.d.ts +12 -7
  56. package/lib/containerRuntime.d.ts.map +1 -1
  57. package/lib/containerRuntime.js +126 -56
  58. package/lib/containerRuntime.js.map +1 -1
  59. package/lib/dataStore.d.ts +1 -36
  60. package/lib/dataStore.d.ts.map +1 -1
  61. package/lib/dataStore.js +4 -26
  62. package/lib/dataStore.js.map +1 -1
  63. package/lib/dataStoreContext.d.ts +5 -7
  64. package/lib/dataStoreContext.d.ts.map +1 -1
  65. package/lib/dataStoreContext.js +13 -8
  66. package/lib/dataStoreContext.js.map +1 -1
  67. package/lib/dataStores.d.ts +1 -1
  68. package/lib/dataStores.d.ts.map +1 -1
  69. package/lib/dataStores.js +3 -3
  70. package/lib/dataStores.js.map +1 -1
  71. package/lib/garbageCollection.d.ts +25 -11
  72. package/lib/garbageCollection.d.ts.map +1 -1
  73. package/lib/garbageCollection.js +98 -55
  74. package/lib/garbageCollection.js.map +1 -1
  75. package/lib/index.d.ts +0 -1
  76. package/lib/index.d.ts.map +1 -1
  77. package/lib/index.js +0 -1
  78. package/lib/index.js.map +1 -1
  79. package/lib/packageVersion.d.ts +1 -1
  80. package/lib/packageVersion.js +1 -1
  81. package/lib/packageVersion.js.map +1 -1
  82. package/lib/pendingStateManager.d.ts.map +1 -1
  83. package/lib/pendingStateManager.js +1 -6
  84. package/lib/pendingStateManager.js.map +1 -1
  85. package/lib/runningSummarizer.d.ts +1 -1
  86. package/lib/runningSummarizer.d.ts.map +1 -1
  87. package/lib/runningSummarizer.js +1 -1
  88. package/lib/runningSummarizer.js.map +1 -1
  89. package/lib/summarizer.d.ts +3 -4
  90. package/lib/summarizer.d.ts.map +1 -1
  91. package/lib/summarizer.js +8 -9
  92. package/lib/summarizer.js.map +1 -1
  93. package/lib/summaryGenerator.d.ts +1 -1
  94. package/lib/summaryGenerator.d.ts.map +1 -1
  95. package/lib/summaryGenerator.js +1 -1
  96. package/lib/summaryGenerator.js.map +1 -1
  97. package/lib/summaryManager.d.ts +2 -6
  98. package/lib/summaryManager.d.ts.map +1 -1
  99. package/lib/summaryManager.js +5 -11
  100. package/lib/summaryManager.js.map +1 -1
  101. package/package.json +12 -12
  102. package/src/batchTracker.ts +80 -0
  103. package/src/containerRuntime.ts +180 -63
  104. package/src/dataStore.ts +6 -42
  105. package/src/dataStoreContext.ts +17 -15
  106. package/src/dataStores.ts +9 -4
  107. package/src/garbageCollection.ts +125 -67
  108. package/src/index.ts +0 -1
  109. package/src/packageVersion.ts +1 -1
  110. package/src/pendingStateManager.ts +4 -8
  111. package/src/runningSummarizer.ts +3 -3
  112. package/src/summarizer.ts +8 -8
  113. package/src/summaryGenerator.ts +2 -2
  114. package/src/summaryManager.ts +5 -20
@@ -12,6 +12,7 @@ import { IGCRuntimeOptions } from "./containerRuntime";
12
12
  import { IContainerRuntimeMetadata } from "./summaryFormat";
13
13
  export declare const gcTreeKey = "gc";
14
14
  export declare const gcBlobPrefix = "__gc";
15
+ export declare const defaultSessionExpiryDurationMs: number;
15
16
  /** The statistics of the system state after a garbage collection run. */
16
17
  export interface IGCStats {
17
18
  /** The number of nodes in the container. */
@@ -35,6 +36,8 @@ export interface IGarbageCollectionRuntime {
35
36
  getGCData(fullGC?: boolean): Promise<IGarbageCollectionData>;
36
37
  /** After GC has run, called to notify the runtime of routes that are used in it. */
37
38
  updateUsedRoutes(usedRoutes: string[], gcTimestamp?: number): void;
39
+ /** Called when the runtime should close because of an error. */
40
+ closeFn(error?: ICriticalContainerError): void;
38
41
  }
39
42
  /** Defines the contract for the garbage collector. */
40
43
  export interface IGarbageCollector {
@@ -66,7 +69,7 @@ export interface IGarbageCollector {
66
69
  /** Called when the latest summary of the system has been refreshed. */
67
70
  latestSummaryStateRefreshed(result: RefreshSummaryResult, readAndParseBlob: ReadAndParseBlob): Promise<void>;
68
71
  /** Called when a node is updated. Used to detect and log when an inactive node is changed or loaded. */
69
- nodeUpdated(nodePath: string, reason: "Loaded" | "Changed", packagePath?: readonly string[], requestHeaders?: IRequestHeader): void;
72
+ nodeUpdated(nodePath: string, reason: "Loaded" | "Changed", timestampMs?: number, packagePath?: readonly string[], requestHeaders?: IRequestHeader): void;
70
73
  /** Called when a reference is added to a node. Used to identify nodes that were referenced between summaries. */
71
74
  addedOutboundReference(fromNodePath: string, toNodePath: string): void;
72
75
  dispose(): void;
@@ -82,10 +85,15 @@ export declare class GarbageCollector implements IGarbageCollector {
82
85
  private readonly deleteUnusedRoutes;
83
86
  /** For a given node path, returns the node's package path. */
84
87
  private readonly getNodePackagePath;
85
- /** Returns the current timestamp to be assigned to nodes that become unreferenced. */
86
- private readonly getCurrentTimestampMs;
87
- private readonly closeFn;
88
- static create(provider: IGarbageCollectionRuntime, gcOptions: IGCRuntimeOptions, deleteUnusedRoutes: (unusedRoutes: string[]) => void, getNodePackagePath: (nodeId: string) => readonly string[] | undefined, getCurrentTimestampMs: () => number, closeFn: (error?: ICriticalContainerError) => void, baseSnapshot: ISnapshotTree | undefined, readAndParseBlob: ReadAndParseBlob, baseLogger: ITelemetryLogger, existing: boolean, metadata?: IContainerRuntimeMetadata): IGarbageCollector;
88
+ /**
89
+ * Returns a referenced timestamp to be used to track unreferenced nodes. This is a server generated timestamp
90
+ * and may not be available if there aren't any ops processed yet. If so, we skip tracking unreferenced state
91
+ * such as time when node becomes unreferenced or inactive.
92
+ */
93
+ private readonly getCurrentReferenceTimestampMs;
94
+ /** Returns the timestamp of the last summary generated for this container. */
95
+ private readonly getLastSummaryTimestampMs;
96
+ static create(provider: IGarbageCollectionRuntime, gcOptions: IGCRuntimeOptions, deleteUnusedRoutes: (unusedRoutes: string[]) => void, getNodePackagePath: (nodeId: string) => readonly string[] | undefined, getCurrentReferenceTimestampMs: () => number | undefined, getLastSummaryTimestampMs: () => number | undefined, baseSnapshot: ISnapshotTree | undefined, readAndParseBlob: ReadAndParseBlob, baseLogger: ITelemetryLogger, existing: boolean, metadata?: IContainerRuntimeMetadata): IGarbageCollector;
89
97
  /**
90
98
  * Tells whether GC should be run based on the GC options and local storage flags.
91
99
  */
@@ -149,8 +157,14 @@ export declare class GarbageCollector implements IGarbageCollector {
149
157
  deleteUnusedRoutes: (unusedRoutes: string[]) => void,
150
158
  /** For a given node path, returns the node's package path. */
151
159
  getNodePackagePath: (nodePath: string) => readonly string[] | undefined,
152
- /** Returns the current timestamp to be assigned to nodes that become unreferenced. */
153
- getCurrentTimestampMs: () => number, closeFn: (error?: ICriticalContainerError) => void, baseSnapshot: ISnapshotTree | undefined, readAndParseBlob: ReadAndParseBlob, baseLogger: ITelemetryLogger, existing: boolean, metadata?: IContainerRuntimeMetadata);
160
+ /**
161
+ * Returns a referenced timestamp to be used to track unreferenced nodes. This is a server generated timestamp
162
+ * and may not be available if there aren't any ops processed yet. If so, we skip tracking unreferenced state
163
+ * such as time when node becomes unreferenced or inactive.
164
+ */
165
+ getCurrentReferenceTimestampMs: () => number | undefined,
166
+ /** Returns the timestamp of the last summary generated for this container. */
167
+ getLastSummaryTimestampMs: () => number | undefined, baseSnapshot: ISnapshotTree | undefined, readAndParseBlob: ReadAndParseBlob, baseLogger: ITelemetryLogger, existing: boolean, metadata?: IContainerRuntimeMetadata);
154
168
  /**
155
169
  * Runs garbage collection and udpates the reference / used state of the nodes in the container.
156
170
  * @returns the number of data stores that have been marked as unreferenced.
@@ -183,10 +197,11 @@ export declare class GarbageCollector implements IGarbageCollector {
183
197
  * Called when a node with the given id is updated. If the node is inactive, log an error.
184
198
  * @param nodePath - The id of the node that changed.
185
199
  * @param reason - Whether the node was loaded or changed.
200
+ * @param timestampMs - The timestamp when the node changed.
186
201
  * @param packagePath - The package path of the node. This may not be available if the node hasn't been loaded yet.
187
202
  * @param requestHeaders - If the node was loaded via request path, the headers in the request.
188
203
  */
189
- nodeUpdated(nodePath: string, reason: "Loaded" | "Changed", packagePath?: readonly string[], requestHeaders?: IRequestHeader): void;
204
+ nodeUpdated(nodePath: string, reason: "Loaded" | "Changed", timestampMs?: number, packagePath?: readonly string[], requestHeaders?: IRequestHeader): void;
190
205
  /**
191
206
  * Called when an outbound reference is added to a node. This is used to identify all nodes that have been
192
207
  * referenced between summaries so that their unreferenced timestamp can be reset.
@@ -207,7 +222,7 @@ export declare class GarbageCollector implements IGarbageCollector {
207
222
  * 3. Clears tracking for nodes that were unreferenced but became referenced in this run.
208
223
  * @param gcData - The data representing the reference graph on which GC is run.
209
224
  * @param gcResult - The result of the GC run on the gcData.
210
- * @param currentTimestampMs - The current timestamp to be used for unreferenced nodes' timestamp.
225
+ * @param currentReferenceTimestampMs - The timestamp to be used for unreferenced nodes' timestamp.
211
226
  */
212
227
  private updateCurrentState;
213
228
  /**
@@ -236,8 +251,7 @@ export declare class GarbageCollector implements IGarbageCollector {
236
251
  */
237
252
  private generateStatsAndLogEvents;
238
253
  /**
239
- * Logs an event if a node is inactive and is used. If the package data for the node exists, log immediately. Else,
240
- * queue it and it will be logged the next time GC runs as the package data should be available then.
254
+ * Logs an event if a node is inactive and is used.
241
255
  */
242
256
  private logIfInactive;
243
257
  }
@@ -1 +1 @@
1
- {"version":3,"file":"garbageCollection.d.ts","sourceRoot":"","sources":["../src/garbageCollection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAEtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAC;AAEhF,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AASjE,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AACrE,OAAO,EAEH,sBAAsB,EAEtB,6BAA6B,EAC7B,qBAAqB,EACxB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACH,gBAAgB,EAChB,oBAAoB,EAEvB,MAAM,+BAA+B,CAAC;AAUvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,EAGH,yBAAyB,EAI5B,MAAM,iBAAiB,CAAC;AAMzB,eAAO,MAAM,SAAS,OAAO,CAAC;AAE9B,eAAO,MAAM,YAAY,SAAS,CAAC;AAgBnC,yEAAyE;AACzE,MAAM,WAAW,QAAQ;IACrB,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,cAAc,EAAE,MAAM,CAAC;IACvB,yDAAyD;IACzD,cAAc,EAAE,MAAM,CAAC;IACvB,+DAA+D;IAC/D,mBAAmB,EAAE,MAAM,CAAC;IAC5B,2EAA2E;IAC3E,gBAAgB,EAAE,MAAM,CAAC;IACzB,iFAAiF;IACjF,qBAAqB,EAAE,MAAM,CAAC;CACjC;AAYD,qFAAqF;AACrF,MAAM,WAAW,yBAAyB;IACtC,mFAAmF;IACnF,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,0DAA0D;IAC1D,SAAS,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAC7D,oFAAoF;IACpF,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACtE;AAED,sDAAsD;AACtD,MAAM,WAAW,iBAAiB;IAC9B,0CAA0C;IAC1C,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,8DAA8D;IAC9D,QAAQ,CAAC,sBAAsB,EAAE,MAAM,GAAG,SAAS,CAAC;IACpD;;;;OAIG;IACH,QAAQ,CAAC,uBAAuB,EAAE,MAAM,CAAC;IACzC,mFAAmF;IACnF,QAAQ,CAAC,sBAAsB,EAAE,OAAO,CAAC;IACzC,+EAA+E;IAC/E,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,kFAAkF;IAClF,cAAc,CACV,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,gBAAgB,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAC9F,OAAO,CAAC,QAAQ,CAAC,CAAC;IACrB,+DAA+D;IAC/D,SAAS,IAAI,qBAAqB,GAAG,SAAS,CAAC;IAC/C,iFAAiF;IACjF,yBAAyB,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,6BAA6B,CAAC,CAAC,CAAC;IACjF,uEAAuE;IACvE,2BAA2B,CAAC,MAAM,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7G,wGAAwG;IACxG,WAAW,CACP,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,QAAQ,GAAG,SAAS,EAC5B,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,EAC/B,cAAc,CAAC,EAAE,cAAc,GAChC,IAAI,CAAC;IACR,iHAAiH;IACjH,sBAAsB,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACvE,OAAO,IAAI,IAAI,CAAC;CACnB;AAmCD;;;GAGG;AACH,qBAAa,gBAAiB,YAAW,iBAAiB;IAuHlD,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,yFAAyF;IACzF,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IACnC,8DAA8D;IAC9D,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IACnC,sFAAsF;IACtF,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO;WA9Hd,MAAM,CAChB,QAAQ,EAAE,yBAAyB,EACnC,SAAS,EAAE,iBAAiB,EAC5B,kBAAkB,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,IAAI,EACpD,kBAAkB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,SAAS,MAAM,EAAE,GAAG,SAAS,EACrE,qBAAqB,EAAE,MAAM,MAAM,EACnC,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,uBAAuB,KAAK,IAAI,EAClD,YAAY,EAAE,aAAa,GAAG,SAAS,EACvC,gBAAgB,EAAE,gBAAgB,EAClC,UAAU,EAAE,gBAAgB,EAC5B,QAAQ,EAAE,OAAO,EACjB,QAAQ,CAAC,EAAE,yBAAyB,GACrC,iBAAiB;IAgBpB;;OAEG;IACH,SAAgB,WAAW,EAAE,OAAO,CAAC;IAErC;;OAEG;IACH,SAAgB,sBAAsB,EAAE,MAAM,GAAG,SAAS,CAAC;IAE3D;;;;OAIG;IACH,IAAW,uBAAuB,IAAI,MAAM,CAE3C;IAED;;;;;;;OAOG;IACH,IAAW,sBAAsB,IAAI,OAAO,CAG3C;IAED;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAU;IACpC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAU;IACzC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;IACnC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAoB;IAEvC;;OAEG;IACH,OAAO,CAAC,gBAAgB,CAAkB;IAC1C,IAAW,eAAe,IAAI,OAAO,CAEnC;IAEF;;;;;;;;;MASE;IACF,OAAO,CAAC,sBAAsB,CAAkB;IAGhD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAa;IAE9C,OAAO,CAAC,sBAAsB,CAAY;IAG1C,OAAO,CAAC,iBAAiB,CAAqC;IAG9D,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAoC;IAG3E,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAgB;IAErD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAsD;IAE1F,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IAEzC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAoD;IAE3F,OAAO,CAAC,kBAAkB,CAAC,CAAgC;IAI3D,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAA0B;IAEnE,OAAO,CAAC,kBAAkB,CAA4B;IAEtD,SAAS,aACY,QAAQ,EAAE,yBAAyB,EACnC,SAAS,EAAE,iBAAiB;IAC7C,yFAAyF;IACxE,kBAAkB,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,IAAI;IACrE,8DAA8D;IAC7C,kBAAkB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,SAAS,MAAM,EAAE,GAAG,SAAS;IACxF,sFAAsF;IACrE,qBAAqB,EAAE,MAAM,MAAM,EACnC,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,uBAAuB,KAAK,IAAI,EACnE,YAAY,EAAE,aAAa,GAAG,SAAS,EACvC,gBAAgB,EAAE,gBAAgB,EAClC,UAAU,EAAE,gBAAgB,EAC5B,QAAQ,EAAE,OAAO,EACjB,QAAQ,CAAC,EAAE,yBAAyB;IAyNxC;;;OAGG;IACU,cAAc,CACvB,OAAO,EAAE;QACL,0CAA0C;QAC1C,MAAM,CAAC,EAAE,gBAAgB,CAAC;QAC1B,sDAAsD;QACtD,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,oCAAoC;QACpC,MAAM,CAAC,EAAE,OAAO,CAAC;KACpB,GACF,OAAO,CAAC,QAAQ,CAAC;IA+CpB;;;;OAIG;IACI,SAAS,IAAI,qBAAqB,GAAG,SAAS;IAkBrD;;;OAGG;IACU,yBAAyB,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,6BAA6B,CAAC,CAAC;IAI7F;;;OAGG;IACU,2BAA2B,CACpC,MAAM,EAAE,oBAAoB,EAC5B,gBAAgB,EAAE,gBAAgB,GACnC,OAAO,CAAC,IAAI,CAAC;IAoBhB;;;;;;OAMG;IACI,WAAW,CACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,QAAQ,GAAG,SAAS,EAC5B,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,EAC/B,cAAc,CAAC,EAAE,cAAc;IAenC;;;;;;OAMG;IACI,sBAAsB,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;IAkB/D,OAAO,IAAI,IAAI;IAOtB;;OAEG;YACW,kCAAkC;IAQhD;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;IAgC1B;;;;;;;OAOG;IACH,OAAO,CAAC,uBAAuB;IAkD/B;;;;;;;OAOG;IACH,OAAO,CAAC,4BAA4B;IAgDpC;;;;;OAKG;IACH,OAAO,CAAC,yBAAyB;IA2DjC;;;OAGG;IACH,OAAO,CAAC,aAAa;CA+BxB"}
1
+ {"version":3,"file":"garbageCollection.d.ts","sourceRoot":"","sources":["../src/garbageCollection.ts"],"names":[],"mappings":"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"}
@@ -4,7 +4,7 @@
4
4
  * Licensed under the MIT License.
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.GarbageCollector = exports.gcBlobPrefix = exports.gcTreeKey = void 0;
7
+ exports.GarbageCollector = exports.defaultSessionExpiryDurationMs = exports.gcBlobPrefix = exports.gcTreeKey = void 0;
8
8
  const common_utils_1 = require("@fluidframework/common-utils");
9
9
  const container_utils_1 = require("@fluidframework/container-utils");
10
10
  const garbage_collector_1 = require("@fluidframework/garbage-collector");
@@ -31,30 +31,48 @@ const writeAtRootKey = "Fluid.GarbageCollection.WriteDataAtRoot";
31
31
  // Feature gate key to expire a session after a set period of time.
32
32
  const runSessionExpiry = "Fluid.GarbageCollection.RunSessionExpiry";
33
33
  const defaultDeleteTimeoutMs = 7 * 24 * 60 * 60 * 1000; // 7 days
34
- const defaultSessionExpiryDurationMs = 30 * 24 * 60 * 60 * 1000; // 30 days
34
+ exports.defaultSessionExpiryDurationMs = 30 * 24 * 60 * 60 * 1000; // 30 days
35
35
  ;
36
36
  /**
37
37
  * Helper class that tracks the state of an unreferenced node such as the time it was unreferenced. It also sets
38
38
  * the node's state to inactive if it remains unreferenced for a given amount of time (inactiveTimeoutMs).
39
39
  */
40
40
  class UnreferencedStateTracker {
41
- constructor(unreferencedTimestampMs, inactiveTimeoutMs) {
41
+ constructor(unreferencedTimestampMs, inactiveTimeoutMs, currentReferenceTimestampMs) {
42
42
  this.unreferencedTimestampMs = unreferencedTimestampMs;
43
+ this.inactiveTimeoutMs = inactiveTimeoutMs;
43
44
  this._inactive = false;
44
- // If the timeout has already expired, the node should become inactive immediately. Otherwise, start a timer of
45
- // inactiveTimeoutMs after which the node will become inactive.
46
- if (inactiveTimeoutMs <= 0) {
47
- this._inactive = true;
48
- }
49
- else {
50
- this.timer = new common_utils_1.Timer(inactiveTimeoutMs, () => { this._inactive = true; });
51
- this.timer.start();
45
+ // If there is no current reference timestamp, don't track the node's inactive state. This will happen later
46
+ // when updateTracking is called with a reference timestamp.
47
+ if (currentReferenceTimestampMs !== undefined) {
48
+ this.updateTracking(currentReferenceTimestampMs);
52
49
  }
53
50
  }
54
51
  get inactive() {
55
52
  return this._inactive;
56
53
  }
57
- /** Stop tracking this node. Reset the unreferenced timer, if any, and reset inactive state. */
54
+ /**
55
+ * Updates the tracking state based on the provided timestamp.
56
+ */
57
+ updateTracking(currentReferenceTimestampMs) {
58
+ var _a;
59
+ const unreferencedDurationMs = currentReferenceTimestampMs - this.unreferencedTimestampMs;
60
+ // If the timeout has already expired, the node has become inactive.
61
+ if (unreferencedDurationMs > this.inactiveTimeoutMs) {
62
+ this._inactive = true;
63
+ (_a = this.timer) === null || _a === void 0 ? void 0 : _a.clear();
64
+ return;
65
+ }
66
+ // The node isn't inactive yet. Restart a timer for the duration remaining for it to become inactive.
67
+ const remainingDurationMs = this.inactiveTimeoutMs - unreferencedDurationMs;
68
+ if (this.timer === undefined) {
69
+ this.timer = new common_utils_1.Timer(remainingDurationMs, () => { this._inactive = true; });
70
+ }
71
+ this.timer.restart(remainingDurationMs);
72
+ }
73
+ /**
74
+ * Stop tracking this node. Reset the unreferenced timer, if any, and reset inactive state.
75
+ */
58
76
  stopTracking() {
59
77
  var _a;
60
78
  (_a = this.timer) === null || _a === void 0 ? void 0 : _a.clear();
@@ -71,15 +89,21 @@ class GarbageCollector {
71
89
  deleteUnusedRoutes,
72
90
  /** For a given node path, returns the node's package path. */
73
91
  getNodePackagePath,
74
- /** Returns the current timestamp to be assigned to nodes that become unreferenced. */
75
- getCurrentTimestampMs, closeFn, baseSnapshot, readAndParseBlob, baseLogger, existing, metadata) {
92
+ /**
93
+ * Returns a referenced timestamp to be used to track unreferenced nodes. This is a server generated timestamp
94
+ * and may not be available if there aren't any ops processed yet. If so, we skip tracking unreferenced state
95
+ * such as time when node becomes unreferenced or inactive.
96
+ */
97
+ getCurrentReferenceTimestampMs,
98
+ /** Returns the timestamp of the last summary generated for this container. */
99
+ getLastSummaryTimestampMs, baseSnapshot, readAndParseBlob, baseLogger, existing, metadata) {
76
100
  var _a, _b, _c, _d, _e;
77
101
  this.provider = provider;
78
102
  this.gcOptions = gcOptions;
79
103
  this.deleteUnusedRoutes = deleteUnusedRoutes;
80
104
  this.getNodePackagePath = getNodePackagePath;
81
- this.getCurrentTimestampMs = getCurrentTimestampMs;
82
- this.closeFn = closeFn;
105
+ this.getCurrentReferenceTimestampMs = getCurrentReferenceTimestampMs;
106
+ this.getLastSummaryTimestampMs = getLastSummaryTimestampMs;
83
107
  /**
84
108
  * Tells whether the GC data should be written to the root of the summary tree.
85
109
  */
@@ -125,14 +149,14 @@ class GarbageCollector {
125
149
  this.gcEnabled = gcOptions.gcAllowed === true;
126
150
  // Set the Session Expiry only if the flag is enabled or the test option is set.
127
151
  if (this.mc.config.getBoolean(runSessionExpiry) && this.gcEnabled) {
128
- this.sessionExpiryTimeoutMs = defaultSessionExpiryDurationMs;
152
+ this.sessionExpiryTimeoutMs = exports.defaultSessionExpiryDurationMs;
129
153
  }
130
154
  }
131
155
  // If session expiry is enabled, we need to close the container when the timeout expires
132
156
  if (this.sessionExpiryTimeoutMs !== undefined) {
133
157
  const timeoutMs = this.sessionExpiryTimeoutMs;
134
158
  setLongTimeout(timeoutMs, () => {
135
- this.closeFn(new container_utils_1.ClientSessionExpiredError(`Client session expired.`, timeoutMs));
159
+ this.provider.closeFn(new container_utils_1.ClientSessionExpiredError(`Client session expired.`, timeoutMs));
136
160
  }, (timer) => {
137
161
  this.sessionExpiryTimer = timer;
138
162
  });
@@ -215,22 +239,21 @@ class GarbageCollector {
215
239
  // very first summary generated by detached container. In both cases, GC was not run - return undefined.
216
240
  return Object.keys(gcState.gcNodes).length === 1 ? undefined : gcState;
217
241
  });
218
- // Set up the initializer which initializes the base GC state from the base snapshot. Use lazy promise because
219
- // we only do this once - the very first time we run GC.
242
+ /**
243
+ * Set up the initializer which initializes the base GC state from the base snapshot. Note that the reference
244
+ * timestamp maybe from old ops which were not summarized and stored in the file. So, the unreferenced state
245
+ * may be out of date. This is fine because the state is updated every time GC runs based on the time then.
246
+ */
220
247
  this.initializeBaseStateP = new common_utils_1.LazyPromise(async () => {
221
- const currentTimestampMs = this.getCurrentTimestampMs();
248
+ const currentReferenceTimestampMs = this.getCurrentReferenceTimestampMs();
222
249
  const baseState = await baseSummaryStateP;
223
250
  if (baseState === undefined) {
224
251
  return;
225
252
  }
226
253
  const gcNodes = {};
227
254
  for (const [nodeId, nodeData] of Object.entries(baseState.gcNodes)) {
228
- const unreferencedTimestampMs = nodeData.unreferencedTimestampMs;
229
- if (unreferencedTimestampMs !== undefined) {
230
- // Get how long it has been since the node was unreferenced. Start a timeout for the remaining time
231
- // left for it to be eligible for deletion.
232
- const unreferencedDurationMs = currentTimestampMs - unreferencedTimestampMs;
233
- this.unreferencedNodesState.set(nodeId, new UnreferencedStateTracker(unreferencedTimestampMs, this.deleteTimeoutMs - unreferencedDurationMs));
255
+ if (nodeData.unreferencedTimestampMs !== undefined) {
256
+ this.unreferencedNodesState.set(nodeId, new UnreferencedStateTracker(nodeData.unreferencedTimestampMs, this.deleteTimeoutMs, currentReferenceTimestampMs));
234
257
  }
235
258
  gcNodes[nodeId] = Array.from(nodeData.outboundRoutes);
236
259
  }
@@ -268,18 +291,20 @@ class GarbageCollector {
268
291
  // used in the container.
269
292
  if (this.shouldRunGC) {
270
293
  this.initializeBaseStateP.catch((error) => {
271
- throw new container_utils_1.DataProcessingError(error === null || error === void 0 ? void 0 : error.message, "FailedToInitializeGC", {
294
+ const dpe = container_utils_1.DataProcessingError.wrapIfUnrecognized(error, "FailedToInitializeGC");
295
+ dpe.addTelemetryProperties({
272
296
  gcEnabled: this.gcEnabled,
273
297
  runSweep: this.shouldRunSweep,
274
298
  writeAtRoot: this._writeDataAtRoot,
275
299
  testMode: this.testMode,
276
300
  sessionExpiry: this.sessionExpiryTimeoutMs,
277
301
  });
302
+ throw dpe;
278
303
  });
279
304
  }
280
305
  }
281
- static create(provider, gcOptions, deleteUnusedRoutes, getNodePackagePath, getCurrentTimestampMs, closeFn, baseSnapshot, readAndParseBlob, baseLogger, existing, metadata) {
282
- return new GarbageCollector(provider, gcOptions, deleteUnusedRoutes, getNodePackagePath, getCurrentTimestampMs, closeFn, baseSnapshot, readAndParseBlob, baseLogger, existing, metadata);
306
+ static create(provider, gcOptions, deleteUnusedRoutes, getNodePackagePath, getCurrentReferenceTimestampMs, getLastSummaryTimestampMs, baseSnapshot, readAndParseBlob, baseLogger, existing, metadata) {
307
+ return new GarbageCollector(provider, gcOptions, deleteUnusedRoutes, getNodePackagePath, getCurrentReferenceTimestampMs, getLastSummaryTimestampMs, baseSnapshot, readAndParseBlob, baseLogger, existing, metadata);
283
308
  }
284
309
  /**
285
310
  * This tracks two things:
@@ -322,9 +347,9 @@ class GarbageCollector {
322
347
  // the current run. We need to identify than and update their unreferenced state if needed.
323
348
  this.updateStateSinceLastRun(gcData);
324
349
  // Update the current state of the system based on the GC run.
325
- const currentTimestampMs = this.getCurrentTimestampMs();
326
- this.updateCurrentState(gcData, gcResult, currentTimestampMs);
327
- this.provider.updateUsedRoutes(gcResult.referencedNodeIds, currentTimestampMs);
350
+ const currentReferenceTimestampMs = this.getCurrentReferenceTimestampMs();
351
+ this.updateCurrentState(gcData, gcResult, currentReferenceTimestampMs);
352
+ this.provider.updateUsedRoutes(gcResult.referencedNodeIds, currentReferenceTimestampMs);
328
353
  if (runSweep) {
329
354
  // Placeholder for running sweep logic.
330
355
  }
@@ -390,14 +415,15 @@ class GarbageCollector {
390
415
  * Called when a node with the given id is updated. If the node is inactive, log an error.
391
416
  * @param nodePath - The id of the node that changed.
392
417
  * @param reason - Whether the node was loaded or changed.
418
+ * @param timestampMs - The timestamp when the node changed.
393
419
  * @param packagePath - The package path of the node. This may not be available if the node hasn't been loaded yet.
394
420
  * @param requestHeaders - If the node was loaded via request path, the headers in the request.
395
421
  */
396
- nodeUpdated(nodePath, reason, packagePath, requestHeaders) {
422
+ nodeUpdated(nodePath, reason, timestampMs, packagePath, requestHeaders) {
397
423
  if (!this.shouldRunGC) {
398
424
  return;
399
425
  }
400
- this.logIfInactive(reason, nodePath, this.getCurrentTimestampMs(), packagePath, requestHeaders);
426
+ this.logIfInactive(reason, nodePath, timestampMs, packagePath, requestHeaders);
401
427
  }
402
428
  /**
403
429
  * Called when an outbound reference is added to a node. This is used to identify all nodes that have been
@@ -415,7 +441,7 @@ class GarbageCollector {
415
441
  outboundRoutes.push(toNodePath);
416
442
  this.referencesSinceLastRun.set(fromNodePath, outboundRoutes);
417
443
  // If the node that got referenced is inactive, log an event as that may indicate use-after-delete.
418
- this.logIfInactive("Revived", toNodePath, this.getCurrentTimestampMs(), this.getNodePackagePath(toNodePath));
444
+ this.logIfInactive("Revived", toNodePath);
419
445
  }
420
446
  dispose() {
421
447
  if (this.sessionExpiryTimer !== undefined) {
@@ -440,24 +466,11 @@ class GarbageCollector {
440
466
  * 3. Clears tracking for nodes that were unreferenced but became referenced in this run.
441
467
  * @param gcData - The data representing the reference graph on which GC is run.
442
468
  * @param gcResult - The result of the GC run on the gcData.
443
- * @param currentTimestampMs - The current timestamp to be used for unreferenced nodes' timestamp.
469
+ * @param currentReferenceTimestampMs - The timestamp to be used for unreferenced nodes' timestamp.
444
470
  */
445
- updateCurrentState(gcData, gcResult, currentTimestampMs) {
471
+ updateCurrentState(gcData, gcResult, currentReferenceTimestampMs) {
446
472
  this.gcDataFromLastRun = garbage_collector_1.cloneGCData(gcData);
447
473
  this.referencesSinceLastRun.clear();
448
- // Iterate through the deleted nodes and start tracking if they became unreferenced in this run.
449
- for (const nodeId of gcResult.deletedNodeIds) {
450
- // The time when the node became unreferenced. This is added to the current GC state.
451
- let unreferencedTimestampMs = currentTimestampMs;
452
- const nodeStateTracker = this.unreferencedNodesState.get(nodeId);
453
- if (nodeStateTracker !== undefined) {
454
- unreferencedTimestampMs = nodeStateTracker.unreferencedTimestampMs;
455
- }
456
- else {
457
- // Start tracking this node as it became unreferenced in this run.
458
- this.unreferencedNodesState.set(nodeId, new UnreferencedStateTracker(unreferencedTimestampMs, this.deleteTimeoutMs));
459
- }
460
- }
461
474
  // Iterate through the referenced nodes and stop tracking if they were unreferenced before.
462
475
  for (const nodeId of gcResult.referencedNodeIds) {
463
476
  const nodeStateTracker = this.unreferencedNodesState.get(nodeId);
@@ -468,6 +481,28 @@ class GarbageCollector {
468
481
  this.unreferencedNodesState.delete(nodeId);
469
482
  }
470
483
  }
484
+ /**
485
+ * If there is no current reference time, skip tracking when a node becomes unreferenced. This would happen
486
+ * if no ops have been processed ever and we still try to run GC. If so, there is nothing interesting to track
487
+ * anyway.
488
+ */
489
+ if (currentReferenceTimestampMs === undefined) {
490
+ return;
491
+ }
492
+ /**
493
+ * If a node became unreferenced in this run, start tracking it.
494
+ * If a node was already unreferenced, update its tracking information. Since the current reference time is
495
+ * from the ops seen, this will ensure that we keep updating the unreferenced state as time moves forward.
496
+ */
497
+ for (const nodeId of gcResult.deletedNodeIds) {
498
+ const nodeStateTracker = this.unreferencedNodesState.get(nodeId);
499
+ if (nodeStateTracker === undefined) {
500
+ this.unreferencedNodesState.set(nodeId, new UnreferencedStateTracker(currentReferenceTimestampMs, this.deleteTimeoutMs, currentReferenceTimestampMs));
501
+ }
502
+ else {
503
+ nodeStateTracker.updateTracking(currentReferenceTimestampMs);
504
+ }
505
+ }
471
506
  }
472
507
  /**
473
508
  * Since GC runs periodically, the GC data that is generated only tells us the state of the world at that point in
@@ -631,10 +666,14 @@ class GarbageCollector {
631
666
  return gcStats;
632
667
  }
633
668
  /**
634
- * Logs an event if a node is inactive and is used. If the package data for the node exists, log immediately. Else,
635
- * queue it and it will be logged the next time GC runs as the package data should be available then.
669
+ * Logs an event if a node is inactive and is used.
636
670
  */
637
- logIfInactive(eventSuffix, nodeId, timestampMs, packagePath, requestHeaders) {
671
+ logIfInactive(eventSuffix, nodeId, currentReferenceTimestampMs = this.getCurrentReferenceTimestampMs(), packagePath, requestHeaders) {
672
+ // If there is no reference timestamp to work with, no ops have been processed after creation. If so, skip
673
+ // logging as nothing interesting would have happened worth logging.
674
+ if (currentReferenceTimestampMs === undefined) {
675
+ return;
676
+ }
638
677
  const eventName = `inactiveObject_${eventSuffix}`;
639
678
  // We log a particular event for a given node only once so that it is not too noisy.
640
679
  const uniqueEventId = `${nodeId}-${eventName}`;
@@ -644,13 +683,17 @@ class GarbageCollector {
644
683
  const event = {
645
684
  eventName,
646
685
  id: nodeId,
647
- age: timestampMs - nodeState.unreferencedTimestampMs,
686
+ age: currentReferenceTimestampMs - nodeState.unreferencedTimestampMs,
648
687
  timeout: this.deleteTimeoutMs,
688
+ lastSummaryTime: this.getLastSummaryTimestampMs(),
649
689
  externalRequest: requestHeaders === null || requestHeaders === void 0 ? void 0 : requestHeaders[_1.RuntimeHeaders.externalRequest],
650
690
  viaHandle: requestHeaders === null || requestHeaders === void 0 ? void 0 : requestHeaders[_1.RuntimeHeaders.viaHandle],
651
691
  };
652
- if (packagePath !== undefined) {
653
- this.mc.logger.sendErrorEvent(Object.assign(Object.assign({}, event), { pkg: { value: `/${packagePath.join("/")}`, tag: telemetry_utils_1.TelemetryDataTag.PackageData } }));
692
+ // If the package data for the node exists, log immediately. Otherwise, queue it and it will be logged the
693
+ // next time GC runs as the package data should be available then.
694
+ const pkg = packagePath !== null && packagePath !== void 0 ? packagePath : this.getNodePackagePath(nodeId);
695
+ if (pkg !== undefined) {
696
+ this.mc.logger.sendErrorEvent(Object.assign(Object.assign({}, event), { pkg: { value: `/${pkg.join("/")}`, tag: telemetry_utils_1.TelemetryDataTag.PackageData } }));
654
697
  }
655
698
  else {
656
699
  this.pendingEventsQueue.push(event);