@fluidframework/container-loader 2.0.0-internal.1.1.3 → 2.0.0-internal.1.2.0

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 (92) hide show
  1. package/dist/catchUpMonitor.d.ts +6 -17
  2. package/dist/catchUpMonitor.d.ts.map +1 -1
  3. package/dist/catchUpMonitor.js +5 -36
  4. package/dist/catchUpMonitor.js.map +1 -1
  5. package/dist/collabWindowTracker.d.ts +1 -1
  6. package/dist/collabWindowTracker.d.ts.map +1 -1
  7. package/dist/collabWindowTracker.js +2 -1
  8. package/dist/collabWindowTracker.js.map +1 -1
  9. package/dist/connectionManager.d.ts +1 -1
  10. package/dist/connectionManager.d.ts.map +1 -1
  11. package/dist/connectionManager.js +8 -11
  12. package/dist/connectionManager.js.map +1 -1
  13. package/dist/connectionStateHandler.d.ts +80 -26
  14. package/dist/connectionStateHandler.d.ts.map +1 -1
  15. package/dist/connectionStateHandler.js +170 -89
  16. package/dist/connectionStateHandler.js.map +1 -1
  17. package/dist/container.d.ts +22 -11
  18. package/dist/container.d.ts.map +1 -1
  19. package/dist/container.js +107 -125
  20. package/dist/container.js.map +1 -1
  21. package/dist/containerContext.d.ts +18 -7
  22. package/dist/containerContext.d.ts.map +1 -1
  23. package/dist/containerContext.js +18 -8
  24. package/dist/containerContext.js.map +1 -1
  25. package/dist/containerStorageAdapter.d.ts +10 -24
  26. package/dist/containerStorageAdapter.d.ts.map +1 -1
  27. package/dist/containerStorageAdapter.js +50 -16
  28. package/dist/containerStorageAdapter.js.map +1 -1
  29. package/dist/deltaManager.d.ts +1 -1
  30. package/dist/deltaManager.d.ts.map +1 -1
  31. package/dist/deltaManager.js +18 -6
  32. package/dist/deltaManager.js.map +1 -1
  33. package/dist/loader.d.ts +1 -1
  34. package/dist/loader.js.map +1 -1
  35. package/dist/packageVersion.d.ts +1 -1
  36. package/dist/packageVersion.js +1 -1
  37. package/dist/packageVersion.js.map +1 -1
  38. package/dist/protocol.d.ts.map +1 -1
  39. package/dist/protocol.js +2 -1
  40. package/dist/protocol.js.map +1 -1
  41. package/lib/catchUpMonitor.d.ts +6 -17
  42. package/lib/catchUpMonitor.d.ts.map +1 -1
  43. package/lib/catchUpMonitor.js +5 -35
  44. package/lib/catchUpMonitor.js.map +1 -1
  45. package/lib/collabWindowTracker.d.ts +1 -1
  46. package/lib/collabWindowTracker.d.ts.map +1 -1
  47. package/lib/collabWindowTracker.js +3 -2
  48. package/lib/collabWindowTracker.js.map +1 -1
  49. package/lib/connectionManager.d.ts +1 -1
  50. package/lib/connectionManager.d.ts.map +1 -1
  51. package/lib/connectionManager.js +9 -14
  52. package/lib/connectionManager.js.map +1 -1
  53. package/lib/connectionStateHandler.d.ts +80 -26
  54. package/lib/connectionStateHandler.d.ts.map +1 -1
  55. package/lib/connectionStateHandler.js +170 -90
  56. package/lib/connectionStateHandler.js.map +1 -1
  57. package/lib/container.d.ts +22 -11
  58. package/lib/container.d.ts.map +1 -1
  59. package/lib/container.js +110 -128
  60. package/lib/container.js.map +1 -1
  61. package/lib/containerContext.d.ts +18 -7
  62. package/lib/containerContext.d.ts.map +1 -1
  63. package/lib/containerContext.js +19 -9
  64. package/lib/containerContext.js.map +1 -1
  65. package/lib/containerStorageAdapter.d.ts +10 -24
  66. package/lib/containerStorageAdapter.d.ts.map +1 -1
  67. package/lib/containerStorageAdapter.js +50 -15
  68. package/lib/containerStorageAdapter.js.map +1 -1
  69. package/lib/deltaManager.d.ts +1 -1
  70. package/lib/deltaManager.d.ts.map +1 -1
  71. package/lib/deltaManager.js +18 -6
  72. package/lib/deltaManager.js.map +1 -1
  73. package/lib/loader.d.ts +1 -1
  74. package/lib/loader.js.map +1 -1
  75. package/lib/packageVersion.d.ts +1 -1
  76. package/lib/packageVersion.js +1 -1
  77. package/lib/packageVersion.js.map +1 -1
  78. package/lib/protocol.d.ts.map +1 -1
  79. package/lib/protocol.js +2 -1
  80. package/lib/protocol.js.map +1 -1
  81. package/package.json +13 -13
  82. package/src/catchUpMonitor.ts +7 -47
  83. package/src/collabWindowTracker.ts +4 -3
  84. package/src/connectionManager.ts +9 -11
  85. package/src/connectionStateHandler.ts +231 -106
  86. package/src/container.ts +132 -147
  87. package/src/containerContext.ts +22 -8
  88. package/src/containerStorageAdapter.ts +64 -15
  89. package/src/deltaManager.ts +20 -7
  90. package/src/loader.ts +1 -1
  91. package/src/packageVersion.ts +1 -1
  92. package/src/protocol.ts +2 -1
