@fluidframework/container-runtime 2.0.0-rc.3.0.0 → 2.0.0-rc.3.0.10

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 (127) hide show
  1. package/api-report/container-runtime.api.md +30 -12
  2. package/dist/channelCollection.d.ts +5 -3
  3. package/dist/channelCollection.d.ts.map +1 -1
  4. package/dist/channelCollection.js +88 -29
  5. package/dist/channelCollection.js.map +1 -1
  6. package/dist/containerRuntime.d.ts +6 -1
  7. package/dist/containerRuntime.d.ts.map +1 -1
  8. package/dist/containerRuntime.js +55 -48
  9. package/dist/containerRuntime.js.map +1 -1
  10. package/dist/dataStoreContext.d.ts +1 -1
  11. package/dist/dataStoreContexts.d.ts +2 -0
  12. package/dist/dataStoreContexts.d.ts.map +1 -1
  13. package/dist/dataStoreContexts.js +7 -0
  14. package/dist/dataStoreContexts.js.map +1 -1
  15. package/dist/gc/garbageCollection.d.ts +4 -11
  16. package/dist/gc/garbageCollection.d.ts.map +1 -1
  17. package/dist/gc/garbageCollection.js +45 -29
  18. package/dist/gc/garbageCollection.js.map +1 -1
  19. package/dist/gc/gcDefinitions.d.ts +26 -5
  20. package/dist/gc/gcDefinitions.d.ts.map +1 -1
  21. package/dist/gc/gcDefinitions.js.map +1 -1
  22. package/dist/gc/gcHelpers.d.ts +5 -4
  23. package/dist/gc/gcHelpers.d.ts.map +1 -1
  24. package/dist/gc/gcHelpers.js +14 -2
  25. package/dist/gc/gcHelpers.js.map +1 -1
  26. package/dist/gc/gcTelemetry.d.ts +13 -2
  27. package/dist/gc/gcTelemetry.d.ts.map +1 -1
  28. package/dist/gc/gcTelemetry.js +24 -21
  29. package/dist/gc/gcTelemetry.js.map +1 -1
  30. package/dist/gc/index.d.ts +2 -2
  31. package/dist/gc/index.d.ts.map +1 -1
  32. package/dist/gc/index.js +2 -2
  33. package/dist/gc/index.js.map +1 -1
  34. package/dist/index.d.ts +2 -2
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +2 -1
  37. package/dist/index.js.map +1 -1
  38. package/dist/legacy.d.ts +1 -0
  39. package/dist/metadata.d.ts +2 -2
  40. package/dist/metadata.d.ts.map +1 -1
  41. package/dist/metadata.js.map +1 -1
  42. package/dist/opLifecycle/batchManager.d.ts +4 -1
  43. package/dist/opLifecycle/batchManager.d.ts.map +1 -1
  44. package/dist/opLifecycle/batchManager.js +0 -10
  45. package/dist/opLifecycle/batchManager.js.map +1 -1
  46. package/dist/opLifecycle/outbox.d.ts +0 -4
  47. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  48. package/dist/opLifecycle/outbox.js +7 -38
  49. package/dist/opLifecycle/outbox.js.map +1 -1
  50. package/dist/packageVersion.d.ts +1 -1
  51. package/dist/packageVersion.d.ts.map +1 -1
  52. package/dist/packageVersion.js +1 -1
  53. package/dist/packageVersion.js.map +1 -1
  54. package/dist/summary/documentSchema.js +1 -1
  55. package/dist/summary/documentSchema.js.map +1 -1
  56. package/lib/channelCollection.d.ts +5 -3
  57. package/lib/channelCollection.d.ts.map +1 -1
  58. package/lib/channelCollection.js +90 -31
  59. package/lib/channelCollection.js.map +1 -1
  60. package/lib/containerRuntime.d.ts +6 -1
  61. package/lib/containerRuntime.d.ts.map +1 -1
  62. package/lib/containerRuntime.js +54 -47
  63. package/lib/containerRuntime.js.map +1 -1
  64. package/lib/dataStoreContext.d.ts +1 -1
  65. package/lib/dataStoreContexts.d.ts +2 -0
  66. package/lib/dataStoreContexts.d.ts.map +1 -1
  67. package/lib/dataStoreContexts.js +7 -0
  68. package/lib/dataStoreContexts.js.map +1 -1
  69. package/lib/gc/garbageCollection.d.ts +4 -11
  70. package/lib/gc/garbageCollection.d.ts.map +1 -1
  71. package/lib/gc/garbageCollection.js +47 -31
  72. package/lib/gc/garbageCollection.js.map +1 -1
  73. package/lib/gc/gcDefinitions.d.ts +26 -5
  74. package/lib/gc/gcDefinitions.d.ts.map +1 -1
  75. package/lib/gc/gcDefinitions.js.map +1 -1
  76. package/lib/gc/gcHelpers.d.ts +5 -4
  77. package/lib/gc/gcHelpers.d.ts.map +1 -1
  78. package/lib/gc/gcHelpers.js +12 -1
  79. package/lib/gc/gcHelpers.js.map +1 -1
  80. package/lib/gc/gcTelemetry.d.ts +13 -2
  81. package/lib/gc/gcTelemetry.d.ts.map +1 -1
  82. package/lib/gc/gcTelemetry.js +24 -21
  83. package/lib/gc/gcTelemetry.js.map +1 -1
  84. package/lib/gc/index.d.ts +2 -2
  85. package/lib/gc/index.d.ts.map +1 -1
  86. package/lib/gc/index.js +1 -1
  87. package/lib/gc/index.js.map +1 -1
  88. package/lib/index.d.ts +2 -2
  89. package/lib/index.d.ts.map +1 -1
  90. package/lib/index.js +1 -1
  91. package/lib/index.js.map +1 -1
  92. package/lib/legacy.d.ts +1 -0
  93. package/lib/metadata.d.ts +2 -2
  94. package/lib/metadata.d.ts.map +1 -1
  95. package/lib/metadata.js.map +1 -1
  96. package/lib/opLifecycle/batchManager.d.ts +4 -1
  97. package/lib/opLifecycle/batchManager.d.ts.map +1 -1
  98. package/lib/opLifecycle/batchManager.js +0 -10
  99. package/lib/opLifecycle/batchManager.js.map +1 -1
  100. package/lib/opLifecycle/outbox.d.ts +0 -4
  101. package/lib/opLifecycle/outbox.d.ts.map +1 -1
  102. package/lib/opLifecycle/outbox.js +7 -38
  103. package/lib/opLifecycle/outbox.js.map +1 -1
  104. package/lib/packageVersion.d.ts +1 -1
  105. package/lib/packageVersion.d.ts.map +1 -1
  106. package/lib/packageVersion.js +1 -1
  107. package/lib/packageVersion.js.map +1 -1
  108. package/lib/summary/documentSchema.js +1 -1
  109. package/lib/summary/documentSchema.js.map +1 -1
  110. package/package.json +20 -20
  111. package/src/channelCollection.ts +108 -49
  112. package/src/containerRuntime.ts +66 -80
  113. package/src/dataStoreContexts.ts +12 -0
  114. package/src/gc/garbageCollection.ts +63 -41
  115. package/src/gc/gcDefinitions.ts +21 -9
  116. package/src/gc/gcHelpers.ts +14 -1
  117. package/src/gc/gcTelemetry.ts +56 -47
  118. package/src/gc/index.ts +2 -1
  119. package/src/index.ts +2 -0
  120. package/src/metadata.ts +2 -2
  121. package/src/opLifecycle/README.md +4 -4
  122. package/src/opLifecycle/batchManager.ts +5 -14
  123. package/src/opLifecycle/outbox.ts +7 -53
  124. package/src/packageVersion.ts +1 -1
  125. package/src/summary/documentSchema.ts +1 -1
  126. package/dist/public.d.ts +0 -12
  127. package/lib/public.d.ts +0 -12
