@fluidframework/container-loader 2.0.0-dev.5.3.2.178189 → 2.0.0-dev.6.4.0.191457

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 (173) hide show
  1. package/CHANGELOG.md +131 -0
  2. package/README.md +10 -6
  3. package/dist/audience.d.ts +1 -0
  4. package/dist/audience.d.ts.map +1 -1
  5. package/dist/audience.js +5 -3
  6. package/dist/audience.js.map +1 -1
  7. package/dist/catchUpMonitor.js +2 -2
  8. package/dist/catchUpMonitor.js.map +1 -1
  9. package/dist/connectionManager.d.ts +5 -5
  10. package/dist/connectionManager.d.ts.map +1 -1
  11. package/dist/connectionManager.js +97 -93
  12. package/dist/connectionManager.js.map +1 -1
  13. package/dist/connectionStateHandler.d.ts +15 -14
  14. package/dist/connectionStateHandler.d.ts.map +1 -1
  15. package/dist/connectionStateHandler.js +50 -52
  16. package/dist/connectionStateHandler.js.map +1 -1
  17. package/dist/container.d.ts +20 -9
  18. package/dist/container.d.ts.map +1 -1
  19. package/dist/container.js +327 -277
  20. package/dist/container.js.map +1 -1
  21. package/dist/containerContext.d.ts +2 -7
  22. package/dist/containerContext.d.ts.map +1 -1
  23. package/dist/containerContext.js +2 -14
  24. package/dist/containerContext.js.map +1 -1
  25. package/dist/containerStorageAdapter.d.ts.map +1 -1
  26. package/dist/containerStorageAdapter.js +12 -13
  27. package/dist/containerStorageAdapter.js.map +1 -1
  28. package/dist/contracts.d.ts +21 -8
  29. package/dist/contracts.d.ts.map +1 -1
  30. package/dist/contracts.js +3 -3
  31. package/dist/contracts.js.map +1 -1
  32. package/dist/debugLogger.d.ts +30 -0
  33. package/dist/debugLogger.d.ts.map +1 -0
  34. package/dist/debugLogger.js +95 -0
  35. package/dist/debugLogger.js.map +1 -0
  36. package/dist/deltaManager.d.ts +21 -10
  37. package/dist/deltaManager.d.ts.map +1 -1
  38. package/dist/deltaManager.js +114 -66
  39. package/dist/deltaManager.js.map +1 -1
  40. package/dist/deltaQueue.d.ts +1 -1
  41. package/dist/deltaQueue.d.ts.map +1 -1
  42. package/dist/deltaQueue.js +10 -10
  43. package/dist/deltaQueue.js.map +1 -1
  44. package/dist/disposal.d.ts +2 -2
  45. package/dist/disposal.d.ts.map +1 -1
  46. package/dist/disposal.js +1 -1
  47. package/dist/disposal.js.map +1 -1
  48. package/dist/error.d.ts +23 -0
  49. package/dist/error.d.ts.map +1 -0
  50. package/dist/error.js +32 -0
  51. package/dist/error.js.map +1 -0
  52. package/dist/loader.d.ts +22 -3
  53. package/dist/loader.d.ts.map +1 -1
  54. package/dist/loader.js +82 -51
  55. package/dist/loader.js.map +1 -1
  56. package/dist/noopHeuristic.d.ts +2 -2
  57. package/dist/noopHeuristic.d.ts.map +1 -1
  58. package/dist/noopHeuristic.js +6 -5
  59. package/dist/noopHeuristic.js.map +1 -1
  60. package/dist/packageVersion.d.ts +1 -1
  61. package/dist/packageVersion.js +1 -1
  62. package/dist/packageVersion.js.map +1 -1
  63. package/dist/protocol.d.ts +4 -2
  64. package/dist/protocol.d.ts.map +1 -1
  65. package/dist/protocol.js +25 -4
  66. package/dist/protocol.js.map +1 -1
  67. package/dist/quorum.d.ts +4 -1
  68. package/dist/quorum.d.ts.map +1 -1
  69. package/dist/quorum.js +1 -13
  70. package/dist/quorum.js.map +1 -1
  71. package/dist/retriableDocumentStorageService.d.ts.map +1 -1
  72. package/dist/retriableDocumentStorageService.js +4 -4
  73. package/dist/retriableDocumentStorageService.js.map +1 -1
  74. package/dist/utils.d.ts +8 -1
  75. package/dist/utils.d.ts.map +1 -1
  76. package/dist/utils.js +30 -11
  77. package/dist/utils.js.map +1 -1
  78. package/lib/audience.d.ts +1 -0
  79. package/lib/audience.d.ts.map +1 -1
  80. package/lib/audience.js +4 -2
  81. package/lib/audience.js.map +1 -1
  82. package/lib/catchUpMonitor.js +1 -1
  83. package/lib/catchUpMonitor.js.map +1 -1
  84. package/lib/connectionManager.d.ts +5 -5
  85. package/lib/connectionManager.d.ts.map +1 -1
  86. package/lib/connectionManager.js +74 -67
  87. package/lib/connectionManager.js.map +1 -1
  88. package/lib/connectionStateHandler.d.ts +15 -14
  89. package/lib/connectionStateHandler.d.ts.map +1 -1
  90. package/lib/connectionStateHandler.js +27 -29
  91. package/lib/connectionStateHandler.js.map +1 -1
  92. package/lib/container.d.ts +20 -9
  93. package/lib/container.d.ts.map +1 -1
  94. package/lib/container.js +288 -238
  95. package/lib/container.js.map +1 -1
  96. package/lib/containerContext.d.ts +2 -7
  97. package/lib/containerContext.d.ts.map +1 -1
  98. package/lib/containerContext.js +2 -14
  99. package/lib/containerContext.js.map +1 -1
  100. package/lib/containerStorageAdapter.d.ts.map +1 -1
  101. package/lib/containerStorageAdapter.js +5 -6
  102. package/lib/containerStorageAdapter.js.map +1 -1
  103. package/lib/contracts.d.ts +21 -8
  104. package/lib/contracts.d.ts.map +1 -1
  105. package/lib/contracts.js +3 -3
  106. package/lib/contracts.js.map +1 -1
  107. package/lib/debugLogger.d.ts +30 -0
  108. package/lib/debugLogger.d.ts.map +1 -0
  109. package/lib/debugLogger.js +91 -0
  110. package/lib/debugLogger.js.map +1 -0
  111. package/lib/deltaManager.d.ts +21 -10
  112. package/lib/deltaManager.d.ts.map +1 -1
  113. package/lib/deltaManager.js +88 -37
  114. package/lib/deltaManager.js.map +1 -1
  115. package/lib/deltaQueue.d.ts +1 -1
  116. package/lib/deltaQueue.d.ts.map +1 -1
  117. package/lib/deltaQueue.js +3 -3
  118. package/lib/deltaQueue.js.map +1 -1
  119. package/lib/disposal.d.ts +2 -2
  120. package/lib/disposal.d.ts.map +1 -1
  121. package/lib/disposal.js +1 -1
  122. package/lib/disposal.js.map +1 -1
  123. package/lib/error.d.ts +23 -0
  124. package/lib/error.d.ts.map +1 -0
  125. package/lib/error.js +28 -0
  126. package/lib/error.js.map +1 -0
  127. package/lib/loader.d.ts +22 -3
  128. package/lib/loader.d.ts.map +1 -1
  129. package/lib/loader.js +82 -51
  130. package/lib/loader.js.map +1 -1
  131. package/lib/noopHeuristic.d.ts +2 -2
  132. package/lib/noopHeuristic.d.ts.map +1 -1
  133. package/lib/noopHeuristic.js +2 -1
  134. package/lib/noopHeuristic.js.map +1 -1
  135. package/lib/packageVersion.d.ts +1 -1
  136. package/lib/packageVersion.js +1 -1
  137. package/lib/packageVersion.js.map +1 -1
  138. package/lib/protocol.d.ts +4 -2
  139. package/lib/protocol.d.ts.map +1 -1
  140. package/lib/protocol.js +25 -4
  141. package/lib/protocol.js.map +1 -1
  142. package/lib/quorum.d.ts +4 -1
  143. package/lib/quorum.d.ts.map +1 -1
  144. package/lib/quorum.js +0 -11
  145. package/lib/quorum.js.map +1 -1
  146. package/lib/retriableDocumentStorageService.d.ts.map +1 -1
  147. package/lib/retriableDocumentStorageService.js +2 -2
  148. package/lib/retriableDocumentStorageService.js.map +1 -1
  149. package/lib/utils.d.ts +8 -1
  150. package/lib/utils.d.ts.map +1 -1
  151. package/lib/utils.js +25 -7
  152. package/lib/utils.js.map +1 -1
  153. package/package.json +26 -32
  154. package/src/audience.ts +7 -1
  155. package/src/catchUpMonitor.ts +1 -1
  156. package/src/connectionManager.ts +75 -51
  157. package/src/connectionStateHandler.ts +31 -38
  158. package/src/container.ts +335 -240
  159. package/src/containerContext.ts +0 -16
  160. package/src/containerStorageAdapter.ts +2 -1
  161. package/src/contracts.ts +27 -11
  162. package/src/debugLogger.ts +113 -0
  163. package/src/deltaManager.ts +84 -34
  164. package/src/deltaQueue.ts +2 -1
  165. package/src/disposal.ts +2 -2
  166. package/src/error.ts +44 -0
  167. package/src/loader.ts +83 -35
  168. package/src/noopHeuristic.ts +3 -2
  169. package/src/packageVersion.ts +1 -1
  170. package/src/protocol.ts +33 -2
  171. package/src/quorum.ts +0 -10
  172. package/src/retriableDocumentStorageService.ts +2 -4
  173. package/src/utils.ts +33 -8