@@ -3,14 +3,17 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { ITelemetryLogger } from "@fluidframework/common-definitions";
6
+ import { IDisposable, ITelemetryLogger } from "@fluidframework/common-definitions";
7
+ import { assert } from "@fluidframework/common-utils";
7
8
  import { ISnapshotTreeWithBlobContents } from "@fluidframework/container-definitions";
8
9
  import {
9
10
  FetchSource,
11
+ IDocumentService,
10
12
  IDocumentStorageService,
11
13
  IDocumentStorageServicePolicies,
12
14
  ISummaryContext,
13
15
  } from "@fluidframework/driver-definitions";
16
+ import { UsageError } from "@fluidframework/driver-utils";
14
17
  import {
15
18
  ICreateBlobResponse,
16
19
  ISnapshotTree,
@@ -19,14 +22,52 @@ import {
19
22
  IVersion,
20
23
  } from "@fluidframework/protocol-definitions";
21
24
  import { IDetachedBlobStorage } from "./loader";
25
+ import { ProtocolTreeStorageService } from "./protocolTreeDocumentStorageService";
26
+ import { RetriableDocumentStorageService } from "./retriableDocumentStorageService";
22
27
 
23
28
  /**
24
29
  * This class wraps the actual storage and make sure no wrong apis are called according to
25
30
  * container attach state.
26
31
  */
27
- export class ContainerStorageAdapter implements IDocumentStorageService {
32
+ export class ContainerStorageAdapter implements IDocumentStorageService, IDisposable {
28
33
  private readonly blobContents: { [id: string]: ArrayBufferLike; } = {};
29
- constructor(private readonly storageGetter: () => IDocumentStorageService) {}
34
+ private _storageService: IDocumentStorageService & Partial<IDisposable>;
35
+
36
+ constructor(
37
+ detachedBlobStorage: IDetachedBlobStorage | undefined,
38
+ private readonly logger: ITelemetryLogger,
39
+ private readonly captureProtocolSummary?: () => ISummaryTree,
40
+ ) {
41
+ this._storageService = new BlobOnlyStorage(detachedBlobStorage, logger);
42
+ }
43
+
44
+ disposed: boolean = false;
45
+ dispose(error?: Error): void {
46
+ this._storageService?.dispose?.(error);
47
+ this.disposed = true;
48
+ }
49
+
50
+ public async connectToService(service: IDocumentService): Promise<void> {
51
+ if (!(this._storageService instanceof BlobOnlyStorage)) {
52
+ return;
53
+ }
54
+
55
+ const storageService = await service.connectToStorage();
56
+ const retriableStorage = this._storageService =
57
+ new RetriableDocumentStorageService(
58
+ storageService,
59
+ this.logger);
60
+
61
+ if (this.captureProtocolSummary !== undefined) {
62
+ this.logger.sendTelemetryEvent({ eventName: "summarizeProtocolTreeEnabled" });
63
+ this._storageService =
64
+ new ProtocolTreeStorageService(retriableStorage, this.captureProtocolSummary);
65
+ }
66
+
67
+ // ensure we did not lose that policy in the process of wrapping
68
+ assert(storageService.policies?.minBlobSize === this._storageService.policies?.minBlobSize,
69
+ 0x0e0 /* "lost minBlobSize policy" */);
70
+ }
30
71
 
31
72
  public loadSnapshotForRehydratingContainer(snapshotTree: ISnapshotTreeWithBlobContents) {
32
73
  this.getBlobContents(snapshotTree);
@@ -45,17 +86,17 @@ export class ContainerStorageAdapter implements IDocumentStorageService {
45
86
  // back-compat 0.40 containerRuntime requests policies even in detached container if storage is present
46
87
  // and storage is always present in >=0.41.
47
88
  try {
48
- return this.storageGetter().policies;
89
+ return this._storageService.policies;
49
90
  } catch (e) {}
50
91
  return undefined;
51
92
  }
52
93
 
53
94
  public get repositoryUrl(): string {
54
- return this.storageGetter().repositoryUrl;
95
+ return this._storageService.repositoryUrl;
55
96
  }
56
97
 
57
98
  public async getSnapshotTree(version?: IVersion, scenarioName?: string): Promise<ISnapshotTree | null> {
58
- return this.storageGetter().getSnapshotTree(version, scenarioName);
99
+ return this._storageService.getSnapshotTree(version, scenarioName);
59
100
  }
60
101
 
61
102
  public async readBlob(id: string): Promise<ArrayBufferLike> {
@@ -63,7 +104,7 @@ export class ContainerStorageAdapter implements IDocumentStorageService {
63
104
  if (blob !== undefined) {
64
105
  return blob;
65
106
  }
66
- return this.storageGetter().readBlob(id);
107
+ return this._storageService.readBlob(id);
67
108
  }
68
109
 
69
110
  public async getVersions(
@@ -72,19 +113,19 @@ export class ContainerStorageAdapter implements IDocumentStorageService {
72
113
  scenarioName?: string,
73
114
  fetchSource?: FetchSource,
74
115
  ): Promise<IVersion[]> {
75
- return this.storageGetter().getVersions(versionId, count, scenarioName, fetchSource);
116
+ return this._storageService.getVersions(versionId, count, scenarioName, fetchSource);
76
117
  }
77
118
 
78
119
  public async uploadSummaryWithContext(summary: ISummaryTree, context: ISummaryContext): Promise<string> {
79
- return this.storageGetter().uploadSummaryWithContext(summary, context);
120
+ return this._storageService.uploadSummaryWithContext(summary, context);
80
121
  }
81
122
 
82
123
  public async downloadSummary(handle: ISummaryHandle): Promise<ISummaryTree> {
83
- return this.storageGetter().downloadSummary(handle);
124
+ return this._storageService.downloadSummary(handle);
84
125
  }
85
126
 
86
127
  public async createBlob(file: ArrayBufferLike): Promise<ICreateBlobResponse> {
87
- return this.storageGetter().createBlob(file);
128
+ return this._storageService.createBlob(file);
88
129
  }
89
130
  }
90
131
 
@@ -92,18 +133,25 @@ export class ContainerStorageAdapter implements IDocumentStorageService {
92
133
  * Storage which only supports createBlob() and readBlob(). This is used with IDetachedBlobStorage to support
93
134
  * blobs in detached containers.
94
135
  */
95
- export class BlobOnlyStorage implements IDocumentStorageService {
136
+ class BlobOnlyStorage implements IDocumentStorageService {
96
137
  constructor(
97
- private readonly blobStorage: IDetachedBlobStorage,
138
+ private readonly detachedStorage: IDetachedBlobStorage | undefined,
98
139
  private readonly logger: ITelemetryLogger,
99
140
  ) { }
100
141
 
101
142
  public async createBlob(content: ArrayBufferLike): Promise<ICreateBlobResponse> {
102
- return this.blobStorage.createBlob(content);
143
+ return this.verifyStorage().createBlob(content);
103
144
  }
104
145
 
105
146
  public async readBlob(blobId: string): Promise<ArrayBufferLike> {
106
- return this.blobStorage.readBlob(blobId);
147
+ return this.verifyStorage().readBlob(blobId);
148
+ }
149
+
150
+ private verifyStorage(): IDetachedBlobStorage {
151
+ if (this.detachedStorage === undefined) {
152
+ throw new UsageError("Real storage calls not allowed in Unattached container");
153
+ }
154
+ return this.detachedStorage;
107
155
  }
108
156
 
109
157
  public get policies(): IDocumentStorageServicePolicies | undefined {
@@ -123,6 +171,7 @@ export class BlobOnlyStorage implements IDocumentStorageService {
123
171
  /* eslint-enable @typescript-eslint/unbound-method */
124
172
 
125
173
  private notCalled(): never {
174
+ this.verifyStorage();
126
175
  try {
127
176
  // some browsers may not populate stack unless exception is thrown
128
177
  throw new Error("BlobOnlyStorage not implemented method used");
@@ -199,12 +199,12 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
199
199
  public get readOnlyInfo() { return this.connectionManager.readOnlyInfo; }
200
200
  public get clientDetails() { return this.connectionManager.clientDetails; }
201
201
 
202
- public submit(type: MessageType, contents: any, batch = false, metadata?: any) {
202
+ public submit(type: MessageType, contents?: string, batch = false, metadata?: any) {
203
203
  if (this.currentlyProcessingOps && this.preventConcurrentOpSend) {
204
204
  this.close(new UsageError("Making changes to data model is disallowed while processing ops."));
205
205
  }
206
206
  const messagePartial: Omit<IDocumentMessage, "clientSequenceNumber"> = {
207
- contents: JSON.stringify(contents),
207
+ contents,
208
208
  metadata,
209
209
  referenceSequenceNumber: this.lastProcessedSequenceNumber,
210
210
  type,
@@ -218,7 +218,9 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
218
218
  return -1;
219
219
  }
220
220
 
221
- this.opsSize += message.contents.length;
221
+ if (contents !== undefined) {
222
+ this.opsSize += contents.length;
223
+ }
222
224
 
223
225
  this.messageBuffer.push(message);
224
226
 
@@ -233,15 +235,26 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
233
235
  public submitSignal(content: any) { return this.connectionManager.submitSignal(content); }
234
236
 
235
237
  public flush() {
236
- if (this.messageBuffer.length === 0) {
238
+ const batch = this.messageBuffer;
239
+ if (batch.length === 0) {
237
240
  return;
238
241
  }
239
242
 
243
+ this.messageBuffer = [];
244
+
240
245
  // The prepareFlush event allows listeners to append metadata to the batch prior to submission.
241
- this.emit("prepareSend", this.messageBuffer);
246
+ this.emit("prepareSend", batch);
242
247
 
243
- this.connectionManager.sendMessages(this.messageBuffer);
244
- this.messageBuffer = [];
248
+ if (batch.length === 1) {
249
+ assert(batch[0].metadata?.batch === undefined, 0x3c9 /* no batch markup on single message */);
250
+ } else {
251
+ assert(batch[0].metadata?.batch === true, 0x3ca /* no start batch markup */);
252
+ assert(batch[batch.length - 1].metadata?.batch === false, 0x3cb /* no end batch markup */);
253
+ }
254
+
255
+ this.connectionManager.sendMessages(batch);
256
+
257
+ assert(this.messageBuffer.length === 0, 0x3cc /* reentrancy */);
245
258
  }
246
259
 
247
260
  public get connectionProps(): ITelemetryProperties {
package/src/loader.ts CHANGED
@@ -133,7 +133,7 @@ export interface ILoaderOptions extends ILoaderOptions1 {
133
133
 
134
134
  /**
135
135
  * @deprecated IFluidModuleWithDetails interface is moved to
136
- * {@link @fluidframework/container-definition#IFluidModuleWithDetails}
136
+ * {@link @fluidframework/container-definitions#IFluidModuleWithDetails}
137
137
  * to have all the code loading modules in one package. #8193
138
138
  * Encapsulates a module entry point with corresponding code details.
139
139
  */
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/container-loader";
9
- export const pkgVersion = "2.0.0-internal.1.1.3";
9
+ export const pkgVersion = "2.0.0-internal.1.2.0";
package/src/protocol.ts CHANGED
@@ -18,6 +18,7 @@ import {
18
18
  ISignalMessage,
19
19
  MessageType,
20
20
  } from "@fluidframework/protocol-definitions";
21
+ import { canBeCoalescedByService } from "@fluidframework/driver-utils";
21
22
 
22
23
  /**
23
24
  * Function to be used for creating a protocol handler.
@@ -68,7 +69,7 @@ export class ProtocolHandler extends ProtocolOpHandler implements IProtocolHandl
68
69
  throw new Error("Remote message's clientId is missing from the quorum");
69
70
  }
70
71
 
71
- if (client?.shouldHaveLeft === true && message.type !== MessageType.NoOp) {
72
+ if (client?.shouldHaveLeft === true && !canBeCoalescedByService(message)) {
72
73
  // pre-0.58 error message: messageClientIdShouldHaveLeft
73
74
  throw new Error("Remote message's clientId already should have left");
74
75
  }