@@ -14,6 +14,7 @@ import {
14
14
  tagCodeArtifacts,
15
15
  } from "@fluidframework/telemetry-utils/internal";
16
16
 
17
+ import type { Tagged } from "@fluidframework/core-interfaces";
17
18
  import { RuntimeHeaderData } from "../containerRuntime.js";
18
19
  import { ICreateContainerMetadata } from "../summary/index.js";
19
20
 
@@ -43,11 +44,12 @@ interface ICommonProps {
43
44
 
44
45
  /** The event that is logged when unreferenced node is used after a certain time. */
45
46
  interface IUnreferencedEventProps extends ICreateContainerMetadata, ICommonProps {
47
+ /** The id that GC uses to track the node. May or may not match id */
48
+ trackedId: string;
46
49
  state: UnreferencedState;
47
- id: {
48
- value: string;
49
- tag: string;
50
- };
50
+ /** The full path (in GC Path format) to the node in question */
51
+ id: Tagged<string>;
52
+ fromId?: Tagged<string>;
51
53
  type: GCNodeType;
52
54
  unrefTime: number;
53
55
  age: number;
@@ -56,19 +58,24 @@ interface IUnreferencedEventProps extends ICreateContainerMetadata, ICommonProps
56
58
  [K in keyof GCFeatureMatrix]: GCFeatureMatrix[K];
57
59
  };
58
60
  timeout?: number;
59
- fromId?: {
60
- value: string;
61
- tag: string;
62
- };
63
61
  }
