@fluidframework/container-runtime 2.0.0-internal.2.1.1 → 2.0.0-internal.2.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 (161) hide show
  1. package/.eslintrc.js +1 -1
  2. package/dist/blobManager.d.ts +20 -5
  3. package/dist/blobManager.d.ts.map +1 -1
  4. package/dist/blobManager.js +57 -15
  5. package/dist/blobManager.js.map +1 -1
  6. package/dist/containerRuntime.d.ts +39 -40
  7. package/dist/containerRuntime.d.ts.map +1 -1
  8. package/dist/containerRuntime.js +115 -278
  9. package/dist/containerRuntime.js.map +1 -1
  10. package/dist/dataStoreContext.d.ts +3 -1
  11. package/dist/dataStoreContext.d.ts.map +1 -1
  12. package/dist/dataStoreContext.js +21 -3
  13. package/dist/dataStoreContext.js.map +1 -1
  14. package/dist/dataStores.d.ts +8 -5
  15. package/dist/dataStores.d.ts.map +1 -1
  16. package/dist/dataStores.js +26 -13
  17. package/dist/dataStores.js.map +1 -1
  18. package/dist/garbageCollection.d.ts +15 -17
  19. package/dist/garbageCollection.d.ts.map +1 -1
  20. package/dist/garbageCollection.js +92 -106
  21. package/dist/garbageCollection.js.map +1 -1
  22. package/dist/garbageCollectionConstants.d.ts +19 -0
  23. package/dist/garbageCollectionConstants.d.ts.map +1 -0
  24. package/dist/garbageCollectionConstants.js +34 -0
  25. package/dist/garbageCollectionConstants.js.map +1 -0
  26. package/dist/gcSweepReadyUsageDetection.js +2 -2
  27. package/dist/gcSweepReadyUsageDetection.js.map +1 -1
  28. package/dist/index.d.ts +4 -2
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +8 -6
  31. package/dist/index.js.map +1 -1
  32. package/dist/opLifecycle/batchManager.d.ts +30 -0
  33. package/dist/opLifecycle/batchManager.d.ts.map +1 -0
  34. package/dist/{batchManager.js → opLifecycle/batchManager.js} +25 -10
  35. package/dist/opLifecycle/batchManager.js.map +1 -0
  36. package/dist/opLifecycle/definitions.d.ts +40 -0
  37. package/dist/opLifecycle/definitions.d.ts.map +1 -0
  38. package/dist/opLifecycle/definitions.js +7 -0
  39. package/dist/opLifecycle/definitions.js.map +1 -0
  40. package/dist/opLifecycle/index.d.ts +12 -0
  41. package/dist/opLifecycle/index.d.ts.map +1 -0
  42. package/dist/opLifecycle/index.js +21 -0
  43. package/dist/opLifecycle/index.js.map +1 -0
  44. package/dist/opLifecycle/opCompressor.d.ts +18 -0
  45. package/dist/opLifecycle/opCompressor.d.ts.map +1 -0
  46. package/dist/opLifecycle/opCompressor.js +53 -0
  47. package/dist/opLifecycle/opCompressor.js.map +1 -0
  48. package/dist/opLifecycle/opDecompressor.d.ts +20 -0
  49. package/dist/opLifecycle/opDecompressor.d.ts.map +1 -0
  50. package/dist/opLifecycle/opDecompressor.js +72 -0
  51. package/dist/opLifecycle/opDecompressor.js.map +1 -0
  52. package/dist/opLifecycle/opSplitter.d.ts +17 -0
  53. package/dist/opLifecycle/opSplitter.d.ts.map +1 -0
  54. package/dist/opLifecycle/opSplitter.js +61 -0
  55. package/dist/opLifecycle/opSplitter.js.map +1 -0
  56. package/dist/opLifecycle/outbox.d.ts +47 -0
  57. package/dist/opLifecycle/outbox.d.ts.map +1 -0
  58. package/dist/opLifecycle/outbox.js +153 -0
  59. package/dist/opLifecycle/outbox.js.map +1 -0
  60. package/dist/opLifecycle/remoteMessageProcessor.d.ts +26 -0
  61. package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -0
  62. package/dist/opLifecycle/remoteMessageProcessor.js +81 -0
  63. package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -0
  64. package/dist/packageVersion.d.ts +1 -1
  65. package/dist/packageVersion.js +1 -1
  66. package/dist/packageVersion.js.map +1 -1
  67. package/dist/summaryFormat.js +2 -2
  68. package/dist/summaryFormat.js.map +1 -1
  69. package/lib/blobManager.d.ts +20 -5
  70. package/lib/blobManager.d.ts.map +1 -1
  71. package/lib/blobManager.js +59 -17
  72. package/lib/blobManager.js.map +1 -1
  73. package/lib/containerRuntime.d.ts +39 -40
  74. package/lib/containerRuntime.d.ts.map +1 -1
  75. package/lib/containerRuntime.js +113 -275
  76. package/lib/containerRuntime.js.map +1 -1
  77. package/lib/dataStoreContext.d.ts +3 -1
  78. package/lib/dataStoreContext.d.ts.map +1 -1
  79. package/lib/dataStoreContext.js +23 -5
  80. package/lib/dataStoreContext.js.map +1 -1
  81. package/lib/dataStores.d.ts +8 -5
  82. package/lib/dataStores.d.ts.map +1 -1
  83. package/lib/dataStores.js +28 -15
  84. package/lib/dataStores.js.map +1 -1
  85. package/lib/garbageCollection.d.ts +15 -17
  86. package/lib/garbageCollection.d.ts.map +1 -1
  87. package/lib/garbageCollection.js +72 -86
  88. package/lib/garbageCollection.js.map +1 -1
  89. package/lib/garbageCollectionConstants.d.ts +19 -0
  90. package/lib/garbageCollectionConstants.d.ts.map +1 -0
  91. package/lib/garbageCollectionConstants.js +31 -0
  92. package/lib/garbageCollectionConstants.js.map +1 -0
  93. package/lib/gcSweepReadyUsageDetection.js +1 -1
  94. package/lib/gcSweepReadyUsageDetection.js.map +1 -1
  95. package/lib/index.d.ts +4 -2
  96. package/lib/index.d.ts.map +1 -1
  97. package/lib/index.js +3 -2
  98. package/lib/index.js.map +1 -1
  99. package/lib/opLifecycle/batchManager.d.ts +30 -0
  100. package/lib/opLifecycle/batchManager.d.ts.map +1 -0
  101. package/lib/{batchManager.js → opLifecycle/batchManager.js} +25 -10
  102. package/lib/opLifecycle/batchManager.js.map +1 -0
  103. package/lib/opLifecycle/definitions.d.ts +40 -0
  104. package/lib/opLifecycle/definitions.d.ts.map +1 -0
  105. package/lib/opLifecycle/definitions.js +6 -0
  106. package/lib/opLifecycle/definitions.js.map +1 -0
  107. package/lib/opLifecycle/index.d.ts +12 -0
  108. package/lib/opLifecycle/index.d.ts.map +1 -0
  109. package/lib/opLifecycle/index.js +11 -0
  110. package/lib/opLifecycle/index.js.map +1 -0
  111. package/lib/opLifecycle/opCompressor.d.ts +18 -0
  112. package/lib/opLifecycle/opCompressor.d.ts.map +1 -0
  113. package/lib/opLifecycle/opCompressor.js +49 -0
  114. package/lib/opLifecycle/opCompressor.js.map +1 -0
  115. package/lib/opLifecycle/opDecompressor.d.ts +20 -0
  116. package/lib/opLifecycle/opDecompressor.d.ts.map +1 -0
  117. package/lib/opLifecycle/opDecompressor.js +68 -0
  118. package/lib/opLifecycle/opDecompressor.js.map +1 -0
  119. package/lib/opLifecycle/opSplitter.d.ts +17 -0
  120. package/lib/opLifecycle/opSplitter.d.ts.map +1 -0
  121. package/lib/opLifecycle/opSplitter.js +57 -0
  122. package/lib/opLifecycle/opSplitter.js.map +1 -0
  123. package/lib/opLifecycle/outbox.d.ts +47 -0
  124. package/lib/opLifecycle/outbox.d.ts.map +1 -0
  125. package/lib/opLifecycle/outbox.js +149 -0
  126. package/lib/opLifecycle/outbox.js.map +1 -0
  127. package/lib/opLifecycle/remoteMessageProcessor.d.ts +26 -0
  128. package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -0
  129. package/lib/opLifecycle/remoteMessageProcessor.js +76 -0
  130. package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -0
  131. package/lib/packageVersion.d.ts +1 -1
  132. package/lib/packageVersion.js +1 -1
  133. package/lib/packageVersion.js.map +1 -1
  134. package/lib/summaryFormat.js +1 -1
  135. package/lib/summaryFormat.js.map +1 -1
  136. package/package.json +35 -21
  137. package/prettier.config.cjs +8 -0
  138. package/src/blobManager.ts +74 -19
  139. package/src/containerRuntime.ts +144 -341
  140. package/src/dataStoreContext.ts +33 -5
  141. package/src/dataStores.ts +32 -16
  142. package/src/garbageCollection.ts +106 -82
  143. package/src/garbageCollectionConstants.ts +35 -0
  144. package/src/gcSweepReadyUsageDetection.ts +1 -1
  145. package/src/index.ts +6 -4
  146. package/src/{batchManager.ts → opLifecycle/batchManager.ts} +41 -23
  147. package/src/opLifecycle/definitions.ts +44 -0
  148. package/src/opLifecycle/index.ts +17 -0
  149. package/src/opLifecycle/opCompressor.ts +64 -0
  150. package/src/opLifecycle/opDecompressor.ts +84 -0
  151. package/src/opLifecycle/opSplitter.ts +78 -0
  152. package/src/opLifecycle/outbox.ts +204 -0
  153. package/src/opLifecycle/remoteMessageProcessor.ts +90 -0
  154. package/src/packageVersion.ts +1 -1
  155. package/src/summaryFormat.ts +1 -1
  156. package/dist/batchManager.d.ts +0 -36
  157. package/dist/batchManager.d.ts.map +0 -1
  158. package/dist/batchManager.js.map +0 -1
  159. package/lib/batchManager.d.ts +0 -36
  160. package/lib/batchManager.d.ts.map +0 -1
  161. package/lib/batchManager.js.map +0 -1
