@fluidframework/container-runtime 2.0.0-internal.1.0.0.82628 → 2.0.0-internal.1.0.0.84253

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 (68) hide show
  1. package/dist/batchTracker.js +1 -1
  2. package/dist/batchTracker.js.map +1 -1
  3. package/dist/blobManager.d.ts.map +1 -1
  4. package/dist/blobManager.js +16 -16
  5. package/dist/blobManager.js.map +1 -1
  6. package/dist/containerRuntime.d.ts +1 -38
  7. package/dist/containerRuntime.d.ts.map +1 -1
  8. package/dist/containerRuntime.js +51 -105
  9. package/dist/containerRuntime.js.map +1 -1
  10. package/dist/dataStore.d.ts +1 -1
  11. package/dist/dataStore.d.ts.map +1 -1
  12. package/dist/dataStore.js +2 -3
  13. package/dist/dataStore.js.map +1 -1
  14. package/dist/dataStores.d.ts +1 -1
  15. package/dist/dataStores.d.ts.map +1 -1
  16. package/dist/dataStores.js +2 -2
  17. package/dist/dataStores.js.map +1 -1
  18. package/dist/packageVersion.d.ts +1 -1
  19. package/dist/packageVersion.js +1 -1
  20. package/dist/packageVersion.js.map +1 -1
  21. package/dist/runningSummarizer.d.ts +14 -0
  22. package/dist/runningSummarizer.d.ts.map +1 -1
  23. package/dist/runningSummarizer.js +25 -0
  24. package/dist/runningSummarizer.js.map +1 -1
  25. package/dist/summarizer.d.ts.map +1 -1
  26. package/dist/summarizer.js +33 -3
  27. package/dist/summarizer.js.map +1 -1
  28. package/dist/summaryGenerator.js +1 -1
  29. package/dist/summaryGenerator.js.map +1 -1
  30. package/lib/batchTracker.js +1 -1
  31. package/lib/batchTracker.js.map +1 -1
  32. package/lib/blobManager.d.ts.map +1 -1
  33. package/lib/blobManager.js +16 -16
  34. package/lib/blobManager.js.map +1 -1
  35. package/lib/containerRuntime.d.ts +1 -38
  36. package/lib/containerRuntime.d.ts.map +1 -1
  37. package/lib/containerRuntime.js +51 -105
  38. package/lib/containerRuntime.js.map +1 -1
  39. package/lib/dataStore.d.ts +1 -1
  40. package/lib/dataStore.d.ts.map +1 -1
  41. package/lib/dataStore.js +2 -3
  42. package/lib/dataStore.js.map +1 -1
  43. package/lib/dataStores.d.ts +1 -1
  44. package/lib/dataStores.d.ts.map +1 -1
  45. package/lib/dataStores.js +2 -2
  46. package/lib/dataStores.js.map +1 -1
  47. package/lib/packageVersion.d.ts +1 -1
  48. package/lib/packageVersion.js +1 -1
  49. package/lib/packageVersion.js.map +1 -1
  50. package/lib/runningSummarizer.d.ts +14 -0
  51. package/lib/runningSummarizer.d.ts.map +1 -1
  52. package/lib/runningSummarizer.js +25 -0
  53. package/lib/runningSummarizer.js.map +1 -1
  54. package/lib/summarizer.d.ts.map +1 -1
  55. package/lib/summarizer.js +35 -5
  56. package/lib/summarizer.js.map +1 -1
  57. package/lib/summaryGenerator.js +1 -1
  58. package/lib/summaryGenerator.js.map +1 -1
  59. package/package.json +27 -18
  60. package/src/batchTracker.ts +1 -1
  61. package/src/blobManager.ts +20 -16
  62. package/src/containerRuntime.ts +71 -155
  63. package/src/dataStore.ts +1 -4
  64. package/src/dataStores.ts +13 -13
  65. package/src/packageVersion.ts +1 -1
  66. package/src/runningSummarizer.ts +33 -1
  67. package/src/summarizer.ts +46 -10
  68. package/src/summaryGenerator.ts +1 -1
package/src/dataStores.ts CHANGED
@@ -29,11 +29,11 @@ import {
29
29
  ITelemetryContext,
30
30
  } from "@fluidframework/runtime-definitions";