64
62
 
65
63
  /** Properties passed to nodeUsed function when a node is used. */
66
64
  interface INodeUsageProps extends ICommonProps {
65
+ /** The full path (in GC Path format) to the node in question */
67
66
  id: string;
67
+ /** Latest timestamp received from the server, as a baseline for computing GC state/age */
68
68
  currentReferenceTimestampMs: number | undefined;
69
+ /** The package path of the node. This may not be available if the node hasn't been loaded yet */
69
70
  packagePath: readonly string[] | undefined;
71
+ /** In case of Revived - what node added the reference? */
70
72
  fromId?: string;
73
+ /** In case of Revived - was it revived due to autorecovery? */
71
74
  autorecovery?: true;
75
+ /** URL (including query string) if this usage came from a request */
76
+ requestUrl?: string;
77
+ /** Original request headers if this usage came from a request or handle.get */
78
+ requestHeaders?: string;
72
79
  }
73
80
 
74
81
  /**
@@ -143,18 +150,34 @@ export class GCTelemetryTracker {
143
150
  }
144
151
 
145
152
  /**
146
- * Called when a node is used. If the node is not active or tombstoned, log telemetry indicating object is used
153
+ * Called when a node is used. If the node is inactive or tombstoned, log telemetry indicating object is used
147
154
  * when it should not have been.
155
+ * @param trackedId - The id that GC uses to track the node. For SubDataStore nodes, this should be the DataStore ID.
156
+ * @param INodeUsageProps - All kind of details about this event to be logged
148
157
  */