@@ -0,0 +1,57 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import { DataCorruptionError, extractSafePropertiesFromMessage } from "@fluidframework/container-utils";
6
+ import { ContainerMessageType } from "../containerRuntime";
7
+ /**
8
+ * Responsible for creating and reconstructing chunked messages.
9
+ */
10
+ export class OpSplitter {
11
+ constructor(chunks) {
12
+ this.chunkMap = new Map(chunks);
13
+ }
14
+ get chunks() {
15
+ return this.chunkMap;
16
+ }
17
+ processRemoteMessage(message) {
18
+ if (message.type !== ContainerMessageType.ChunkedOp) {
19
+ return message;
20
+ }
21
+ const clientId = message.clientId;
22
+ const chunkedContent = message.contents;
23
+ this.addChunk(clientId, chunkedContent, message);
24
+ if (chunkedContent.chunkId < chunkedContent.totalChunks) {
25
+ // We are processing the op in chunks but haven't reached
26
+ // the last chunk yet in order to reconstruct the original op
27
+ return message;
28
+ }
29
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
30
+ const serializedContent = this.chunkMap.get(clientId).join("");
31
+ this.clearPartialChunks(clientId);
32
+ const newMessage = Object.assign({}, message);
33
+ newMessage.contents = serializedContent === "" ? undefined : JSON.parse(serializedContent);
34
+ newMessage.type = chunkedContent.originalType;
35
+ return newMessage;
36
+ }
37
+ clearPartialChunks(clientId) {
38
+ if (this.chunkMap.has(clientId)) {
39
+ this.chunkMap.delete(clientId);
40
+ }
41
+ }
42
+ addChunk(clientId, chunkedContent, originalMessage) {
43
+ let map = this.chunkMap.get(clientId);
44
+ if (map === undefined) {
45
+ map = [];
46
+ this.chunkMap.set(clientId, map);
47
+ }
48
+ if (chunkedContent.chunkId !== map.length + 1) {
49
+ // We are expecting the chunks to be processed sequentially, in the same order as they are sent.
50
+ // Therefore, the chunkId of the incoming op needs to match the length of the array (1-based indexing)
51
+ // holding the existing chunks for that particular clientId.
52
+ throw new DataCorruptionError("Chunk Id mismatch", Object.assign(Object.assign({}, extractSafePropertiesFromMessage(originalMessage)), { chunkMapLength: map.length, chunkId: chunkedContent.chunkId, totalChunks: chunkedContent.totalChunks }));
53
+ }
54
+ map.push(chunkedContent.contents);
55
+ }
56
+ }
57
+ //# sourceMappingURL=opSplitter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opSplitter.js","sourceRoot":"","sources":["../../src/opLifecycle/opSplitter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,mBAAmB,EAAE,gCAAgC,EAAE,MAAM,iCAAiC,CAAC;AAExG,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAG3D;;GAEG;AACH,MAAM,OAAO,UAAU;IAInB,YAAY,MAA4B;QACpC,IAAI,CAAC,QAAQ,GAAG,IAAI,GAAG,CAAmB,MAAM,CAAC,CAAC;IACtD,CAAC;IAED,IAAW,MAAM;QACb,OAAO,IAAI,CAAC,QAAQ,CAAC;IACzB,CAAC;IAEM,oBAAoB,CAAC,OAAkC;QAC1D,IAAI,OAAO,CAAC,IAAI,KAAK,oBAAoB,CAAC,SAAS,EAAE;YACjD,OAAO,OAAO,CAAC;SAClB;QAED,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QAClC,MAAM,cAAc,GAAG,OAAO,CAAC,QAAsB,CAAC;QACtD,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;QAEjD,IAAI,cAAc,CAAC,OAAO,GAAG,cAAc,CAAC,WAAW,EAAE;YACrD,yDAAyD;YACzD,6DAA6D;YAC7D,OAAO,OAAO,CAAC;SAClB;QAED,oEAAoE;QACpE,MAAM,iBAAiB,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChE,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QAElC,MAAM,UAAU,qBAAQ,OAAO,CAAE,CAAC;QAClC,UAAU,CAAC,QAAQ,GAAG,iBAAiB,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAC3F,UAAU,CAAC,IAAI,GAAG,cAAc,CAAC,YAAY,CAAC;QAC9C,OAAO,UAAU,CAAC;IACtB,CAAC;IAEM,kBAAkB,CAAC,QAAgB;QACtC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;YAC7B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;SAClC;IACL,CAAC;IAEO,QAAQ,CAAC,QAAgB,EAAE,cAA0B,EAAE,eAA0C;QACrG,IAAI,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACtC,IAAI,GAAG,KAAK,SAAS,EAAE;YACnB,GAAG,GAAG,EAAE,CAAC;YACT,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;SACpC;QAED,IAAI,cAAc,CAAC,OAAO,KAAK,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE;YAC3C,gGAAgG;YAChG,sGAAsG;YACtG,4DAA4D;YAC5D,MAAM,IAAI,mBAAmB,CAAC,mBAAmB,kCAC1C,gCAAgC,CAAC,eAAe,CAAC,KACpD,cAAc,EAAE,GAAG,CAAC,MAAM,EAC1B,OAAO,EAAE,cAAc,CAAC,OAAO,EAC/B,WAAW,EAAE,cAAc,CAAC,WAAW,IACzC,CAAC;SACN;QAED,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IACtC,CAAC;CACJ","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { DataCorruptionError, extractSafePropertiesFromMessage } from \"@fluidframework/container-utils\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { ContainerMessageType } from \"../containerRuntime\";\nimport { IChunkedOp } from \"./definitions\";\n\n/**\n * Responsible for creating and reconstructing chunked messages.\n */\nexport class OpSplitter {\n // Local copy of incomplete received chunks.\n private readonly chunkMap: Map<string, string[]>;\n\n constructor(chunks: [string, string[]][]) {\n this.chunkMap = new Map<string, string[]>(chunks);\n }\n\n public get chunks(): ReadonlyMap<string, string[]> {\n return this.chunkMap;\n }\n\n public processRemoteMessage(message: ISequencedDocumentMessage): ISequencedDocumentMessage {\n if (message.type !== ContainerMessageType.ChunkedOp) {\n return message;\n }\n\n const clientId = message.clientId;\n const chunkedContent = message.contents as IChunkedOp;\n this.addChunk(clientId, chunkedContent, message);\n\n if (chunkedContent.chunkId < chunkedContent.totalChunks) {\n // We are processing the op in chunks but haven't reached\n // the last chunk yet in order to reconstruct the original op\n return message;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const serializedContent = this.chunkMap.get(clientId)!.join(\"\");\n this.clearPartialChunks(clientId);\n\n const newMessage = { ...message };\n newMessage.contents = serializedContent === \"\" ? undefined : JSON.parse(serializedContent);\n newMessage.type = chunkedContent.originalType;\n return newMessage;\n }\n\n public clearPartialChunks(clientId: string) {\n if (this.chunkMap.has(clientId)) {\n this.chunkMap.delete(clientId);\n }\n }\n\n private addChunk(clientId: string, chunkedContent: IChunkedOp, originalMessage: ISequencedDocumentMessage) {\n let map = this.chunkMap.get(clientId);\n if (map === undefined) {\n map = [];\n this.chunkMap.set(clientId, map);\n }\n\n if (chunkedContent.chunkId !== map.length + 1) {\n // We are expecting the chunks to be processed sequentially, in the same order as they are sent.\n // Therefore, the chunkId of the incoming op needs to match the length of the array (1-based indexing)\n // holding the existing chunks for that particular clientId.\n throw new DataCorruptionError(\"Chunk Id mismatch\", {\n ...extractSafePropertiesFromMessage(originalMessage),\n chunkMapLength: map.length,\n chunkId: chunkedContent.chunkId,\n totalChunks: chunkedContent.totalChunks,\n });\n }\n\n map.push(chunkedContent.contents);\n }\n}\n"]}
@@ -0,0 +1,47 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import { IContainerContext } from "@fluidframework/container-definitions";
6
+ import { ICompressionRuntimeOptions } from "../containerRuntime";
7
+ import { PendingStateManager } from "../pendingStateManager";
8
+ import { BatchMessage } from "./definitions";
9
+ import { OpCompressor } from "./opCompressor";
10
+ export interface IOutboxConfig {
11
+ readonly compressionOptions: ICompressionRuntimeOptions;
12
+ readonly maxBatchSizeInBytes: number;
13
+ }
14
+ export interface IOutboxParameters {
15
+ readonly shouldSend: () => boolean;
16
+ readonly pendingStateManager: PendingStateManager;
17
+ readonly containerContext: IContainerContext;
18
+ readonly config: IOutboxConfig;
19
+ readonly compressor: OpCompressor;
20
+ }
21
+ export declare class Outbox {
22
+ private readonly params;
23
+ private readonly attachFlowBatch;
24
+ private readonly mainBatch;
25
+ private readonly defaultAttachFlowSoftLimitInBytes;
26
+ constructor(params: IOutboxParameters);
27
+ get isEmpty(): boolean;
28
+ submit(message: BatchMessage): void;
29
+ submitAttach(message: BatchMessage): void;
30
+ flush(): void;
31
+ private flushInternal;
32
+ private compressBatch;
33
+ /**
34
+ * Sends the batch object to the container context to be sent over the wire.
35
+ *
36
+ * @param batch - batch to be sent
37
+ * @returns the client sequence number of the last batched op which was sent and
38
+ * -1 if there are no ops or the container cannot send ops.
39
+ */
40
+ private sendBatch;
41
+ private persistBatch;
42
+ checkpoint(): {
43
+ mainBatch: import("./definitions").IBatchCheckpoint;
44
+ attachFlowBatch: import("./definitions").IBatchCheckpoint;
45
+ };
46
+ }
47
+ //# sourceMappingURL=outbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbox.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/outbox.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAG1E,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE7D,OAAO,EAAE,YAAY,EAAU,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,MAAM,WAAW,aAAa;IAC1B,QAAQ,CAAC,kBAAkB,EAAE,0BAA0B,CAAC;IAExD,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;CACxC;AAED,MAAM,WAAW,iBAAiB;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC;IACnC,QAAQ,CAAC,mBAAmB,EAAE,mBAAmB,CAAC;IAClD,QAAQ,CAAC,gBAAgB,EAAE,iBAAiB,CAAC;IAC7C,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC;CACrC;AAED,qBAAa,MAAM;IAKH,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJnC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAe;IAC/C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,iCAAiC,CAAa;gBAElC,MAAM,EAAE,iBAAiB;IAetD,IAAW,OAAO,IAAI,OAAO,CAE5B;IAEM,MAAM,CAAC,OAAO,EAAE,YAAY;IAa5B,YAAY,CAAC,OAAO,EAAE,YAAY;IA4BlC,KAAK;IAKZ,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,aAAa;IAyBrB;;;;;;OAMG;IACH,OAAO,CAAC,SAAS;IAuCjB,OAAO,CAAC,YAAY;IAoBb,UAAU;;;;CAMpB"}
@@ -0,0 +1,149 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import { assert } from "@fluidframework/common-utils";
6
+ import { GenericError } from "@fluidframework/container-utils";
7
+ import { MessageType } from "@fluidframework/protocol-definitions";
8
+ import { BatchManager } from "./batchManager";
9
+ ;
10
+ export class Outbox {
11
+ constructor(params) {
12
+ this.params = params;
13
+ this.defaultAttachFlowSoftLimitInBytes = 64 * 1024;
14
+ const isCompressionEnabled = this.params.config.compressionOptions.minimumBatchSizeInBytes !== Number.POSITIVE_INFINITY;
15
+ // We need to allow infinite size batches if we enable compression
16
+ const hardLimit = isCompressionEnabled ? Infinity : this.params.config.maxBatchSizeInBytes;
17
+ const softLimit = isCompressionEnabled ? Infinity : this.defaultAttachFlowSoftLimitInBytes;
18
+ this.attachFlowBatch = new BatchManager({
19
+ hardLimit,
20
+ softLimit,
21
+ });
22
+ this.mainBatch = new BatchManager({
23
+ hardLimit
24
+ });
25
+ }
26
+ get isEmpty() {
27
+ return this.attachFlowBatch.length === 0 && this.mainBatch.length === 0;
28
+ }
29
+ submit(message) {
30
+ var _a, _b;
31
+ if (!this.mainBatch.push(message)) {
32
+ throw new GenericError("BatchTooLarge",
33
+ /* error */ undefined, {
34
+ opSize: (_b = ((_a = message.contents) === null || _a === void 0 ? void 0 : _a.length)) !== null && _b !== void 0 ? _b : 0,
35
+ count: this.mainBatch.length,
36
+ limit: this.mainBatch.options.hardLimit,
37
+ });
38
+ }
39
+ }
40
+ submitAttach(message) {
41
+ var _a, _b;
42
+ if (!this.attachFlowBatch.push(message)) {
43
+ // BatchManager has two limits - soft limit & hard limit. Soft limit is only engaged
44
+ // when queue is not empty.
45
+ // Flush queue & retry. Failure on retry would mean - single message is bigger than hard limit
46
+ this.flushInternal(this.attachFlowBatch.popBatch());
47
+ if (!this.attachFlowBatch.push(message)) {
48
+ throw new GenericError("BatchTooLarge",
49
+ /* error */ undefined, {
50
+ opSize: (_b = ((_a = message.contents) === null || _a === void 0 ? void 0 : _a.length)) !== null && _b !== void 0 ? _b : 0,
51
+ count: this.attachFlowBatch.length,
52
+ limit: this.attachFlowBatch.options.hardLimit,
53
+ });
54
+ }
55
+ }
56
+ // If compression is enabled, we will always successfully receive
57
+ // attach ops and compress then send them at the next JS turn, regardless
58
+ // of the overall size of the accumulated ops in the batch.
59
+ // However, it is more efficient to flush these ops faster, preferably
60
+ // after they reach a size which would benefit from compression.
61
+ if (this.attachFlowBatch.contentSizeInBytes >= this.params.config.compressionOptions.minimumBatchSizeInBytes) {
62
+ this.flushInternal(this.attachFlowBatch.popBatch());
63
+ }
64
+ }
65
+ flush() {
66
+ this.flushInternal(this.attachFlowBatch.popBatch());
67
+ this.flushInternal(this.mainBatch.popBatch());
68
+ }
69
+ flushInternal(rawBatch) {
70
+ const processedBatch = this.compressBatch(rawBatch);
71
+ const clientSequenceNumber = this.sendBatch(processedBatch);
72
+ this.persistBatch(clientSequenceNumber, rawBatch.content);
73
+ }
74
+ compressBatch(batch) {
75
+ if (batch.content.length === 0
76
+ || this.params.config.compressionOptions === undefined
77
+ || this.params.config.compressionOptions.minimumBatchSizeInBytes > batch.contentSizeInBytes) {
78
+ // Nothing to do if the batch is empty or if compression is disabled or if we don't need to compress
79
+ return batch;
80
+ }
81
+ const compressedBatch = this.params.compressor.compressBatch(batch);
82
+ if (compressedBatch.contentSizeInBytes > this.params.config.maxBatchSizeInBytes) {
83
+ throw new GenericError("BatchTooLarge",
84
+ /* error */ undefined, {
85
+ opSize: batch.contentSizeInBytes,
86
+ count: batch.content.length,
87
+ limit: this.params.config.maxBatchSizeInBytes,
88
+ compressed: true,
89
+ });
90
+ }
91
+ // If we don't reach the maximum supported size of a batch, it safe to be sent as is
92
+ return compressedBatch;
93
+ }
94
+ /**
95
+ * Sends the batch object to the container context to be sent over the wire.
96
+ *
97
+ * @param batch - batch to be sent
98
+ * @returns the client sequence number of the last batched op which was sent and
99
+ * -1 if there are no ops or the container cannot send ops.
100
+ */
101
+ sendBatch(batch) {
102
+ var _a;
103
+ let clientSequenceNumber = -1;
104
+ const length = batch.content.length;
105
+ // Did we disconnect in the middle of turn-based batch?
106
+ // If so, do nothing, as pending state manager will resubmit it correctly on reconnect.
107
+ if (length === 0 || !this.params.shouldSend()) {
108
+ return clientSequenceNumber;
109
+ }
110
+ if (this.params.containerContext.submitBatchFn === undefined) {
111
+ // Legacy path - supporting old loader versions. Can be removed only when LTS moves above
112
+ // version that has support for batches (submitBatchFn)
113
+ for (const message of batch.content) {
114
+ // Legacy path doesn't support compressed payloads and will submit uncompressed payload anyways
115
+ if ((_a = message.metadata) === null || _a === void 0 ? void 0 : _a.compressed) {
116
+ delete message.metadata.compressed;
117
+ }
118
+ clientSequenceNumber = this.params.containerContext.submitFn(MessageType.Operation, message.deserializedContent, true, // batch
119
+ message.metadata);
120
+ }
121
+ this.params.containerContext.deltaManager.flush();
122
+ }
123
+ else {
124
+ // returns clientSequenceNumber of last message in a batch
125
+ clientSequenceNumber = this.params.containerContext.submitBatchFn(batch.content.map((message) => ({ contents: message.contents, metadata: message.metadata })));
126
+ }
127
+ // Convert from clientSequenceNumber of last message in the batch to clientSequenceNumber of first message.
128
+ clientSequenceNumber -= length - 1;
129
+ assert(clientSequenceNumber >= 0, 0x3d0 /* clientSequenceNumber can't be negative */);
130
+ return clientSequenceNumber;
131
+ }
132
+ persistBatch(initialClientSequenceNumber, batch) {
133
+ let clientSequenceNumber = initialClientSequenceNumber;
134
+ // Let the PendingStateManager know that a message was submitted.
135
+ // In future, need to shift toward keeping batch as a whole!
136
+ for (const message of batch) {
137
+ this.params.pendingStateManager.onSubmitMessage(message.deserializedContent.type, clientSequenceNumber, message.referenceSequenceNumber, message.deserializedContent.contents, message.localOpMetadata, message.metadata);
138
+ clientSequenceNumber++;
139
+ }
140
+ this.params.pendingStateManager.onFlush();
141
+ }
142
+ checkpoint() {
143
+ return {
144
+ mainBatch: this.mainBatch.checkpoint(),
145
+ attachFlowBatch: this.attachFlowBatch.checkpoint(),
146
+ };
147
+ }
148
+ }
149
+ //# sourceMappingURL=outbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbox.js","sourceRoot":"","sources":["../../src/opLifecycle/outbox.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 { IContainerContext } from \"@fluidframework/container-definitions\";\nimport { GenericError } from \"@fluidframework/container-utils\";\nimport { MessageType } from \"@fluidframework/protocol-definitions\";\nimport { ICompressionRuntimeOptions } from \"../containerRuntime\";\nimport { PendingStateManager } from \"../pendingStateManager\";\nimport { BatchManager } from \"./batchManager\";\nimport { BatchMessage, IBatch } from \"./definitions\";\nimport { OpCompressor } from \"./opCompressor\";\n\nexport interface IOutboxConfig {\n readonly compressionOptions: ICompressionRuntimeOptions;\n // The maximum size of a batch that we can send over the wire.\n readonly maxBatchSizeInBytes: number;\n};\n\nexport interface IOutboxParameters {\n readonly shouldSend: () => boolean,\n readonly pendingStateManager: PendingStateManager,\n readonly containerContext: IContainerContext,\n readonly config: IOutboxConfig,\n readonly compressor: OpCompressor;\n}\n\nexport class Outbox {\n private readonly attachFlowBatch: BatchManager;\n private readonly mainBatch: BatchManager;\n private readonly defaultAttachFlowSoftLimitInBytes = 64 * 1024;\n\n constructor(private readonly params: IOutboxParameters) {\n const isCompressionEnabled = this.params.config.compressionOptions.minimumBatchSizeInBytes !== Number.POSITIVE_INFINITY;\n // We need to allow infinite size batches if we enable compression\n const hardLimit = isCompressionEnabled ? Infinity : this.params.config.maxBatchSizeInBytes;\n const softLimit = isCompressionEnabled ? Infinity : this.defaultAttachFlowSoftLimitInBytes;\n\n this.attachFlowBatch = new BatchManager({\n hardLimit,\n softLimit,\n });\n this.mainBatch = new BatchManager({\n hardLimit\n });\n }\n\n public get isEmpty(): boolean {\n return this.attachFlowBatch.length === 0 && this.mainBatch.length === 0;\n }\n\n public submit(message: BatchMessage) {\n if (!this.mainBatch.push(message)) {\n throw new GenericError(\n \"BatchTooLarge\",\n /* error */ undefined,\n {\n opSize: (message.contents?.length) ?? 0,\n count: this.mainBatch.length,\n limit: this.mainBatch.options.hardLimit,\n });\n }\n }\n\n public submitAttach(message: BatchMessage) {\n if (!this.attachFlowBatch.push(message)) {\n // BatchManager has two limits - soft limit & hard limit. Soft limit is only engaged\n // when queue is not empty.\n // Flush queue & retry. Failure on retry would mean - single message is bigger than hard limit\n this.flushInternal(this.attachFlowBatch.popBatch());\n if (!this.attachFlowBatch.push(message)) {\n throw new GenericError(\n \"BatchTooLarge\",\n /* error */ undefined,\n {\n opSize: (message.contents?.length) ?? 0,\n count: this.attachFlowBatch.length,\n limit: this.attachFlowBatch.options.hardLimit,\n });\n }\n }\n\n // If compression is enabled, we will always successfully receive\n // attach ops and compress then send them at the next JS turn, regardless\n // of the overall size of the accumulated ops in the batch.\n // However, it is more efficient to flush these ops faster, preferably\n // after they reach a size which would benefit from compression.\n if (this.attachFlowBatch.contentSizeInBytes >= this.params.config.compressionOptions.minimumBatchSizeInBytes) {\n this.flushInternal(this.attachFlowBatch.popBatch());\n }\n }\n\n public flush() {\n this.flushInternal(this.attachFlowBatch.popBatch());\n this.flushInternal(this.mainBatch.popBatch());\n }\n\n private flushInternal(rawBatch: IBatch) {\n const processedBatch = this.compressBatch(rawBatch);\n const clientSequenceNumber = this.sendBatch(processedBatch);\n\n this.persistBatch(clientSequenceNumber, rawBatch.content);\n }\n\n private compressBatch(batch: IBatch): IBatch {\n if (batch.content.length === 0\n || this.params.config.compressionOptions === undefined\n || this.params.config.compressionOptions.minimumBatchSizeInBytes > batch.contentSizeInBytes) {\n // Nothing to do if the batch is empty or if compression is disabled or if we don't need to compress\n return batch;\n }\n\n const compressedBatch = this.params.compressor.compressBatch(batch);\n if (compressedBatch.contentSizeInBytes > this.params.config.maxBatchSizeInBytes) {\n throw new GenericError(\n \"BatchTooLarge\",\n /* error */ undefined,\n {\n opSize: batch.contentSizeInBytes,\n count: batch.content.length,\n limit: this.params.config.maxBatchSizeInBytes,\n compressed: true,\n });\n }\n\n // If we don't reach the maximum supported size of a batch, it safe to be sent as is\n return compressedBatch;\n }\n\n /**\n * Sends the batch object to the container context to be sent over the wire.\n *\n * @param batch - batch to be sent\n * @returns the client sequence number of the last batched op which was sent and\n * -1 if there are no ops or the container cannot send ops.\n */\n private sendBatch(batch: IBatch): number {\n let clientSequenceNumber: number = -1;\n const length = batch.content.length;\n\n // Did we disconnect in the middle of turn-based batch?\n // If so, do nothing, as pending state manager will resubmit it correctly on reconnect.\n if (length === 0 || !this.params.shouldSend()) {\n return clientSequenceNumber;\n }\n\n if (this.params.containerContext.submitBatchFn === undefined) {\n // Legacy path - supporting old loader versions. Can be removed only when LTS moves above\n // version that has support for batches (submitBatchFn)\n for (const message of batch.content) {\n // Legacy path doesn't support compressed payloads and will submit uncompressed payload anyways\n if (message.metadata?.compressed) {\n delete message.metadata.compressed;\n }\n\n clientSequenceNumber = this.params.containerContext.submitFn(\n MessageType.Operation,\n message.deserializedContent,\n true, // batch\n message.metadata);\n }\n\n this.params.containerContext.deltaManager.flush();\n } else {\n // returns clientSequenceNumber of last message in a batch\n clientSequenceNumber = this.params.containerContext.submitBatchFn(\n batch.content.map((message) => ({ contents: message.contents, metadata: message.metadata })));\n }\n\n // Convert from clientSequenceNumber of last message in the batch to clientSequenceNumber of first message.\n clientSequenceNumber -= length - 1;\n assert(clientSequenceNumber >= 0, 0x3d0 /* clientSequenceNumber can't be negative */);\n return clientSequenceNumber;\n }\n\n private persistBatch(initialClientSequenceNumber: number, batch: BatchMessage[]) {\n let clientSequenceNumber = initialClientSequenceNumber;\n // Let the PendingStateManager know that a message was submitted.\n // In future, need to shift toward keeping batch as a whole!\n for (const message of batch) {\n this.params.pendingStateManager.onSubmitMessage(\n message.deserializedContent.type,\n clientSequenceNumber,\n message.referenceSequenceNumber,\n message.deserializedContent.contents,\n message.localOpMetadata,\n message.metadata,\n );\n\n clientSequenceNumber++;\n }\n\n this.params.pendingStateManager.onFlush();\n }\n\n public checkpoint() {\n return {\n mainBatch: this.mainBatch.checkpoint(),\n attachFlowBatch: this.attachFlowBatch.checkpoint(),\n };\n }\n}\n"]}
@@ -0,0 +1,26 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
6
+ import { OpDecompressor } from "./opDecompressor";
7
+ import { OpSplitter } from "./opSplitter";
8
+ export declare class RemoteMessageProcessor {
9
+ private readonly opSplitter;
10
+ private readonly opDecompressor;
11
+ constructor(opSplitter: OpSplitter, opDecompressor: OpDecompressor);
12
+ get partialMessages(): ReadonlyMap<string, string[]>;
13
+ clearPartialMessagesFor(clientId: string): void;
14
+ process(remoteMessage: ISequencedDocumentMessage): ISequencedDocumentMessage;
15
+ }
16
+ /**
17
+ * Unpacks runtime messages.
18
+ *
19
+ * @remarks This API makes no promises regarding backward-compatibility. This is internal API.
20
+ * @param message - message (as it observed in storage / service)
21
+ * @returns unpacked runtime message
22
+ *
23
+ * @internal
24
+ */
25
+ export declare function unpackRuntimeMessage(message: ISequencedDocumentMessage): boolean;
26
+ //# sourceMappingURL=remoteMessageProcessor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remoteMessageProcessor.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/remoteMessageProcessor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,yBAAyB,EAAe,MAAM,sCAAsC,CAAC;AAE9F,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,qBAAa,sBAAsB;IAE3B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,cAAc;gBADd,UAAU,EAAE,UAAU,EACtB,cAAc,EAAE,cAAc;IAGnD,IAAW,eAAe,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAE1D;IAEM,uBAAuB,CAAC,QAAQ,EAAE,MAAM;IAIxC,OAAO,CAAC,aAAa,EAAE,yBAAyB,GAAG,yBAAyB;CAStF;AA6BD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAkBhF"}
@@ -0,0 +1,76 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import { MessageType } from "@fluidframework/protocol-definitions";
6
+ import { ContainerMessageType } from "../containerRuntime";
7
+ export class RemoteMessageProcessor {
8
+ constructor(opSplitter, opDecompressor) {
9
+ this.opSplitter = opSplitter;
10
+ this.opDecompressor = opDecompressor;
11
+ }
12
+ get partialMessages() {
13
+ return this.opSplitter.chunks;
14
+ }
15
+ clearPartialMessagesFor(clientId) {
16
+ this.opSplitter.clearPartialChunks(clientId);
17
+ }
18
+ process(remoteMessage) {
19
+ let message = copy(remoteMessage);
20
+ message = this.opDecompressor.processMessage(message);
21
+ unpackRuntimeMessage(message);
22
+ message = this.opSplitter.processRemoteMessage(message);
23
+ return message;
24
+ }
25
+ }
26
+ const copy = (remoteMessage) => {
27
+ // Do shallow copy of message, as the processing flow will modify it.
28
+ // There might be multiple container instances receiving same message
29
+ // We do not need to make deep copy, as each layer will just replace message.content itself,
30
+ // but would not modify contents details
31
+ const message = Object.assign({}, remoteMessage);
32
+ // back-compat: ADO #1385: eventually should become unconditional, but only for runtime messages!
33
+ // System message may have no contents, or in some cases (mostly for back-compat) they may have actual objects.
34
+ // Old ops may contain empty string (I assume noops).
35
+ if (typeof message.contents === "string" && message.contents !== "") {
36
+ message.contents = JSON.parse(message.contents);
37
+ }
38
+ return message;
39
+ };
40
+ /**
41
+ * For a given message, it moves the nested contents and type on level up.
42
+ *
43
+ */
44
+ const unpack = (message) => {
45
+ const innerContents = message.contents;
46
+ message.type = innerContents.type;
47
+ message.contents = innerContents.contents;
48
+ };
49
+ /**
50
+ * Unpacks runtime messages.
51
+ *
52
+ * @remarks This API makes no promises regarding backward-compatibility. This is internal API.
53
+ * @param message - message (as it observed in storage / service)
54
+ * @returns unpacked runtime message
55
+ *
56
+ * @internal
57
+ */
58
+ export function unpackRuntimeMessage(message) {
59
+ if (message.type !== MessageType.Operation) {
60
+ // Legacy format, but it's already "unpacked",
61
+ // i.e. message.type is actually ContainerMessageType.
62
+ // Or it's non-runtime message.
63
+ // Nothing to do in such case.
64
+ return false;
65
+ }
66
+ // legacy op format?
67
+ if (message.contents.address !== undefined && message.contents.type === undefined) {
68
+ message.type = ContainerMessageType.FluidDataStoreOp;
69
+ }
70
+ else {
71
+ // new format
72
+ unpack(message);
73
+ }
74
+ return true;
75
+ }
76
+ //# sourceMappingURL=remoteMessageProcessor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remoteMessageProcessor.js","sourceRoot":"","sources":["../../src/opLifecycle/remoteMessageProcessor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAA6B,WAAW,EAAE,MAAM,sCAAsC,CAAC;AAC9F,OAAO,EAAE,oBAAoB,EAA2B,MAAM,qBAAqB,CAAC;AAIpF,MAAM,OAAO,sBAAsB;IAC/B,YACqB,UAAsB,EACtB,cAA8B;QAD9B,eAAU,GAAV,UAAU,CAAY;QACtB,mBAAc,GAAd,cAAc,CAAgB;IAC/C,CAAC;IAEL,IAAW,eAAe;QACtB,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;IAClC,CAAC;IAEM,uBAAuB,CAAC,QAAgB;QAC3C,IAAI,CAAC,UAAU,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACjD,CAAC;IAEM,OAAO,CAAC,aAAwC;QACnD,IAAI,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC;QAElC,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QACtD,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAC9B,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAExD,OAAO,OAAO,CAAC;IACnB,CAAC;CACJ;AAED,MAAM,IAAI,GAAG,CAAC,aAAwC,EAA6B,EAAE;IACjF,qEAAqE;IACrE,qEAAqE;IACrE,4FAA4F;IAC5F,wCAAwC;IACxC,MAAM,OAAO,qBAAQ,aAAa,CAAE,CAAC;IAErC,iGAAiG;IACjG,+GAA+G;IAC/G,qDAAqD;IACrD,IAAI,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,IAAI,OAAO,CAAC,QAAQ,KAAK,EAAE,EAAE;QACjE,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;KACnD;IAED,OAAO,OAAO,CAAC;AACnB,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,GAAG,CAAC,OAAkC,EAAE,EAAE;IAClD,MAAM,aAAa,GAAG,OAAO,CAAC,QAAmC,CAAC;IAClE,OAAO,CAAC,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC;IAClC,OAAO,CAAC,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC;AAC9C,CAAC,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAkC;IACnE,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,CAAC,SAAS,EAAE;QACxC,8CAA8C;QAC9C,sDAAsD;QACtD,+BAA+B;QAC/B,8BAA8B;QAC9B,OAAO,KAAK,CAAC;KAChB;IAED,oBAAoB;IACpB,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,KAAK,SAAS,EAAE;QAC/E,OAAO,CAAC,IAAI,GAAG,oBAAoB,CAAC,gBAAgB,CAAC;KACxD;SAAM;QACH,aAAa;QACb,MAAM,CAAC,OAAO,CAAC,CAAC;KACnB;IAED,OAAO,IAAI,CAAC;AAChB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ISequencedDocumentMessage, MessageType } from \"@fluidframework/protocol-definitions\";\nimport { ContainerMessageType, ContainerRuntimeMessage } from \"../containerRuntime\";\nimport { OpDecompressor } from \"./opDecompressor\";\nimport { OpSplitter } from \"./opSplitter\";\n\nexport class RemoteMessageProcessor {\n constructor(\n private readonly opSplitter: OpSplitter,\n private readonly opDecompressor: OpDecompressor,\n ) { }\n\n public get partialMessages(): ReadonlyMap<string, string[]> {\n return this.opSplitter.chunks;\n }\n\n public clearPartialMessagesFor(clientId: string) {\n this.opSplitter.clearPartialChunks(clientId);\n }\n\n public process(remoteMessage: ISequencedDocumentMessage): ISequencedDocumentMessage {\n let message = copy(remoteMessage);\n\n message = this.opDecompressor.processMessage(message);\n unpackRuntimeMessage(message);\n message = this.opSplitter.processRemoteMessage(message);\n\n return message;\n }\n}\n\nconst copy = (remoteMessage: ISequencedDocumentMessage): ISequencedDocumentMessage => {\n // Do shallow copy of message, as the processing flow will modify it.\n // There might be multiple container instances receiving same message\n // We do not need to make deep copy, as each layer will just replace message.content itself,\n // but would not modify contents details\n const message = { ...remoteMessage };\n\n // back-compat: ADO #1385: eventually should become unconditional, but only for runtime messages!\n // System message may have no contents, or in some cases (mostly for back-compat) they may have actual objects.\n // Old ops may contain empty string (I assume noops).\n if (typeof message.contents === \"string\" && message.contents !== \"\") {\n message.contents = JSON.parse(message.contents);\n }\n\n return message;\n};\n\n/**\n * For a given message, it moves the nested contents and type on level up.\n *\n */\nconst unpack = (message: ISequencedDocumentMessage) => {\n const innerContents = message.contents as ContainerRuntimeMessage;\n message.type = innerContents.type;\n message.contents = innerContents.contents;\n};\n\n/**\n * Unpacks runtime messages.\n *\n * @remarks This API makes no promises regarding backward-compatibility. This is internal API.\n * @param message - message (as it observed in storage / service)\n * @returns unpacked runtime message\n *\n * @internal\n */\nexport function unpackRuntimeMessage(message: ISequencedDocumentMessage): boolean {\n if (message.type !== MessageType.Operation) {\n // Legacy format, but it's already \"unpacked\",\n // i.e. message.type is actually ContainerMessageType.\n // Or it's non-runtime message.\n // Nothing to do in such case.\n return false;\n }\n\n // legacy op format?\n if (message.contents.address !== undefined && message.contents.type === undefined) {\n message.type = ContainerMessageType.FluidDataStoreOp;\n } else {\n // new format\n unpack(message);\n }\n\n return true;\n}\n"]}
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export declare const pkgName = "@fluidframework/container-runtime";
8
- export declare const pkgVersion = "2.0.0-internal.2.1.1";
8
+ export declare const pkgVersion = "2.0.0-internal.2.2.0";
9
9
  //# sourceMappingURL=packageVersion.d.ts.map
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export const pkgName = "@fluidframework/container-runtime";
8
- export const pkgVersion = "2.0.0-internal.2.1.1";
8
+ export const pkgVersion = "2.0.0-internal.2.2.0";
9
9
  //# sourceMappingURL=packageVersion.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,mCAAmC,CAAC;AAC3D,MAAM,CAAC,MAAM,UAAU,GAAG,sBAAsB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/container-runtime\";\nexport const pkgVersion = \"2.0.0-internal.2.1.1\";\n"]}
