@fluidframework/container-loader 2.0.0-internal.5.1.1 → 2.0.0-internal.5.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 (93) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/catchUpMonitor.d.ts +1 -1
  3. package/dist/catchUpMonitor.d.ts.map +1 -1
  4. package/dist/catchUpMonitor.js.map +1 -1
  5. package/dist/connectionManager.d.ts.map +1 -1
  6. package/dist/connectionManager.js.map +1 -1
  7. package/dist/connectionStateHandler.d.ts +3 -0
  8. package/dist/connectionStateHandler.d.ts.map +1 -1
  9. package/dist/connectionStateHandler.js +10 -8
  10. package/dist/connectionStateHandler.js.map +1 -1
  11. package/dist/container.d.ts +20 -27
  12. package/dist/container.d.ts.map +1 -1
  13. package/dist/container.js +164 -104
  14. package/dist/container.js.map +1 -1
  15. package/dist/containerContext.d.ts +22 -58
  16. package/dist/containerContext.d.ts.map +1 -1
  17. package/dist/containerContext.js +27 -200
  18. package/dist/containerContext.js.map +1 -1
  19. package/dist/containerStorageAdapter.d.ts +1 -1
  20. package/dist/containerStorageAdapter.d.ts.map +1 -1
  21. package/dist/containerStorageAdapter.js.map +1 -1
  22. package/dist/noopHeuristic.d.ts +23 -0
  23. package/dist/noopHeuristic.d.ts.map +1 -0
  24. package/dist/{collabWindowTracker.js → noopHeuristic.js} +30 -42
  25. package/dist/noopHeuristic.js.map +1 -0
  26. package/dist/packageVersion.d.ts +1 -1
  27. package/dist/packageVersion.js +1 -1
  28. package/dist/packageVersion.js.map +1 -1
  29. package/dist/protocol.d.ts +1 -12
  30. package/dist/protocol.d.ts.map +1 -1
  31. package/dist/protocol.js +0 -18
  32. package/dist/protocol.js.map +1 -1
  33. package/dist/protocolTreeDocumentStorageService.d.ts +1 -1
  34. package/dist/protocolTreeDocumentStorageService.d.ts.map +1 -1
  35. package/dist/protocolTreeDocumentStorageService.js.map +1 -1
  36. package/dist/retriableDocumentStorageService.d.ts +1 -1
  37. package/dist/retriableDocumentStorageService.d.ts.map +1 -1
  38. package/dist/retriableDocumentStorageService.js.map +1 -1
  39. package/lib/catchUpMonitor.d.ts +1 -1
  40. package/lib/catchUpMonitor.d.ts.map +1 -1
  41. package/lib/catchUpMonitor.js.map +1 -1
  42. package/lib/connectionManager.d.ts.map +1 -1
  43. package/lib/connectionManager.js.map +1 -1
  44. package/lib/connectionStateHandler.d.ts +3 -0
  45. package/lib/connectionStateHandler.d.ts.map +1 -1
  46. package/lib/connectionStateHandler.js +10 -8
  47. package/lib/connectionStateHandler.js.map +1 -1
  48. package/lib/container.d.ts +20 -27
  49. package/lib/container.d.ts.map +1 -1
  50. package/lib/container.js +166 -106
  51. package/lib/container.js.map +1 -1
  52. package/lib/containerContext.d.ts +22 -58
  53. package/lib/containerContext.d.ts.map +1 -1
  54. package/lib/containerContext.js +27 -200
  55. package/lib/containerContext.js.map +1 -1
  56. package/lib/containerStorageAdapter.d.ts +1 -1
  57. package/lib/containerStorageAdapter.d.ts.map +1 -1
  58. package/lib/containerStorageAdapter.js.map +1 -1
  59. package/lib/noopHeuristic.d.ts +23 -0
  60. package/lib/noopHeuristic.d.ts.map +1 -0
  61. package/lib/{collabWindowTracker.js → noopHeuristic.js} +30 -42
  62. package/lib/noopHeuristic.js.map +1 -0
  63. package/lib/packageVersion.d.ts +1 -1
  64. package/lib/packageVersion.js +1 -1
  65. package/lib/packageVersion.js.map +1 -1
  66. package/lib/protocol.d.ts +1 -12
  67. package/lib/protocol.d.ts.map +1 -1
  68. package/lib/protocol.js +0 -18
  69. package/lib/protocol.js.map +1 -1
  70. package/lib/protocolTreeDocumentStorageService.d.ts +1 -1
  71. package/lib/protocolTreeDocumentStorageService.d.ts.map +1 -1
  72. package/lib/protocolTreeDocumentStorageService.js.map +1 -1
  73. package/lib/retriableDocumentStorageService.d.ts +1 -1
  74. package/lib/retriableDocumentStorageService.d.ts.map +1 -1
  75. package/lib/retriableDocumentStorageService.js.map +1 -1
  76. package/package.json +11 -11
  77. package/src/catchUpMonitor.ts +1 -1
  78. package/src/connectionManager.ts +2 -1
  79. package/src/connectionStateHandler.ts +14 -9
  80. package/src/container.ts +247 -126
  81. package/src/containerContext.ts +32 -318
  82. package/src/containerStorageAdapter.ts +1 -1
  83. package/src/{collabWindowTracker.ts → noopHeuristic.ts} +37 -47
  84. package/src/packageVersion.ts +1 -1
  85. package/src/protocol.ts +0 -39
  86. package/src/protocolTreeDocumentStorageService.ts +1 -1
  87. package/src/retriableDocumentStorageService.ts +2 -1
  88. package/dist/collabWindowTracker.d.ts +0 -19
  89. package/dist/collabWindowTracker.d.ts.map +0 -1
  90. package/dist/collabWindowTracker.js.map +0 -1
  91. package/lib/collabWindowTracker.d.ts +0 -19
  92. package/lib/collabWindowTracker.d.ts.map +0 -1
  93. package/lib/collabWindowTracker.js.map +0 -1