149
- public nodeUsed(nodeUsageProps: INodeUsageProps) {
158
+ public nodeUsed(
159
+ trackedId: string,
160
+ {
161
+ usageType,
162
+ currentReferenceTimestampMs,
163
+ packagePath,
164
+ id: untaggedId,
165
+ fromId: untaggedFromId,
166
+ isTombstoned,
167
+ ...otherNodeUsageProps
168
+ }: INodeUsageProps,
169
+ ) {
150
170
  // If there is no reference timestamp to work with, no ops have been processed after creation. If so, skip
151
171
  // logging as nothing interesting would have happened worth logging.
152
- if (nodeUsageProps.currentReferenceTimestampMs === undefined) {
172
+ if (currentReferenceTimestampMs === undefined) {
153
173
  return;
154
174
  }
155
175
 
156
- const nodeStateTracker = this.getNodeStateTracker(nodeUsageProps.id);
157
- const nodeType = this.getNodeType(nodeUsageProps.id);
176
+ // Note: For SubDataStore Load usage, trackedId will be the DataStore's id, not the full path in question.
177
+ // This is necessary because the SubDataStore path may be unrecognized by GC (if suited for a custom request handler)
178
+ const nodeStateTracker = this.getNodeStateTracker(trackedId);
179
+ const nodeType = this.getNodeType(untaggedId);
180
+
158
181
  const timeout = (() => {
159
182
  switch (nodeStateTracker?.state) {
160
183
  case UnreferencedState.Inactive:
@@ -170,33 +193,27 @@ export class GCTelemetryTracker {
170
193
  return undefined;
171
194
  }
172
195
  })();
173
- const {
174
- usageType,
175
- currentReferenceTimestampMs,
176
- packagePath,
177
- id: untaggedId,
178
- fromId: untaggedFromId,
179
- ...propsToLog
180
- } = nodeUsageProps;
181
196
  const { persistedGcFeatureMatrix, ...configs } = this.configs;
182
- const unrefEventProps: Omit<IUnreferencedEventProps, "state" | "usageType"> = {
197
+ const unrefEventProps = {
198
+ trackedId,
183
199
  type: nodeType,
184
200
  unrefTime: nodeStateTracker?.unreferencedTimestampMs ?? -1,
185
201
  age:
186
202
  nodeStateTracker !== undefined
187
- ? nodeUsageProps.currentReferenceTimestampMs -
188
- nodeStateTracker.unreferencedTimestampMs
203
+ ? currentReferenceTimestampMs - nodeStateTracker.unreferencedTimestampMs
189
204
  : -1,
190
205
  timeout,
206
+ isTombstoned,
191
207
  ...tagCodeArtifacts({ id: untaggedId, fromId: untaggedFromId }),
192
- ...propsToLog,
208
+ ...otherNodeUsageProps,
193
209
  ...this.createContainerMetadata,
194
210
  gcConfigs: { ...configs, ...persistedGcFeatureMatrix },
195
- };
211
+ } satisfies Omit<IUnreferencedEventProps, "state" | "usageType"> &
212
+ typeof otherNodeUsageProps;
196
213
 
197
214
  // If the node that is used is tombstoned, log a tombstone telemetry.
198
- if (nodeUsageProps.isTombstoned) {
199
- this.logTombstoneUsageTelemetry(nodeUsageProps, unrefEventProps, nodeType, usageType);
215
+ if (isTombstoned) {
216
+ this.logTombstoneUsageTelemetry(unrefEventProps, nodeType, usageType, packagePath);
200
217
  }
201
218
 
202
219
  // After logging tombstone telemetry, if the node's unreferenced state is not tracked, there is nothing
@@ -206,16 +223,9 @@ export class GCTelemetryTracker {
206
223
  }
207
224
 
208
225
  const state = nodeStateTracker.state;
209
- const uniqueEventId = `${state}-${nodeUsageProps.id}-${nodeUsageProps.usageType}`;
226
+ const uniqueEventId = `${state}-${untaggedId}-${usageType}`;
210
227
 
211
- if (
212
- !this.shouldLogNonActiveEvent(
213
- nodeType,
214
- nodeUsageProps.usageType,
215
- nodeStateTracker,
216
- uniqueEventId,
217
- )
218
- ) {
228
+ if (!this.shouldLogNonActiveEvent(nodeType, usageType, nodeStateTracker, uniqueEventId)) {
219
229
  return;
220
230
  }
221
231
 
@@ -229,8 +239,8 @@ export class GCTelemetryTracker {
229
239
  // SweepReady errors are usages of Objects that will be deleted by GC Sweep!
230
240
  if (this.isSummarizerClient) {
231
241
  this.pendingEventsQueue.push({
232
- ...unrefEventProps,
233
- usageType: nodeUsageProps.usageType,
242
+ ...unrefEventProps, // Note: Contains some properties from INodeUsageProps as well
243
+ usageType,
234
244
  state,
235
245
  });
236
246
  } else {
@@ -238,11 +248,11 @@ export class GCTelemetryTracker {
238
248
  // summarizer clients if they are based off of user actions (such as scrolling to content for these objects)
239
249
  // Events generated:
240
250
  // InactiveObject_Loaded, SweepReadyObject_Loaded
241
- if (nodeUsageProps.usageType === "Loaded") {
251
+ if (usageType === "Loaded") {
242
252
  const { id, fromId, headers, gcConfigs, ...detailedProps } = unrefEventProps;
243
253
  const event = {
244
- eventName: `${state}Object_${nodeUsageProps.usageType}`,
245
- ...tagCodeArtifacts({ pkg: nodeUsageProps.packagePath?.join("/") }),
254
+ eventName: `${state}Object_${usageType}`,
255
+ ...tagCodeArtifacts({ pkg: packagePath?.join("/") }),
246
256
  stack: generateStack(),
247
257
  id,
248
258
  fromId,
@@ -262,10 +272,10 @@ export class GCTelemetryTracker {
262
272
  * Logs telemetry when a tombstoned object is changed, revived or loaded.
263
273
  */
264
274
  private logTombstoneUsageTelemetry(
265
- nodeUsageProps: INodeUsageProps,
266
275
  unrefEventProps: Omit<IUnreferencedEventProps, "state" | "usageType">,
267
276
  nodeType: GCNodeType,
268
277
  usageType: NodeUsageType,
278
+ packagePath?: readonly string[],
269
279
  ) {
270
280
  // This will log the following events:
271
281
  // GC_Tombstone_DataStore_Requested, GC_Tombstone_DataStore_Changed, GC_Tombstone_DataStore_Revived
@@ -275,12 +285,12 @@ export class GCTelemetryTracker {
275
285
  const eventUsageName = usageType === "Loaded" ? "Requested" : usageType;
276
286
  const event = {
277
287
  eventName: `GC_Tombstone_${nodeType}_${eventUsageName}`,
278
- pkg: tagCodeArtifacts({ pkg: nodeUsageProps.packagePath?.join("/") }).pkg,
288
+ ...tagCodeArtifacts({ pkg: packagePath?.join("/") }),
279
289
  stack: generateStack(),
280
290
  id,
281
291
  fromId,
282
292
  headers: { ...headers },
283
- details: detailedProps,
293
+ details: detailedProps, // Also includes some properties from INodeUsageProps type
284
294
  gcConfigs,
285
295
  tombstoneFlags: {
286
296
  DisableTombstone: this.mc.config.getBoolean(disableTombstoneKey),
@@ -372,7 +382,6 @@ export class GCTelemetryTracker {
372
382
  // InactiveObject_Loaded, InactiveObject_Changed, InactiveObject_Revived
373
383
  // SweepReadyObject_Loaded, SweepReadyObject_Changed, SweepReadyObject_Revived
374
384
  for (const eventProps of this.pendingEventsQueue) {
375
- // const { usageType, state, id, fromId, ...propsToLog } = eventProps;
376
385
  const { usageType, state, id, fromId, headers, gcConfigs, ...detailedProps } =
377
386
  eventProps;
378
387
  /**
@@ -381,7 +390,7 @@ export class GCTelemetryTracker {
381
390
  * Loaded and Changed events are logged only if the node is not active. If the node is active, it was
382
391
  * revived and a Revived event will be logged for it.
383
392
  */
384
- const nodeStateTracker = this.getNodeStateTracker(eventProps.id.value);
393
+ const nodeStateTracker = this.getNodeStateTracker(detailedProps.trackedId); // Note: This is never SubDataStore path
385
394
  const active =
386
395
  nodeStateTracker === undefined ||
387
396
  nodeStateTracker.state === UnreferencedState.Active;
package/src/gc/index.ts CHANGED
@@ -23,6 +23,7 @@ export {
23
23
  IGarbageCollectorCreateParams,
24
24
  IGCMetadata,
25
25
  IGCMetadata_Deprecated,
26
+ IGCNodeUpdatedProps,
26
27
  IGCResult,
27
28
  IGCRuntimeOptions,
28
29
  IMarkPhaseStats,
@@ -46,8 +47,8 @@ export {
46
47
  cloneGCData,
47
48
  concatGarbageCollectionStates,
48
49
  getGCVersionInEffect,
49
- trimLeadingAndTrailingSlashes,
50
50
  unpackChildNodesGCDetails,
51
+ urlToGCNodePath,
51
52
  } from "./gcHelpers.js";
52
53
  export { runGarbageCollection } from "./gcReferenceGraphAlgorithm.js";
53
54
  export {
package/src/index.ts CHANGED
@@ -13,6 +13,7 @@ export {
13
13
  isRuntimeMessage,
14
14
  agentSchedulerId,
15
15
  ContainerRuntime,
16
+ DeletedResponseHeaderKey,
16
17
  TombstoneResponseHeaderKey,
17
18
  InactiveResponseHeaderKey,
18
19
  ISummaryConfiguration,
@@ -47,6 +48,7 @@ export {
47
48
  IGCRuntimeOptions,
48
49
  IMarkPhaseStats,
49
50
  ISweepPhaseStats,
51
+ IGCNodeUpdatedProps,
50
52
  IGCStats,
51
53
  } from "./gc/index.js";
52
54
  export {
package/src/metadata.ts CHANGED
@@ -19,8 +19,8 @@ export interface IBlobMetadata {
19
19
  }
20
20
 
21
21
  /**
22
- * The IdCompressor needs to know if this is a replayed savedOp as those need to be skipped in stashed ops scenarios.
22
+ * ContainerRuntime needs to know if this is a replayed savedOp as those need to be skipped in stashed ops scenarios.
23
23
  */
24
- export interface IIdAllocationMetadata {
24
+ export interface ISavedOpMetadata {
25
25
  savedOp?: boolean;
26
26
  }
@@ -339,19 +339,19 @@ stateDiagram-v2
339
339
  state "Store original (uncompressed, unchunked, ungrouped) batch locally" as store
340
340
  state if_compression <<choice>>
341
341
  [*] --> ContainerRuntime.submit
342
- ContainerRuntime.submit --> outbox.submitAttach
342
+ ContainerRuntime.submit --> outbox.submitIdAllocation
343
343
  ContainerRuntime.submit --> outbox.submitBlobAttach
344
344
  ContainerRuntime.submit --> outbox.submit
345
345
  outbox.submit --> scheduleFlush
346
- outbox.submitAttach --> scheduleFlush
346
+ outbox.submitIdAllocation --> scheduleFlush
347
347
  outbox.submitBlobAttach --> scheduleFlush
348
348
  scheduleFlush --> jsTurn
349
349
  jsTurn --> flush
350
350
  flush --> outbox.flushInternalMain
351
- flush --> outbox.flushInternalAttach
351
+ flush --> outbox.flushInternalIdAllocation
352
352
  flush --> outbox.flushInternalBlobAttach
353
353
  outbox.flushInternalMain --> flushInternal
354
- outbox.flushInternalAttach --> flushInternal
354
+ outbox.flushInternalIdAllocation --> flushInternal
355
355
  outbox.flushInternalBlobAttach --> flushInternal
356
356
  flushInternal --> ContainerRuntime.reSubmit: if batch has reentrant ops and should group
357
357
  ContainerRuntime.reSubmit --> flushInternal
@@ -9,8 +9,12 @@ import { BatchMessage, IBatch, IBatchCheckpoint } from "./definitions.js";
9
9
 
10
10
  export interface IBatchManagerOptions {
11
11
  readonly hardLimit: number;
12
- readonly softLimit?: number;
13
12
  readonly compressionOptions?: ICompressionRuntimeOptions;
13
+
14
+ /**
15
+ * If true, the outbox is allowed to rebase the batch during flushing.
16
+ */
17
+ readonly canRebase: boolean;
14
18
  }
15
19
 
16
20
  export interface BatchSequenceNumbers {
@@ -72,19 +76,6 @@ export class BatchManager {
72
76
  // initially stored as base64, and that requires only 2 extra escape characters.
73
77
  const socketMessageSize = contentSize + opOverhead * opCount;
74
78
 
75
- // If we were provided soft limit, check for exceeding it.
76
- // But only if we have any ops, as the intention here is to flush existing ops (on exceeding this limit)
77
- // and start over. That's not an option if we have no ops.
78
- // If compression is enabled, the soft and hard limit are ignored and the message will be pushed anyways.
79
- // Cases where the message is still too large will be handled by the maxConsecutiveReconnects path.
80
- if (
81
- this.options.softLimit !== undefined &&
82
- this.length > 0 &&
83
- socketMessageSize >= this.options.softLimit
84
- ) {
85
- return false;
86
- }
87
-
88
79
  if (socketMessageSize >= this.options.hardLimit) {
89
80
  return false;
90
81
  }
@@ -89,11 +89,9 @@ export function getLongStack<T>(action: () => T, length: number = 50): T {
89
89
 
90
90
  export class Outbox {
91
91
  private readonly mc: MonitoringContext;
92
- private readonly attachFlowBatch: BatchManager;
93
92
  private readonly mainBatch: BatchManager;
94
93
  private readonly blobAttachBatch: BatchManager;
95
94
  private readonly idAllocationBatch: BatchManager;
96
- private readonly defaultAttachFlowSoftLimitInBytes = 320 * 1024;
97
95
  private batchRebasesToReport = 5;
98
96
  private rebasing = false;
99
97
 
@@ -113,21 +111,14 @@ export class Outbox {
113
111
  Number.POSITIVE_INFINITY;
114
112
  // We need to allow infinite size batches if we enable compression
115
113
  const hardLimit = isCompressionEnabled ? Infinity : this.params.config.maxBatchSizeInBytes;
116
- const softLimit = isCompressionEnabled ? Infinity : this.defaultAttachFlowSoftLimitInBytes;
117
114
 
118
- this.attachFlowBatch = new BatchManager({ hardLimit, softLimit });
119
- this.mainBatch = new BatchManager({ hardLimit });
120
- this.blobAttachBatch = new BatchManager({ hardLimit });
121
- this.idAllocationBatch = new BatchManager({ hardLimit });
115
+ this.mainBatch = new BatchManager({ hardLimit, canRebase: true });
116
+ this.blobAttachBatch = new BatchManager({ hardLimit, canRebase: true });
117
+ this.idAllocationBatch = new BatchManager({ hardLimit, canRebase: false });
122
118
  }
123
119
 
124
120
  public get messageCount(): number {
125
- return (
126
- this.attachFlowBatch.length +
127
- this.mainBatch.length +
128
- this.blobAttachBatch.length +
129
- this.idAllocationBatch.length
130
- );
121
+ return this.mainBatch.length + this.blobAttachBatch.length + this.idAllocationBatch.length;
131
122
  }
132
123
 
133
124
  public get isEmpty(): boolean {
@@ -142,13 +133,11 @@ export class Outbox {
142
133
  */
143
134
  private maybeFlushPartialBatch() {
144
135
  const mainBatchSeqNums = this.mainBatch.sequenceNumbers;
145
- const attachFlowBatchSeqNums = this.attachFlowBatch.sequenceNumbers;
146
136
  const blobAttachSeqNums = this.blobAttachBatch.sequenceNumbers;
147
137
  const idAllocSeqNums = this.idAllocationBatch.sequenceNumbers;
148
138
  assert(
149
139
  this.params.config.disablePartialFlush ||
150
- (sequenceNumbersMatch(mainBatchSeqNums, attachFlowBatchSeqNums) &&
151
- sequenceNumbersMatch(mainBatchSeqNums, blobAttachSeqNums) &&
140
+ (sequenceNumbersMatch(mainBatchSeqNums, blobAttachSeqNums) &&
152
141
  sequenceNumbersMatch(mainBatchSeqNums, idAllocSeqNums)),
153
142
  0x58d /* Reference sequence numbers from both batches must be in sync */,
154
143
  );
@@ -157,7 +146,6 @@ export class Outbox {
157
146
 
158
147
  if (
159
148
  sequenceNumbersMatch(mainBatchSeqNums, currentSequenceNumbers) &&
160
- sequenceNumbersMatch(attachFlowBatchSeqNums, currentSequenceNumbers) &&
161
149
  sequenceNumbersMatch(blobAttachSeqNums, currentSequenceNumbers) &&
162
150
  sequenceNumbersMatch(idAllocSeqNums, currentSequenceNumbers)
163
151
  ) {
@@ -172,8 +160,6 @@ export class Outbox {
172
160
  eventName: "ReferenceSequenceNumberMismatch",
173
161
  mainReferenceSequenceNumber: mainBatchSeqNums.referenceSequenceNumber,
174
162
  mainClientSequenceNumber: mainBatchSeqNums.clientSequenceNumber,
175
- attachReferenceSequenceNumber: attachFlowBatchSeqNums.referenceSequenceNumber,
176
- attachClientSequenceNumber: attachFlowBatchSeqNums.clientSequenceNumber,
177
163
  blobAttachReferenceSequenceNumber: blobAttachSeqNums.referenceSequenceNumber,
178
164
  blobAttachClientSequenceNumber: blobAttachSeqNums.clientSequenceNumber,
179
165
  currentReferenceSequenceNumber: currentSequenceNumbers.referenceSequenceNumber,
@@ -194,37 +180,6 @@ export class Outbox {
194
180
  this.addMessageToBatchManager(this.mainBatch, message);
195
181
  }
196
182
 
197
- public submitAttach(message: BatchMessage) {
198
- this.maybeFlushPartialBatch();
199
-
200
- if (
201
- !this.attachFlowBatch.push(
202
- message,
203
- this.isContextReentrant(),
204
- this.params.getCurrentSequenceNumbers().clientSequenceNumber,
205
- )
206
- ) {
207
- // BatchManager has two limits - soft limit & hard limit. Soft limit is only engaged
208
- // when queue is not empty.
209
- // Flush queue & retry. Failure on retry would mean - single message is bigger than hard limit
210
- this.flushInternal(this.attachFlowBatch);
211
-
212
- this.addMessageToBatchManager(this.attachFlowBatch, message);
213
- }
214
-
215
- // If compression is enabled, we will always successfully receive
216
- // attach ops and compress then send them at the next JS turn, regardless
217
- // of the overall size of the accumulated ops in the batch.
218
- // However, it is more efficient to flush these ops faster, preferably
219
- // after they reach a size which would benefit from compression.
220
- if (
221
- this.attachFlowBatch.contentSizeInBytes >=
222
- this.params.config.compressionOptions.minimumBatchSizeInBytes
223
- ) {
224
- this.flushInternal(this.attachFlowBatch);
225
- }
226
- }
227
-
228
183
  public submitBlobAttach(message: BatchMessage) {
229
184
  this.maybeFlushPartialBatch();
230
185
 
@@ -303,7 +258,6 @@ export class Outbox {
303
258
 
304
259
  private flushAll() {
305
260
  this.flushInternal(this.idAllocationBatch);
306
- this.flushInternal(this.attachFlowBatch);
307
261
  this.flushInternal(this.blobAttachBatch, true /* disableGroupedBatching */);
308
262
  this.flushInternal(this.mainBatch);
309
263
  }
@@ -316,7 +270,7 @@ export class Outbox {
316
270
  const rawBatch = batchManager.popBatch();
317
271
  const shouldGroup =
318
272
  !disableGroupedBatching && this.params.groupingManager.shouldGroup(rawBatch);
319
- if (rawBatch.hasReentrantOps === true && shouldGroup) {
273
+ if (batchManager.options.canRebase && rawBatch.hasReentrantOps === true && shouldGroup) {
320
274
  assert(!this.rebasing, 0x6fa /* A rebased batch should never have reentrant ops */);
321
275
  // If a batch contains reentrant ops (ops created as a result from processing another op)
322
276
  // it needs to be rebased so that we can ensure consistent reference sequence numbers
@@ -346,6 +300,7 @@ export class Outbox {
346
300
  */
347
301
  private rebase(rawBatch: IBatch, batchManager: BatchManager) {
348
302
  assert(!this.rebasing, 0x6fb /* Reentrancy */);
303
+ assert(batchManager.options.canRebase, "BatchManager does not support rebase");
349
304
 
350
305
  this.rebasing = true;
351
306
  for (const message of rawBatch.content) {
@@ -479,7 +434,6 @@ export class Outbox {
479
434
  const mainBatch: IBatchCheckpoint = this.mainBatch.checkpoint();
480
435
  return {
481
436
  mainBatch,
482
- attachFlowBatch: this.attachFlowBatch.checkpoint(),
483
437
  blobAttachBatch: this.blobAttachBatch.checkpoint(),
484
438
  };
485
439
  }
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/container-runtime";
9
- export const pkgVersion = "2.0.0-rc.3.0.0";
9
+ export const pkgVersion = "2.0.0-rc.3.0.10";
@@ -552,6 +552,7 @@ export class DocumentsSchemaController {
552
552
  */
553
553
  public maybeSendSchemaMessage(): IDocumentSchemaChangeMessage | undefined {
554
554
  if (this.sendOp && this.futureSchema !== undefined) {
555
+ this.sendOp = false;
555
556
  assert(
556
557
  this.explicitSchemaControl &&
557
558
  this.futureSchema.runtime.explicitSchemaControl === true,
@@ -562,7 +563,6 @@ export class DocumentsSchemaController {
562
563
  refSeq: this.documentSchema.refSeq,
563
564
  };
564
565
  }
565
- this.sendOp = false;
566
566
  }
567
567
 
568
568
  /**
package/dist/public.d.ts DELETED
@@ -1,12 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
-
6
- /*
7
- * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
8
- * Generated by "flub generate entrypoints" in @fluidframework/build-tools.
9
- */
10
-
11
- export {}
12
-
package/lib/public.d.ts DELETED
@@ -1,12 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
-
6
- /*
7
- * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
8
- * Generated by "flub generate entrypoints" in @fluidframework/build-tools.
9
- */
10
-
11
- export {}
12
-