1
+ {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,mCAAmC,CAAC;AAC3D,MAAM,CAAC,MAAM,UAAU,GAAG,sBAAsB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/container-runtime\";\nexport const pkgVersion = \"2.0.0-internal.2.2.0\";\n"]}
@@ -6,7 +6,7 @@ import { assert } from "@fluidframework/common-utils";
6
6
  import { readAndParse } from "@fluidframework/driver-utils";
7
7
  import { SummaryType } from "@fluidframework/protocol-definitions";
8
8
  import { channelsTreeName } from "@fluidframework/runtime-definitions";
9
- import { gcTreeKey } from "./garbageCollection";
9
+ import { gcTreeKey } from "./garbageCollectionConstants";
10
10
  export function getAttributesFormatVersion(attributes) {
11
11
  if (attributes.summaryFormatVersion) {
12
12
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"summaryFormat.js","sourceRoot":"","sources":["../src/summaryFormat.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 { IDocumentStorageService } from \"@fluidframework/driver-definitions\";\nimport { readAndParse } from \"@fluidframework/driver-utils\";\nimport { ISequencedDocumentMessage, ISnapshotTree, SummaryType } from \"@fluidframework/protocol-definitions\";\nimport { channelsTreeName, ISummaryTreeWithStats } from \"@fluidframework/runtime-definitions\";\nimport { gcTreeKey } from \"./garbageCollection\";\n\ntype OmitAttributesVersions<T> = Omit<T, \"snapshotFormatVersion\" | \"summaryFormatVersion\">;\ninterface IFluidDataStoreAttributes0 {\n readonly snapshotFormatVersion?: undefined;\n readonly summaryFormatVersion?: undefined;\n pkg: string;\n /**\n * This tells whether a data store is root. Root data stores are never collected.\n * Non-root data stores may be collected if they are not used. If this is not present, default it to\n * true. This will ensure that older data stores are incorrectly collected.\n */\n readonly isRootDataStore?: boolean;\n}\ninterface IFluidDataStoreAttributes1 extends OmitAttributesVersions<IFluidDataStoreAttributes0> {\n readonly snapshotFormatVersion: \"0.1\";\n readonly summaryFormatVersion?: undefined;\n}\ninterface IFluidDataStoreAttributes2 extends OmitAttributesVersions<IFluidDataStoreAttributes1> {\n /** Switch from snapshotFormatVersion to summaryFormatVersion */\n readonly snapshotFormatVersion?: undefined;\n readonly summaryFormatVersion: 2;\n /**\n * True if channels are not isolated in .channels subtrees, otherwise isolated.\n * This is required in both datastore attributes as well as the root container,\n * because reused summary handles may cause different format versions in each\n * datastore subtree within the summary.\n */\n readonly disableIsolatedChannels?: true;\n}\n/**\n * Added IFluidDataStoreAttributes similar to IChannelAttributes which will tell the attributes of a\n * store like the package, snapshotFormatVersion to take different decisions based on a particular\n * snapshotFormatVersion.\n */\nexport type ReadFluidDataStoreAttributes =\n | IFluidDataStoreAttributes0\n | IFluidDataStoreAttributes1\n | IFluidDataStoreAttributes2;\nexport type WriteFluidDataStoreAttributes = IFluidDataStoreAttributes1 | IFluidDataStoreAttributes2;\n\nexport function getAttributesFormatVersion(attributes: ReadFluidDataStoreAttributes): number {\n if (attributes.summaryFormatVersion) {\n /**\n * Version 2+: Introduces .channels trees for isolation of\n * channel trees from data store objects.\n */\n return attributes.summaryFormatVersion;\n } else if (attributes.snapshotFormatVersion === \"0.1\") {\n /**\n * Version 1: from this version the pkg within the data store\n * attributes blob is a JSON array rather than a string.\n */\n return 1;\n }\n /**\n * Version 0: format version is missing from summary.\n * This indicates it is an older version.\n */\n return 0;\n}\n\nexport function hasIsolatedChannels(attributes: ReadFluidDataStoreAttributes): boolean {\n return !!attributes.summaryFormatVersion && !attributes.disableIsolatedChannels;\n}\nexport interface IContainerRuntimeMetadata extends ICreateContainerMetadata, IGCMetadata {\n readonly summaryFormatVersion: 1;\n /** The last message processed at the time of summary. Only primitive property types are added to the summary. */\n readonly message: ISummaryMetadataMessage | undefined;\n /** True if channels are not isolated in .channels subtrees, otherwise isolated. */\n readonly disableIsolatedChannels?: true;\n /** The summary number for a container's summary. Incremented on summaries throughout its lifetime. */\n readonly summaryNumber?: number;\n}\n\nexport interface ICreateContainerMetadata {\n /** Runtime version of the container when it was first created */\n createContainerRuntimeVersion?: string;\n /** Timestamp of the container when it was first created */\n createContainerTimestamp?: number;\n}\n\nexport type GCVersion = number;\nexport interface IGCMetadata {\n /**\n * The version of the GC code that was run to generate the GC data that is written in the summary.\n * Also, used to determine whether GC is enabled for this container or not:\n * - A value of 0 or undefined means GC is disabled.\n * - A value greater than 0 means GC is enabled.\n */\n readonly gcFeature?: GCVersion;\n /**\n * Tells whether the GC sweep phase is enabled for this container.\n * - True means sweep phase is enabled.\n * - False means sweep phase is disabled. If GC is disabled as per gcFeature, sweep is also disabled.\n */\n readonly sweepEnabled?: boolean;\n /** If this is present, the session for this container will expire after this time and the container will close */\n readonly sessionExpiryTimeoutMs?: number;\n /** How long to wait after an object is unreferenced before deleting it via GC Sweep */\n readonly sweepTimeoutMs?: number;\n}\n\n/** The properties of an ISequencedDocumentMessage to be stored in the metadata blob in summary. */\nexport type ISummaryMetadataMessage = Pick<ISequencedDocumentMessage,\n | \"clientId\"\n | \"clientSequenceNumber\"\n | \"minimumSequenceNumber\"\n | \"referenceSequenceNumber\"\n | \"sequenceNumber\"\n | \"timestamp\"\n | \"type\">;\n\n/**\n * Extracts the properties from an ISequencedDocumentMessage as defined by ISummaryMetadataMessage. This message is\n * added to the metadata blob in summary.\n */\nexport const extractSummaryMetadataMessage = (\n message?: ISequencedDocumentMessage,\n): ISummaryMetadataMessage | undefined => message === undefined ? undefined : {\n clientId: message.clientId,\n clientSequenceNumber: message.clientSequenceNumber,\n minimumSequenceNumber: message.minimumSequenceNumber,\n referenceSequenceNumber: message.referenceSequenceNumber,\n sequenceNumber: message.sequenceNumber,\n timestamp: message.timestamp,\n type: message.type,\n};\n\nexport function getMetadataFormatVersion(metadata?: IContainerRuntimeMetadata): number {\n /**\n * Version 2+: Introduces runtime sequence number for data verification.\n *\n * Version 1+: Introduces .metadata blob and .channels trees for isolation of\n * data store trees from container-level objects.\n * Also introduces enableGC option stored in the summary.\n *\n * Version 0: metadata blob missing; format version is missing from summary.\n * This indicates it is an older version.\n */\n return metadata?.summaryFormatVersion ?? 0;\n}\n\nexport const aliasBlobName = \".aliases\";\nexport const metadataBlobName = \".metadata\";\nexport const chunksBlobName = \".chunks\";\nexport const electedSummarizerBlobName = \".electedSummarizer\";\nexport const blobsTreeName = \".blobs\";\n\nexport function rootHasIsolatedChannels(metadata?: IContainerRuntimeMetadata): boolean {\n return !!metadata && !metadata.disableIsolatedChannels;\n}\n\nexport function getGCVersion(metadata?: IGCMetadata): GCVersion {\n if (!metadata) {\n // Force to 0/disallowed in prior versions\n return 0;\n }\n return metadata.gcFeature ?? 0;\n}\n\nexport const protocolTreeName = \".protocol\";\n\n/**\n * List of tree IDs at the container level which are reserved.\n * This is for older versions of summaries that do not yet have an\n * isolated data stores namespace. Without the namespace, this must\n * be used to prevent name collisions with data store IDs.\n */\nexport const nonDataStorePaths = [protocolTreeName, \".logTail\", \".serviceProtocol\", blobsTreeName, gcTreeKey];\n\nexport const dataStoreAttributesBlobName = \".component\";\n\n/**\n * Modifies summary tree and stats to put tree under .channels tree.\n *\n * @param summarizeResult - Summary tree and stats to modify\n *\n * @example\n * Converts from:\n * ```typescript\n * {\n * type: SummaryType.Tree,\n * tree: { a: {...}, b: {...}, c: {...} },\n * }\n * ```\n *\n * to:\n *\n * ```typescript\n * {\n * type: SummaryType.Tree,\n * tree: {\n * \".channels\": {\n * type: SummaryType.Tree,\n * tree: { a: {...}, b: {...}, c: {...} }\n * },\n * },\n * }\n * ```\n * And adds +1 to treeNodeCount in stats.\n */\nexport function wrapSummaryInChannelsTree(summarizeResult: ISummaryTreeWithStats): void {\n summarizeResult.summary = {\n type: SummaryType.Tree,\n tree: { [channelsTreeName]: summarizeResult.summary },\n };\n summarizeResult.stats.treeNodeCount++;\n}\n\nexport async function getFluidDataStoreAttributes(\n storage: IDocumentStorageService,\n snapshot: ISnapshotTree,\n): Promise<ReadFluidDataStoreAttributes> {\n const attributes = await readAndParse<ReadFluidDataStoreAttributes>(\n storage, snapshot.blobs[dataStoreAttributesBlobName]);\n // Use the snapshotFormatVersion to determine how the pkg is encoded in the snapshot.\n // For snapshotFormatVersion = \"0.1\" (1) or above, pkg is jsonified, otherwise it is just a string.\n // However the feature of loading a detached container from snapshot, is added when the\n // snapshotFormatVersion is at least \"0.1\" (1), so we don't expect it to be anything else.\n const formatVersion = getAttributesFormatVersion(attributes);\n assert(formatVersion > 0,\n 0x1d5 /* Invalid snapshot format version */);\n return attributes;\n}\n"]}
1
+ {"version":3,"file":"summaryFormat.js","sourceRoot":"","sources":["../src/summaryFormat.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAEtD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAA4C,WAAW,EAAE,MAAM,sCAAsC,CAAC;AAC7G,OAAO,EAAE,gBAAgB,EAAyB,MAAM,qCAAqC,CAAC;AAC9F,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAyCzD,MAAM,UAAU,0BAA0B,CAAC,UAAwC;IAC/E,IAAI,UAAU,CAAC,oBAAoB,EAAE;QACjC;;;WAGG;QACH,OAAO,UAAU,CAAC,oBAAoB,CAAC;KAC1C;SAAM,IAAI,UAAU,CAAC,qBAAqB,KAAK,KAAK,EAAE;QACnD;;;WAGG;QACH,OAAO,CAAC,CAAC;KACZ;IACD;;;OAGG;IACH,OAAO,CAAC,CAAC;AACb,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,UAAwC;IACxE,OAAO,CAAC,CAAC,UAAU,CAAC,oBAAoB,IAAI,CAAC,UAAU,CAAC,uBAAuB,CAAC;AACpF,CAAC;AAiDD;;;GAGG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,CACzC,OAAmC,EACA,EAAE,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAC1E,QAAQ,EAAE,OAAO,CAAC,QAAQ;IAC1B,oBAAoB,EAAE,OAAO,CAAC,oBAAoB;IAClD,qBAAqB,EAAE,OAAO,CAAC,qBAAqB;IACpD,uBAAuB,EAAE,OAAO,CAAC,uBAAuB;IACxD,cAAc,EAAE,OAAO,CAAC,cAAc;IACtC,SAAS,EAAE,OAAO,CAAC,SAAS;IAC5B,IAAI,EAAE,OAAO,CAAC,IAAI;CACrB,CAAC;AAEF,MAAM,UAAU,wBAAwB,CAAC,QAAoC;;IACzE;;;;;;;;;OASG;IACH,OAAO,MAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,oBAAoB,mCAAI,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,UAAU,CAAC;AACxC,MAAM,CAAC,MAAM,gBAAgB,GAAG,WAAW,CAAC;AAC5C,MAAM,CAAC,MAAM,cAAc,GAAG,SAAS,CAAC;AACxC,MAAM,CAAC,MAAM,yBAAyB,GAAG,oBAAoB,CAAC;AAC9D,MAAM,CAAC,MAAM,aAAa,GAAG,QAAQ,CAAC;AAEtC,MAAM,UAAU,uBAAuB,CAAC,QAAoC;IACxE,OAAO,CAAC,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,uBAAuB,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAAsB;;IAC/C,IAAI,CAAC,QAAQ,EAAE;QACX,0CAA0C;QAC1C,OAAO,CAAC,CAAC;KACZ;IACD,OAAO,MAAA,QAAQ,CAAC,SAAS,mCAAI,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,WAAW,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,gBAAgB,EAAE,UAAU,EAAE,kBAAkB,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;AAE9G,MAAM,CAAC,MAAM,2BAA2B,GAAG,YAAY,CAAC;AAExD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,UAAU,yBAAyB,CAAC,eAAsC;IAC5E,eAAe,CAAC,OAAO,GAAG;QACtB,IAAI,EAAE,WAAW,CAAC,IAAI;QACtB,IAAI,EAAE,EAAE,CAAC,gBAAgB,CAAC,EAAE,eAAe,CAAC,OAAO,EAAE;KACxD,CAAC;IACF,eAAe,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC;AAC1C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC7C,OAAgC,EAChC,QAAuB;IAEvB,MAAM,UAAU,GAAG,MAAM,YAAY,CACjC,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC,CAAC;IAC1D,qFAAqF;IACrF,mGAAmG;IACnG,uFAAuF;IACvF,0FAA0F;IAC1F,MAAM,aAAa,GAAG,0BAA0B,CAAC,UAAU,CAAC,CAAC;IAC7D,MAAM,CAAC,aAAa,GAAG,CAAC,EACpB,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACjD,OAAO,UAAU,CAAC;AACtB,CAAC","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 { IDocumentStorageService } from \"@fluidframework/driver-definitions\";\nimport { readAndParse } from \"@fluidframework/driver-utils\";\nimport { ISequencedDocumentMessage, ISnapshotTree, SummaryType } from \"@fluidframework/protocol-definitions\";\nimport { channelsTreeName, ISummaryTreeWithStats } from \"@fluidframework/runtime-definitions\";\nimport { gcTreeKey } from \"./garbageCollectionConstants\";\n\ntype OmitAttributesVersions<T> = Omit<T, \"snapshotFormatVersion\" | \"summaryFormatVersion\">;\ninterface IFluidDataStoreAttributes0 {\n readonly snapshotFormatVersion?: undefined;\n readonly summaryFormatVersion?: undefined;\n pkg: string;\n /**\n * This tells whether a data store is root. Root data stores are never collected.\n * Non-root data stores may be collected if they are not used. If this is not present, default it to\n * true. This will ensure that older data stores are incorrectly collected.\n */\n readonly isRootDataStore?: boolean;\n}\ninterface IFluidDataStoreAttributes1 extends OmitAttributesVersions<IFluidDataStoreAttributes0> {\n readonly snapshotFormatVersion: \"0.1\";\n readonly summaryFormatVersion?: undefined;\n}\ninterface IFluidDataStoreAttributes2 extends OmitAttributesVersions<IFluidDataStoreAttributes1> {\n /** Switch from snapshotFormatVersion to summaryFormatVersion */\n readonly snapshotFormatVersion?: undefined;\n readonly summaryFormatVersion: 2;\n /**\n * True if channels are not isolated in .channels subtrees, otherwise isolated.\n * This is required in both datastore attributes as well as the root container,\n * because reused summary handles may cause different format versions in each\n * datastore subtree within the summary.\n */\n readonly disableIsolatedChannels?: true;\n}\n/**\n * Added IFluidDataStoreAttributes similar to IChannelAttributes which will tell the attributes of a\n * store like the package, snapshotFormatVersion to take different decisions based on a particular\n * snapshotFormatVersion.\n */\nexport type ReadFluidDataStoreAttributes =\n | IFluidDataStoreAttributes0\n | IFluidDataStoreAttributes1\n | IFluidDataStoreAttributes2;\nexport type WriteFluidDataStoreAttributes = IFluidDataStoreAttributes1 | IFluidDataStoreAttributes2;\n\nexport function getAttributesFormatVersion(attributes: ReadFluidDataStoreAttributes): number {\n if (attributes.summaryFormatVersion) {\n /**\n * Version 2+: Introduces .channels trees for isolation of\n * channel trees from data store objects.\n */\n return attributes.summaryFormatVersion;\n } else if (attributes.snapshotFormatVersion === \"0.1\") {\n /**\n * Version 1: from this version the pkg within the data store\n * attributes blob is a JSON array rather than a string.\n */\n return 1;\n }\n /**\n * Version 0: format version is missing from summary.\n * This indicates it is an older version.\n */\n return 0;\n}\n\nexport function hasIsolatedChannels(attributes: ReadFluidDataStoreAttributes): boolean {\n return !!attributes.summaryFormatVersion && !attributes.disableIsolatedChannels;\n}\nexport interface IContainerRuntimeMetadata extends ICreateContainerMetadata, IGCMetadata {\n readonly summaryFormatVersion: 1;\n /** The last message processed at the time of summary. Only primitive property types are added to the summary. */\n readonly message: ISummaryMetadataMessage | undefined;\n /** True if channels are not isolated in .channels subtrees, otherwise isolated. */\n readonly disableIsolatedChannels?: true;\n /** The summary number for a container's summary. Incremented on summaries throughout its lifetime. */\n readonly summaryNumber?: number;\n}\n\nexport interface ICreateContainerMetadata {\n /** Runtime version of the container when it was first created */\n createContainerRuntimeVersion?: string;\n /** Timestamp of the container when it was first created */\n createContainerTimestamp?: number;\n}\n\nexport type GCVersion = number;\nexport interface IGCMetadata {\n /**\n * The version of the GC code that was run to generate the GC data that is written in the summary.\n * Also, used to determine whether GC is enabled for this container or not:\n * - A value of 0 or undefined means GC is disabled.\n * - A value greater than 0 means GC is enabled.\n */\n readonly gcFeature?: GCVersion;\n /**\n * Tells whether the GC sweep phase is enabled for this container.\n * - True means sweep phase is enabled.\n * - False means sweep phase is disabled. If GC is disabled as per gcFeature, sweep is also disabled.\n */\n readonly sweepEnabled?: boolean;\n /** If this is present, the session for this container will expire after this time and the container will close */\n readonly sessionExpiryTimeoutMs?: number;\n /** How long to wait after an object is unreferenced before deleting it via GC Sweep */\n readonly sweepTimeoutMs?: number;\n}\n\n/** The properties of an ISequencedDocumentMessage to be stored in the metadata blob in summary. */\nexport type ISummaryMetadataMessage = Pick<ISequencedDocumentMessage,\n | \"clientId\"\n | \"clientSequenceNumber\"\n | \"minimumSequenceNumber\"\n | \"referenceSequenceNumber\"\n | \"sequenceNumber\"\n | \"timestamp\"\n | \"type\">;\n\n/**\n * Extracts the properties from an ISequencedDocumentMessage as defined by ISummaryMetadataMessage. This message is\n * added to the metadata blob in summary.\n */\nexport const extractSummaryMetadataMessage = (\n message?: ISequencedDocumentMessage,\n): ISummaryMetadataMessage | undefined => message === undefined ? undefined : {\n clientId: message.clientId,\n clientSequenceNumber: message.clientSequenceNumber,\n minimumSequenceNumber: message.minimumSequenceNumber,\n referenceSequenceNumber: message.referenceSequenceNumber,\n sequenceNumber: message.sequenceNumber,\n timestamp: message.timestamp,\n type: message.type,\n};\n\nexport function getMetadataFormatVersion(metadata?: IContainerRuntimeMetadata): number {\n /**\n * Version 2+: Introduces runtime sequence number for data verification.\n *\n * Version 1+: Introduces .metadata blob and .channels trees for isolation of\n * data store trees from container-level objects.\n * Also introduces enableGC option stored in the summary.\n *\n * Version 0: metadata blob missing; format version is missing from summary.\n * This indicates it is an older version.\n */\n return metadata?.summaryFormatVersion ?? 0;\n}\n\nexport const aliasBlobName = \".aliases\";\nexport const metadataBlobName = \".metadata\";\nexport const chunksBlobName = \".chunks\";\nexport const electedSummarizerBlobName = \".electedSummarizer\";\nexport const blobsTreeName = \".blobs\";\n\nexport function rootHasIsolatedChannels(metadata?: IContainerRuntimeMetadata): boolean {\n return !!metadata && !metadata.disableIsolatedChannels;\n}\n\nexport function getGCVersion(metadata?: IGCMetadata): GCVersion {\n if (!metadata) {\n // Force to 0/disallowed in prior versions\n return 0;\n }\n return metadata.gcFeature ?? 0;\n}\n\nexport const protocolTreeName = \".protocol\";\n\n/**\n * List of tree IDs at the container level which are reserved.\n * This is for older versions of summaries that do not yet have an\n * isolated data stores namespace. Without the namespace, this must\n * be used to prevent name collisions with data store IDs.\n */\nexport const nonDataStorePaths = [protocolTreeName, \".logTail\", \".serviceProtocol\", blobsTreeName, gcTreeKey];\n\nexport const dataStoreAttributesBlobName = \".component\";\n\n/**\n * Modifies summary tree and stats to put tree under .channels tree.\n *\n * @param summarizeResult - Summary tree and stats to modify\n *\n * @example\n * Converts from:\n * ```typescript\n * {\n * type: SummaryType.Tree,\n * tree: { a: {...}, b: {...}, c: {...} },\n * }\n * ```\n *\n * to:\n *\n * ```typescript\n * {\n * type: SummaryType.Tree,\n * tree: {\n * \".channels\": {\n * type: SummaryType.Tree,\n * tree: { a: {...}, b: {...}, c: {...} }\n * },\n * },\n * }\n * ```\n * And adds +1 to treeNodeCount in stats.\n */\nexport function wrapSummaryInChannelsTree(summarizeResult: ISummaryTreeWithStats): void {\n summarizeResult.summary = {\n type: SummaryType.Tree,\n tree: { [channelsTreeName]: summarizeResult.summary },\n };\n summarizeResult.stats.treeNodeCount++;\n}\n\nexport async function getFluidDataStoreAttributes(\n storage: IDocumentStorageService,\n snapshot: ISnapshotTree,\n): Promise<ReadFluidDataStoreAttributes> {\n const attributes = await readAndParse<ReadFluidDataStoreAttributes>(\n storage, snapshot.blobs[dataStoreAttributesBlobName]);\n // Use the snapshotFormatVersion to determine how the pkg is encoded in the snapshot.\n // For snapshotFormatVersion = \"0.1\" (1) or above, pkg is jsonified, otherwise it is just a string.\n // However the feature of loading a detached container from snapshot, is added when the\n // snapshotFormatVersion is at least \"0.1\" (1), so we don't expect it to be anything else.\n const formatVersion = getAttributesFormatVersion(attributes);\n assert(formatVersion > 0,\n 0x1d5 /* Invalid snapshot format version */);\n return attributes;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/container-runtime",
3
- "version": "2.0.0-internal.2.1.1",
3
+ "version": "2.0.0-internal.2.2.0",
4
4
  "description": "Fluid container runtime",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -28,15 +28,19 @@
28
28
  "clean": "rimraf dist lib *.tsbuildinfo *.build.log",
29
29
  "eslint": "eslint --format stylish src",
30
30
  "eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
31
+ "format": "npm run prettier:fix",
31
32
  "lint": "npm run eslint",
32
33
  "lint:fix": "npm run eslint:fix",
34
+ "prettier": "prettier --check . --ignore-path ../../../.prettierignore",
35
+ "prettier:fix": "prettier --write . --ignore-path ../../../.prettierignore",
33
36
  "test": "npm run test:mocha",
34
37
  "test:coverage": "nyc npm test -- --reporter xunit --reporter-option output=nyc/junit-report.xml",
35
38
  "test:mocha": "mocha --ignore 'dist/test/types/*' --recursive dist/test -r node_modules/@fluidframework/mocha-test-setup --unhandled-rejections=strict",
36
39
  "test:mocha:verbose": "cross-env FLUID_TEST_VERBOSE=1 npm run test:mocha",
37
40
  "tsc": "tsc",
38
41
  "tsc:watch": "tsc --watch",
39
- "typetests:gen": "fluid-type-validator -g -d ."
42
+ "typetests:gen": "flub generate typetests --generate --dir .",
43
+ "typetests:prepare": "flub generate typetests --prepare --dir . --pin"
40
44
  },
41
45
  "nyc": {
42
46
  "all": true,
@@ -61,31 +65,31 @@
61
65
  "dependencies": {
62
66
  "@fluidframework/common-definitions": "^0.20.1",
63
67
  "@fluidframework/common-utils": "^1.0.0",
64
- "@fluidframework/container-definitions": ">=2.0.0-internal.2.1.1 <2.0.0-internal.3.0.0",
65
- "@fluidframework/container-runtime-definitions": ">=2.0.0-internal.2.1.1 <2.0.0-internal.3.0.0",
66
- "@fluidframework/container-utils": ">=2.0.0-internal.2.1.1 <2.0.0-internal.3.0.0",
67
- "@fluidframework/core-interfaces": ">=2.0.0-internal.2.1.1 <2.0.0-internal.3.0.0",
68
- "@fluidframework/datastore": ">=2.0.0-internal.2.1.1 <2.0.0-internal.3.0.0",
69
- "@fluidframework/driver-definitions": ">=2.0.0-internal.2.1.1 <2.0.0-internal.3.0.0",
70
- "@fluidframework/driver-utils": ">=2.0.0-internal.2.1.1 <2.0.0-internal.3.0.0",
71
- "@fluidframework/garbage-collector": ">=2.0.0-internal.2.1.1 <2.0.0-internal.3.0.0",
68
+ "@fluidframework/container-definitions": ">=2.0.0-internal.2.2.0 <2.0.0-internal.3.0.0",
69
+ "@fluidframework/container-runtime-definitions": ">=2.0.0-internal.2.2.0 <2.0.0-internal.3.0.0",
70
+ "@fluidframework/container-utils": ">=2.0.0-internal.2.2.0 <2.0.0-internal.3.0.0",
71
+ "@fluidframework/core-interfaces": ">=2.0.0-internal.2.2.0 <2.0.0-internal.3.0.0",
72
+ "@fluidframework/datastore": ">=2.0.0-internal.2.2.0 <2.0.0-internal.3.0.0",
73
+ "@fluidframework/driver-definitions": ">=2.0.0-internal.2.2.0 <2.0.0-internal.3.0.0",
74
+ "@fluidframework/driver-utils": ">=2.0.0-internal.2.2.0 <2.0.0-internal.3.0.0",
75
+ "@fluidframework/garbage-collector": ">=2.0.0-internal.2.2.0 <2.0.0-internal.3.0.0",
72
76
  "@fluidframework/protocol-base": "^0.1038.2000",
73
77
  "@fluidframework/protocol-definitions": "^1.1.0",
74
- "@fluidframework/runtime-definitions": ">=2.0.0-internal.2.1.1 <2.0.0-internal.3.0.0",
75
- "@fluidframework/runtime-utils": ">=2.0.0-internal.2.1.1 <2.0.0-internal.3.0.0",
76
- "@fluidframework/telemetry-utils": ">=2.0.0-internal.2.1.1 <2.0.0-internal.3.0.0",
78
+ "@fluidframework/runtime-definitions": ">=2.0.0-internal.2.2.0 <2.0.0-internal.3.0.0",
79
+ "@fluidframework/runtime-utils": ">=2.0.0-internal.2.2.0 <2.0.0-internal.3.0.0",
80
+ "@fluidframework/telemetry-utils": ">=2.0.0-internal.2.2.0 <2.0.0-internal.3.0.0",
77
81
  "double-ended-queue": "^2.1.0-0",
78
82
  "lz4js": "^0.2.0",
79
83
  "uuid": "^8.3.1"
80
84
  },
81
85
  "devDependencies": {
82
- "@fluid-tools/build-cli": "^0.5.0",
86
+ "@fluid-tools/build-cli": "^0.7.0",
83
87
  "@fluidframework/build-common": "^1.1.0",
84
- "@fluidframework/build-tools": "^0.5.0",
85
- "@fluidframework/container-runtime-previous": "npm:@fluidframework/container-runtime@2.0.0-internal.2.0.0",
86
- "@fluidframework/eslint-config-fluid": "^1.1.0",
87
- "@fluidframework/mocha-test-setup": ">=2.0.0-internal.2.1.1 <2.0.0-internal.3.0.0",
88
- "@fluidframework/test-runtime-utils": ">=2.0.0-internal.2.1.1 <2.0.0-internal.3.0.0",
88
+ "@fluidframework/build-tools": "^0.7.0",
89
+ "@fluidframework/container-runtime-previous": "npm:@fluidframework/container-runtime@2.0.0-internal.2.1.0",
90
+ "@fluidframework/eslint-config-fluid": "^1.2.0",
91
+ "@fluidframework/mocha-test-setup": ">=2.0.0-internal.2.2.0 <2.0.0-internal.3.0.0",
92
+ "@fluidframework/test-runtime-utils": ">=2.0.0-internal.2.2.0 <2.0.0-internal.3.0.0",
89
93
  "@microsoft/api-extractor": "^7.22.2",
90
94
  "@rushstack/eslint-config": "^2.5.1",
91
95
  "@types/double-ended-queue": "^2.1.0",
@@ -104,9 +108,19 @@
104
108
  "typescript": "~4.5.5"
105
109
  },
106
110
  "typeValidation": {
107
- "version": "2.0.0-internal.2.1.0",
111
+ "version": "2.0.0-internal.2.2.0",
112
+ "baselineRange": ">=2.0.0-internal.2.1.0 <2.0.0-internal.2.2.0",
113
+ "baselineVersion": "2.0.0-internal.2.1.0",
108
114
  "broken": {
109
- "RemovedInterfaceDeclaration_IGarbageCollectionRuntime": {
115
+ "InterfaceDeclaration_ICompressionRuntimeOptions": {
116
+ "backCompat": false,
117
+ "forwardCompat": false
118
+ },
119
+ "InterfaceDeclaration_IContainerRuntimeOptions": {
120
+ "backCompat": false,
121
+ "forwardCompat": false
122
+ },
123
+ "ClassDeclaration_ContainerRuntime": {
110
124
  "forwardCompat": false,
111
125
  "backCompat": false
112
126
  }
@@ -0,0 +1,8 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ module.exports = {
7
+ ...require("@fluidframework/build-common/prettier.config.cjs"),
8
+ };