@fluidframework/container-loader 1.2.6 → 2.0.0-dev.1.3.0.96595

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 (157) hide show
  1. package/.mocharc.js +12 -0
  2. package/dist/audience.d.ts +2 -6
  3. package/dist/audience.d.ts.map +1 -1
  4. package/dist/audience.js +6 -11
  5. package/dist/audience.js.map +1 -1
  6. package/dist/catchUpMonitor.d.ts +29 -0
  7. package/dist/catchUpMonitor.d.ts.map +1 -0
  8. package/dist/catchUpMonitor.js +43 -0
  9. package/dist/catchUpMonitor.js.map +1 -0
  10. package/dist/collabWindowTracker.d.ts +1 -1
  11. package/dist/collabWindowTracker.d.ts.map +1 -1
  12. package/dist/collabWindowTracker.js +12 -4
  13. package/dist/collabWindowTracker.js.map +1 -1
  14. package/dist/connectionManager.d.ts +5 -5
  15. package/dist/connectionManager.d.ts.map +1 -1
  16. package/dist/connectionManager.js +43 -22
  17. package/dist/connectionManager.js.map +1 -1
  18. package/dist/connectionState.d.ts +0 -5
  19. package/dist/connectionState.d.ts.map +1 -1
  20. package/dist/connectionState.js +0 -5
  21. package/dist/connectionState.js.map +1 -1
  22. package/dist/connectionStateHandler.d.ts +84 -22
  23. package/dist/connectionStateHandler.d.ts.map +1 -1
  24. package/dist/connectionStateHandler.js +172 -59
  25. package/dist/connectionStateHandler.js.map +1 -1
  26. package/dist/container.d.ts +29 -17
  27. package/dist/container.d.ts.map +1 -1
  28. package/dist/container.js +181 -171
  29. package/dist/container.js.map +1 -1
  30. package/dist/containerContext.d.ts +18 -7
  31. package/dist/containerContext.d.ts.map +1 -1
  32. package/dist/containerContext.js +18 -8
  33. package/dist/containerContext.js.map +1 -1
  34. package/dist/containerStorageAdapter.d.ts +11 -25
  35. package/dist/containerStorageAdapter.d.ts.map +1 -1
  36. package/dist/containerStorageAdapter.js +51 -17
  37. package/dist/containerStorageAdapter.js.map +1 -1
  38. package/dist/contracts.d.ts +5 -5
  39. package/dist/contracts.js.map +1 -1
  40. package/dist/deltaManager.d.ts +4 -1
  41. package/dist/deltaManager.d.ts.map +1 -1
  42. package/dist/deltaManager.js +39 -12
  43. package/dist/deltaManager.js.map +1 -1
  44. package/dist/deltaManagerProxy.d.ts +4 -1
  45. package/dist/deltaManagerProxy.d.ts.map +1 -1
  46. package/dist/deltaQueue.d.ts +9 -2
  47. package/dist/deltaQueue.d.ts.map +1 -1
  48. package/dist/deltaQueue.js +31 -26
  49. package/dist/deltaQueue.js.map +1 -1
  50. package/dist/index.d.ts +1 -0
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js.map +1 -1
  53. package/dist/loader.d.ts +8 -1
  54. package/dist/loader.d.ts.map +1 -1
  55. package/dist/loader.js +4 -3
  56. package/dist/loader.js.map +1 -1
  57. package/dist/packageVersion.d.ts +1 -1
  58. package/dist/packageVersion.d.ts.map +1 -1
  59. package/dist/packageVersion.js +1 -1
  60. package/dist/packageVersion.js.map +1 -1
  61. package/dist/protocol.d.ts +27 -0
  62. package/dist/protocol.d.ts.map +1 -0
  63. package/dist/protocol.js +79 -0
  64. package/dist/protocol.js.map +1 -0
  65. package/dist/protocolTreeDocumentStorageService.d.ts +1 -1
  66. package/dist/protocolTreeDocumentStorageService.d.ts.map +1 -1
  67. package/dist/retriableDocumentStorageService.d.ts +2 -2
  68. package/dist/retriableDocumentStorageService.d.ts.map +1 -1
  69. package/dist/retriableDocumentStorageService.js +2 -2
  70. package/dist/retriableDocumentStorageService.js.map +1 -1
  71. package/lib/audience.d.ts +2 -6
  72. package/lib/audience.d.ts.map +1 -1
  73. package/lib/audience.js +6 -11
  74. package/lib/audience.js.map +1 -1
  75. package/lib/catchUpMonitor.d.ts +29 -0
  76. package/lib/catchUpMonitor.d.ts.map +1 -0
  77. package/lib/catchUpMonitor.js +39 -0
  78. package/lib/catchUpMonitor.js.map +1 -0
  79. package/lib/collabWindowTracker.d.ts +1 -1
  80. package/lib/collabWindowTracker.d.ts.map +1 -1
  81. package/lib/collabWindowTracker.js +13 -5
  82. package/lib/collabWindowTracker.js.map +1 -1
  83. package/lib/connectionManager.d.ts +5 -5
  84. package/lib/connectionManager.d.ts.map +1 -1
  85. package/lib/connectionManager.js +44 -25
  86. package/lib/connectionManager.js.map +1 -1
  87. package/lib/connectionState.d.ts +0 -5
  88. package/lib/connectionState.d.ts.map +1 -1
  89. package/lib/connectionState.js +0 -5
  90. package/lib/connectionState.js.map +1 -1
  91. package/lib/connectionStateHandler.d.ts +84 -22
  92. package/lib/connectionStateHandler.d.ts.map +1 -1
  93. package/lib/connectionStateHandler.js +171 -59
  94. package/lib/connectionStateHandler.js.map +1 -1
  95. package/lib/container.d.ts +29 -17
  96. package/lib/container.d.ts.map +1 -1
  97. package/lib/container.js +184 -174
  98. package/lib/container.js.map +1 -1
  99. package/lib/containerContext.d.ts +18 -7
  100. package/lib/containerContext.d.ts.map +1 -1
  101. package/lib/containerContext.js +19 -9
  102. package/lib/containerContext.js.map +1 -1
  103. package/lib/containerStorageAdapter.d.ts +11 -25
  104. package/lib/containerStorageAdapter.d.ts.map +1 -1
  105. package/lib/containerStorageAdapter.js +51 -16
  106. package/lib/containerStorageAdapter.js.map +1 -1
  107. package/lib/contracts.d.ts +5 -5
  108. package/lib/contracts.js.map +1 -1
  109. package/lib/deltaManager.d.ts +4 -1
  110. package/lib/deltaManager.d.ts.map +1 -1
  111. package/lib/deltaManager.js +41 -14
  112. package/lib/deltaManager.js.map +1 -1
  113. package/lib/deltaManagerProxy.d.ts +4 -1
  114. package/lib/deltaManagerProxy.d.ts.map +1 -1
  115. package/lib/deltaQueue.d.ts +9 -2
  116. package/lib/deltaQueue.d.ts.map +1 -1
  117. package/lib/deltaQueue.js +32 -27
  118. package/lib/deltaQueue.js.map +1 -1
  119. package/lib/index.d.ts +1 -0
  120. package/lib/index.d.ts.map +1 -1
  121. package/lib/index.js.map +1 -1
  122. package/lib/loader.d.ts +8 -1
  123. package/lib/loader.d.ts.map +1 -1
  124. package/lib/loader.js +4 -3
  125. package/lib/loader.js.map +1 -1
  126. package/lib/packageVersion.d.ts +1 -1
  127. package/lib/packageVersion.d.ts.map +1 -1
  128. package/lib/packageVersion.js +1 -1
  129. package/lib/packageVersion.js.map +1 -1
  130. package/lib/protocol.d.ts +27 -0
  131. package/lib/protocol.d.ts.map +1 -0
  132. package/lib/protocol.js +75 -0
  133. package/lib/protocol.js.map +1 -0
  134. package/lib/protocolTreeDocumentStorageService.d.ts +1 -1
  135. package/lib/protocolTreeDocumentStorageService.d.ts.map +1 -1
  136. package/lib/retriableDocumentStorageService.d.ts +2 -2
  137. package/lib/retriableDocumentStorageService.d.ts.map +1 -1
  138. package/lib/retriableDocumentStorageService.js +2 -2
  139. package/lib/retriableDocumentStorageService.js.map +1 -1
  140. package/package.json +27 -19
  141. package/src/audience.ts +8 -14
  142. package/src/catchUpMonitor.ts +59 -0
  143. package/src/collabWindowTracker.ts +15 -6
  144. package/src/connectionManager.ts +56 -33
  145. package/src/connectionState.ts +0 -6
  146. package/src/connectionStateHandler.ts +235 -70
  147. package/src/container.ts +241 -218
  148. package/src/containerContext.ts +22 -8
  149. package/src/containerStorageAdapter.ts +71 -16
  150. package/src/contracts.ts +7 -7
  151. package/src/deltaManager.ts +48 -15
  152. package/src/deltaQueue.ts +34 -28
  153. package/src/index.ts +4 -0
  154. package/src/loader.ts +14 -3
  155. package/src/packageVersion.ts +1 -1
  156. package/src/protocol.ts +120 -0
  157. package/src/retriableDocumentStorageService.ts +8 -2