@@ -1,19 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
- import { ISequencedDocumentMessage, MessageType } from "@fluidframework/protocol-definitions";
6
- export declare class CollabWindowTracker {
7
- private readonly submit;
8
- private readonly NoopCountFrequency;
9
- private opsCountSinceNoop;
10
- private readonly timer;
11
- constructor(submit: (type: MessageType) => void, NoopTimeFrequency?: number, NoopCountFrequency?: number);
12
- /**
13
- * Schedules as ack to the server to update the reference sequence number
14
- */
15
- scheduleSequenceNumberUpdate(message: ISequencedDocumentMessage, immediateNoOp: boolean): void;
16
- private submitNoop;
17
- stopSequenceNumberUpdate(): void;
18
- }
19
- //# sourceMappingURL=collabWindowTracker.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"collabWindowTracker.d.ts","sourceRoot":"","sources":["../src/collabWindowTracker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,yBAAyB,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AAyB9F,qBAAa,mBAAmB;IAK9B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAEvB,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IANpC,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoB;gBAGxB,MAAM,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,EACpD,iBAAiB,GAAE,MAAiC,EACnC,kBAAkB,GAAE,MAAkC;IAaxE;;OAEG;IACI,4BAA4B,CAClC,OAAO,EAAE,yBAAyB,EAClC,aAAa,EAAE,OAAO,GACpB,IAAI;IAuCP,OAAO,CAAC,UAAU;IAUX,wBAAwB,IAAI,IAAI;CASvC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"collabWindowTracker.js","sourceRoot":"","sources":["../src/collabWindowTracker.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, Timer } from \"@fluidframework/common-utils\";\nimport { ISequencedDocumentMessage, MessageType } from \"@fluidframework/protocol-definitions\";\nimport { isRuntimeMessage, MessageType2 } from \"@fluidframework/driver-utils\";\n\nconst defaultNoopTimeFrequency = 2000;\nconst defaultNoopCountFrequency = 50;\n\n// Here are key considerations when deciding conditions for when to send non-immediate noops:\n// 1. Sending them too often results in increase in file size and bandwidth, as well as catch up performance\n// 2. Sending too infrequently ensures that collab window is large, and as result Sequence DDS would have\n// large catchUp blobs - see Issue #6364\n// 3. Similarly, processes that rely on \"core\" snapshot (and can't parse trailing ops, including above), like search\n// parser in SPO, will result in non-accurate results due to presence of catch up blobs.\n// 4. Ordering service used 250ms timeout to coalesce non-immediate noops. It was changed to 2000 ms to allow more\n// aggressive noop sending from client side.\n// 5. Number of ops sent by all clients is proportional to number of \"write\" clients (every client sends noops),\n// but number of sequenced noops is a function of time (one op per 2 seconds at most).\n// We should consider impact to both outbound traffic (might be huge, depends on number of clients) and file size.\n// Please also see Issue #5629 for more discussions.\n//\n// With that, the current algorithm is as follows:\n// 1. Sent noop 2000 ms of receiving an op if no ops were sent by this client within this timeframe.\n// This will ensure that MSN moves forward with reasonable speed. If that results in too many sequenced noops,\n// server timeout of 2000ms should be reconsidered to be increased.\n// 2. If there are more than 50 ops received without sending any ops, send noop to keep collab window small.\n// Note that system ops (including noops themselves) are excluded, so it's 1 noop per 50 real ops.\nexport class CollabWindowTracker {\n\tprivate opsCountSinceNoop = 0;\n\tprivate readonly timer: Timer | undefined;\n\n\tconstructor(\n\t\tprivate readonly submit: (type: MessageType) => void,\n\t\tNoopTimeFrequency: number = defaultNoopTimeFrequency,\n\t\tprivate readonly NoopCountFrequency: number = defaultNoopCountFrequency,\n\t) {\n\t\tif (NoopTimeFrequency !== Infinity) {\n\t\t\tthis.timer = new Timer(NoopTimeFrequency, () => {\n\t\t\t\t// Can get here due to this.stopSequenceNumberUpdate() not resetting timer.\n\t\t\t\t// Also timer callback can fire even after timer cancellation if it was queued before cancellation.\n\t\t\t\tif (this.opsCountSinceNoop !== 0) {\n\t\t\t\t\tthis.submitNoop(false /* immediate */);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Schedules as ack to the server to update the reference sequence number\n\t */\n\tpublic scheduleSequenceNumberUpdate(\n\t\tmessage: ISequencedDocumentMessage,\n\t\timmediateNoOp: boolean,\n\t): void {\n\t\t// While processing a message, an immediate no-op can be requested.\n\t\t// i.e. to expedite approve or commit phase of quorum.\n\t\tif (immediateNoOp) {\n\t\t\tthis.submitNoop(true /* immediate */);\n\t\t\treturn;\n\t\t}\n\n\t\t// We don't acknowledge no-ops to avoid acknowledgement cycles (i.e. ack the MSN\n\t\t// update, which updates the MSN, then ack the update, etc...).\n\t\t// Intent here is for runtime (and DDSes) not to keep too much tracking state / memory\n\t\t// due to runtime ops from other clients.\n\t\tif (!isRuntimeMessage(message)) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.opsCountSinceNoop++;\n\t\tif (this.opsCountSinceNoop === this.NoopCountFrequency) {\n\t\t\t// Ensure we only send noop after a batch of many ops is processed\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-floating-promises\n\t\t\tPromise.resolve().then(() => {\n\t\t\t\tif (this.opsCountSinceNoop >= this.NoopCountFrequency) {\n\t\t\t\t\tthis.submitNoop(false /* immediate */);\n\t\t\t\t\t// reset count now that all ops are processed\n\t\t\t\t\tthis.opsCountSinceNoop = 0;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t});\n\t\t}\n\n\t\tif (this.timer !== undefined) {\n\t\t\tif (this.opsCountSinceNoop === 1) {\n\t\t\t\tthis.timer.restart();\n\t\t\t}\n\n\t\t\tassert(this.timer.hasTimer, 0x242 /* \"has timer\" */);\n\t\t}\n\t}\n\n\tprivate submitNoop(immediate: boolean) {\n\t\t// Anything other than null is immediate noop\n\t\t// ADO:1385: Remove cast and use MessageType once definition changes propagate\n\t\tthis.submit(immediate ? (MessageType2.Accept as unknown as MessageType) : MessageType.NoOp);\n\t\tassert(\n\t\t\tthis.opsCountSinceNoop === 0,\n\t\t\t0x243 /* \"stopSequenceNumberUpdate should be called as result of sending any op!\" */,\n\t\t);\n\t}\n\n\tpublic stopSequenceNumberUpdate(): void {\n\t\tthis.opsCountSinceNoop = 0;\n\t\t// Ideally, we cancel timer here. But that will result in too often set/reset cycle if this client\n\t\t// keeps sending ops. In most cases it's actually better to let it expire (at most - 4 times per second)\n\t\t// for nothing, then have a ton of set/reset cycles.\n\t\t// Note that Timer.restart() is smart and will not change timer expiration if we keep extending timer\n\t\t// expiration - it will restart the timer instead when it fires with adjusted expiration.\n\t\t// this.timer.clear();\n\t}\n}\n"]}
@@ -1,19 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
- import { ISequencedDocumentMessage, MessageType } from "@fluidframework/protocol-definitions";
6
- export declare class CollabWindowTracker {
7
- private readonly submit;
8
- private readonly NoopCountFrequency;
9
- private opsCountSinceNoop;
10
- private readonly timer;
11
- constructor(submit: (type: MessageType) => void, NoopTimeFrequency?: number, NoopCountFrequency?: number);
12
- /**
13
- * Schedules as ack to the server to update the reference sequence number
14
- */
15
- scheduleSequenceNumberUpdate(message: ISequencedDocumentMessage, immediateNoOp: boolean): void;
16
- private submitNoop;
17
- stopSequenceNumberUpdate(): void;
18
- }
19
- //# sourceMappingURL=collabWindowTracker.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"collabWindowTracker.d.ts","sourceRoot":"","sources":["../src/collabWindowTracker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,yBAAyB,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AAyB9F,qBAAa,mBAAmB;IAK9B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAEvB,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IANpC,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoB;gBAGxB,MAAM,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,EACpD,iBAAiB,GAAE,MAAiC,EACnC,kBAAkB,GAAE,MAAkC;IAaxE;;OAEG;IACI,4BAA4B,CAClC,OAAO,EAAE,yBAAyB,EAClC,aAAa,EAAE,OAAO,GACpB,IAAI;IAuCP,OAAO,CAAC,UAAU;IAUX,wBAAwB,IAAI,IAAI;CASvC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"collabWindowTracker.js","sourceRoot":"","sources":["../src/collabWindowTracker.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, Timer } from \"@fluidframework/common-utils\";\nimport { ISequencedDocumentMessage, MessageType } from \"@fluidframework/protocol-definitions\";\nimport { isRuntimeMessage, MessageType2 } from \"@fluidframework/driver-utils\";\n\nconst defaultNoopTimeFrequency = 2000;\nconst defaultNoopCountFrequency = 50;\n\n// Here are key considerations when deciding conditions for when to send non-immediate noops:\n// 1. Sending them too often results in increase in file size and bandwidth, as well as catch up performance\n// 2. Sending too infrequently ensures that collab window is large, and as result Sequence DDS would have\n// large catchUp blobs - see Issue #6364\n// 3. Similarly, processes that rely on \"core\" snapshot (and can't parse trailing ops, including above), like search\n// parser in SPO, will result in non-accurate results due to presence of catch up blobs.\n// 4. Ordering service used 250ms timeout to coalesce non-immediate noops. It was changed to 2000 ms to allow more\n// aggressive noop sending from client side.\n// 5. Number of ops sent by all clients is proportional to number of \"write\" clients (every client sends noops),\n// but number of sequenced noops is a function of time (one op per 2 seconds at most).\n// We should consider impact to both outbound traffic (might be huge, depends on number of clients) and file size.\n// Please also see Issue #5629 for more discussions.\n//\n// With that, the current algorithm is as follows:\n// 1. Sent noop 2000 ms of receiving an op if no ops were sent by this client within this timeframe.\n// This will ensure that MSN moves forward with reasonable speed. If that results in too many sequenced noops,\n// server timeout of 2000ms should be reconsidered to be increased.\n// 2. If there are more than 50 ops received without sending any ops, send noop to keep collab window small.\n// Note that system ops (including noops themselves) are excluded, so it's 1 noop per 50 real ops.\nexport class CollabWindowTracker {\n\tprivate opsCountSinceNoop = 0;\n\tprivate readonly timer: Timer | undefined;\n\n\tconstructor(\n\t\tprivate readonly submit: (type: MessageType) => void,\n\t\tNoopTimeFrequency: number = defaultNoopTimeFrequency,\n\t\tprivate readonly NoopCountFrequency: number = defaultNoopCountFrequency,\n\t) {\n\t\tif (NoopTimeFrequency !== Infinity) {\n\t\t\tthis.timer = new Timer(NoopTimeFrequency, () => {\n\t\t\t\t// Can get here due to this.stopSequenceNumberUpdate() not resetting timer.\n\t\t\t\t// Also timer callback can fire even after timer cancellation if it was queued before cancellation.\n\t\t\t\tif (this.opsCountSinceNoop !== 0) {\n\t\t\t\t\tthis.submitNoop(false /* immediate */);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Schedules as ack to the server to update the reference sequence number\n\t */\n\tpublic scheduleSequenceNumberUpdate(\n\t\tmessage: ISequencedDocumentMessage,\n\t\timmediateNoOp: boolean,\n\t): void {\n\t\t// While processing a message, an immediate no-op can be requested.\n\t\t// i.e. to expedite approve or commit phase of quorum.\n\t\tif (immediateNoOp) {\n\t\t\tthis.submitNoop(true /* immediate */);\n\t\t\treturn;\n\t\t}\n\n\t\t// We don't acknowledge no-ops to avoid acknowledgement cycles (i.e. ack the MSN\n\t\t// update, which updates the MSN, then ack the update, etc...).\n\t\t// Intent here is for runtime (and DDSes) not to keep too much tracking state / memory\n\t\t// due to runtime ops from other clients.\n\t\tif (!isRuntimeMessage(message)) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.opsCountSinceNoop++;\n\t\tif (this.opsCountSinceNoop === this.NoopCountFrequency) {\n\t\t\t// Ensure we only send noop after a batch of many ops is processed\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-floating-promises\n\t\t\tPromise.resolve().then(() => {\n\t\t\t\tif (this.opsCountSinceNoop >= this.NoopCountFrequency) {\n\t\t\t\t\tthis.submitNoop(false /* immediate */);\n\t\t\t\t\t// reset count now that all ops are processed\n\t\t\t\t\tthis.opsCountSinceNoop = 0;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t});\n\t\t}\n\n\t\tif (this.timer !== undefined) {\n\t\t\tif (this.opsCountSinceNoop === 1) {\n\t\t\t\tthis.timer.restart();\n\t\t\t}\n\n\t\t\tassert(this.timer.hasTimer, 0x242 /* \"has timer\" */);\n\t\t}\n\t}\n\n\tprivate submitNoop(immediate: boolean) {\n\t\t// Anything other than null is immediate noop\n\t\t// ADO:1385: Remove cast and use MessageType once definition changes propagate\n\t\tthis.submit(immediate ? (MessageType2.Accept as unknown as MessageType) : MessageType.NoOp);\n\t\tassert(\n\t\t\tthis.opsCountSinceNoop === 0,\n\t\t\t0x243 /* \"stopSequenceNumberUpdate should be called as result of sending any op!\" */,\n\t\t);\n\t}\n\n\tpublic stopSequenceNumberUpdate(): void {\n\t\tthis.opsCountSinceNoop = 0;\n\t\t// Ideally, we cancel timer here. But that will result in too often set/reset cycle if this client\n\t\t// keeps sending ops. In most cases it's actually better to let it expire (at most - 4 times per second)\n\t\t// for nothing, then have a ton of set/reset cycles.\n\t\t// Note that Timer.restart() is smart and will not change timer expiration if we keep extending timer\n\t\t// expiration - it will restart the timer instead when it fires with adjusted expiration.\n\t\t// this.timer.clear();\n\t}\n}\n"]}