package/src/loader.ts CHANGED
@@ -6,14 +6,13 @@
6
6
  import { v4 as uuid } from "uuid";
7
7
  import {
8
8
  ITelemetryLoggerExt,
9
- ChildLogger,
10
- DebugLogger,
11
9
  IConfigProviderBase,
12
- loggerToMonitoringContext,
13
10
  mixinMonitoringContext,
14
11
  MonitoringContext,
15
12
  PerformanceEvent,
16
13
  sessionStorageConfigProvider,
14
+ createChildMonitoringContext,
15
+ UsageError,
17
16
  } from "@fluidframework/telemetry-utils";
18
17
  import {
19
18
  ITelemetryBaseLogger,
@@ -39,18 +38,15 @@ import {
39
38
  IResolvedUrl,
40
39
  IUrlResolver,
41
40
  } from "@fluidframework/driver-definitions";
42
- import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
41
+ import { IClientDetails } from "@fluidframework/protocol-definitions";
43
42
  import { Container, IPendingContainerState } from "./container";
44
43
  import { IParsedUrl, parseUrl } from "./utils";
45
44
  import { pkgVersion } from "./packageVersion";
46
45
  import { ProtocolHandlerBuilder } from "./protocol";
46
+ import { DebugLogger } from "./debugLogger";
47
47
 
48
48
  function canUseCache(request: IRequest): boolean {
49
- if (request.headers === undefined) {
50
- return true;
51
- }
52
-
53
- return request.headers[LoaderHeader.cache] !== false;
49
+ return request.headers?.[LoaderHeader.cache] === true;
54
50
  }
55
51
 
56
52
  function ensureResolvedUrlDefined(
@@ -69,6 +65,9 @@ export class RelativeLoader implements ILoader {
69
65
  private readonly loader: ILoader | undefined,
70
66
  ) {}
71
67
 
68
+ /**
69
+ * @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the Container's IFluidRouter/request.
70
+ */
72
71
  public get IFluidRouter(): IFluidRouter {
73
72
  return this;
74
73
  }
@@ -100,6 +99,9 @@ export class RelativeLoader implements ILoader {
100
99
  return this.loader.resolve(request);
101
100
  }
102
101
 
102
+ /**
103
+ * @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the Container's IFluidRouter/request.
104
+ */
103
105
  public async request(request: IRequest): Promise<IResponse> {
104
106
  if (request.url.startsWith("/")) {
105
107
  const container = await this.resolve(request);
@@ -149,7 +151,7 @@ export interface ICodeDetailsLoader extends Partial<IProvideFluidCodeDetailsComp
149
151
  * Load the code module (package) that is capable to interact with the document.
150
152
  *
151
153
  * @param source - Code proposal that articulates the current schema the document is written in.
152
- * @returns - Code module entry point along with the code details associated with it.
154
+ * @returns Code module entry point along with the code details associated with it.
153
155
  */
154
156
  load(source: IFluidCodeDetails): Promise<IFluidModuleWithDetails>;
155
157
  }
@@ -343,15 +345,33 @@ export class Loader implements IHostLoader {
343
345
  protocolHandlerBuilder,
344
346
  subLogger: subMc.logger,
345
347
  };
346
- this.mc = loggerToMonitoringContext(ChildLogger.create(this.services.subLogger, "Loader"));
348
+ this.mc = createChildMonitoringContext({
349
+ logger: this.services.subLogger,
350
+ namespace: "Loader",
351
+ });
347
352
  }
348
353
 
354
+ /**
355
+ * @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the Container's IFluidRouter/request.
356
+ */
349
357
  public get IFluidRouter(): IFluidRouter {
350
358
  return this;
351
359
  }
352
360
 
353
- public async createDetachedContainer(codeDetails: IFluidCodeDetails): Promise<IContainer> {
354
- const container = await Container.createDetached(this.services, codeDetails);
361
+ public async createDetachedContainer(
362
+ codeDetails: IFluidCodeDetails,
363
+ createDetachedProps?: {
364
+ canReconnect?: boolean;
365
+ clientDetailsOverride?: IClientDetails;
366
+ },
367
+ ): Promise<IContainer> {
368
+ const container = await Container.createDetached(
369
+ {
370
+ ...createDetachedProps,
371
+ ...this.services,
372
+ },
373
+ codeDetails,
374
+ );
355
375
 
356
376
  if (this.cachingEnabled) {
357
377
  container.once("attached", () => {
@@ -366,8 +386,20 @@ export class Loader implements IHostLoader {
366
386
  return container;
367
387
  }
368
388
 
369
- public async rehydrateDetachedContainerFromSnapshot(snapshot: string): Promise<IContainer> {
370
- return Container.rehydrateDetachedFromSnapshot(this.services, snapshot);
389
+ public async rehydrateDetachedContainerFromSnapshot(
390
+ snapshot: string,
391
+ createDetachedProps?: {
392
+ canReconnect?: boolean;
393
+ clientDetailsOverride?: IClientDetails;
394
+ },
395
+ ): Promise<IContainer> {
396
+ return Container.rehydrateDetachedFromSnapshot(
397
+ {
398
+ ...createDetachedProps,
399
+ ...this.services,
400
+ },
401
+ snapshot,
402
+ );
371
403
  }
372
404
 
373
405
  public async resolve(request: IRequest, pendingLocalState?: string): Promise<IContainer> {
@@ -381,6 +413,9 @@ export class Loader implements IHostLoader {
381
413
  });
382
414
  }
383
415
 
416
+ /**
417
+ * @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the Container's IFluidRouter/request.
418
+ */
384
419
  public async request(request: IRequest): Promise<IResponse> {
385
420
  return PerformanceEvent.timedExecAsync(
386
421
  this.mc.logger,
@@ -407,16 +442,23 @@ export class Loader implements IHostLoader {
407
442
  this.containers.set(key, containerP);
408
443
  containerP
409
444
  .then((container) => {
410
- // If the container is closed or becomes closed after we resolve it, remove it from the cache.
411
- if (container.closed) {
445
+ // If the container is closed/disposed or becomes closed/disposed after we resolve it,
446
+ // remove it from the cache.
447
+ if (container.closed || container.disposed) {
412
448
  this.containers.delete(key);
413
449
  } else {
414
450
  container.once("closed", () => {
415
451
  this.containers.delete(key);
416
452
  });
453
+ container.once("disposed", () => {
454
+ this.containers.delete(key);
455
+ });
417
456
  }
418
457
  })
419
- .catch((error) => {});
458
+ .catch((error) => {
459
+ // If an error occured while resolving the container request, then remove it from the cache.
460
+ this.containers.delete(key);
461
+ });
420
462
  }
421
463
 
422
464
  private async resolveCore(
@@ -447,11 +489,29 @@ export class Loader implements IHostLoader {
447
489
  // If set in both query string and headers, use query string. Also write the value from the query string into the header either way.
448
490
  request.headers[LoaderHeader.version] =
449
491
  parsed.version ?? request.headers[LoaderHeader.version];
492
+ const cacheHeader = request.headers[LoaderHeader.cache];
450
493
  const canCache =
451
- this.cachingEnabled &&
452
- request.headers[LoaderHeader.cache] !== false &&
494
+ // Take header value if present, else use ILoaderOptions.cache value
495
+ (cacheHeader !== undefined ? cacheHeader === true : this.cachingEnabled) &&
453
496
  pendingLocalState === undefined;
454
- const fromSequenceNumber = request.headers[LoaderHeader.sequenceNumber] ?? -1;
497
+ const fromSequenceNumber = request.headers[LoaderHeader.sequenceNumber] as
498
+ | number
499
+ | undefined;
500
+ const opsBeforeReturn = request.headers[LoaderHeader.loadMode]?.opsBeforeReturn as
501
+ | string
502
+ | undefined;
503
+
504
+ if (
505
+ opsBeforeReturn === "sequenceNumber" &&
506
+ (fromSequenceNumber === undefined || fromSequenceNumber < 0)
507
+ ) {
508
+ // If opsBeforeReturn is set to "sequenceNumber", then fromSequenceNumber should be set to a non-negative integer.
509
+ throw new UsageError("sequenceNumber must be set to a non-negative integer");
510
+ } else if (opsBeforeReturn !== "sequenceNumber" && fromSequenceNumber !== undefined) {
511
+ // If opsBeforeReturn is not set to "sequenceNumber", then fromSequenceNumber should be undefined (default value).
512
+ // In this case, we should throw an error since opsBeforeReturn is not explicitly set to "sequenceNumber".
513
+ throw new UsageError('opsBeforeReturn must be set to "sequenceNumber"');
514
+ }
455
515
 
456
516
  let container: Container;
457
517
  if (canCache) {
@@ -468,24 +528,11 @@ export class Loader implements IHostLoader {
468
528
  container = await this.loadContainer(request, resolvedAsFluid, pendingLocalState);
469
529
  }
470
530
 
471
- if (container.deltaManager.lastSequenceNumber <= fromSequenceNumber) {
472
- await new Promise<void>((resolve, reject) => {
473
- function opHandler(message: ISequencedDocumentMessage) {
474
- if (message.sequenceNumber > fromSequenceNumber) {
475
- resolve();
476
- container.removeListener("op", opHandler);
477
- }
478
- }
479
-
480
- container.on("op", opHandler);
481
- });
482
- }
483
-
484
531
  return { container, parsed };
485
532
  }
486
533
 
487
534
  private get cachingEnabled() {
488
- return this.services.options.cache !== false;
535
+ return this.services.options.cache === true;
489
536
  }
490
537
 
491
538
  private async loadContainer(
@@ -499,6 +546,7 @@ export class Loader implements IHostLoader {
499
546
  version: request.headers?.[LoaderHeader.version] ?? undefined,
500
547
  loadMode: request.headers?.[LoaderHeader.loadMode],
501
548
  pendingLocalState,
549
+ loadToSequenceNumber: request.headers?.[LoaderHeader.sequenceNumber],
502
550
  },
503
551
  {
504
552
  canReconnect: request.headers?.[LoaderHeader.reconnect],
@@ -3,10 +3,11 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { assert, Timer, TypedEventEmitter } from "@fluidframework/common-utils";
6
+ import { TypedEventEmitter } from "@fluid-internal/client-utils";
7
+ import { assert, Timer } from "@fluidframework/core-utils";
7
8
  import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
8
9
  import { isRuntimeMessage } from "@fluidframework/driver-utils";
9
- import { IEvent } from "@fluidframework/common-definitions";
10
+ import { IEvent } from "@fluidframework/core-interfaces";
10
11
 
11
12
  const defaultNoopTimeFrequency = 2000;
12
13
  const defaultNoopCountFrequency = 50;
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/container-loader";
9
- export const pkgVersion = "2.0.0-dev.5.3.2.178189";
9
+ export const pkgVersion = "2.0.0-dev.6.4.0.191457";
package/src/protocol.ts CHANGED
@@ -4,6 +4,7 @@
4
4
  */
5
5
 
6
6
  import { IAudienceOwner } from "@fluidframework/container-definitions";
7
+ import { canBeCoalescedByService } from "@fluidframework/driver-utils";
7
8
  import {
8
9
  IProtocolHandler as IBaseProtocolHandler,
9
10
  IQuorumSnapshot,
@@ -11,8 +12,12 @@ import {
11
12
  } from "@fluidframework/protocol-base";
12
13
  import {
13
14
  IDocumentAttributes,
15
+ IProcessMessageResult,
16
+ ISequencedClient,
17
+ ISequencedDocumentMessage,
14
18
  ISignalClient,
15
19
  ISignalMessage,
20
+ MessageType,
16
21
  } from "@fluidframework/protocol-definitions";
17
22
 
18
23
  // "term" was an experimental feature that is being removed. The only safe value to use is 1.
@@ -44,12 +49,12 @@ export class ProtocolHandler extends ProtocolOpHandler implements IProtocolHandl
44
49
  attributes: IDocumentAttributes,
45
50
  quorumSnapshot: IQuorumSnapshot,
46
51
  sendProposal: (key: string, value: any) => number,
47
- readonly audience: IAudienceOwner,
52
+ public readonly audience: IAudienceOwner,
53
+ private readonly shouldClientHaveLeft: (clientId: string) => boolean,
48
54
  ) {
49
55
  super(
50
56
  attributes.minimumSequenceNumber,
51
57
  attributes.sequenceNumber,
52
- OnlyValidTermValue,
53
58
  quorumSnapshot.members,
54
59
  quorumSnapshot.proposals,
55
60
  quorumSnapshot.values,
@@ -66,6 +71,32 @@ export class ProtocolHandler extends ProtocolOpHandler implements IProtocolHandl
66
71
  }
67
72
  }
68
73
 
74
+ public processMessage(
75
+ message: ISequencedDocumentMessage,
76
+ local: boolean,
77
+ ): IProcessMessageResult {
78
+ const client: ISequencedClient | undefined = this.quorum.getMember(message.clientId);
79
+
80
+ // Check and report if we're getting messages from a clientId that we previously
81
+ // flagged as shouldHaveLeft, or from a client that's not in the quorum but should be
82
+ if (message.clientId != null) {
83
+ if (client === undefined && message.type !== MessageType.ClientJoin) {
84
+ // pre-0.58 error message: messageClientIdMissingFromQuorum
85
+ throw new Error("Remote message's clientId is missing from the quorum");
86
+ }
87
+
88
+ // Here checking canBeCoalescedByService is used as an approximation of "is benign to process despite being unexpected".
89
+ // It's still not good to see these messages from unexpected clientIds, but since they don't harm the integrity of the
90
+ // document we don't need to blow up aggressively.
91
+ if (this.shouldClientHaveLeft(message.clientId) && !canBeCoalescedByService(message)) {
92
+ // pre-0.58 error message: messageClientIdShouldHaveLeft
93
+ throw new Error("Remote message's clientId already should have left");
94
+ }
95
+ }
96
+
97
+ return super.processMessage(message, local);
98
+ }
99
+
69
100
  public processSignal(message: ISignalMessage) {
70
101
  const innerContent = message.content as { content: any; type: string };
71
102
  switch (innerContent.type) {
package/src/quorum.ts CHANGED
@@ -2,19 +2,9 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { assert } from "@fluidframework/common-utils";
6
5
  import { IFluidCodeDetails } from "@fluidframework/core-interfaces";
7
6
  import { ICommittedProposal } from "@fluidframework/protocol-definitions";
8
7
 
9
- export function getCodeDetailsFromQuorumValues(
10
- quorumValues: [string, ICommittedProposal][],
11
- ): IFluidCodeDetails {
12
- const qValuesMap = new Map(quorumValues);
13
- const proposal = qValuesMap.get("code");
14
- assert(proposal !== undefined, 0x2dc /* "Cannot find code proposal" */);
15
- return proposal?.value as IFluidCodeDetails;
16
- }
17
-
18
8
  export function initQuorumValuesFromCodeDetails(
19
9
  source: IFluidCodeDetails,
20
10
  ): [string, ICommittedProposal][] {
@@ -3,8 +3,7 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { assert } from "@fluidframework/common-utils";
7
- import { GenericError } from "@fluidframework/container-utils";
6
+ import { assert } from "@fluidframework/core-utils";
8
7
  import {
9
8
  FetchSource,
10
9
  IDocumentStorageService,
@@ -19,8 +18,7 @@ import {
19
18
  IVersion,
20
19
  } from "@fluidframework/protocol-definitions";
21
20
  import { IDisposable } from "@fluidframework/core-interfaces";
22
-
23
- import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
21
+ import { GenericError, ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
24
22
  import { runWithRetry } from "@fluidframework/driver-utils";
25
23
 
26
24
  export class RetriableDocumentStorageService implements IDocumentStorageService, IDisposable {
package/src/utils.ts CHANGED
@@ -5,19 +5,16 @@
5
5
 
6
6
  import { parse } from "url";
7
7
  import { v4 as uuid } from "uuid";
8
- import {
9
- assert,
10
- stringToBuffer,
11
- Uint8ArrayToArrayBuffer,
12
- unreachableCase,
13
- } from "@fluidframework/common-utils";
8
+ import { stringToBuffer, Uint8ArrayToArrayBuffer } from "@fluid-internal/client-utils";
9
+ import { assert, unreachableCase } from "@fluidframework/core-utils";
14
10
  import { ISummaryTree, ISnapshotTree, SummaryType } from "@fluidframework/protocol-definitions";
15
11
  import { LoggingError } from "@fluidframework/telemetry-utils";
16
12
  import {
13
+ CombinedAppAndProtocolSummary,
17
14
  DeltaStreamConnectionForbiddenError,
18
15
  isCombinedAppAndProtocolSummary,
19
16
  } from "@fluidframework/driver-utils";
20
- import { DriverErrorType } from "@fluidframework/driver-definitions";
17
+ import { DriverErrorTypes } from "@fluidframework/driver-definitions";
21
18
 
22
19
  // This is used when we rehydrate a container from the snapshot. Here we put the blob contents
23
20
  // in separate property: blobContents.
@@ -51,6 +48,34 @@ export function parseUrl(url: string): IParsedUrl | undefined {
51
48
  : undefined;
52
49
  }
53
50
 
51
+ /**
52
+ * Combine the app summary and protocol summary in 1 tree.
53
+ * @param appSummary - Summary of the app.
54
+ * @param protocolSummary - Summary of the protocol.
55
+ * @internal
56
+ */
57
+ export function combineAppAndProtocolSummary(
58
+ appSummary: ISummaryTree,
59
+ protocolSummary: ISummaryTree,
60
+ ): CombinedAppAndProtocolSummary {
61
+ assert(
62
+ !isCombinedAppAndProtocolSummary(appSummary),
63
+ 0x5a8 /* app summary is already a combined tree! */,
64
+ );
65
+ assert(
66
+ !isCombinedAppAndProtocolSummary(protocolSummary),
67
+ 0x5a9 /* protocol summary is already a combined tree! */,
68
+ );
69
+ const createNewSummary: CombinedAppAndProtocolSummary = {
70
+ type: SummaryType.Tree,
71
+ tree: {
72
+ ".protocol": protocolSummary,
73
+ ".app": appSummary,
74
+ },
75
+ };
76
+ return createNewSummary;
77
+ }
78
+
54
79
  /**
55
80
  * Converts summary tree (for upload) to snapshot tree (for download).
56
81
  * Summary tree blobs contain contents, but snapshot tree blobs normally
@@ -156,6 +181,6 @@ export function isDeltaStreamConnectionForbiddenError(
156
181
  return (
157
182
  typeof error === "object" &&
158
183
  error !== null &&
159
- error?.errorType === DriverErrorType.deltaStreamConnectionForbidden
184
+ error?.errorType === DriverErrorTypes.deltaStreamConnectionForbidden
160
185
  );
161
186
  }