@@ -1 +1 @@
1
- {"version":3,"file":"retriableDocumentStorageService.js","sourceRoot":"","sources":["../src/retriableDocumentStorageService.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert } from \"@fluidframework/common-utils\";\nimport { GenericError } from \"@fluidframework/container-utils\";\nimport {\n IDocumentStorageService,\n IDocumentStorageServicePolicies,\n ISummaryContext,\n} from \"@fluidframework/driver-definitions\";\nimport {\n ICreateBlobResponse,\n ISnapshotTree,\n ISummaryHandle,\n ISummaryTree,\n IVersion,\n} from \"@fluidframework/protocol-definitions\";\nimport { IDisposable, ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { runWithRetry } from \"@fluidframework/driver-utils\";\n\nexport class RetriableDocumentStorageService implements IDocumentStorageService, IDisposable {\n private _disposed = false;\n constructor(\n private readonly internalStorageService: IDocumentStorageService,\n private readonly logger: ITelemetryLogger,\n ) {\n }\n\n public get policies(): IDocumentStorageServicePolicies | undefined {\n return this.internalStorageService.policies;\n }\n public get disposed() { return this._disposed; }\n public dispose() {\n this._disposed = true;\n }\n\n public get repositoryUrl(): string {\n return this.internalStorageService.repositoryUrl;\n }\n\n public async getSnapshotTree(version?: IVersion, scenarioName?: string): Promise<ISnapshotTree | null> {\n return this.runWithRetry(\n async () => this.internalStorageService.getSnapshotTree(version, scenarioName),\n \"storage_getSnapshotTree\",\n );\n }\n\n public async readBlob(id: string): Promise<ArrayBufferLike> {\n return this.runWithRetry(\n async () => this.internalStorageService.readBlob(id),\n \"storage_readBlob\",\n );\n }\n\n public async getVersions(versionId: string | null, count: number, scenarioName?: string): Promise<IVersion[]> {\n return this.runWithRetry(\n async () => this.internalStorageService.getVersions(versionId, count, scenarioName),\n \"storage_getVersions\",\n );\n }\n\n public async uploadSummaryWithContext(summary: ISummaryTree, context: ISummaryContext): Promise<string> {\n // Not using retry loop here. Couple reasons:\n // 1. If client lost connectivity, then retry loop will result in uploading stale summary\n // by stale summarizer after connectivity comes back. It will cause failures for this client and for\n // real (new) summarizer. This problem in particular should be solved in future by supplying abort handle\n // on all APIs and caller (ContainerRuntime.submitSummary) aborting call on loss of connectivity\n // 2. Similar, if we get 429 with retryAfter = 10 minutes, it's likely not the right call to retry summary\n // upload in 10 minutes - it's better to keep processing ops and retry later. Though caller needs to take\n // retryAfter into account!\n // But retry loop is required for creation flow (Container.attach)\n assert((context.referenceSequenceNumber === 0) === (context.ackHandle === undefined),\n 0x251 /* \"creation summary has to have seq=0 && handle === undefined\" */);\n if (context.referenceSequenceNumber !== 0) {\n return this.internalStorageService.uploadSummaryWithContext(summary, context);\n }\n\n // Creation flow with attachment blobs - need to do retries!\n return this.runWithRetry(\n async () => this.internalStorageService.uploadSummaryWithContext(summary, context),\n \"storage_uploadSummaryWithContext\",\n );\n }\n\n public async downloadSummary(handle: ISummaryHandle): Promise<ISummaryTree> {\n return this.runWithRetry(\n async () => this.internalStorageService.downloadSummary(handle),\n \"storage_downloadSummary\",\n );\n }\n\n public async createBlob(file: ArrayBufferLike): Promise<ICreateBlobResponse> {\n return this.runWithRetry(\n async () => this.internalStorageService.createBlob(file),\n \"storage_createBlob\",\n );\n }\n\n private checkStorageDisposed() {\n if (this._disposed) {\n // pre-0.58 error message: storageServiceDisposedCannotRetry\n throw new GenericError(\"Storage Service is disposed. Cannot retry\", { canRetry: false });\n }\n return undefined;\n }\n\n private async runWithRetry<T>(api: () => Promise<T>, callName: string): Promise<T> {\n return runWithRetry(\n api,\n callName,\n this.logger,\n {\n onRetry: () => this.checkStorageDisposed(),\n },\n );\n }\n}\n"]}
1
+ {"version":3,"file":"retriableDocumentStorageService.js","sourceRoot":"","sources":["../src/retriableDocumentStorageService.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert } from \"@fluidframework/common-utils\";\nimport { GenericError } from \"@fluidframework/container-utils\";\nimport {\n FetchSource,\n IDocumentStorageService,\n IDocumentStorageServicePolicies,\n ISummaryContext,\n} from \"@fluidframework/driver-definitions\";\nimport {\n ICreateBlobResponse,\n ISnapshotTree,\n ISummaryHandle,\n ISummaryTree,\n IVersion,\n} from \"@fluidframework/protocol-definitions\";\nimport { IDisposable, ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { runWithRetry } from \"@fluidframework/driver-utils\";\n\nexport class RetriableDocumentStorageService implements IDocumentStorageService, IDisposable {\n private _disposed = false;\n constructor(\n private readonly internalStorageService: IDocumentStorageService,\n private readonly logger: ITelemetryLogger,\n ) {\n }\n\n public get policies(): IDocumentStorageServicePolicies | undefined {\n return this.internalStorageService.policies;\n }\n public get disposed() { return this._disposed; }\n public dispose() {\n this._disposed = true;\n }\n\n public get repositoryUrl(): string {\n return this.internalStorageService.repositoryUrl;\n }\n\n public async getSnapshotTree(version?: IVersion, scenarioName?: string): Promise<ISnapshotTree | null> {\n return this.runWithRetry(\n async () => this.internalStorageService.getSnapshotTree(version, scenarioName),\n \"storage_getSnapshotTree\",\n );\n }\n\n public async readBlob(id: string): Promise<ArrayBufferLike> {\n return this.runWithRetry(\n async () => this.internalStorageService.readBlob(id),\n \"storage_readBlob\",\n );\n }\n\n public async getVersions(\n versionId: string | null,\n count: number,\n scenarioName?: string,\n fetchSource?: FetchSource,\n ): Promise<IVersion[]> {\n return this.runWithRetry(\n async () => this.internalStorageService.getVersions(versionId, count, scenarioName, fetchSource),\n \"storage_getVersions\",\n );\n }\n\n public async uploadSummaryWithContext(summary: ISummaryTree, context: ISummaryContext): Promise<string> {\n // Not using retry loop here. Couple reasons:\n // 1. If client lost connectivity, then retry loop will result in uploading stale summary\n // by stale summarizer after connectivity comes back. It will cause failures for this client and for\n // real (new) summarizer. This problem in particular should be solved in future by supplying abort handle\n // on all APIs and caller (ContainerRuntime.submitSummary) aborting call on loss of connectivity\n // 2. Similar, if we get 429 with retryAfter = 10 minutes, it's likely not the right call to retry summary\n // upload in 10 minutes - it's better to keep processing ops and retry later. Though caller needs to take\n // retryAfter into account!\n // But retry loop is required for creation flow (Container.attach)\n assert((context.referenceSequenceNumber === 0) === (context.ackHandle === undefined),\n 0x251 /* \"creation summary has to have seq=0 && handle === undefined\" */);\n if (context.referenceSequenceNumber !== 0) {\n return this.internalStorageService.uploadSummaryWithContext(summary, context);\n }\n\n // Creation flow with attachment blobs - need to do retries!\n return this.runWithRetry(\n async () => this.internalStorageService.uploadSummaryWithContext(summary, context),\n \"storage_uploadSummaryWithContext\",\n );\n }\n\n public async downloadSummary(handle: ISummaryHandle): Promise<ISummaryTree> {\n return this.runWithRetry(\n async () => this.internalStorageService.downloadSummary(handle),\n \"storage_downloadSummary\",\n );\n }\n\n public async createBlob(file: ArrayBufferLike): Promise<ICreateBlobResponse> {\n return this.runWithRetry(\n async () => this.internalStorageService.createBlob(file),\n \"storage_createBlob\",\n );\n }\n\n private checkStorageDisposed() {\n if (this._disposed) {\n // pre-0.58 error message: storageServiceDisposedCannotRetry\n throw new GenericError(\"Storage Service is disposed. Cannot retry\", { canRetry: false });\n }\n return undefined;\n }\n\n private async runWithRetry<T>(api: () => Promise<T>, callName: string): Promise<T> {\n return runWithRetry(\n api,\n callName,\n this.logger,\n {\n onRetry: () => this.checkStorageDisposed(),\n },\n );\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/container-loader",
3
- "version": "1.2.6",
3
+ "version": "2.0.0-dev.1.3.0.96595",
4
4
  "description": "Fluid container loader",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -62,27 +62,28 @@
62
62
  },
63
63
  "dependencies": {
64
64
  "@fluidframework/common-definitions": "^0.20.1",
65
- "@fluidframework/common-utils": "^0.32.1",
66
- "@fluidframework/container-definitions": "^1.2.6",
67
- "@fluidframework/container-utils": "^1.2.6",
68
- "@fluidframework/core-interfaces": "^1.2.6",
69
- "@fluidframework/driver-definitions": "^1.2.6",
70
- "@fluidframework/driver-utils": "^1.2.6",
71
- "@fluidframework/protocol-base": "^0.1036.5000",
72
- "@fluidframework/protocol-definitions": "^0.1028.2000",
73
- "@fluidframework/telemetry-utils": "^1.2.6",
65
+ "@fluidframework/common-utils": "^1.0.0",
66
+ "@fluidframework/container-definitions": "2.0.0-dev.1.3.0.96595",
67
+ "@fluidframework/container-utils": "2.0.0-dev.1.3.0.96595",
68
+ "@fluidframework/core-interfaces": "2.0.0-dev.1.3.0.96595",
69
+ "@fluidframework/driver-definitions": "2.0.0-dev.1.3.0.96595",
70
+ "@fluidframework/driver-utils": "2.0.0-dev.1.3.0.96595",
71
+ "@fluidframework/protocol-base": "^0.1037.2001",
72
+ "@fluidframework/protocol-definitions": "^1.0.0",
73
+ "@fluidframework/telemetry-utils": "2.0.0-dev.1.3.0.96595",
74
74
  "abort-controller": "^3.0.0",
75
75
  "double-ended-queue": "^2.1.0-0",
76
76
  "lodash": "^4.17.21",
77
+ "url": "^0.11.0",
77
78
  "uuid": "^8.3.1"
78
79
  },
79
80
  "devDependencies": {
80
- "@fluidframework/build-common": "^0.24.0",
81
- "@fluidframework/build-tools": "^0.2.74327",
82
- "@fluidframework/container-loader-previous": "npm:@fluidframework/container-loader@1.2.1",
83
- "@fluidframework/eslint-config-fluid": "^0.28.2000",
84
- "@fluidframework/mocha-test-setup": "^1.2.6",
85
- "@fluidframework/test-loader-utils": "^1.2.6",
81
+ "@fluidframework/build-common": "^1.0.0",
82
+ "@fluidframework/build-tools": "^0.4.6000",
83
+ "@fluidframework/container-loader-previous": "npm:@fluidframework/container-loader@^1.0.0",
84
+ "@fluidframework/eslint-config-fluid": "^1.0.0",
85
+ "@fluidframework/mocha-test-setup": "2.0.0-dev.1.3.0.96595",
86
+ "@fluidframework/test-loader-utils": "2.0.0-dev.1.3.0.96595",
86
87
  "@microsoft/api-extractor": "^7.22.2",
87
88
  "@rushstack/eslint-config": "^2.5.1",
88
89
  "@types/double-ended-queue": "^2.1.0",
@@ -91,7 +92,7 @@
91
92
  "@types/node": "^14.18.0",
92
93
  "@types/sinon": "^7.0.13",
93
94
  "concurrently": "^6.2.0",
94
- "copyfiles": "^2.1.0",
95
+ "copyfiles": "^2.4.1",
95
96
  "cross-env": "^7.0.2",
96
97
  "eslint": "~8.6.0",
97
98
  "mocha": "^10.0.0",
@@ -102,7 +103,14 @@
102
103
  "typescript-formatter": "7.1.0"
103
104
  },
104
105
  "typeValidation": {
105
- "version": "1.2.2",
106
- "broken": {}
106
+ "version": "2.0.0",
107
+ "broken": {
108
+ "EnumDeclaration_ConnectionState": {
109
+ "forwardCompat": false
110
+ },
111
+ "ClassDeclaration_Container": {
112
+ "forwardCompat": false
113
+ }
114
+ }
107
115
  }
108
116
  }