31
31
  import {
32
- convertSnapshotTreeToSummaryTree,
33
- convertToSummaryTree,
34
- create404Response,
35
- responseToException,
36
- SummaryTreeBuilder,
32
+ convertSnapshotTreeToSummaryTree,
33
+ convertToSummaryTree,
34
+ create404Response,
35
+ responseToException,
36
+ SummaryTreeBuilder,
37
37
  } from "@fluidframework/runtime-utils";
38
38
  import { ChildLogger, LoggingError, TelemetryDataTag } from "@fluidframework/telemetry-utils";
39
39
  import { AttachState } from "@fluidframework/container-definitions";
@@ -56,10 +56,10 @@ import { GCNodeType } from "./garbageCollection";
56
56
 
57
57
  type PendingAliasResolve = (success: boolean) => void;
58
58
 
59
- /**
60
- * This class encapsulates data store handling. Currently it is only used by the container runtime,
61
- * but eventually could be hosted on any channel once we formalize the channel api boundary.
62
- */
59
+ /**
60
+ * This class encapsulates data store handling. Currently it is only used by the container runtime,
61
+ * but eventually could be hosted on any channel once we formalize the channel api boundary.
62
+ */
63
63
  export class DataStores implements IDisposable {
64
64
  // Stores tracked by the Domain
65
65
  private readonly pendingAttach = new Map<string, IAttachMessage>();
@@ -202,7 +202,7 @@ export class DataStores implements IDisposable {
202
202
  return;
203
203
  }
204
204
 
205
- // If a non-local operation then go and create the object, otherwise mark it as officially attached.
205
+ // If a non-local operation then go and create the object, otherwise mark it as officially attached.
206
206
  if (this.alreadyProcessed(attachMessage.id)) {
207
207
  // TODO: dataStoreId may require a different tag from PackageData #7488
208
208
  const error = new DataCorruptionError(
@@ -362,7 +362,7 @@ export class DataStores implements IDisposable {
362
362
  return context;
363
363
  }
364
364
 
365
- public _createFluidDataStoreContext(pkg: string[], id: string, isRoot: boolean, props?: any) {
365
+ public _createFluidDataStoreContext(pkg: string[], id: string, props?: any) {
366
366
  assert(!id.includes("/"), 0x30d /* Id cannot contain slashes */);
367
367
  const context = new LocalFluidDataStoreContext({
368
368
  id,
@@ -376,7 +376,7 @@ export class DataStores implements IDisposable {
376
376
  ),
377
377
  makeLocallyVisibleFn: () => this.makeDataStoreLocallyVisible(id),
378
378
  snapshotTree: undefined,
379
- isRootDataStore: isRoot,
379
+ isRootDataStore: false,
380
380
  writeGCDataAtRoot: this.writeGCDataAtRoot,
381
381
  disableIsolatedChannels: this.runtime.disableIsolatedChannels,
382
382
  createProps: props,
@@ -481,7 +481,7 @@ export class DataStores implements IDisposable {
481
481
  } else {
482
482
  eventName = "attached";
483
483
  }
484
- for (const [,context] of this.contexts) {
484
+ for (const [, context] of this.contexts) {
485
485
  // Fire only for bounded stores.
486
486
  if (!this.contexts.isNotBound(context.id)) {
487
487
  context.emit(eventName);
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/container-runtime";
9
- export const pkgVersion = "2.0.0-internal.1.0.0.82628";
9
+ export const pkgVersion = "2.0.0-internal.1.0.0.84253";
@@ -106,10 +106,10 @@ export class RunningSummarizer implements IDisposable {
106
106
  }
107
107
 
108
108
  public get disposed() { return this._disposed; }
109
-
110
109
  private stopping = false;
111
110
  private _disposed = false;
112
111
  private summarizingLock: Promise<void> | undefined;
112
+ private refreshSummaryAckLock: Promise<void> | undefined;
113
113
  private tryWhileSummarizing = false;
114
114
  private readonly pendingAckTimer: PromiseTimer;
115
115
  private heuristicRunner?: ISummarizeHeuristicRunner;
@@ -329,6 +329,31 @@ export class RunningSummarizer implements IDisposable {
329
329
  this.initialized = true;
330
330
  }
331
331
 
332
+ /**
333
+ * Blocks a new summarizer from running in case RefreshSummaryAck is being processed.
334
+ * Assumes that caller checked upfront for lack of concurrent action (this.refreshSummaryAckLock)
335
+ * before calling this API. I.e. caller is responsible for either erroring out or waiting on this promise.
336
+ * Note: The refreshSummaryAckLock makes sure no summarizer gets enqueued or processed
337
+ * until the refresh has completed. One can't rely uniquely on the summarizingLock as the
338
+ * refreshLatestSummaryAck also happens during the time summarizingLock !== undefined.
339
+ * Ex. Summarizer submits a summay + op and then waits for the Summary Ack to proceed
340
+ * with the refreshLatestSummaryAck and complete the summary.
341
+ * @param action - action to perform.
342
+ * @returns - result of action.
343
+ */
344
+ public async lockedRefreshSummaryAckAction<T>(action: () => Promise<T>) {
345
+ assert(this.refreshSummaryAckLock === undefined,
346
+ 0x396 /* Refresh Summary Ack - Caller is responsible for checking lock */);
347
+
348
+ const refreshSummaryAckLock = new Deferred<void>();
349
+ this.refreshSummaryAckLock = refreshSummaryAckLock.promise;
350
+
351
+ return action().finally(() => {
352
+ refreshSummaryAckLock.resolve();
353
+ this.refreshSummaryAckLock = undefined;
354
+ });
355
+ }
356
+
332
357
  /**
333
358
  * Runs single summary action that prevents any other concurrent actions.
334
359
  * Assumes that caller checked upfront for lack of concurrent action (this.summarizingLock)
@@ -343,6 +368,8 @@ export class RunningSummarizer implements IDisposable {
343
368
  this.summarizingLock = summarizingLock.promise;
344
369
 
345
370
  this.summarizeCount++;
371
+ // Make sure the RefreshLatestSummaryAck is not being executed.
372
+ await this.refreshSummaryAckLock;
346
373
 
347
374
  return action().finally(() => {
348
375
  summarizingLock.resolve();
@@ -446,6 +473,10 @@ export class RunningSummarizer implements IDisposable {
446
473
  });
447
474
  await delay(delaySeconds * 1000);
448
475
  }
476
+
477
+ // Make sure the refresh Summary Ack is not being executed.
478
+ await this.refreshSummaryAckLock;
479
+
449
480
  // Note: no need to account for cancellationToken.waitCancelled here, as
450
481
  // this is accounted SummaryGenerator.summarizeCore that controls receivedSummaryAckOrNack.
451
482
  const resultSummarize = this.generator.summarize(summarizeProps, options, cancellationToken);
@@ -494,6 +525,7 @@ export class RunningSummarizer implements IDisposable {
494
525
  // The heuristics are blocking concurrent summarize attempts.
495
526
  throw new UsageError("Attempted to run an already-running summarizer on demand");
496
527
  }
528
+
497
529
  const result = this.trySummarizeOnce(
498
530
  { reason: `onDemand/${reason}` },
499
531
  options,
package/src/summarizer.ts CHANGED
@@ -8,9 +8,15 @@ import { Deferred } from "@fluidframework/common-utils";
8
8
  import { ITelemetryLogger } from "@fluidframework/common-definitions";
9
9
  import { ILoader, LoaderHeader } from "@fluidframework/container-definitions";
10
10
  import { UsageError } from "@fluidframework/container-utils";
11
- import { DriverHeader } from "@fluidframework/driver-definitions";
11
+ import { DriverErrorType, DriverHeader } from "@fluidframework/driver-definitions";
12
12
  import { requestFluidObject } from "@fluidframework/runtime-utils";
13
- import { ChildLogger, IFluidErrorBase, LoggingError, wrapErrorAndLog } from "@fluidframework/telemetry-utils";
13
+ import {
14
+ ChildLogger,
15
+ IFluidErrorBase,
16
+ isFluidError,
17
+ LoggingError,
18
+ wrapErrorAndLog,
19
+ } from "@fluidframework/telemetry-utils";
14
20
  import {
15
21
  FluidObject,
16
22
  IFluidHandleContext,
@@ -20,7 +26,7 @@ import {
20
26
  import { ISummaryConfiguration } from "./containerRuntime";
21
27
  import { ICancellableSummarizerController } from "./runWhileConnectedCoordinator";
22
28
  import { summarizerClientType } from "./summarizerClientElection";
23
- import { SummaryCollection } from "./summaryCollection";
29
+ import { IAckedSummary, SummaryCollection } from "./summaryCollection";
24
30
  import { SummarizerHandle } from "./summarizerHandle";
25
31
  import { RunningSummarizer } from "./runningSummarizer";
26
32
  import {
@@ -361,22 +367,52 @@ export class Summarizer extends EventEmitter implements ISummarizer {
361
367
 
362
368
  private async handleSummaryAcks() {
363
369
  let refSequenceNumber = this.runtime.deltaManager.initialSequenceNumber;
370
+ let ack: IAckedSummary | undefined;
364
371
  while (this.runningSummarizer) {
365
372
  const summaryLogger = this.runningSummarizer.tryGetCorrelatedLogger(refSequenceNumber) ?? this.logger;
366
373
  try {
367
- const ack = await this.summaryCollection.waitSummaryAck(refSequenceNumber);
374
+ // Initialize ack with undefined if exception happens inside of waitSummaryAck on second iteration,
375
+ // we record undefined, not previous handles.
376
+ ack = undefined;
377
+ ack = await this.summaryCollection.waitSummaryAck(refSequenceNumber);
368
378
  refSequenceNumber = ack.summaryOp.referenceSequenceNumber;
369
-
370
- await this.internalsProvider.refreshLatestSummaryAck(
371
- ack.summaryOp.contents.handle,
372
- ack.summaryAck.contents.handle,
373
- refSequenceNumber,
374
- summaryLogger,
379
+ const summaryOpHandle = ack.summaryOp.contents.handle;
380
+ const summaryAckHandle = ack.summaryAck.contents.handle;
381
+ // Make sure we block any summarizer from being executed/enqueued while
382
+ // executing the refreshLatestSummaryAck.
383
+ // https://dev.azure.com/fluidframework/internal/_workitems/edit/779
384
+ await this.runningSummarizer.lockedRefreshSummaryAckAction(async () =>
385
+ this.internalsProvider.refreshLatestSummaryAck(
386
+ summaryOpHandle,
387
+ summaryAckHandle,
388
+ refSequenceNumber,
389
+ summaryLogger,
390
+ ).catch(async (error) => {
391
+ // If the error is 404, so maybe the fetched version no longer exists on server. We just
392
+ // ignore this error in that case, as that means we will have another summaryAck for the
393
+ // latest version with which we will refresh the state. However in case of single commit
394
+ // summary, we might me missing a summary ack, so in that case we are still fine as the
395
+ // code in `submitSummary` function in container runtime, will refresh the latest state
396
+ // by calling `refreshLatestSummaryAckFromServer` and we will be fine.
397
+ if (isFluidError(error)
398
+ && error.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError) {
399
+ summaryLogger.sendTelemetryEvent({
400
+ eventName: "HandleSummaryAckErrorIgnored",
401
+ referenceSequenceNumber: refSequenceNumber,
402
+ proposalHandle: summaryOpHandle,
403
+ ackHandle: summaryAckHandle,
404
+ }, error);
405
+ } else {
406
+ throw error;
407
+ }
408
+ }),
375
409
  );
376
410
  } catch (error) {
377
411
  summaryLogger.sendErrorEvent({
378
412
  eventName: "HandleSummaryAckError",
379
413
  referenceSequenceNumber: refSequenceNumber,
414
+ handle: ack?.summaryOp?.contents?.handle,
415
+ ackHandle: ack?.summaryAck?.contents?.handle,
380
416
  }, error);
381
417
  }
382
418
  refSequenceNumber++;
@@ -420,7 +420,7 @@ export class SummaryGenerator {
420
420
  nonRuntimeOpsSinceLastSummary: this.heuristicData.numNonRuntimeOps,
421
421
  };
422
422
 
423
- default: assert(true, "Unexpected summary stage");
423
+ default: assert(true, 0x397 /* Unexpected summary stage */);
424
424
  }
425
425
 
426
426
  return initialProps;