package/src/audience.ts CHANGED
@@ -3,13 +3,13 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
  import { EventEmitter } from "events";
6
- import { IAudience } from "@fluidframework/container-definitions";
6
+ import { IAudienceOwner } from "@fluidframework/container-definitions";
7
7
  import { IClient } from "@fluidframework/protocol-definitions";
8
8
 
9
9
  /**
10
10
  * Audience represents all clients connected to the op stream.
11
11
  */
12
- export class Audience extends EventEmitter implements IAudience {
12
+ export class Audience extends EventEmitter implements IAudienceOwner {
13
13
  private readonly members = new Map<string, IClient>();
14
14
 
15
15
  public on(event: "addMember" | "removeMember", listener: (clientId: string, client: IClient) => void): this;
@@ -21,8 +21,12 @@ export class Audience extends EventEmitter implements IAudience {
21
21
  * Adds a new client to the audience
22
22
  */
23
23
  public addMember(clientId: string, details: IClient) {
24
- this.members.set(clientId, details);
25
- this.emit("addMember", clientId, details);
24
+ // Given that signal delivery is unreliable process, we might observe same client being added twice
25
+ // In such case we should see exactly same payload (IClient), and should not raise event twice!
26
+ if (!this.members.has(clientId)) {
27
+ this.members.set(clientId, details);
28
+ this.emit("addMember", clientId, details);
29
+ }
26
30
  }
27
31
 
28
32
  /**
@@ -53,14 +57,4 @@ export class Audience extends EventEmitter implements IAudience {
53
57
  public getMember(clientId: string): IClient | undefined {
54
58
  return this.members.get(clientId);
55
59
  }
56
-
57
- /**
58
- * Clears the audience
59
- */
60
- public clear(): void {
61
- const clientIds = this.members.keys();
62
- for (const clientId of clientIds) {
63
- this.removeMember(clientId);
64
- }
65
- }
66
60
  }
@@ -0,0 +1,59 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import { IDisposable } from "@fluidframework/common-definitions";
7
+ import { assert } from "@fluidframework/common-utils";
8
+ import { IDeltaManager } from "@fluidframework/container-definitions";
9
+ import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
10
+
11
+ /** @see CatchUpMonitor for usage */
12
+ type CaughtUpListener = () => void;
13
+
14
+ /** Monitor that emits an event when a Container has caught up to a given point in the op stream */
15
+ export type ICatchUpMonitor = IDisposable;
16
+
17
+ /**
18
+ * Monitors a Container's DeltaManager, notifying listeners when all ops have been processed
19
+ * that were known at the time the monitor was created.
20
+ */
21
+ export class CatchUpMonitor implements ICatchUpMonitor {
22
+ private readonly targetSeqNumber: number;
23
+ private caughtUp: boolean = false;
24
+
25
+ private readonly opHandler = (message: Pick<ISequencedDocumentMessage, "sequenceNumber">) => {
26
+ if (!this.caughtUp && message.sequenceNumber >= this.targetSeqNumber) {
27
+ this.caughtUp = true;
28
+ this.listener();
29
+ }
30
+ };
31
+
32
+ /**
33
+ * Create the CatchUpMonitor, setting the target sequence number to wait for based on DeltaManager's current state.
34
+ */
35
+ constructor(
36
+ private readonly deltaManager: IDeltaManager<any, any>,
37
+ private readonly listener: CaughtUpListener,
38
+ ) {
39
+ this.targetSeqNumber = this.deltaManager.lastKnownSeqNumber;
40
+
41
+ assert(this.targetSeqNumber >= this.deltaManager.lastSequenceNumber,
42
+ 0x37c /* Cannot wait for seqNumber below last processed sequence number */);
43
+
44
+ this.deltaManager.on("op", this.opHandler);
45
+
46
+ // Simulate the last processed op to set caughtUp in case we already are
47
+ this.opHandler({ sequenceNumber: this.deltaManager.lastSequenceNumber });
48
+ }
49
+
50
+ public disposed: boolean = false;
51
+ public dispose() {
52
+ if (this.disposed) {
53
+ return;
54
+ }
55
+ this.disposed = true;
56
+
57
+ this.deltaManager.off("op", this.opHandler);
58
+ }
59
+ }
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { assert, Timer } from "@fluidframework/common-utils";
7
7
  import { ISequencedDocumentMessage, MessageType } from "@fluidframework/protocol-definitions";
8
- import { isRuntimeMessage } from "@fluidframework/driver-utils";
8
+ import { isRuntimeMessage, MessageType2 } from "@fluidframework/driver-utils";
9
9
 
10
10
  const defaultNoopTimeFrequency = 2000;
11
11
  const defaultNoopCountFrequency = 50;
@@ -34,7 +34,7 @@ export class CollabWindowTracker {
34
34
  private readonly timer: Timer | undefined;
35
35
 
36
36
  constructor(
37
- private readonly submit: (type: MessageType, contents: any) => void,
37
+ private readonly submit: (type: MessageType) => void,
38
38
  NoopTimeFrequency: number = defaultNoopTimeFrequency,
39
39
  private readonly NoopCountFrequency: number = defaultNoopCountFrequency,
40
40
  ) {
@@ -69,9 +69,17 @@ export class CollabWindowTracker {
69
69
  }
70
70
 
71
71
  this.opsCountSinceNoop++;
72
- if (this.opsCountSinceNoop >= this.NoopCountFrequency) {
73
- this.submitNoop(false /* immediate */);
74
- return;
72
+ if (this.opsCountSinceNoop === this.NoopCountFrequency) {
73
+ // Ensure we only send noop after a batch of many ops is processed
74
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
75
+ Promise.resolve().then(() => {
76
+ assert(this.opsCountSinceNoop >= this.NoopCountFrequency,
77
+ 0x3ae /* not enough ops were sent to reach the noop frequency */);
78
+ this.submitNoop(false /* immediate */);
79
+ // reset count now that all ops are processed
80
+ this.opsCountSinceNoop = 0;
81
+ return;
82
+ });
75
83
  }
76
84
 
77
85
  if (this.timer !== undefined) {
@@ -85,7 +93,8 @@ export class CollabWindowTracker {
85
93
 
86
94
  private submitNoop(immediate: boolean) {
87
95
  // Anything other than null is immediate noop
88
- this.submit(MessageType.NoOp, immediate ? "" : null);
96
+ // ADO:1385: Remove cast and use MessageType once definition changes propagate
97
+ this.submit(immediate ? (MessageType2.Accept as unknown as MessageType) : MessageType.NoOp);
89
98
  assert(this.opsCountSinceNoop === 0,
90
99
  0x243 /* "stopSequenceNumberUpdate should be called as result of sending any op!" */);
91
100
  }
@@ -31,7 +31,7 @@ import {
31
31
  waitForConnectedState,
32
32
  DeltaStreamConnectionForbiddenError,
33
33
  logNetworkFailure,
34
- // isRuntimeMessage,
34
+ isRuntimeMessage,
35
35
  } from "@fluidframework/driver-utils";
36
36
  import {
37
37
  ConnectionMode,
@@ -59,6 +59,7 @@ import {
59
59
  IConnectionManagerFactoryArgs,
60
60
  } from "./contracts";
61
61
  import { DeltaQueue } from "./deltaQueue";
62
+ import { SignalType } from "./protocol";
62
63
 
63
64
  const MaxReconnectDelayInMs = 8000;
64
65
  const InitialReconnectDelayInMs = 1000;
@@ -97,7 +98,6 @@ class NoDeltaStream
97
98
  serviceConfiguration: IClientConfiguration = {
98
99
  maxMessageSize: 0,
99
100
  blockSize: 0,
100
- summary: undefined as any,
101
101
  };
102
102
  checkpointSequenceNumber?: number | undefined = undefined;
103
103
  submit(messages: IDocumentMessage[]): void {
@@ -137,8 +137,8 @@ interface IPendingConnection {
137
137
 
138
138
  /**
139
139
  * Implementation of IConnectionManager, used by Container class
140
- * Implements constant connectivity to relay service, by reconnecting in case of loast connection or error.
141
- * Exposes various controls to influecen this process, including manual reconnects, forced read-only mode, etc.
140
+ * Implements constant connectivity to relay service, by reconnecting in case of lost connection or error.
141
+ * Exposes various controls to influence this process, including manual reconnects, forced read-only mode, etc.
142
142
  */
143
143
  export class ConnectionManager implements IConnectionManager {
144
144
  /** Connection mode used when reconnecting on error or disconnect. */
@@ -169,7 +169,7 @@ export class ConnectionManager implements IConnectionManager {
169
169
  private clientSequenceNumber = 0;
170
170
  private clientSequenceNumberObserved = 0;
171
171
  /** Counts the number of noops sent by the client which may not be acked. */
172
- private trailingNoopCount = 0;
172
+ private localOpsToIgnore = 0;
173
173
 
174
174
  /** track clientId used last time when we sent any ops */
175
175
  private lastSubmittedClientId: string | undefined;
@@ -202,7 +202,7 @@ export class ConnectionManager implements IConnectionManager {
202
202
  * Automatic reconnecting enabled or disabled.
203
203
  * If set to Never, then reconnecting will never be allowed.
204
204
  */
205
- public get reconnectMode(): ReconnectMode {
205
+ public get reconnectMode(): ReconnectMode {
206
206
  return this._reconnectMode;
207
207
  }
208
208
 
@@ -234,21 +234,19 @@ export class ConnectionManager implements IConnectionManager {
234
234
  * Returns set of props that can be logged in telemetry that provide some insights / statistics
235
235
  * about current or last connection (if there is no connection at the moment)
236
236
  */
237
- public get connectionProps(): ITelemetryProperties {
238
- if (this.connection !== undefined) {
239
- return this._connectionProps;
240
- } else {
241
- return {
237
+ public get connectionProps(): ITelemetryProperties {
238
+ return this.connection !== undefined
239
+ ? this._connectionProps
240
+ : {
242
241
  ...this._connectionProps,
243
242
  // Report how many ops this client sent in last disconnected session
244
243
  sentOps: this.clientSequenceNumber,
245
244
  };
246
- }
247
245
  }
248
246
 
249
247
  public shouldJoinWrite(): boolean {
250
248
  // We don't have to wait for ack for topmost NoOps. So subtract those.
251
- return this.clientSequenceNumberObserved < (this.clientSequenceNumber - this.trailingNoopCount);
249
+ return this.clientSequenceNumberObserved < (this.clientSequenceNumber - this.localOpsToIgnore);
252
250
  }
253
251
 
254
252
  /**
@@ -379,7 +377,7 @@ export class ConnectionManager implements IConnectionManager {
379
377
  *
380
378
  * @param readonly - set or clear force readonly.
381
379
  */
382
- public forceReadonly(readonly: boolean) {
380
+ public forceReadonly(readonly: boolean) {
383
381
  if (readonly !== this._forceReadonly) {
384
382
  this.logger.sendTelemetryEvent({
385
383
  eventName: "ForceReadOnly",
@@ -568,11 +566,11 @@ export class ConnectionManager implements IConnectionManager {
568
566
  }
569
567
 
570
568
  /**
571
- * Start the connection. Any error should result in container being close.
572
- * And report the error if it excape for any reason.
569
+ * Start the connection. Any error should result in container being closed.
570
+ * And report the error if it escapes for any reason.
573
571
  * @param args - The connection arguments
574
572
  */
575
- private triggerConnect(connectionMode: ConnectionMode) {
573
+ private triggerConnect(connectionMode: ConnectionMode) {
576
574
  assert(this.connection === undefined, 0x239 /* "called only in disconnected state" */);
577
575
  if (this.reconnectMode !== ReconnectMode.Enabled) {
578
576
  return;
@@ -585,7 +583,7 @@ export class ConnectionManager implements IConnectionManager {
585
583
  * @param reason - Text description of disconnect reason to emit with disconnect event
586
584
  * @returns A boolean that indicates if there was an existing connection (or pending connection) to disconnect
587
585
  */
588
- private disconnectFromDeltaStream(reason: string): boolean {
586
+ private disconnectFromDeltaStream(reason: string): boolean {
589
587
  this.pendingReconnect = false;
590
588
 
591
589
  if (this.connection === undefined) {
@@ -638,7 +636,7 @@ export class ConnectionManager implements IConnectionManager {
638
636
  * initial messages.
639
637
  * @param connection - The newly established connection
640
638
  */
641
- private setupNewSuccessfulConnection(connection: IDocumentDeltaConnection, requestedMode: ConnectionMode) {
639
+ private setupNewSuccessfulConnection(connection: IDocumentDeltaConnection, requestedMode: ConnectionMode) {
642
640
  // Old connection should have been cleaned up before establishing a new one
643
641
  assert(this.connection === undefined, 0x0e6 /* "old connection exists on new connection setup" */);
644
642
  assert(!connection.disposed, 0x28a /* "can't be disposed - Callers need to ensure that!" */);
@@ -716,17 +714,43 @@ export class ConnectionManager implements IConnectionManager {
716
714
  initialMessages,
717
715
  this.connectFirstConnection ? "InitialOps" : "ReconnectOps");
718
716
 
719
- if (connection.initialSignals !== undefined) {
720
- for (const signal of connection.initialSignals) {
721
- this.props.signalHandler(signal);
722
- }
723
- }
724
-
725
717
  const details = ConnectionManager.detailsFromConnection(connection);
726
718
  details.checkpointSequenceNumber = checkpointSequenceNumber;
727
719
  this.props.connectHandler(details);
728
720
 
729
721
  this.connectFirstConnection = false;
722
+
723
+ // Synthesize clear & join signals out of initialClients state.
724
+ // This allows us to have single way to process signals, and makes it simpler to initialize
725
+ // protocol in Container.
726
+ const clearSignal: ISignalMessage = {
727
+ clientId: null, // system message
728
+ content: JSON.stringify({
729
+ type: SignalType.Clear,
730
+ }),
731
+ };
732
+ this.props.signalHandler(clearSignal);
733
+
734
+ for (const priorClient of connection.initialClients ?? []) {
735
+ const joinSignal: ISignalMessage = {
736
+ clientId: null, // system signal
737
+ content: JSON.stringify({
738
+ type: SignalType.ClientJoin,
739
+ content: priorClient, // ISignalClient
740
+ }),
741
+ };
742
+ this.props.signalHandler(joinSignal);
743
+ }
744
+
745
+ // Unfortunately, there is no defined order between initialSignals (including join & leave signals)
746
+ // and connection.initialClients. In practice, connection.initialSignals quite often contains join signal
747
+ // for "self" and connection.initialClients does not contain "self", so we have to process them after
748
+ // "clear" signal above.
749
+ if (connection.initialSignals !== undefined) {
750
+ for (const signal of connection.initialSignals) {
751
+ this.props.signalHandler(signal);
752
+ }
753
+ }
730
754
  }
731
755
 
732
756
  /**
@@ -736,7 +760,7 @@ export class ConnectionManager implements IConnectionManager {
736
760
  * @param error - Error reconnect information including whether or not to reconnect
737
761
  * @returns A promise that resolves when the connection is reestablished or we stop trying
738
762
  */
739
- private reconnectOnError(
763
+ private reconnectOnError(
740
764
  requestedMode: ConnectionMode,
741
765
  error: IAnyDriverError,
742
766
  ) {
@@ -744,7 +768,7 @@ export class ConnectionManager implements IConnectionManager {
744
768
  requestedMode,
745
769
  error.message,
746
770
  error)
747
- .catch(this.props.closeHandler);
771
+ .catch(this.props.closeHandler);
748
772
  }
749
773
 
750
774
  /**
@@ -773,7 +797,7 @@ export class ConnectionManager implements IConnectionManager {
773
797
  this.logger.sendTelemetryEvent({
774
798
  eventName: "reconnectingDespiteFatalError",
775
799
  reconnectMode: this.reconnectMode,
776
- }, error);
800
+ }, error);
777
801
  }
778
802
 
779
803
  if (this.reconnectMode === ReconnectMode.Never) {
@@ -820,10 +844,10 @@ export class ConnectionManager implements IConnectionManager {
820
844
  this.clientSequenceNumberObserved = 0;
821
845
  }
822
846
 
823
- if (message.type === MessageType.NoOp) {
824
- this.trailingNoopCount++;
847
+ if (!isRuntimeMessage(message)) {
848
+ this.localOpsToIgnore++;
825
849
  } else {
826
- this.trailingNoopCount = 0;
850
+ this.localOpsToIgnore = 0;
827
851
  }
828
852
 
829
853
  return {
@@ -858,8 +882,7 @@ export class ConnectionManager implements IConnectionManager {
858
882
  "Switch to write", // message
859
883
  );
860
884
  }
861
- })
862
- .catch(() => {});
885
+ }).catch(() => { });
863
886
  }
864
887
  return;
865
888
  }
@@ -17,12 +17,6 @@ export enum ConnectionState {
17
17
  */
18
18
  EstablishingConnection = 3,
19
19
 
20
- /**
21
- * See {@link ConnectionState.CatchingUp}, which is the new name for this state.
22
- * @deprecated - This state itself is not gone, just being renamed. Please use {@link ConnectionState.CatchingUp}.
23
- */
24
- Connecting = 1,
25
-
26
20
  /**
27
21
  * The container has an inbound connection only, and is catching up to the latest known state from the service.
28
22
  */