@fluidframework/container-runtime 2.0.0-dev-rc.2.0.0.245554 → 2.0.0-dev-rc.2.0.0.246488

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 (81) hide show
  1. package/api-report/container-runtime.api.md +3 -2
  2. package/dist/channelCollection.d.ts +1 -0
  3. package/dist/channelCollection.d.ts.map +1 -1
  4. package/dist/channelCollection.js +13 -8
  5. package/dist/channelCollection.js.map +1 -1
  6. package/dist/container-runtime-alpha.d.ts +0 -1
  7. package/dist/container-runtime-beta.d.ts +0 -1
  8. package/dist/container-runtime-public.d.ts +0 -1
  9. package/dist/container-runtime-untrimmed.d.ts +2 -2
  10. package/dist/containerRuntime.d.ts.map +1 -1
  11. package/dist/containerRuntime.js +22 -14
  12. package/dist/containerRuntime.js.map +1 -1
  13. package/dist/dataStoreContext.d.ts +1 -1
  14. package/dist/dataStoreContext.d.ts.map +1 -1
  15. package/dist/dataStoreContext.js.map +1 -1
  16. package/dist/dataStoreRegistry.d.ts +4 -0
  17. package/dist/dataStoreRegistry.d.ts.map +1 -1
  18. package/dist/dataStoreRegistry.js +2 -2
  19. package/dist/dataStoreRegistry.js.map +1 -1
  20. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  21. package/dist/opLifecycle/outbox.js +12 -6
  22. package/dist/opLifecycle/outbox.js.map +1 -1
  23. package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  24. package/dist/opLifecycle/remoteMessageProcessor.js +5 -2
  25. package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
  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/scheduleManager.d.ts.map +1 -1
  30. package/dist/scheduleManager.js +4 -0
  31. package/dist/scheduleManager.js.map +1 -1
  32. package/dist/summary/orderedClientElection.d.ts.map +1 -1
  33. package/dist/summary/orderedClientElection.js +4 -0
  34. package/dist/summary/orderedClientElection.js.map +1 -1
  35. package/lib/channelCollection.d.ts +1 -0
  36. package/lib/channelCollection.d.ts.map +1 -1
  37. package/lib/channelCollection.js +13 -8
  38. package/lib/channelCollection.js.map +1 -1
  39. package/lib/container-runtime-alpha.d.ts +0 -1
  40. package/lib/container-runtime-beta.d.ts +0 -1
  41. package/lib/container-runtime-public.d.ts +0 -1
  42. package/lib/container-runtime-untrimmed.d.ts +2 -2
  43. package/lib/containerRuntime.d.ts.map +1 -1
  44. package/lib/containerRuntime.js +22 -14
  45. package/lib/containerRuntime.js.map +1 -1
  46. package/lib/dataStoreContext.d.ts +1 -1
  47. package/lib/dataStoreContext.d.ts.map +1 -1
  48. package/lib/dataStoreContext.js.map +1 -1
  49. package/lib/dataStoreRegistry.d.ts +4 -0
  50. package/lib/dataStoreRegistry.d.ts.map +1 -1
  51. package/lib/dataStoreRegistry.js.map +1 -1
  52. package/lib/opLifecycle/outbox.d.ts.map +1 -1
  53. package/lib/opLifecycle/outbox.js +12 -6
  54. package/lib/opLifecycle/outbox.js.map +1 -1
  55. package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  56. package/lib/opLifecycle/remoteMessageProcessor.js +5 -2
  57. package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
  58. package/lib/packageVersion.d.ts +1 -1
  59. package/lib/packageVersion.js +1 -1
  60. package/lib/packageVersion.js.map +1 -1
  61. package/lib/scheduleManager.d.ts.map +1 -1
  62. package/lib/scheduleManager.js +4 -0
  63. package/lib/scheduleManager.js.map +1 -1
  64. package/lib/summary/orderedClientElection.d.ts.map +1 -1
  65. package/lib/summary/orderedClientElection.js +4 -0
  66. package/lib/summary/orderedClientElection.js.map +1 -1
  67. package/lib/test/dataStoreCreation.spec.js.map +1 -1
  68. package/lib/test/dataStoreRegistry.spec.js.map +1 -1
  69. package/lib/test/fuzz/summarizerFuzzSuite.js.map +1 -1
  70. package/lib/test/opLifecycle/opSplitter.spec.js.map +1 -1
  71. package/lib/test/throttler.spec.js.map +1 -1
  72. package/package.json +16 -16
  73. package/src/channelCollection.ts +15 -9
  74. package/src/containerRuntime.ts +23 -16
  75. package/src/dataStoreContext.ts +1 -1
  76. package/src/dataStoreRegistry.ts +1 -0
  77. package/src/opLifecycle/outbox.ts +14 -7
  78. package/src/opLifecycle/remoteMessageProcessor.ts +6 -2
  79. package/src/packageVersion.ts +1 -1
  80. package/src/scheduleManager.ts +1 -0
  81. package/src/summary/orderedClientElection.ts +1 -0
@@ -1 +1 @@
1
- {"version":3,"file":"dataStoreCreation.spec.js","sourceRoot":"","sources":["../../src/test/dataStoreCreation.spec.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 */\nimport { strict as assert } from \"assert\";\n\nimport { FluidObject } from \"@fluidframework/core-interfaces\";\nimport { IDocumentStorageService } from \"@fluidframework/driver-definitions\";\nimport {\n\tIFluidDataStoreContext,\n\tIFluidDataStoreFactory,\n\tIFluidDataStoreRegistry,\n\tFluidDataStoreRegistryEntry,\n\tNamedFluidDataStoreRegistryEntries,\n\tSummarizeInternalFn,\n\tCreateChildSummarizerNodeFn,\n\tCreateSummarizerNodeSource,\n} from \"@fluidframework/runtime-definitions\";\nimport { createChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { MockFluidDataStoreRuntime } from \"@fluidframework/test-runtime-utils\";\n\nimport { LocalFluidDataStoreContext } from \"../dataStoreContext.js\";\nimport { wrapContextForInnerChannel } from \"../channelCollection.js\";\nimport { ContainerRuntime } from \"../containerRuntime.js\";\nimport { createRootSummarizerNodeWithGC } from \"../summary/index.js\";\n\ndescribe(\"Data Store Creation Tests\", () => {\n\tdescribe(\"Store creation via local context creation and realize\", () => {\n\t\t/**\n\t\t * These tests simulate dataStore and subDataStore creation by creating local contexts and realizing them.\n\t\t * The dataStore tree for these tests is as follows:\n\t\t *\n\t\t * ```\n\t\t * Default\n\t\t * |\n\t\t * |\n\t\t * DataStore A\n\t\t * / \\\\\n\t\t * / \\\\\n\t\t * DataStore B DataStore C\n\t\t * ```\n\t\t */\n\n\t\tlet storage: IDocumentStorageService;\n\t\tlet scope: FluidObject;\n\t\tconst makeLocallyVisibleFn = () => {};\n\t\tlet containerRuntime: ContainerRuntime;\n\t\tconst defaultName = \"default\";\n\t\tconst dataStoreAName = \"dataStoreA\";\n\t\tconst dataStoreBName = \"dataStoreB\";\n\t\tconst dataStoreCName = \"dataStoreC\";\n\t\tlet getCreateSummarizerNodeFn: (id: string) => CreateChildSummarizerNodeFn;\n\n\t\t// Helper function that creates a FluidDataStoreRegistryEntry with the registry entries\n\t\t// provided to it.\n\t\tfunction createDataStoreRegistryEntry(\n\t\t\tentries: NamedFluidDataStoreRegistryEntries,\n\t\t): FluidDataStoreRegistryEntry {\n\t\t\tconst registryEntries = new Map(entries);\n\t\t\tconst factory: IFluidDataStoreFactory = {\n\t\t\t\ttype: \"store-type\",\n\t\t\t\tget IFluidDataStoreFactory() {\n\t\t\t\t\treturn factory;\n\t\t\t\t},\n\t\t\t\tinstantiateDataStore: async (context: IFluidDataStoreContext) =>\n\t\t\t\t\tnew MockFluidDataStoreRuntime(),\n\t\t\t};\n\t\t\tconst registry: IFluidDataStoreRegistry = {\n\t\t\t\tget IFluidDataStoreRegistry() {\n\t\t\t\t\treturn registry;\n\t\t\t\t},\n\t\t\t\t// Returns the registry entry as per the entries provided in the param.\n\t\t\t\tget: async (pkg) => registryEntries.get(pkg),\n\t\t\t};\n\n\t\t\tconst entry: FluidDataStoreRegistryEntry = {\n\t\t\t\tget IFluidDataStoreFactory() {\n\t\t\t\t\treturn factory;\n\t\t\t\t},\n\t\t\t\tget IFluidDataStoreRegistry() {\n\t\t\t\t\treturn registry;\n\t\t\t\t},\n\t\t\t};\n\t\t\treturn entry;\n\t\t}\n\n\t\tbeforeEach(async () => {\n\t\t\t// DataStore B is a leaf dataStore and its registry does not have any entries.\n\t\t\tconst entryB = createDataStoreRegistryEntry([]);\n\t\t\t// DataStore C is a leaf dataStore and its registry does not have any entries.\n\t\t\tconst entryC = createDataStoreRegistryEntry([]);\n\t\t\t// DataStore A's registry has entries for dataStore B and dataStore C.\n\t\t\tconst entryA = createDataStoreRegistryEntry([\n\t\t\t\t[dataStoreBName, Promise.resolve(entryB)],\n\t\t\t\t[dataStoreCName, Promise.resolve(entryC)],\n\t\t\t]);\n\t\t\t// The default dataStore's registry has entry for only dataStore A.\n\t\t\tconst entryDefault = createDataStoreRegistryEntry([\n\t\t\t\t[dataStoreAName, Promise.resolve(entryA)],\n\t\t\t]);\n\n\t\t\t// Create the global registry for the container that can only create the default dataStore.\n\t\t\tconst globalRegistryEntries = new Map([[defaultName, Promise.resolve(entryDefault)]]);\n\t\t\tconst globalRegistry: IFluidDataStoreRegistry = {\n\t\t\t\tget IFluidDataStoreRegistry() {\n\t\t\t\t\treturn globalRegistry;\n\t\t\t\t},\n\t\t\t\tget: async (pkg) => globalRegistryEntries.get(pkg),\n\t\t\t};\n\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\tcontainerRuntime = {\n\t\t\t\tIFluidDataStoreRegistry: globalRegistry,\n\t\t\t\ton: (event, listener) => {},\n\t\t\t\tlogger: createChildLogger(),\n\t\t\t\tclientDetails: {},\n\t\t\t} as ContainerRuntime;\n\t\t\tconst summarizerNode = createRootSummarizerNodeWithGC(\n\t\t\t\tcreateChildLogger(),\n\t\t\t\t(() => {}) as unknown as SummarizeInternalFn,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t);\n\t\t\tgetCreateSummarizerNodeFn = (id: string) => (si: SummarizeInternalFn) =>\n\t\t\t\tsummarizerNode.createChild(si, id, { type: CreateSummarizerNodeSource.Local });\n\t\t});\n\n\t\tit(\"Valid global dataStore\", async () => {\n\t\t\tlet success: boolean = true;\n\t\t\tconst dataStoreId = \"default-Id\";\n\t\t\t// Create the default dataStore that is in the global registry.\n\t\t\tconst context: LocalFluidDataStoreContext = new LocalFluidDataStoreContext({\n\t\t\t\tid: dataStoreId,\n\t\t\t\tpkg: [defaultName],\n\t\t\t\tparentContext: wrapContextForInnerChannel(dataStoreId, containerRuntime),\n\t\t\t\tstorage,\n\t\t\t\tscope,\n\t\t\t\tcreateSummarizerNodeFn: getCreateSummarizerNodeFn(dataStoreId),\n\t\t\t\tmakeLocallyVisibleFn,\n\t\t\t\tsnapshotTree: undefined,\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\tawait context.realize();\n\t\t\t} catch (error) {\n\t\t\t\tsuccess = false;\n\t\t\t}\n\t\t\t// Verify that realize was successful.\n\t\t\tassert.strictEqual(success, true);\n\t\t});\n\n\t\tit(\"Invalid global dataStore\", async () => {\n\t\t\tlet success: boolean = true;\n\t\t\tconst dataStoreId = \"A-Id\";\n\t\t\t// Create dataStore A that is not in the global registry.\n\t\t\tconst context: LocalFluidDataStoreContext = new LocalFluidDataStoreContext({\n\t\t\t\tid: dataStoreId,\n\t\t\t\tpkg: [dataStoreAName],\n\t\t\t\tparentContext: wrapContextForInnerChannel(dataStoreId, containerRuntime),\n\t\t\t\tstorage,\n\t\t\t\tscope,\n\t\t\t\tcreateSummarizerNodeFn: getCreateSummarizerNodeFn(dataStoreId),\n\t\t\t\tmakeLocallyVisibleFn,\n\t\t\t\tsnapshotTree: undefined,\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\tawait context.realize();\n\t\t\t} catch (error) {\n\t\t\t\tsuccess = false;\n\t\t\t}\n\t\t\t// Verify that realize throws an error.\n\t\t\tassert.strictEqual(success, false);\n\t\t});\n\n\t\tit(\"Valid subDataStore from the global dataStore\", async () => {\n\t\t\tlet success: boolean = true;\n\t\t\tconst dataStoreId = \"A-Id\";\n\t\t\t// Create dataStore A that is in the registry of the default dataStore.\n\t\t\tconst contextA: LocalFluidDataStoreContext = new LocalFluidDataStoreContext({\n\t\t\t\tid: dataStoreId,\n\t\t\t\tpkg: [defaultName, dataStoreAName],\n\t\t\t\tparentContext: wrapContextForInnerChannel(dataStoreId, containerRuntime),\n\t\t\t\tstorage,\n\t\t\t\tscope,\n\t\t\t\tcreateSummarizerNodeFn: getCreateSummarizerNodeFn(dataStoreId),\n\t\t\t\tmakeLocallyVisibleFn,\n\t\t\t\tsnapshotTree: undefined,\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\tawait contextA.realize();\n\t\t\t} catch (error) {\n\t\t\t\tsuccess = false;\n\t\t\t}\n\t\t\t// Verify that realize was successful.\n\t\t\tassert.strictEqual(success, true);\n\t\t});\n\n\t\tit(\"Invalid subDataStore from the global dataStore\", async () => {\n\t\t\tlet success: boolean = true;\n\t\t\tconst dataStoreId = \"B-Id\";\n\t\t\t// Create dataStore B that is in not the registry of the default dataStore.\n\t\t\tconst contextB: LocalFluidDataStoreContext = new LocalFluidDataStoreContext({\n\t\t\t\tid: dataStoreId,\n\t\t\t\tpkg: [defaultName, dataStoreBName],\n\t\t\t\tparentContext: wrapContextForInnerChannel(dataStoreId, containerRuntime),\n\t\t\t\tstorage,\n\t\t\t\tscope,\n\t\t\t\tcreateSummarizerNodeFn: getCreateSummarizerNodeFn(dataStoreId),\n\t\t\t\tmakeLocallyVisibleFn,\n\t\t\t\tsnapshotTree: undefined,\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\tawait contextB.realize();\n\t\t\t} catch (error) {\n\t\t\t\tsuccess = false;\n\t\t\t}\n\t\t\t// Verify that realize throws an error.\n\t\t\tassert.strictEqual(success, false);\n\t\t});\n\n\t\tit(\"Valid subDataStore at depth 2\", async () => {\n\t\t\tlet success: boolean = true;\n\t\t\tconst dataStoreBId = \"B-Id\";\n\t\t\t// Create dataStore B that is in the registry of dataStore A (which is at depth 2).\n\t\t\tconst contextB: LocalFluidDataStoreContext = new LocalFluidDataStoreContext({\n\t\t\t\tid: dataStoreBId,\n\t\t\t\tpkg: [defaultName, dataStoreAName, dataStoreBName],\n\t\t\t\tparentContext: wrapContextForInnerChannel(dataStoreBId, containerRuntime),\n\t\t\t\tstorage,\n\t\t\t\tscope,\n\t\t\t\tcreateSummarizerNodeFn: getCreateSummarizerNodeFn(dataStoreBId),\n\t\t\t\tmakeLocallyVisibleFn,\n\t\t\t\tsnapshotTree: undefined,\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\tawait contextB.realize();\n\t\t\t} catch (error) {\n\t\t\t\tsuccess = false;\n\t\t\t}\n\t\t\t// Verify that realize was successful.\n\t\t\tassert.strictEqual(success, true);\n\n\t\t\tconst dataStoreCId = \"C-Id\";\n\t\t\t// Create dataStore C that is in the registry of dataStore A (which is at depth 2).\n\t\t\tconst contextC: LocalFluidDataStoreContext = new LocalFluidDataStoreContext({\n\t\t\t\tid: dataStoreCId,\n\t\t\t\tpkg: [defaultName, dataStoreAName, dataStoreCName],\n\t\t\t\tparentContext: wrapContextForInnerChannel(dataStoreCId, containerRuntime),\n\t\t\t\tstorage,\n\t\t\t\tscope,\n\t\t\t\tcreateSummarizerNodeFn: getCreateSummarizerNodeFn(dataStoreCId),\n\t\t\t\tmakeLocallyVisibleFn,\n\t\t\t\tsnapshotTree: undefined,\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\tawait contextC.realize();\n\t\t\t} catch (error) {\n\t\t\t\tsuccess = false;\n\t\t\t}\n\t\t\t// Verify that realize was successful.\n\t\t\tassert.strictEqual(success, true);\n\t\t});\n\n\t\tit(\"Invalid subDataStore at depth 2\", async () => {\n\t\t\tlet success: boolean = true;\n\t\t\tconst dataStoreId = \"fake-Id\";\n\t\t\t// Create a fake dataStore that is not in the registry of dataStore A (which is at depth 2).\n\t\t\tconst contextFake: LocalFluidDataStoreContext = new LocalFluidDataStoreContext({\n\t\t\t\tid: dataStoreId,\n\t\t\t\tpkg: [defaultName, dataStoreAName, \"fake\"],\n\t\t\t\tparentContext: wrapContextForInnerChannel(dataStoreId, containerRuntime),\n\t\t\t\tstorage,\n\t\t\t\tscope,\n\t\t\t\tcreateSummarizerNodeFn: getCreateSummarizerNodeFn(dataStoreId),\n\t\t\t\tmakeLocallyVisibleFn,\n\t\t\t\tsnapshotTree: undefined,\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\tawait contextFake.realize();\n\t\t\t} catch (error) {\n\t\t\t\tsuccess = false;\n\t\t\t}\n\t\t\t// Verify that realize throws an error.\n\t\t\tassert.strictEqual(success, false);\n\t\t});\n\n\t\tit(\"Invalid subDataStore at depth 3\", async () => {\n\t\t\tlet success: boolean = true;\n\t\t\tconst dataStoreId = \"fake-Id\";\n\t\t\t// Create a fake dataStore that is not in the registry of dataStore B (which is at depth 3).\n\t\t\tconst contextFake: LocalFluidDataStoreContext = new LocalFluidDataStoreContext({\n\t\t\t\tid: dataStoreId,\n\t\t\t\tpkg: [defaultName, dataStoreAName, \"fake\"],\n\t\t\t\tparentContext: wrapContextForInnerChannel(dataStoreId, containerRuntime),\n\t\t\t\tstorage,\n\t\t\t\tscope,\n\t\t\t\tcreateSummarizerNodeFn: getCreateSummarizerNodeFn(dataStoreId),\n\t\t\t\tmakeLocallyVisibleFn,\n\t\t\t\tsnapshotTree: undefined,\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\tawait contextFake.realize();\n\t\t\t} catch (error) {\n\t\t\t\tsuccess = false;\n\t\t\t}\n\t\t\t// Verify that realize throws an error.\n\t\t\tassert.strictEqual(success, false);\n\t\t});\n\n\t\tit(\"SubDataStore which is in the registry of the parent dataStore\", async () => {\n\t\t\tlet success: boolean = true;\n\t\t\tconst dataStoreId = \"C-Id\";\n\t\t\t// Create dataStore C that is in parent's registry but not in the registry of dataStore B.\n\t\t\tconst contextC: LocalFluidDataStoreContext = new LocalFluidDataStoreContext({\n\t\t\t\tid: dataStoreId,\n\t\t\t\tpkg: [defaultName, dataStoreAName, dataStoreBName, dataStoreCName],\n\t\t\t\tparentContext: wrapContextForInnerChannel(dataStoreId, containerRuntime),\n\t\t\t\tstorage,\n\t\t\t\tscope,\n\t\t\t\tcreateSummarizerNodeFn: getCreateSummarizerNodeFn(dataStoreId),\n\t\t\t\tmakeLocallyVisibleFn,\n\t\t\t\tsnapshotTree: undefined,\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\tawait contextC.realize();\n\t\t\t} catch (error) {\n\t\t\t\tsuccess = false;\n\t\t\t}\n\t\t\t// Verify that realize throws an error.\n\t\t\tassert.strictEqual(success, false);\n\t\t});\n\t});\n});\n"]}
1
+ {"version":3,"file":"dataStoreCreation.spec.js","sourceRoot":"","sources":["../../src/test/dataStoreCreation.spec.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 { strict as assert } from \"assert\";\n\nimport { FluidObject } from \"@fluidframework/core-interfaces\";\nimport { IDocumentStorageService } from \"@fluidframework/driver-definitions\";\nimport {\n\tIFluidDataStoreContext,\n\tIFluidDataStoreFactory,\n\tIFluidDataStoreRegistry,\n\tFluidDataStoreRegistryEntry,\n\tNamedFluidDataStoreRegistryEntries,\n\tSummarizeInternalFn,\n\tCreateChildSummarizerNodeFn,\n\tCreateSummarizerNodeSource,\n} from \"@fluidframework/runtime-definitions\";\nimport { createChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { MockFluidDataStoreRuntime } from \"@fluidframework/test-runtime-utils\";\n\nimport { LocalFluidDataStoreContext } from \"../dataStoreContext.js\";\nimport { wrapContextForInnerChannel } from \"../channelCollection.js\";\nimport { ContainerRuntime } from \"../containerRuntime.js\";\nimport { createRootSummarizerNodeWithGC } from \"../summary/index.js\";\n\ndescribe(\"Data Store Creation Tests\", () => {\n\tdescribe(\"Store creation via local context creation and realize\", () => {\n\t\t/**\n\t\t * These tests simulate dataStore and subDataStore creation by creating local contexts and realizing them.\n\t\t * The dataStore tree for these tests is as follows:\n\t\t *\n\t\t * ```\n\t\t * Default\n\t\t * |\n\t\t * |\n\t\t * DataStore A\n\t\t * / \\\\\n\t\t * / \\\\\n\t\t * DataStore B DataStore C\n\t\t * ```\n\t\t */\n\n\t\tlet storage: IDocumentStorageService;\n\t\tlet scope: FluidObject;\n\t\tconst makeLocallyVisibleFn = () => {};\n\t\tlet containerRuntime: ContainerRuntime;\n\t\tconst defaultName = \"default\";\n\t\tconst dataStoreAName = \"dataStoreA\";\n\t\tconst dataStoreBName = \"dataStoreB\";\n\t\tconst dataStoreCName = \"dataStoreC\";\n\t\tlet getCreateSummarizerNodeFn: (id: string) => CreateChildSummarizerNodeFn;\n\n\t\t// Helper function that creates a FluidDataStoreRegistryEntry with the registry entries\n\t\t// provided to it.\n\t\tfunction createDataStoreRegistryEntry(\n\t\t\tentries: NamedFluidDataStoreRegistryEntries,\n\t\t): FluidDataStoreRegistryEntry {\n\t\t\tconst registryEntries = new Map(entries);\n\t\t\tconst factory: IFluidDataStoreFactory = {\n\t\t\t\ttype: \"store-type\",\n\t\t\t\tget IFluidDataStoreFactory() {\n\t\t\t\t\treturn factory;\n\t\t\t\t},\n\t\t\t\tinstantiateDataStore: async (context: IFluidDataStoreContext) =>\n\t\t\t\t\tnew MockFluidDataStoreRuntime(),\n\t\t\t};\n\t\t\tconst registry: IFluidDataStoreRegistry = {\n\t\t\t\tget IFluidDataStoreRegistry() {\n\t\t\t\t\treturn registry;\n\t\t\t\t},\n\t\t\t\t// Returns the registry entry as per the entries provided in the param.\n\t\t\t\tget: async (pkg) => registryEntries.get(pkg),\n\t\t\t};\n\n\t\t\tconst entry: FluidDataStoreRegistryEntry = {\n\t\t\t\tget IFluidDataStoreFactory() {\n\t\t\t\t\treturn factory;\n\t\t\t\t},\n\t\t\t\tget IFluidDataStoreRegistry() {\n\t\t\t\t\treturn registry;\n\t\t\t\t},\n\t\t\t};\n\t\t\treturn entry;\n\t\t}\n\n\t\tbeforeEach(async () => {\n\t\t\t// DataStore B is a leaf dataStore and its registry does not have any entries.\n\t\t\tconst entryB = createDataStoreRegistryEntry([]);\n\t\t\t// DataStore C is a leaf dataStore and its registry does not have any entries.\n\t\t\tconst entryC = createDataStoreRegistryEntry([]);\n\t\t\t// DataStore A's registry has entries for dataStore B and dataStore C.\n\t\t\tconst entryA = createDataStoreRegistryEntry([\n\t\t\t\t[dataStoreBName, Promise.resolve(entryB)],\n\t\t\t\t[dataStoreCName, Promise.resolve(entryC)],\n\t\t\t]);\n\t\t\t// The default dataStore's registry has entry for only dataStore A.\n\t\t\tconst entryDefault = createDataStoreRegistryEntry([\n\t\t\t\t[dataStoreAName, Promise.resolve(entryA)],\n\t\t\t]);\n\n\t\t\t// Create the global registry for the container that can only create the default dataStore.\n\t\t\tconst globalRegistryEntries = new Map([[defaultName, Promise.resolve(entryDefault)]]);\n\t\t\tconst globalRegistry: IFluidDataStoreRegistry = {\n\t\t\t\tget IFluidDataStoreRegistry() {\n\t\t\t\t\treturn globalRegistry;\n\t\t\t\t},\n\t\t\t\tget: async (pkg) => globalRegistryEntries.get(pkg),\n\t\t\t};\n\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\tcontainerRuntime = {\n\t\t\t\tIFluidDataStoreRegistry: globalRegistry,\n\t\t\t\ton: (event, listener) => {},\n\t\t\t\tlogger: createChildLogger(),\n\t\t\t\tclientDetails: {},\n\t\t\t} as ContainerRuntime;\n\t\t\tconst summarizerNode = createRootSummarizerNodeWithGC(\n\t\t\t\tcreateChildLogger(),\n\t\t\t\t(() => {}) as unknown as SummarizeInternalFn,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t);\n\t\t\tgetCreateSummarizerNodeFn = (id: string) => (si: SummarizeInternalFn) =>\n\t\t\t\tsummarizerNode.createChild(si, id, { type: CreateSummarizerNodeSource.Local });\n\t\t});\n\n\t\tit(\"Valid global dataStore\", async () => {\n\t\t\tlet success: boolean = true;\n\t\t\tconst dataStoreId = \"default-Id\";\n\t\t\t// Create the default dataStore that is in the global registry.\n\t\t\tconst context: LocalFluidDataStoreContext = new LocalFluidDataStoreContext({\n\t\t\t\tid: dataStoreId,\n\t\t\t\tpkg: [defaultName],\n\t\t\t\tparentContext: wrapContextForInnerChannel(dataStoreId, containerRuntime),\n\t\t\t\tstorage,\n\t\t\t\tscope,\n\t\t\t\tcreateSummarizerNodeFn: getCreateSummarizerNodeFn(dataStoreId),\n\t\t\t\tmakeLocallyVisibleFn,\n\t\t\t\tsnapshotTree: undefined,\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\tawait context.realize();\n\t\t\t} catch (error) {\n\t\t\t\tsuccess = false;\n\t\t\t}\n\t\t\t// Verify that realize was successful.\n\t\t\tassert.strictEqual(success, true);\n\t\t});\n\n\t\tit(\"Invalid global dataStore\", async () => {\n\t\t\tlet success: boolean = true;\n\t\t\tconst dataStoreId = \"A-Id\";\n\t\t\t// Create dataStore A that is not in the global registry.\n\t\t\tconst context: LocalFluidDataStoreContext = new LocalFluidDataStoreContext({\n\t\t\t\tid: dataStoreId,\n\t\t\t\tpkg: [dataStoreAName],\n\t\t\t\tparentContext: wrapContextForInnerChannel(dataStoreId, containerRuntime),\n\t\t\t\tstorage,\n\t\t\t\tscope,\n\t\t\t\tcreateSummarizerNodeFn: getCreateSummarizerNodeFn(dataStoreId),\n\t\t\t\tmakeLocallyVisibleFn,\n\t\t\t\tsnapshotTree: undefined,\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\tawait context.realize();\n\t\t\t} catch (error) {\n\t\t\t\tsuccess = false;\n\t\t\t}\n\t\t\t// Verify that realize throws an error.\n\t\t\tassert.strictEqual(success, false);\n\t\t});\n\n\t\tit(\"Valid subDataStore from the global dataStore\", async () => {\n\t\t\tlet success: boolean = true;\n\t\t\tconst dataStoreId = \"A-Id\";\n\t\t\t// Create dataStore A that is in the registry of the default dataStore.\n\t\t\tconst contextA: LocalFluidDataStoreContext = new LocalFluidDataStoreContext({\n\t\t\t\tid: dataStoreId,\n\t\t\t\tpkg: [defaultName, dataStoreAName],\n\t\t\t\tparentContext: wrapContextForInnerChannel(dataStoreId, containerRuntime),\n\t\t\t\tstorage,\n\t\t\t\tscope,\n\t\t\t\tcreateSummarizerNodeFn: getCreateSummarizerNodeFn(dataStoreId),\n\t\t\t\tmakeLocallyVisibleFn,\n\t\t\t\tsnapshotTree: undefined,\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\tawait contextA.realize();\n\t\t\t} catch (error) {\n\t\t\t\tsuccess = false;\n\t\t\t}\n\t\t\t// Verify that realize was successful.\n\t\t\tassert.strictEqual(success, true);\n\t\t});\n\n\t\tit(\"Invalid subDataStore from the global dataStore\", async () => {\n\t\t\tlet success: boolean = true;\n\t\t\tconst dataStoreId = \"B-Id\";\n\t\t\t// Create dataStore B that is in not the registry of the default dataStore.\n\t\t\tconst contextB: LocalFluidDataStoreContext = new LocalFluidDataStoreContext({\n\t\t\t\tid: dataStoreId,\n\t\t\t\tpkg: [defaultName, dataStoreBName],\n\t\t\t\tparentContext: wrapContextForInnerChannel(dataStoreId, containerRuntime),\n\t\t\t\tstorage,\n\t\t\t\tscope,\n\t\t\t\tcreateSummarizerNodeFn: getCreateSummarizerNodeFn(dataStoreId),\n\t\t\t\tmakeLocallyVisibleFn,\n\t\t\t\tsnapshotTree: undefined,\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\tawait contextB.realize();\n\t\t\t} catch (error) {\n\t\t\t\tsuccess = false;\n\t\t\t}\n\t\t\t// Verify that realize throws an error.\n\t\t\tassert.strictEqual(success, false);\n\t\t});\n\n\t\tit(\"Valid subDataStore at depth 2\", async () => {\n\t\t\tlet success: boolean = true;\n\t\t\tconst dataStoreBId = \"B-Id\";\n\t\t\t// Create dataStore B that is in the registry of dataStore A (which is at depth 2).\n\t\t\tconst contextB: LocalFluidDataStoreContext = new LocalFluidDataStoreContext({\n\t\t\t\tid: dataStoreBId,\n\t\t\t\tpkg: [defaultName, dataStoreAName, dataStoreBName],\n\t\t\t\tparentContext: wrapContextForInnerChannel(dataStoreBId, containerRuntime),\n\t\t\t\tstorage,\n\t\t\t\tscope,\n\t\t\t\tcreateSummarizerNodeFn: getCreateSummarizerNodeFn(dataStoreBId),\n\t\t\t\tmakeLocallyVisibleFn,\n\t\t\t\tsnapshotTree: undefined,\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\tawait contextB.realize();\n\t\t\t} catch (error) {\n\t\t\t\tsuccess = false;\n\t\t\t}\n\t\t\t// Verify that realize was successful.\n\t\t\tassert.strictEqual(success, true);\n\n\t\t\tconst dataStoreCId = \"C-Id\";\n\t\t\t// Create dataStore C that is in the registry of dataStore A (which is at depth 2).\n\t\t\tconst contextC: LocalFluidDataStoreContext = new LocalFluidDataStoreContext({\n\t\t\t\tid: dataStoreCId,\n\t\t\t\tpkg: [defaultName, dataStoreAName, dataStoreCName],\n\t\t\t\tparentContext: wrapContextForInnerChannel(dataStoreCId, containerRuntime),\n\t\t\t\tstorage,\n\t\t\t\tscope,\n\t\t\t\tcreateSummarizerNodeFn: getCreateSummarizerNodeFn(dataStoreCId),\n\t\t\t\tmakeLocallyVisibleFn,\n\t\t\t\tsnapshotTree: undefined,\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\tawait contextC.realize();\n\t\t\t} catch (error) {\n\t\t\t\tsuccess = false;\n\t\t\t}\n\t\t\t// Verify that realize was successful.\n\t\t\tassert.strictEqual(success, true);\n\t\t});\n\n\t\tit(\"Invalid subDataStore at depth 2\", async () => {\n\t\t\tlet success: boolean = true;\n\t\t\tconst dataStoreId = \"fake-Id\";\n\t\t\t// Create a fake dataStore that is not in the registry of dataStore A (which is at depth 2).\n\t\t\tconst contextFake: LocalFluidDataStoreContext = new LocalFluidDataStoreContext({\n\t\t\t\tid: dataStoreId,\n\t\t\t\tpkg: [defaultName, dataStoreAName, \"fake\"],\n\t\t\t\tparentContext: wrapContextForInnerChannel(dataStoreId, containerRuntime),\n\t\t\t\tstorage,\n\t\t\t\tscope,\n\t\t\t\tcreateSummarizerNodeFn: getCreateSummarizerNodeFn(dataStoreId),\n\t\t\t\tmakeLocallyVisibleFn,\n\t\t\t\tsnapshotTree: undefined,\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\tawait contextFake.realize();\n\t\t\t} catch (error) {\n\t\t\t\tsuccess = false;\n\t\t\t}\n\t\t\t// Verify that realize throws an error.\n\t\t\tassert.strictEqual(success, false);\n\t\t});\n\n\t\tit(\"Invalid subDataStore at depth 3\", async () => {\n\t\t\tlet success: boolean = true;\n\t\t\tconst dataStoreId = \"fake-Id\";\n\t\t\t// Create a fake dataStore that is not in the registry of dataStore B (which is at depth 3).\n\t\t\tconst contextFake: LocalFluidDataStoreContext = new LocalFluidDataStoreContext({\n\t\t\t\tid: dataStoreId,\n\t\t\t\tpkg: [defaultName, dataStoreAName, \"fake\"],\n\t\t\t\tparentContext: wrapContextForInnerChannel(dataStoreId, containerRuntime),\n\t\t\t\tstorage,\n\t\t\t\tscope,\n\t\t\t\tcreateSummarizerNodeFn: getCreateSummarizerNodeFn(dataStoreId),\n\t\t\t\tmakeLocallyVisibleFn,\n\t\t\t\tsnapshotTree: undefined,\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\tawait contextFake.realize();\n\t\t\t} catch (error) {\n\t\t\t\tsuccess = false;\n\t\t\t}\n\t\t\t// Verify that realize throws an error.\n\t\t\tassert.strictEqual(success, false);\n\t\t});\n\n\t\tit(\"SubDataStore which is in the registry of the parent dataStore\", async () => {\n\t\t\tlet success: boolean = true;\n\t\t\tconst dataStoreId = \"C-Id\";\n\t\t\t// Create dataStore C that is in parent's registry but not in the registry of dataStore B.\n\t\t\tconst contextC: LocalFluidDataStoreContext = new LocalFluidDataStoreContext({\n\t\t\t\tid: dataStoreId,\n\t\t\t\tpkg: [defaultName, dataStoreAName, dataStoreBName, dataStoreCName],\n\t\t\t\tparentContext: wrapContextForInnerChannel(dataStoreId, containerRuntime),\n\t\t\t\tstorage,\n\t\t\t\tscope,\n\t\t\t\tcreateSummarizerNodeFn: getCreateSummarizerNodeFn(dataStoreId),\n\t\t\t\tmakeLocallyVisibleFn,\n\t\t\t\tsnapshotTree: undefined,\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\tawait contextC.realize();\n\t\t\t} catch (error) {\n\t\t\t\tsuccess = false;\n\t\t\t}\n\t\t\t// Verify that realize throws an error.\n\t\t\tassert.strictEqual(success, false);\n\t\t});\n\t});\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"dataStoreRegistry.spec.js","sourceRoot":"","sources":["../../src/test/dataStoreRegistry.spec.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,MAAM,IAAI,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;IACnD,wCAAwC;IACxC,MAAM,WAAW,GAAG,SAAS,CAAC;IAC9B,MAAM,OAAO,GAAG;QACf,CAAC,WAAW,EAAE,EAAE,CAAC;QACjB,CAAC,WAAW,EAAE,EAAE,CAAC;KACjB,CAAC;IAEF,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QAC1C,IAAI;YACH,IAAI,sBAAsB,CAAC,OAA6C,CAAC,CAAC;YAC1E,MAAM,CAAC,IAAI,EAAE,CAAC;SACd;QAAC,OAAO,KAAU,EAAE;YACpB,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,SAAS,EAAE,mBAAmB,CAAC,UAAU,CAAC,CAAC;YACpE,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,EAAE,6BAA6B,CAAC,CAAC;SACjE;IACF,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\nimport { strict as assert } from \"assert\";\nimport { NamedFluidDataStoreRegistryEntries } from \"@fluidframework/runtime-definitions\";\nimport { ContainerErrorTypes } from \"@fluidframework/container-definitions\";\nimport { FluidDataStoreRegistry } from \"../dataStoreRegistry.js\";\n\ndescribe(\"Data Store Registry Creation Tests\", () => {\n\t// Define two entries with the same name\n\tconst defaultName = \"default\";\n\tconst entries = [\n\t\t[defaultName, []],\n\t\t[defaultName, []],\n\t];\n\n\tit(\"Validate duplicate name entries\", () => {\n\t\ttry {\n\t\t\tnew FluidDataStoreRegistry(entries as NamedFluidDataStoreRegistryEntries);\n\t\t\tassert.fail();\n\t\t} catch (error: any) {\n\t\t\tassert.strictEqual(error.errorType, ContainerErrorTypes.usageError);\n\t\t\tassert.strictEqual(error.message, \"Duplicate entry names exist\");\n\t\t}\n\t});\n});\n"]}
1
+ {"version":3,"file":"dataStoreRegistry.spec.js","sourceRoot":"","sources":["../../src/test/dataStoreRegistry.spec.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,IAAI,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;IACnD,wCAAwC;IACxC,MAAM,WAAW,GAAG,SAAS,CAAC;IAC9B,MAAM,OAAO,GAAG;QACf,CAAC,WAAW,EAAE,EAAE,CAAC;QACjB,CAAC,WAAW,EAAE,EAAE,CAAC;KACjB,CAAC;IAEF,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QAC1C,IAAI;YACH,IAAI,sBAAsB,CAAC,OAA6C,CAAC,CAAC;YAC1E,MAAM,CAAC,IAAI,EAAE,CAAC;SACd;QAAC,OAAO,KAAU,EAAE;YACpB,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,SAAS,EAAE,mBAAmB,CAAC,UAAU,CAAC,CAAC;YACpE,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,EAAE,6BAA6B,CAAC,CAAC;SACjE;IACF,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"assert\";\nimport { NamedFluidDataStoreRegistryEntries } from \"@fluidframework/runtime-definitions\";\nimport { ContainerErrorTypes } from \"@fluidframework/container-definitions\";\nimport { FluidDataStoreRegistry } from \"../dataStoreRegistry.js\";\n\ndescribe(\"Data Store Registry Creation Tests\", () => {\n\t// Define two entries with the same name\n\tconst defaultName = \"default\";\n\tconst entries = [\n\t\t[defaultName, []],\n\t\t[defaultName, []],\n\t];\n\n\tit(\"Validate duplicate name entries\", () => {\n\t\ttry {\n\t\t\tnew FluidDataStoreRegistry(entries as NamedFluidDataStoreRegistryEntries);\n\t\t\tassert.fail();\n\t\t} catch (error: any) {\n\t\t\tassert.strictEqual(error.errorType, ContainerErrorTypes.usageError);\n\t\t\tassert.strictEqual(error.message, \"Duplicate entry names exist\");\n\t\t}\n\t});\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"summarizerFuzzSuite.js","sourceRoot":"","sources":["../../../src/test/fuzz/summarizerFuzzSuite.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/* eslint-disable import/no-nodejs-modules */\n\nimport { strict as assert } from \"assert\";\nimport { mkdirSync, readFileSync } from \"fs\";\nimport path from \"path\";\nimport {\n\tBaseFuzzTestState,\n\tcreateFuzzDescribe,\n\tdefaultOptions,\n\tAsyncGenerator,\n\tSaveInfo,\n\tasyncGeneratorFromArray,\n\tmakeRandom,\n\tperformFuzzActionsAsync,\n\tAsyncReducer,\n} from \"@fluid-private/stochastic-test-utils\";\nimport { MockFluidDataStoreRuntime } from \"@fluidframework/test-runtime-utils\";\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport {\n\tIMockContainerRuntimeForSummarizerOptions,\n\tMockContainerRuntimeFactoryForSummarizer,\n\tMockContainerRuntimeForSummarizer,\n} from \"./summarizerFuzzMocks.js\";\nimport type { SummarizerOperation } from \"./fuzzUtils.js\";\n\nexport interface SummarizerFuzzTestState extends BaseFuzzTestState {\n\tcontainerRuntimeFactory: MockContainerRuntimeFactoryForSummarizer;\n\tcontainerRuntime: MockContainerRuntimeForSummarizer;\n}\n\nexport interface SummarizerFuzzModel {\n\tworkloadName: string;\n\tgeneratorFactory: () => AsyncGenerator<SummarizerOperation, SummarizerFuzzTestState>;\n\treducer: AsyncReducer<SummarizerOperation, SummarizerFuzzTestState>;\n}\n\n/**\n * @internal\n */\nexport interface SummarizerFuzzHarnessEvents {\n\t/**\n\t * Raised for each non-summarizer client created during fuzz test execution.\n\t */\n\t(event: \"clientCreate\", listener: (client: SummarizerFuzzTestState) => void);\n\n\t/**\n\t * Raised after creating the initialState but prior to performing the fuzzActions..\n\t */\n\t(event: \"testStart\", listener: (initialState: SummarizerFuzzTestState) => void);\n\n\t/**\n\t * Raised after all fuzzActions have been completed.\n\t */\n\t(event: \"testEnd\", listener: (finalState: SummarizerFuzzTestState) => void);\n}\n\n/**\n * @internal\n */\nexport interface SummarizerFuzzSuiteOptions {\n\t/**\n\t * Number of tests to generate for correctness modes (which are run in the PR gate).\n\t */\n\tdefaultTestCount: number;\n\n\t/**\n\t * Event emitter which allows hooking into interesting points of Summarizer harness execution.\n\t * Test authors that want to subscribe to any of these events should create a `TypedEventEmitter`,\n\t * do so, and pass it in when creating the suite.\n\t */\n\temitter: TypedEventEmitter<SummarizerFuzzHarnessEvents>;\n\n\t/**\n\t * Seed which should be replayed from disk.\n\t *\n\t * This option is intended for quick, by-hand minimization of failure JSON. As such, it adds a `.only`\n\t * to the corresponding replay test.\n\t */\n\treplay?: number;\n\n\t/**\n\t * Runs only the provided seeds.\n\t *\n\t * @example\n\t *\n\t * ```typescript\n\t * // Runs only seed 42 for the given model.\n\t * createSummarizerFuzzSuite(model, { only: [42] });\n\t * ```\n\t *\n\t * @remarks\n\t * If you prefer, a variant of the standard `.only` syntax works. See {@link (createSummarizerFuzzSuite:namespace).only}.\n\t */\n\tonly: Iterable<number>;\n\n\t/**\n\t * Skips the provided seeds.\n\t *\n\t * @example\n\t *\n\t * ```typescript\n\t * // Skips seed 42 for the given model.\n\t * createSummarizerFuzzSuite(model, { skip: [42] });\n\t * ```\n\t *\n\t * @remarks\n\t * If you prefer, a variant of the standard `.skip` syntax works. See {@link (createSummarizerFuzzSuite:namespace).skip}.\n\t */\n\tskip: Iterable<number>;\n\n\t/**\n\t * Whether failure files should be saved to disk, and if so, the directory in which they should be saved.\n\t * Each seed will be saved in a subfolder of this directory obtained by kebab-casing the model name.\n\t *\n\t * Turning on this feature is encouraged for quick minimization.\n\t */\n\tsaveFailures: false | { directory: string };\n\n\tcontainerRuntimeOptions?: IMockContainerRuntimeForSummarizerOptions;\n\n\tparseOperations: (serialized: string) => SummarizerOperation[];\n}\n\n/**\n * @internal\n */\nexport const defaultSummarizerFuzzSuiteOptions: SummarizerFuzzSuiteOptions = {\n\tdefaultTestCount: defaultOptions.defaultTestCount,\n\temitter: new TypedEventEmitter(),\n\tonly: [],\n\tskip: [],\n\tsaveFailures: false,\n\tparseOperations: (serialized: string) => JSON.parse(serialized) as SummarizerOperation[],\n};\n\nexport function createSummarizerFuzzSuite(\n\tmodel: SummarizerFuzzModel,\n\tprovidedOptions?: Partial<SummarizerFuzzSuiteOptions>,\n): void {\n\tconst options: SummarizerFuzzSuiteOptions = {\n\t\t...defaultSummarizerFuzzSuiteOptions,\n\t\t...providedOptions,\n\t\tsaveFailures: false,\n\t};\n\n\tconst only = new Set(options.only);\n\tconst skip = new Set(options.skip);\n\tObject.assign(options, { only, skip });\n\tassert(isInternalOptions(options));\n\n\tconst describeFuzz = createFuzzDescribe({ defaultTestCount: options.defaultTestCount });\n\tdescribeFuzz(model.workloadName, ({ testCount }) => {\n\t\tconst directory = getSaveDirectory(model, options);\n\t\tbefore(() => {\n\t\t\tif (directory !== undefined) {\n\t\t\t\tmkdirSync(directory, { recursive: true });\n\t\t\t}\n\t\t});\n\n\t\tfor (let seed = 0; seed < testCount; seed++) {\n\t\t\trunTest(model, options, seed, getSaveInfo(model, options, seed));\n\t\t}\n\n\t\tif (options.replay !== undefined) {\n\t\t\tconst seed = options.replay;\n\t\t\tdescribe.only(`replay from file`, () => {\n\t\t\t\tconst saveInfo = getSaveInfo(model, options, seed);\n\t\t\t\tassert(\n\t\t\t\t\tsaveInfo !== undefined,\n\t\t\t\t\t\"Cannot replay a file without a directory to save files in!\",\n\t\t\t\t);\n\t\t\t\tconst operations = options.parseOperations(\n\t\t\t\t\treadFileSync(saveInfo.filepath).toString(),\n\t\t\t\t);\n\n\t\t\t\tconst replayModel = {\n\t\t\t\t\t...model,\n\t\t\t\t\t// We lose some type safety here because the options interface isn't generic\n\t\t\t\t\tgeneratorFactory: (): AsyncGenerator<SummarizerOperation, unknown> =>\n\t\t\t\t\t\tasyncGeneratorFromArray(operations),\n\t\t\t\t};\n\t\t\t\trunTest(replayModel, options, seed, undefined);\n\t\t\t});\n\t\t}\n\t});\n}\n\n/**\n * Runs the provided Summarizer fuzz model. All functionality is already assumed to be mixed in.\n * @privateRemarks This is currently file-exported for testing purposes, but it could be reasonable to\n * expose at the package level if we want to expose some of the harness's building blocks.\n */\nasync function runTestForSeed(\n\tmodel: SummarizerFuzzModel,\n\toptions: Omit<SummarizerFuzzSuiteOptions, \"only\" | \"skip\">,\n\tseed: number,\n\tsaveInfo?: SaveInfo,\n): Promise<SummarizerFuzzTestState> {\n\tconst random = makeRandom(seed);\n\tconst containerRuntimeFactory = new MockContainerRuntimeFactoryForSummarizer(\n\t\toptions.containerRuntimeOptions,\n\t);\n\n\tconst containerRuntime = containerRuntimeFactory.createContainerRuntime(\n\t\tnew MockFluidDataStoreRuntime(),\n\t);\n\n\tconst initialState: SummarizerFuzzTestState = {\n\t\tcontainerRuntimeFactory,\n\t\trandom,\n\t\tcontainerRuntime,\n\t};\n\n\toptions.emitter.emit(\"testStart\", initialState);\n\n\tconst finalState = await performFuzzActionsAsync(\n\t\tmodel.generatorFactory(),\n\t\tmodel.reducer,\n\t\tinitialState,\n\t\tsaveInfo,\n\t);\n\n\t// TODO AB#6954: Validate we can summarize\n\n\toptions.emitter.emit(\"testEnd\", finalState);\n\n\treturn finalState;\n}\n\nfunction runTest(\n\tmodel: SummarizerFuzzModel,\n\toptions: InternalOptions,\n\tseed: number,\n\tsaveInfo: SaveInfo | undefined,\n): void {\n\tconst itFn = options.only.has(seed) ? it.only : options.skip.has(seed) ? it.skip : it;\n\titFn(`seed ${seed}`, async () => {\n\t\tconst inCi = !!process.env.TF_BUILD;\n\t\tawait runTestForSeed(model, options, seed, inCi ? undefined : saveInfo);\n\t});\n}\n\n/**\n * @internal\n */\ninterface HasWorkloadName {\n\tworkloadName: string;\n}\n\nfunction getSaveDirectory(\n\tmodel: HasWorkloadName,\n\toptions: SummarizerFuzzSuiteOptions,\n): string | undefined {\n\tif (!options.saveFailures) {\n\t\treturn undefined;\n\t}\n\tconst workloadFriendly = model.workloadName.replace(/[\\s_]+/g, \"-\").toLowerCase();\n\treturn path.join(options.saveFailures.directory, workloadFriendly);\n}\n\nfunction getSaveInfo(\n\tmodel: HasWorkloadName,\n\toptions: SummarizerFuzzSuiteOptions,\n\tseed: number,\n): SaveInfo | undefined {\n\tconst directory = getSaveDirectory(model, options);\n\tif (!directory) {\n\t\treturn undefined;\n\t}\n\tconst filepath = path.join(directory, `${seed}.json`);\n\treturn { saveOnFailure: true, filepath };\n}\n\ntype InternalOptions = Omit<SummarizerFuzzSuiteOptions, \"only\" | \"skip\"> & {\n\tonly: Set<number>;\n\tskip: Set<number>;\n};\n\nfunction isInternalOptions(options: SummarizerFuzzSuiteOptions): options is InternalOptions {\n\treturn options.only instanceof Set && options.skip instanceof Set;\n}\n"]}
1
+ {"version":3,"file":"summarizerFuzzSuite.js","sourceRoot":"","sources":["../../../src/test/fuzz/summarizerFuzzSuite.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\n/* eslint-disable import/no-nodejs-modules */\n\nimport { strict as assert } from \"assert\";\nimport { mkdirSync, readFileSync } from \"fs\";\nimport path from \"path\";\nimport {\n\tBaseFuzzTestState,\n\tcreateFuzzDescribe,\n\tdefaultOptions,\n\tAsyncGenerator,\n\tSaveInfo,\n\tasyncGeneratorFromArray,\n\tmakeRandom,\n\tperformFuzzActionsAsync,\n\tAsyncReducer,\n} from \"@fluid-private/stochastic-test-utils\";\nimport { MockFluidDataStoreRuntime } from \"@fluidframework/test-runtime-utils\";\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport {\n\tIMockContainerRuntimeForSummarizerOptions,\n\tMockContainerRuntimeFactoryForSummarizer,\n\tMockContainerRuntimeForSummarizer,\n} from \"./summarizerFuzzMocks.js\";\nimport type { SummarizerOperation } from \"./fuzzUtils.js\";\n\nexport interface SummarizerFuzzTestState extends BaseFuzzTestState {\n\tcontainerRuntimeFactory: MockContainerRuntimeFactoryForSummarizer;\n\tcontainerRuntime: MockContainerRuntimeForSummarizer;\n}\n\nexport interface SummarizerFuzzModel {\n\tworkloadName: string;\n\tgeneratorFactory: () => AsyncGenerator<SummarizerOperation, SummarizerFuzzTestState>;\n\treducer: AsyncReducer<SummarizerOperation, SummarizerFuzzTestState>;\n}\n\n/**\n * @internal\n */\nexport interface SummarizerFuzzHarnessEvents {\n\t/**\n\t * Raised for each non-summarizer client created during fuzz test execution.\n\t */\n\t(event: \"clientCreate\", listener: (client: SummarizerFuzzTestState) => void);\n\n\t/**\n\t * Raised after creating the initialState but prior to performing the fuzzActions..\n\t */\n\t(event: \"testStart\", listener: (initialState: SummarizerFuzzTestState) => void);\n\n\t/**\n\t * Raised after all fuzzActions have been completed.\n\t */\n\t(event: \"testEnd\", listener: (finalState: SummarizerFuzzTestState) => void);\n}\n\n/**\n * @internal\n */\nexport interface SummarizerFuzzSuiteOptions {\n\t/**\n\t * Number of tests to generate for correctness modes (which are run in the PR gate).\n\t */\n\tdefaultTestCount: number;\n\n\t/**\n\t * Event emitter which allows hooking into interesting points of Summarizer harness execution.\n\t * Test authors that want to subscribe to any of these events should create a `TypedEventEmitter`,\n\t * do so, and pass it in when creating the suite.\n\t */\n\temitter: TypedEventEmitter<SummarizerFuzzHarnessEvents>;\n\n\t/**\n\t * Seed which should be replayed from disk.\n\t *\n\t * This option is intended for quick, by-hand minimization of failure JSON. As such, it adds a `.only`\n\t * to the corresponding replay test.\n\t */\n\treplay?: number;\n\n\t/**\n\t * Runs only the provided seeds.\n\t *\n\t * @example\n\t *\n\t * ```typescript\n\t * // Runs only seed 42 for the given model.\n\t * createSummarizerFuzzSuite(model, { only: [42] });\n\t * ```\n\t *\n\t * @remarks\n\t * If you prefer, a variant of the standard `.only` syntax works. See {@link (createSummarizerFuzzSuite:namespace).only}.\n\t */\n\tonly: Iterable<number>;\n\n\t/**\n\t * Skips the provided seeds.\n\t *\n\t * @example\n\t *\n\t * ```typescript\n\t * // Skips seed 42 for the given model.\n\t * createSummarizerFuzzSuite(model, { skip: [42] });\n\t * ```\n\t *\n\t * @remarks\n\t * If you prefer, a variant of the standard `.skip` syntax works. See {@link (createSummarizerFuzzSuite:namespace).skip}.\n\t */\n\tskip: Iterable<number>;\n\n\t/**\n\t * Whether failure files should be saved to disk, and if so, the directory in which they should be saved.\n\t * Each seed will be saved in a subfolder of this directory obtained by kebab-casing the model name.\n\t *\n\t * Turning on this feature is encouraged for quick minimization.\n\t */\n\tsaveFailures: false | { directory: string };\n\n\tcontainerRuntimeOptions?: IMockContainerRuntimeForSummarizerOptions;\n\n\tparseOperations: (serialized: string) => SummarizerOperation[];\n}\n\n/**\n * @internal\n */\nexport const defaultSummarizerFuzzSuiteOptions: SummarizerFuzzSuiteOptions = {\n\tdefaultTestCount: defaultOptions.defaultTestCount,\n\temitter: new TypedEventEmitter(),\n\tonly: [],\n\tskip: [],\n\tsaveFailures: false,\n\tparseOperations: (serialized: string) => JSON.parse(serialized) as SummarizerOperation[],\n};\n\nexport function createSummarizerFuzzSuite(\n\tmodel: SummarizerFuzzModel,\n\tprovidedOptions?: Partial<SummarizerFuzzSuiteOptions>,\n): void {\n\tconst options: SummarizerFuzzSuiteOptions = {\n\t\t...defaultSummarizerFuzzSuiteOptions,\n\t\t...providedOptions,\n\t\tsaveFailures: false,\n\t};\n\n\tconst only = new Set(options.only);\n\tconst skip = new Set(options.skip);\n\tObject.assign(options, { only, skip });\n\tassert(isInternalOptions(options));\n\n\tconst describeFuzz = createFuzzDescribe({ defaultTestCount: options.defaultTestCount });\n\tdescribeFuzz(model.workloadName, ({ testCount }) => {\n\t\tconst directory = getSaveDirectory(model, options);\n\t\tbefore(() => {\n\t\t\tif (directory !== undefined) {\n\t\t\t\tmkdirSync(directory, { recursive: true });\n\t\t\t}\n\t\t});\n\n\t\tfor (let seed = 0; seed < testCount; seed++) {\n\t\t\trunTest(model, options, seed, getSaveInfo(model, options, seed));\n\t\t}\n\n\t\tif (options.replay !== undefined) {\n\t\t\tconst seed = options.replay;\n\t\t\tdescribe.only(`replay from file`, () => {\n\t\t\t\tconst saveInfo = getSaveInfo(model, options, seed);\n\t\t\t\tassert(\n\t\t\t\t\tsaveInfo !== undefined,\n\t\t\t\t\t\"Cannot replay a file without a directory to save files in!\",\n\t\t\t\t);\n\t\t\t\tconst operations = options.parseOperations(\n\t\t\t\t\treadFileSync(saveInfo.filepath).toString(),\n\t\t\t\t);\n\n\t\t\t\tconst replayModel = {\n\t\t\t\t\t...model,\n\t\t\t\t\t// We lose some type safety here because the options interface isn't generic\n\t\t\t\t\tgeneratorFactory: (): AsyncGenerator<SummarizerOperation, unknown> =>\n\t\t\t\t\t\tasyncGeneratorFromArray(operations),\n\t\t\t\t};\n\t\t\t\trunTest(replayModel, options, seed, undefined);\n\t\t\t});\n\t\t}\n\t});\n}\n\n/**\n * Runs the provided Summarizer fuzz model. All functionality is already assumed to be mixed in.\n * @privateRemarks This is currently file-exported for testing purposes, but it could be reasonable to\n * expose at the package level if we want to expose some of the harness's building blocks.\n */\nasync function runTestForSeed(\n\tmodel: SummarizerFuzzModel,\n\toptions: Omit<SummarizerFuzzSuiteOptions, \"only\" | \"skip\">,\n\tseed: number,\n\tsaveInfo?: SaveInfo,\n): Promise<SummarizerFuzzTestState> {\n\tconst random = makeRandom(seed);\n\tconst containerRuntimeFactory = new MockContainerRuntimeFactoryForSummarizer(\n\t\toptions.containerRuntimeOptions,\n\t);\n\n\tconst containerRuntime = containerRuntimeFactory.createContainerRuntime(\n\t\tnew MockFluidDataStoreRuntime(),\n\t);\n\n\tconst initialState: SummarizerFuzzTestState = {\n\t\tcontainerRuntimeFactory,\n\t\trandom,\n\t\tcontainerRuntime,\n\t};\n\n\toptions.emitter.emit(\"testStart\", initialState);\n\n\tconst finalState = await performFuzzActionsAsync(\n\t\tmodel.generatorFactory(),\n\t\tmodel.reducer,\n\t\tinitialState,\n\t\tsaveInfo,\n\t);\n\n\t// TODO AB#6954: Validate we can summarize\n\n\toptions.emitter.emit(\"testEnd\", finalState);\n\n\treturn finalState;\n}\n\nfunction runTest(\n\tmodel: SummarizerFuzzModel,\n\toptions: InternalOptions,\n\tseed: number,\n\tsaveInfo: SaveInfo | undefined,\n): void {\n\tconst itFn = options.only.has(seed) ? it.only : options.skip.has(seed) ? it.skip : it;\n\titFn(`seed ${seed}`, async () => {\n\t\tconst inCi = !!process.env.TF_BUILD;\n\t\tawait runTestForSeed(model, options, seed, inCi ? undefined : saveInfo);\n\t});\n}\n\n/**\n * @internal\n */\ninterface HasWorkloadName {\n\tworkloadName: string;\n}\n\nfunction getSaveDirectory(\n\tmodel: HasWorkloadName,\n\toptions: SummarizerFuzzSuiteOptions,\n): string | undefined {\n\tif (!options.saveFailures) {\n\t\treturn undefined;\n\t}\n\tconst workloadFriendly = model.workloadName.replace(/[\\s_]+/g, \"-\").toLowerCase();\n\treturn path.join(options.saveFailures.directory, workloadFriendly);\n}\n\nfunction getSaveInfo(\n\tmodel: HasWorkloadName,\n\toptions: SummarizerFuzzSuiteOptions,\n\tseed: number,\n): SaveInfo | undefined {\n\tconst directory = getSaveDirectory(model, options);\n\tif (!directory) {\n\t\treturn undefined;\n\t}\n\tconst filepath = path.join(directory, `${seed}.json`);\n\treturn { saveOnFailure: true, filepath };\n}\n\ntype InternalOptions = Omit<SummarizerFuzzSuiteOptions, \"only\" | \"skip\"> & {\n\tonly: Set<number>;\n\tskip: Set<number>;\n};\n\nfunction isInternalOptions(options: SummarizerFuzzSuiteOptions): options is InternalOptions {\n\treturn options.only instanceof Set && options.skip instanceof Set;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"opSplitter.spec.js","sourceRoot":"","sources":["../../../src/test/opLifecycle/opSplitter.spec.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/* eslint-disable @typescript-eslint/no-non-null-assertion */\n\nimport * as crypto from \"crypto\";\nimport { strict as assert } from \"assert\";\nimport { ContainerMessageType } from \"@fluidframework/container-runtime-previous\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { IBatchMessage } from \"@fluidframework/container-definitions\";\nimport { MockLogger } from \"@fluidframework/telemetry-utils\";\nimport { BatchMessage, IChunkedOp, OpSplitter, splitOp } from \"../../opLifecycle/index.js\";\nimport { CompressionAlgorithms } from \"../../containerRuntime.js\";\n\ndescribe(\"OpSplitter\", () => {\n\tconst batchesSubmitted: { messages: IBatchMessage[]; referenceSequenceNumber?: number }[] = [];\n\n\tconst mockSubmitBatchFn = (\n\t\tbatch: IBatchMessage[],\n\t\treferenceSequenceNumber?: number,\n\t): number => {\n\t\tbatchesSubmitted.push({ messages: batch, referenceSequenceNumber });\n\t\treturn batchesSubmitted.length;\n\t};\n\n\tbeforeEach(() => {\n\t\tbatchesSubmitted.splice(0);\n\t\tmockLogger.clear();\n\t});\n\n\tconst chunkSizeInBytes = 50 * 1024;\n\tconst maxBatchSizeInBytes = 10 * 50 * 1024;\n\tconst mockLogger = new MockLogger();\n\n\tit(\"Reconstruct original chunked op\", () => {\n\t\tconst op1 = generateChunkableOp(chunkSizeInBytes * 2);\n\t\tconst op2 = generateChunkableOp(chunkSizeInBytes * 3);\n\t\tconst chunks1 = wrapChunkedOps(splitOp(op1, chunkSizeInBytes), \"testClient1\");\n\t\tconst chunks2 = wrapChunkedOps(splitOp(op2, chunkSizeInBytes), \"testClient2\");\n\t\tconst opSplitter = new OpSplitter(\n\t\t\t[],\n\t\t\tmockSubmitBatchFn,\n\t\t\t0,\n\t\t\tmaxBatchSizeInBytes,\n\t\t\tmockLogger,\n\t\t);\n\n\t\tassert.equal(opSplitter.processRemoteMessage(chunks1[0]).state, \"Accepted\");\n\t\tassert.equal(opSplitter.processRemoteMessage(chunks2[0]).state, \"Accepted\");\n\n\t\tassert.equal(opSplitter.processRemoteMessage(chunks1[1]).state, \"Accepted\");\n\t\tassert.equal(opSplitter.processRemoteMessage(chunks2[1]).state, \"Accepted\");\n\n\t\tconst chunks1LastResult = opSplitter.processRemoteMessage(chunks1[2]);\n\t\t// The last chunk will reconstruct the original message\n\t\tassert.equal(chunks1LastResult.state, \"Processed\");\n\t\tassertSameMessage(chunks1LastResult.message, op1);\n\t\tassert.equal(opSplitter.chunks.size, 1);\n\n\t\tassert.equal(opSplitter.processRemoteMessage(chunks2[2]).state, \"Accepted\");\n\n\t\tconst chunks2LastResult = opSplitter.processRemoteMessage(chunks2[3]);\n\t\t// The last chunk will reconstruct the original message\n\t\tassert.equal(chunks2LastResult.state, \"Processed\");\n\t\tassertSameMessage(chunks2LastResult.message, op2);\n\n\t\tassert.equal(opSplitter.chunks.size, 0);\n\t});\n\n\tit(\"Reconstruct original chunked op with extra empty op\", () => {\n\t\tconst op1 = generateChunkableOp(chunkSizeInBytes * 2);\n\t\tconst op2 = generateChunkableOp(chunkSizeInBytes * 3);\n\t\tconst chunks1 = wrapChunkedOps(splitOp(op1, chunkSizeInBytes, true), \"testClient1\");\n\t\tconst chunks2 = wrapChunkedOps(splitOp(op2, chunkSizeInBytes, true), \"testClient2\");\n\t\tconst opSplitter = new OpSplitter(\n\t\t\t[],\n\t\t\tmockSubmitBatchFn,\n\t\t\t0,\n\t\t\tmaxBatchSizeInBytes,\n\t\t\tmockLogger,\n\t\t);\n\n\t\tassert.equal(opSplitter.processRemoteMessage(chunks1[0]).state, \"Accepted\");\n\t\tassert.equal(opSplitter.processRemoteMessage(chunks2[0]).state, \"Accepted\");\n\n\t\tassert.equal(opSplitter.processRemoteMessage(chunks1[1]).state, \"Accepted\");\n\t\tassert.equal(opSplitter.processRemoteMessage(chunks2[1]).state, \"Accepted\");\n\n\t\tassert.equal(opSplitter.processRemoteMessage(chunks1[2]).state, \"Accepted\");\n\n\t\tconst chunks1LastResult = opSplitter.processRemoteMessage(chunks1[3]);\n\t\t// The last chunk will reconstruct the original message\n\t\tassert.equal(chunks1LastResult.state, \"Processed\");\n\t\tassertSameMessage(chunks1LastResult.message, op1);\n\t\tassert.equal(opSplitter.chunks.size, 1);\n\n\t\tassert.equal(opSplitter.processRemoteMessage(chunks2[2]).state, \"Accepted\");\n\t\tassert.equal(opSplitter.processRemoteMessage(chunks2[3]).state, \"Accepted\");\n\n\t\tconst chunks2LastResult = opSplitter.processRemoteMessage(chunks2[4]);\n\t\t// The last chunk will reconstruct the original message\n\t\tassert.equal(chunks2LastResult.state, \"Processed\");\n\t\tassertSameMessage(chunks2LastResult.message, op2);\n\n\t\tassert.equal(opSplitter.chunks.size, 0);\n\t});\n\n\tit(\"Reconstruct original chunked op with initial chunks\", () => {\n\t\tconst op = generateChunkableOp(chunkSizeInBytes * 3);\n\t\tconst chunks = wrapChunkedOps(splitOp(op, chunkSizeInBytes), \"testClient\");\n\t\tconst opSplitter = new OpSplitter(\n\t\t\t[],\n\t\t\tmockSubmitBatchFn,\n\t\t\t0,\n\t\t\tmaxBatchSizeInBytes,\n\t\t\tmockLogger,\n\t\t);\n\t\topSplitter.processRemoteMessage(chunks[0]);\n\t\topSplitter.processRemoteMessage(chunks[1]);\n\n\t\tconst otherOpSplitter = new OpSplitter(\n\t\t\tArray.from(opSplitter.chunks),\n\t\t\tmockSubmitBatchFn,\n\t\t\t0,\n\t\t\tmaxBatchSizeInBytes,\n\t\t\tmockLogger,\n\t\t);\n\t\topSplitter.clearPartialChunks(\"testClient\");\n\n\t\totherOpSplitter.processRemoteMessage(chunks[2]);\n\t\tassertSameMessage(otherOpSplitter.processRemoteMessage(chunks[3]).message, op);\n\t});\n\n\tit(\"Clear chunks\", () => {\n\t\tconst chunks = wrapChunkedOps(\n\t\t\tsplitOp(generateChunkableOp(chunkSizeInBytes * 3), chunkSizeInBytes),\n\t\t\t\"testClient\",\n\t\t);\n\t\tconst opSplitter = new OpSplitter(\n\t\t\t[],\n\t\t\tmockSubmitBatchFn,\n\t\t\t0,\n\t\t\tmaxBatchSizeInBytes,\n\t\t\tmockLogger,\n\t\t);\n\t\topSplitter.processRemoteMessage(chunks[0]);\n\n\t\tassert.equal(opSplitter.chunks.size, 1);\n\t\topSplitter.clearPartialChunks(\"noClient\");\n\t\tassert.equal(opSplitter.chunks.size, 1);\n\t\topSplitter.clearPartialChunks(\"testClient\");\n\t\tassert.equal(opSplitter.chunks.size, 0);\n\t});\n\n\tit(\"Throw when processing out-of-order chunks\", () => {\n\t\tconst chunks = wrapChunkedOps(\n\t\t\tsplitOp(generateChunkableOp(chunkSizeInBytes * 3), chunkSizeInBytes),\n\t\t\t\"testClient1\",\n\t\t);\n\t\tconst opSplitter = new OpSplitter(\n\t\t\t[],\n\t\t\tmockSubmitBatchFn,\n\t\t\t0,\n\t\t\tmaxBatchSizeInBytes,\n\t\t\tmockLogger,\n\t\t);\n\t\tassert.throws(() => opSplitter.processRemoteMessage(chunks[2]));\n\t});\n\n\tit(\"Don't accept non-chunked ops\", () => {\n\t\tconst chunks = wrapChunkedOps(\n\t\t\tsplitOp(generateChunkableOp(chunkSizeInBytes * 3), chunkSizeInBytes),\n\t\t\t\"testClient1\",\n\t\t).map((op) => ({ ...op, type: ContainerMessageType.FluidDataStoreOp }));\n\t\tconst opSplitter = new OpSplitter(\n\t\t\t[],\n\t\t\tmockSubmitBatchFn,\n\t\t\t0,\n\t\t\tmaxBatchSizeInBytes,\n\t\t\tmockLogger,\n\t\t);\n\t\tfor (const op of chunks) {\n\t\t\tassert.deepStrictEqual(opSplitter.processRemoteMessage(op), {\n\t\t\t\tmessage: op,\n\t\t\t\tstate: \"Skipped\",\n\t\t\t});\n\t\t}\n\t});\n\n\tit(\"Chunk metadata\", () => {\n\t\tconst originalOp = generateChunkableOp(chunkSizeInBytes * 4);\n\t\tconst chunks = splitOp(originalOp, chunkSizeInBytes);\n\t\tassert.equal(\n\t\t\tchunks\n\t\t\t\t.slice(0, -1)\n\t\t\t\t.every(\n\t\t\t\t\t(chunk) =>\n\t\t\t\t\t\tchunk.originalCompression === undefined &&\n\t\t\t\t\t\tchunk.originalMetadata === undefined,\n\t\t\t\t),\n\t\t\ttrue,\n\t\t);\n\n\t\tconst lastChunk = chunks[chunks.length - 1];\n\t\tassert.deepStrictEqual(lastChunk.originalMetadata, originalOp.metadata);\n\t\tassert.equal(lastChunk.originalCompression, originalOp.compression);\n\t});\n\n\tit(\"Batch split invariants\", () => {\n\t\tconst opSplitter = new OpSplitter(\n\t\t\t[],\n\t\t\tmockSubmitBatchFn,\n\t\t\t50,\n\t\t\tmaxBatchSizeInBytes,\n\t\t\tmockLogger,\n\t\t);\n\t\tconst regularMessage = generateChunkableOp(20);\n\t\tconst compressedMessage = { ...regularMessage, metadata: { compressed: true } };\n\n\t\t// Empty batch\n\t\tassert.throws(() =>\n\t\t\topSplitter.splitFirstBatchMessage({\n\t\t\t\tcontent: [compressedMessage],\n\t\t\t\tcontentSizeInBytes: 0,\n\t\t\t\treferenceSequenceNumber: 0,\n\t\t\t}),\n\t\t);\n\n\t\t// Empty batch\n\t\tassert.throws(() =>\n\t\t\topSplitter.splitFirstBatchMessage({\n\t\t\t\tcontent: [],\n\t\t\t\tcontentSizeInBytes: 1,\n\t\t\t\treferenceSequenceNumber: 0,\n\t\t\t}),\n\t\t);\n\n\t\t// Batch is too small to be chunked\n\t\tassert.throws(() =>\n\t\t\topSplitter.splitFirstBatchMessage({\n\t\t\t\tcontent: [compressedMessage],\n\t\t\t\tcontentSizeInBytes: 1,\n\t\t\t\treferenceSequenceNumber: 0,\n\t\t\t}),\n\t\t);\n\n\t\t// Batch is not compressed\n\t\tassert.throws(() =>\n\t\t\topSplitter.splitFirstBatchMessage({\n\t\t\t\tcontent: [regularMessage],\n\t\t\t\tcontentSizeInBytes: 3,\n\t\t\t\treferenceSequenceNumber: 0,\n\t\t\t}),\n\t\t);\n\n\t\t// Misconfigured op splitter\n\t\tassert.throws(() =>\n\t\t\tnew OpSplitter(\n\t\t\t\t[],\n\t\t\t\tmockSubmitBatchFn,\n\t\t\t\t0,\n\t\t\t\tmaxBatchSizeInBytes,\n\t\t\t\tmockLogger,\n\t\t\t).splitFirstBatchMessage({\n\t\t\t\tcontent: [compressedMessage],\n\t\t\t\tcontentSizeInBytes: 3,\n\t\t\t\treferenceSequenceNumber: 0,\n\t\t\t}),\n\t\t);\n\n\t\t// Old loader\n\t\tassert.throws(() =>\n\t\t\tnew OpSplitter(\n\t\t\t\t[],\n\t\t\t\tundefined,\n\t\t\t\t0,\n\t\t\t\tmaxBatchSizeInBytes,\n\t\t\t\tmockLogger,\n\t\t\t).splitFirstBatchMessage({\n\t\t\t\tcontent: [compressedMessage],\n\t\t\t\tcontentSizeInBytes: 3,\n\t\t\t\treferenceSequenceNumber: 0,\n\t\t\t}),\n\t\t);\n\n\t\t// Misconfigured op splitter\n\t\tassert.throws(() =>\n\t\t\tnew OpSplitter([], mockSubmitBatchFn, 2, 1, mockLogger).splitFirstBatchMessage({\n\t\t\t\tcontent: [compressedMessage],\n\t\t\t\tcontentSizeInBytes: 3,\n\t\t\t\treferenceSequenceNumber: 0,\n\t\t\t}),\n\t\t);\n\n\t\t// Not enabled\n\t\tassert.throws(() =>\n\t\t\tnew OpSplitter(\n\t\t\t\t[],\n\t\t\t\tmockSubmitBatchFn,\n\t\t\t\tNumber.POSITIVE_INFINITY,\n\t\t\t\tmaxBatchSizeInBytes,\n\t\t\t\tmockLogger,\n\t\t\t).splitFirstBatchMessage({\n\t\t\t\tcontent: [compressedMessage],\n\t\t\t\tcontentSizeInBytes: 3,\n\t\t\t\treferenceSequenceNumber: 0,\n\t\t\t}),\n\t\t);\n\t});\n\n\tdescribe(\"Compressed batches\", () => {\n\t\t[false, true].forEach((extraOp) => {\n\t\t\tit(`Split compressed batch with multiple messages with${\n\t\t\t\textraOp ? \"\" : \"out\"\n\t\t\t} extra empty op.`, () => {\n\t\t\t\tconst chunkSize = 20;\n\t\t\t\tconst opSplitter = new OpSplitter(\n\t\t\t\t\t[],\n\t\t\t\t\tmockSubmitBatchFn,\n\t\t\t\t\tchunkSize,\n\t\t\t\t\textraOp ? chunkSize * 2 : maxBatchSizeInBytes,\n\t\t\t\t\tmockLogger,\n\t\t\t\t);\n\t\t\t\tconst largeMessage = generateChunkableOp(100);\n\t\t\t\tconst emptyMessage = generateChunkableOp(0);\n\n\t\t\t\tconst result = opSplitter.splitFirstBatchMessage({\n\t\t\t\t\tcontent: [largeMessage, emptyMessage, emptyMessage, emptyMessage],\n\t\t\t\t\tcontentSizeInBytes: largeMessage.contents?.length ?? 0,\n\t\t\t\t\treferenceSequenceNumber: 0,\n\t\t\t\t});\n\n\t\t\t\tassert.equal(batchesSubmitted.length, 5 + (extraOp ? 1 : 0));\n\t\t\t\tfor (const batch of batchesSubmitted) {\n\t\t\t\t\tassert.equal(batch.messages.length, 1);\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t(batch.messages[0] as BatchMessage).type,\n\t\t\t\t\t\tContainerMessageType.ChunkedOp,\n\t\t\t\t\t);\n\t\t\t\t\tassert.equal(batch.referenceSequenceNumber, 0);\n\t\t\t\t}\n\n\t\t\t\tassert.equal(result.content.length, 4);\n\t\t\t\tconst lastChunk = JSON.parse(result.content[0].contents!).contents as IChunkedOp;\n\t\t\t\tassert.equal(lastChunk.chunkId, lastChunk.totalChunks);\n\t\t\t\tassert.deepStrictEqual(result.content.slice(1), new Array(3).fill(emptyMessage));\n\t\t\t\tassert.equal(\n\t\t\t\t\t!extraOp ||\n\t\t\t\t\t\tJSON.parse(result.content[0].contents!).contents?.contents?.length === 0,\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t\tassert.notEqual(result.contentSizeInBytes, largeMessage.contents?.length ?? 0);\n\t\t\t\tconst contentSentSeparately = batchesSubmitted.map(\n\t\t\t\t\t(x) =>\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\tJSON.parse((x.messages[0] as BatchMessage).contents!)\n\t\t\t\t\t\t\t\t.contents as IChunkedOp\n\t\t\t\t\t\t).contents,\n\t\t\t\t);\n\t\t\t\tconst sentContent = [...contentSentSeparately, lastChunk.contents].reduce(\n\t\t\t\t\t(accumulator, current) => `${accumulator}${current}`,\n\t\t\t\t);\n\t\t\t\tassert.equal(sentContent, largeMessage.contents);\n\n\t\t\t\tassert(\n\t\t\t\t\tmockLogger.matchEvents([\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\teventName: \"OpSplitter:CompressedChunkedBatch\",\n\t\t\t\t\t\t\tlength: result.content.length,\n\t\t\t\t\t\t\tchunks: 100 / 20 + 1 + (extraOp ? 1 : 0),\n\t\t\t\t\t\t\tchunkSizeInBytes: 20,\n\t\t\t\t\t\t},\n\t\t\t\t\t]),\n\t\t\t\t);\n\t\t\t});\n\n\t\t\tit(`Split compressed batch with single message with${\n\t\t\t\textraOp ? \"\" : \"out\"\n\t\t\t} extra empty op.`, () => {\n\t\t\t\tconst chunkSize = 20;\n\t\t\t\tconst opSplitter = new OpSplitter(\n\t\t\t\t\t[],\n\t\t\t\t\tmockSubmitBatchFn,\n\t\t\t\t\t20,\n\t\t\t\t\textraOp ? chunkSize * 2 : maxBatchSizeInBytes,\n\t\t\t\t\tmockLogger,\n\t\t\t\t);\n\t\t\t\tconst largeMessage = generateChunkableOp(100);\n\n\t\t\t\tconst result = opSplitter.splitFirstBatchMessage({\n\t\t\t\t\tcontent: [largeMessage],\n\t\t\t\t\tcontentSizeInBytes: largeMessage.contents?.length ?? 0,\n\t\t\t\t\treferenceSequenceNumber: 0,\n\t\t\t\t});\n\n\t\t\t\tassert.equal(batchesSubmitted.length, 5 + (extraOp ? 1 : 0));\n\t\t\t\tfor (const batch of batchesSubmitted) {\n\t\t\t\t\tassert.equal(batch.messages.length, 1);\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t(batch.messages[0] as BatchMessage).type,\n\t\t\t\t\t\tContainerMessageType.ChunkedOp,\n\t\t\t\t\t);\n\t\t\t\t\tassert.equal(batch.referenceSequenceNumber, 0);\n\t\t\t\t}\n\n\t\t\t\tassert.equal(result.content.length, 1);\n\t\t\t\tassert.notEqual(result.contentSizeInBytes, largeMessage.contents?.length ?? 0);\n\t\t\t\tconst lastChunk = JSON.parse(result.content[0].contents!).contents as IChunkedOp;\n\t\t\t\tassert.equal(lastChunk.chunkId, lastChunk.totalChunks);\n\t\t\t\tassert.equal(\n\t\t\t\t\t!extraOp ||\n\t\t\t\t\t\tJSON.parse(result.content[0].contents!).contents?.contents?.length === 0,\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t\tassert.notEqual(result.contentSizeInBytes, largeMessage.contents?.length ?? 0);\n\t\t\t\tconst contentSentSeparately = batchesSubmitted.map(\n\t\t\t\t\t(x) =>\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\tJSON.parse((x.messages[0] as BatchMessage).contents!)\n\t\t\t\t\t\t\t\t.contents as IChunkedOp\n\t\t\t\t\t\t).contents,\n\t\t\t\t);\n\t\t\t\tconst sentContent = [...contentSentSeparately, lastChunk.contents].reduce(\n\t\t\t\t\t(accumulator, current) => `${accumulator}${current}`,\n\t\t\t\t);\n\t\t\t\tassert.equal(sentContent, largeMessage.contents);\n\n\t\t\t\tassert(\n\t\t\t\t\tmockLogger.matchEvents([\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\teventName: \"OpSplitter:CompressedChunkedBatch\",\n\t\t\t\t\t\t\tlength: result.content.length,\n\t\t\t\t\t\t\tchunks: 100 / 20 + 1 + (extraOp ? 1 : 0),\n\t\t\t\t\t\t\tchunkSizeInBytes: 20,\n\t\t\t\t\t\t},\n\t\t\t\t\t]),\n\t\t\t\t);\n\t\t\t});\n\t\t});\n\t});\n\n\tconst assertSameMessage = (result: ISequencedDocumentMessage, original: BatchMessage) => {\n\t\tassert.deepStrictEqual(result.contents, JSON.parse(original.contents!));\n\t\tassert.strictEqual(result.type, original.type);\n\t\tassert.strictEqual(result.metadata, original.metadata);\n\t\tassert.strictEqual(result.compression, original.compression);\n\t};\n\n\tconst generateChunkableOp = (contentSizeInBytes: number): BatchMessage => {\n\t\tconst contents = { value: crypto.randomBytes(contentSizeInBytes / 2).toString(\"hex\") };\n\t\treturn {\n\t\t\tlocalOpMetadata: undefined,\n\t\t\ttype: ContainerMessageType.FluidDataStoreOp,\n\t\t\treferenceSequenceNumber: Infinity,\n\t\t\tmetadata: { meta: \"data\" },\n\t\t\tcompression: CompressionAlgorithms.lz4,\n\t\t\tcontents: JSON.stringify(contents),\n\t\t};\n\t};\n\n\tconst wrapChunkedOps = (ops: IChunkedOp[], clientId: string): ISequencedDocumentMessage[] =>\n\t\tops.map((op) => {\n\t\t\tconst result = {\n\t\t\t\tcontents: op,\n\t\t\t\tclientId,\n\t\t\t\ttype: ContainerMessageType.ChunkedOp,\n\t\t\t};\n\n\t\t\treturn result as ISequencedDocumentMessage;\n\t\t});\n});\n"]}
1
+ {"version":3,"file":"opSplitter.spec.js","sourceRoot":"","sources":["../../../src/test/opLifecycle/opSplitter.spec.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,6DAA6D;AAE7D,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,EAAE,MAAM,IAAI,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,4CAA4C,CAAC;AAGlF,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC7D,OAAO,EAA4B,UAAU,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAC3F,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAElE,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC3B,MAAM,gBAAgB,GAAsE,EAAE,CAAC;IAE/F,MAAM,iBAAiB,GAAG,CACzB,KAAsB,EACtB,uBAAgC,EACvB,EAAE;QACX,gBAAgB,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC,CAAC;QACpE,OAAO,gBAAgB,CAAC,MAAM,CAAC;IAChC,CAAC,CAAC;IAEF,UAAU,CAAC,GAAG,EAAE;QACf,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC3B,UAAU,CAAC,KAAK,EAAE,CAAC;IACpB,CAAC,CAAC,CAAC;IAEH,MAAM,gBAAgB,GAAG,EAAE,GAAG,IAAI,CAAC;IACnC,MAAM,mBAAmB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC3C,MAAM,UAAU,GAAG,IAAI,UAAU,EAAE,CAAC;IAEpC,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QAC1C,MAAM,GAAG,GAAG,mBAAmB,CAAC,gBAAgB,GAAG,CAAC,CAAC,CAAC;QACtD,MAAM,GAAG,GAAG,mBAAmB,CAAC,gBAAgB,GAAG,CAAC,CAAC,CAAC;QACtD,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,gBAAgB,CAAC,EAAE,aAAa,CAAC,CAAC;QAC9E,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,gBAAgB,CAAC,EAAE,aAAa,CAAC,CAAC;QAC9E,MAAM,UAAU,GAAG,IAAI,UAAU,CAChC,EAAE,EACF,iBAAiB,EACjB,CAAC,EACD,mBAAmB,EACnB,UAAU,CACV,CAAC;QAEF,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAC5E,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAE5E,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAC5E,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAE5E,MAAM,iBAAiB,GAAG,UAAU,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACtE,uDAAuD;QACvD,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QACnD,iBAAiB,CAAC,iBAAiB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAClD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAExC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAE5E,MAAM,iBAAiB,GAAG,UAAU,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACtE,uDAAuD;QACvD,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QACnD,iBAAiB,CAAC,iBAAiB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAElD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC9D,MAAM,GAAG,GAAG,mBAAmB,CAAC,gBAAgB,GAAG,CAAC,CAAC,CAAC;QACtD,MAAM,GAAG,GAAG,mBAAmB,CAAC,gBAAgB,GAAG,CAAC,CAAC,CAAC;QACtD,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,gBAAgB,EAAE,IAAI,CAAC,EAAE,aAAa,CAAC,CAAC;QACpF,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,gBAAgB,EAAE,IAAI,CAAC,EAAE,aAAa,CAAC,CAAC;QACpF,MAAM,UAAU,GAAG,IAAI,UAAU,CAChC,EAAE,EACF,iBAAiB,EACjB,CAAC,EACD,mBAAmB,EACnB,UAAU,CACV,CAAC;QAEF,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAC5E,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAE5E,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAC5E,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAE5E,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAE5E,MAAM,iBAAiB,GAAG,UAAU,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACtE,uDAAuD;QACvD,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QACnD,iBAAiB,CAAC,iBAAiB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAClD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAExC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAC5E,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAE5E,MAAM,iBAAiB,GAAG,UAAU,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACtE,uDAAuD;QACvD,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QACnD,iBAAiB,CAAC,iBAAiB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAElD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC9D,MAAM,EAAE,GAAG,mBAAmB,CAAC,gBAAgB,GAAG,CAAC,CAAC,CAAC;QACrD,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,CAAC,EAAE,EAAE,gBAAgB,CAAC,EAAE,YAAY,CAAC,CAAC;QAC3E,MAAM,UAAU,GAAG,IAAI,UAAU,CAChC,EAAE,EACF,iBAAiB,EACjB,CAAC,EACD,mBAAmB,EACnB,UAAU,CACV,CAAC;QACF,UAAU,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3C,UAAU,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAE3C,MAAM,eAAe,GAAG,IAAI,UAAU,CACrC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAC7B,iBAAiB,EACjB,CAAC,EACD,mBAAmB,EACnB,UAAU,CACV,CAAC;QACF,UAAU,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC;QAE5C,eAAe,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAChD,iBAAiB,CAAC,eAAe,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,cAAc,EAAE,GAAG,EAAE;QACvB,MAAM,MAAM,GAAG,cAAc,CAC5B,OAAO,CAAC,mBAAmB,CAAC,gBAAgB,GAAG,CAAC,CAAC,EAAE,gBAAgB,CAAC,EACpE,YAAY,CACZ,CAAC;QACF,MAAM,UAAU,GAAG,IAAI,UAAU,CAChC,EAAE,EACF,iBAAiB,EACjB,CAAC,EACD,mBAAmB,EACnB,UAAU,CACV,CAAC;QACF,UAAU,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAE3C,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACxC,UAAU,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACxC,UAAU,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC;QAC5C,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACpD,MAAM,MAAM,GAAG,cAAc,CAC5B,OAAO,CAAC,mBAAmB,CAAC,gBAAgB,GAAG,CAAC,CAAC,EAAE,gBAAgB,CAAC,EACpE,aAAa,CACb,CAAC;QACF,MAAM,UAAU,GAAG,IAAI,UAAU,CAChC,EAAE,EACF,iBAAiB,EACjB,CAAC,EACD,mBAAmB,EACnB,UAAU,CACV,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACvC,MAAM,MAAM,GAAG,cAAc,CAC5B,OAAO,CAAC,mBAAmB,CAAC,gBAAgB,GAAG,CAAC,CAAC,EAAE,gBAAgB,CAAC,EACpE,aAAa,CACb,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,oBAAoB,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC;QACxE,MAAM,UAAU,GAAG,IAAI,UAAU,CAChC,EAAE,EACF,iBAAiB,EACjB,CAAC,EACD,mBAAmB,EACnB,UAAU,CACV,CAAC;QACF,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE;YACxB,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,oBAAoB,CAAC,EAAE,CAAC,EAAE;gBAC3D,OAAO,EAAE,EAAE;gBACX,KAAK,EAAE,SAAS;aAChB,CAAC,CAAC;SACH;IACF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gBAAgB,EAAE,GAAG,EAAE;QACzB,MAAM,UAAU,GAAG,mBAAmB,CAAC,gBAAgB,GAAG,CAAC,CAAC,CAAC;QAC7D,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC;QACrD,MAAM,CAAC,KAAK,CACX,MAAM;aACJ,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;aACZ,KAAK,CACL,CAAC,KAAK,EAAE,EAAE,CACT,KAAK,CAAC,mBAAmB,KAAK,SAAS;YACvC,KAAK,CAAC,gBAAgB,KAAK,SAAS,CACrC,EACF,IAAI,CACJ,CAAC;QAEF,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,eAAe,CAAC,SAAS,CAAC,gBAAgB,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;QACxE,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,mBAAmB,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QACjC,MAAM,UAAU,GAAG,IAAI,UAAU,CAChC,EAAE,EACF,iBAAiB,EACjB,EAAE,EACF,mBAAmB,EACnB,UAAU,CACV,CAAC;QACF,MAAM,cAAc,GAAG,mBAAmB,CAAC,EAAE,CAAC,CAAC;QAC/C,MAAM,iBAAiB,GAAG,EAAE,GAAG,cAAc,EAAE,QAAQ,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC;QAEhF,cAAc;QACd,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAClB,UAAU,CAAC,sBAAsB,CAAC;YACjC,OAAO,EAAE,CAAC,iBAAiB,CAAC;YAC5B,kBAAkB,EAAE,CAAC;YACrB,uBAAuB,EAAE,CAAC;SAC1B,CAAC,CACF,CAAC;QAEF,cAAc;QACd,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAClB,UAAU,CAAC,sBAAsB,CAAC;YACjC,OAAO,EAAE,EAAE;YACX,kBAAkB,EAAE,CAAC;YACrB,uBAAuB,EAAE,CAAC;SAC1B,CAAC,CACF,CAAC;QAEF,mCAAmC;QACnC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAClB,UAAU,CAAC,sBAAsB,CAAC;YACjC,OAAO,EAAE,CAAC,iBAAiB,CAAC;YAC5B,kBAAkB,EAAE,CAAC;YACrB,uBAAuB,EAAE,CAAC;SAC1B,CAAC,CACF,CAAC;QAEF,0BAA0B;QAC1B,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAClB,UAAU,CAAC,sBAAsB,CAAC;YACjC,OAAO,EAAE,CAAC,cAAc,CAAC;YACzB,kBAAkB,EAAE,CAAC;YACrB,uBAAuB,EAAE,CAAC;SAC1B,CAAC,CACF,CAAC;QAEF,4BAA4B;QAC5B,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAClB,IAAI,UAAU,CACb,EAAE,EACF,iBAAiB,EACjB,CAAC,EACD,mBAAmB,EACnB,UAAU,CACV,CAAC,sBAAsB,CAAC;YACxB,OAAO,EAAE,CAAC,iBAAiB,CAAC;YAC5B,kBAAkB,EAAE,CAAC;YACrB,uBAAuB,EAAE,CAAC;SAC1B,CAAC,CACF,CAAC;QAEF,aAAa;QACb,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAClB,IAAI,UAAU,CACb,EAAE,EACF,SAAS,EACT,CAAC,EACD,mBAAmB,EACnB,UAAU,CACV,CAAC,sBAAsB,CAAC;YACxB,OAAO,EAAE,CAAC,iBAAiB,CAAC;YAC5B,kBAAkB,EAAE,CAAC;YACrB,uBAAuB,EAAE,CAAC;SAC1B,CAAC,CACF,CAAC;QAEF,4BAA4B;QAC5B,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAClB,IAAI,UAAU,CAAC,EAAE,EAAE,iBAAiB,EAAE,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC,sBAAsB,CAAC;YAC9E,OAAO,EAAE,CAAC,iBAAiB,CAAC;YAC5B,kBAAkB,EAAE,CAAC;YACrB,uBAAuB,EAAE,CAAC;SAC1B,CAAC,CACF,CAAC;QAEF,cAAc;QACd,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAClB,IAAI,UAAU,CACb,EAAE,EACF,iBAAiB,EACjB,MAAM,CAAC,iBAAiB,EACxB,mBAAmB,EACnB,UAAU,CACV,CAAC,sBAAsB,CAAC;YACxB,OAAO,EAAE,CAAC,iBAAiB,CAAC;YAC5B,kBAAkB,EAAE,CAAC;YACrB,uBAAuB,EAAE,CAAC;SAC1B,CAAC,CACF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;QACnC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YACjC,EAAE,CAAC,qDACF,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAChB,kBAAkB,EAAE,GAAG,EAAE;gBACxB,MAAM,SAAS,GAAG,EAAE,CAAC;gBACrB,MAAM,UAAU,GAAG,IAAI,UAAU,CAChC,EAAE,EACF,iBAAiB,EACjB,SAAS,EACT,OAAO,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,mBAAmB,EAC7C,UAAU,CACV,CAAC;gBACF,MAAM,YAAY,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;gBAC9C,MAAM,YAAY,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC;gBAE5C,MAAM,MAAM,GAAG,UAAU,CAAC,sBAAsB,CAAC;oBAChD,OAAO,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,CAAC;oBACjE,kBAAkB,EAAE,YAAY,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC;oBACtD,uBAAuB,EAAE,CAAC;iBAC1B,CAAC,CAAC;gBAEH,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC7D,KAAK,MAAM,KAAK,IAAI,gBAAgB,EAAE;oBACrC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;oBACvC,MAAM,CAAC,KAAK,CACV,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAkB,CAAC,IAAI,EACxC,oBAAoB,CAAC,SAAS,CAC9B,CAAC;oBACF,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,uBAAuB,EAAE,CAAC,CAAC,CAAC;iBAC/C;gBAED,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;gBACvC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAS,CAAC,CAAC,QAAsB,CAAC;gBACjF,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC;gBACvD,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;gBACjF,MAAM,CAAC,KAAK,CACX,CAAC,OAAO;oBACP,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAS,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC,EACzE,IAAI,CACJ,CAAC;gBACF,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,kBAAkB,EAAE,YAAY,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,CAAC,CAAC;gBAC/E,MAAM,qBAAqB,GAAG,gBAAgB,CAAC,GAAG,CACjD,CAAC,CAAC,EAAE,EAAE,CAEJ,IAAI,CAAC,KAAK,CAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAkB,CAAC,QAAS,CAAC;qBACnD,QACF,CAAC,QAAQ,CACX,CAAC;gBACF,MAAM,WAAW,GAAG,CAAC,GAAG,qBAAqB,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC,MAAM,CACxE,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,WAAW,GAAG,OAAO,EAAE,CACpD,CAAC;gBACF,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;gBAEjD,MAAM,CACL,UAAU,CAAC,WAAW,CAAC;oBACtB;wBACC,SAAS,EAAE,mCAAmC;wBAC9C,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM;wBAC7B,MAAM,EAAE,GAAG,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;wBACxC,gBAAgB,EAAE,EAAE;qBACpB;iBACD,CAAC,CACF,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,kDACF,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAChB,kBAAkB,EAAE,GAAG,EAAE;gBACxB,MAAM,SAAS,GAAG,EAAE,CAAC;gBACrB,MAAM,UAAU,GAAG,IAAI,UAAU,CAChC,EAAE,EACF,iBAAiB,EACjB,EAAE,EACF,OAAO,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,mBAAmB,EAC7C,UAAU,CACV,CAAC;gBACF,MAAM,YAAY,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;gBAE9C,MAAM,MAAM,GAAG,UAAU,CAAC,sBAAsB,CAAC;oBAChD,OAAO,EAAE,CAAC,YAAY,CAAC;oBACvB,kBAAkB,EAAE,YAAY,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC;oBACtD,uBAAuB,EAAE,CAAC;iBAC1B,CAAC,CAAC;gBAEH,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC7D,KAAK,MAAM,KAAK,IAAI,gBAAgB,EAAE;oBACrC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;oBACvC,MAAM,CAAC,KAAK,CACV,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAkB,CAAC,IAAI,EACxC,oBAAoB,CAAC,SAAS,CAC9B,CAAC;oBACF,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,uBAAuB,EAAE,CAAC,CAAC,CAAC;iBAC/C;gBAED,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;gBACvC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,kBAAkB,EAAE,YAAY,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,CAAC,CAAC;gBAC/E,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAS,CAAC,CAAC,QAAsB,CAAC;gBACjF,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC;gBACvD,MAAM,CAAC,KAAK,CACX,CAAC,OAAO;oBACP,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAS,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC,EACzE,IAAI,CACJ,CAAC;gBACF,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,kBAAkB,EAAE,YAAY,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,CAAC,CAAC;gBAC/E,MAAM,qBAAqB,GAAG,gBAAgB,CAAC,GAAG,CACjD,CAAC,CAAC,EAAE,EAAE,CAEJ,IAAI,CAAC,KAAK,CAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAkB,CAAC,QAAS,CAAC;qBACnD,QACF,CAAC,QAAQ,CACX,CAAC;gBACF,MAAM,WAAW,GAAG,CAAC,GAAG,qBAAqB,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC,MAAM,CACxE,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,WAAW,GAAG,OAAO,EAAE,CACpD,CAAC;gBACF,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;gBAEjD,MAAM,CACL,UAAU,CAAC,WAAW,CAAC;oBACtB;wBACC,SAAS,EAAE,mCAAmC;wBAC9C,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM;wBAC7B,MAAM,EAAE,GAAG,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;wBACxC,gBAAgB,EAAE,EAAE;qBACpB;iBACD,CAAC,CACF,CAAC;YACH,CAAC,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,iBAAiB,GAAG,CAAC,MAAiC,EAAE,QAAsB,EAAE,EAAE;QACvF,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAS,CAAC,CAAC,CAAC;QACxE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC/C,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACvD,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC9D,CAAC,CAAC;IAEF,MAAM,mBAAmB,GAAG,CAAC,kBAA0B,EAAgB,EAAE;QACxE,MAAM,QAAQ,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC,kBAAkB,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACvF,OAAO;YACN,eAAe,EAAE,SAAS;YAC1B,IAAI,EAAE,oBAAoB,CAAC,gBAAgB;YAC3C,uBAAuB,EAAE,QAAQ;YACjC,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;YAC1B,WAAW,EAAE,qBAAqB,CAAC,GAAG;YACtC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;SAClC,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,CAAC,GAAiB,EAAE,QAAgB,EAA+B,EAAE,CAC3F,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;QACd,MAAM,MAAM,GAAG;YACd,QAAQ,EAAE,EAAE;YACZ,QAAQ;YACR,IAAI,EAAE,oBAAoB,CAAC,SAAS;SACpC,CAAC;QAEF,OAAO,MAAmC,CAAC;IAC5C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/* eslint-disable @typescript-eslint/no-non-null-assertion */\n\nimport * as crypto from \"crypto\";\nimport { strict as assert } from \"assert\";\nimport { ContainerMessageType } from \"@fluidframework/container-runtime-previous\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { IBatchMessage } from \"@fluidframework/container-definitions\";\nimport { MockLogger } from \"@fluidframework/telemetry-utils\";\nimport { BatchMessage, IChunkedOp, OpSplitter, splitOp } from \"../../opLifecycle/index.js\";\nimport { CompressionAlgorithms } from \"../../containerRuntime.js\";\n\ndescribe(\"OpSplitter\", () => {\n\tconst batchesSubmitted: { messages: IBatchMessage[]; referenceSequenceNumber?: number }[] = [];\n\n\tconst mockSubmitBatchFn = (\n\t\tbatch: IBatchMessage[],\n\t\treferenceSequenceNumber?: number,\n\t): number => {\n\t\tbatchesSubmitted.push({ messages: batch, referenceSequenceNumber });\n\t\treturn batchesSubmitted.length;\n\t};\n\n\tbeforeEach(() => {\n\t\tbatchesSubmitted.splice(0);\n\t\tmockLogger.clear();\n\t});\n\n\tconst chunkSizeInBytes = 50 * 1024;\n\tconst maxBatchSizeInBytes = 10 * 50 * 1024;\n\tconst mockLogger = new MockLogger();\n\n\tit(\"Reconstruct original chunked op\", () => {\n\t\tconst op1 = generateChunkableOp(chunkSizeInBytes * 2);\n\t\tconst op2 = generateChunkableOp(chunkSizeInBytes * 3);\n\t\tconst chunks1 = wrapChunkedOps(splitOp(op1, chunkSizeInBytes), \"testClient1\");\n\t\tconst chunks2 = wrapChunkedOps(splitOp(op2, chunkSizeInBytes), \"testClient2\");\n\t\tconst opSplitter = new OpSplitter(\n\t\t\t[],\n\t\t\tmockSubmitBatchFn,\n\t\t\t0,\n\t\t\tmaxBatchSizeInBytes,\n\t\t\tmockLogger,\n\t\t);\n\n\t\tassert.equal(opSplitter.processRemoteMessage(chunks1[0]).state, \"Accepted\");\n\t\tassert.equal(opSplitter.processRemoteMessage(chunks2[0]).state, \"Accepted\");\n\n\t\tassert.equal(opSplitter.processRemoteMessage(chunks1[1]).state, \"Accepted\");\n\t\tassert.equal(opSplitter.processRemoteMessage(chunks2[1]).state, \"Accepted\");\n\n\t\tconst chunks1LastResult = opSplitter.processRemoteMessage(chunks1[2]);\n\t\t// The last chunk will reconstruct the original message\n\t\tassert.equal(chunks1LastResult.state, \"Processed\");\n\t\tassertSameMessage(chunks1LastResult.message, op1);\n\t\tassert.equal(opSplitter.chunks.size, 1);\n\n\t\tassert.equal(opSplitter.processRemoteMessage(chunks2[2]).state, \"Accepted\");\n\n\t\tconst chunks2LastResult = opSplitter.processRemoteMessage(chunks2[3]);\n\t\t// The last chunk will reconstruct the original message\n\t\tassert.equal(chunks2LastResult.state, \"Processed\");\n\t\tassertSameMessage(chunks2LastResult.message, op2);\n\n\t\tassert.equal(opSplitter.chunks.size, 0);\n\t});\n\n\tit(\"Reconstruct original chunked op with extra empty op\", () => {\n\t\tconst op1 = generateChunkableOp(chunkSizeInBytes * 2);\n\t\tconst op2 = generateChunkableOp(chunkSizeInBytes * 3);\n\t\tconst chunks1 = wrapChunkedOps(splitOp(op1, chunkSizeInBytes, true), \"testClient1\");\n\t\tconst chunks2 = wrapChunkedOps(splitOp(op2, chunkSizeInBytes, true), \"testClient2\");\n\t\tconst opSplitter = new OpSplitter(\n\t\t\t[],\n\t\t\tmockSubmitBatchFn,\n\t\t\t0,\n\t\t\tmaxBatchSizeInBytes,\n\t\t\tmockLogger,\n\t\t);\n\n\t\tassert.equal(opSplitter.processRemoteMessage(chunks1[0]).state, \"Accepted\");\n\t\tassert.equal(opSplitter.processRemoteMessage(chunks2[0]).state, \"Accepted\");\n\n\t\tassert.equal(opSplitter.processRemoteMessage(chunks1[1]).state, \"Accepted\");\n\t\tassert.equal(opSplitter.processRemoteMessage(chunks2[1]).state, \"Accepted\");\n\n\t\tassert.equal(opSplitter.processRemoteMessage(chunks1[2]).state, \"Accepted\");\n\n\t\tconst chunks1LastResult = opSplitter.processRemoteMessage(chunks1[3]);\n\t\t// The last chunk will reconstruct the original message\n\t\tassert.equal(chunks1LastResult.state, \"Processed\");\n\t\tassertSameMessage(chunks1LastResult.message, op1);\n\t\tassert.equal(opSplitter.chunks.size, 1);\n\n\t\tassert.equal(opSplitter.processRemoteMessage(chunks2[2]).state, \"Accepted\");\n\t\tassert.equal(opSplitter.processRemoteMessage(chunks2[3]).state, \"Accepted\");\n\n\t\tconst chunks2LastResult = opSplitter.processRemoteMessage(chunks2[4]);\n\t\t// The last chunk will reconstruct the original message\n\t\tassert.equal(chunks2LastResult.state, \"Processed\");\n\t\tassertSameMessage(chunks2LastResult.message, op2);\n\n\t\tassert.equal(opSplitter.chunks.size, 0);\n\t});\n\n\tit(\"Reconstruct original chunked op with initial chunks\", () => {\n\t\tconst op = generateChunkableOp(chunkSizeInBytes * 3);\n\t\tconst chunks = wrapChunkedOps(splitOp(op, chunkSizeInBytes), \"testClient\");\n\t\tconst opSplitter = new OpSplitter(\n\t\t\t[],\n\t\t\tmockSubmitBatchFn,\n\t\t\t0,\n\t\t\tmaxBatchSizeInBytes,\n\t\t\tmockLogger,\n\t\t);\n\t\topSplitter.processRemoteMessage(chunks[0]);\n\t\topSplitter.processRemoteMessage(chunks[1]);\n\n\t\tconst otherOpSplitter = new OpSplitter(\n\t\t\tArray.from(opSplitter.chunks),\n\t\t\tmockSubmitBatchFn,\n\t\t\t0,\n\t\t\tmaxBatchSizeInBytes,\n\t\t\tmockLogger,\n\t\t);\n\t\topSplitter.clearPartialChunks(\"testClient\");\n\n\t\totherOpSplitter.processRemoteMessage(chunks[2]);\n\t\tassertSameMessage(otherOpSplitter.processRemoteMessage(chunks[3]).message, op);\n\t});\n\n\tit(\"Clear chunks\", () => {\n\t\tconst chunks = wrapChunkedOps(\n\t\t\tsplitOp(generateChunkableOp(chunkSizeInBytes * 3), chunkSizeInBytes),\n\t\t\t\"testClient\",\n\t\t);\n\t\tconst opSplitter = new OpSplitter(\n\t\t\t[],\n\t\t\tmockSubmitBatchFn,\n\t\t\t0,\n\t\t\tmaxBatchSizeInBytes,\n\t\t\tmockLogger,\n\t\t);\n\t\topSplitter.processRemoteMessage(chunks[0]);\n\n\t\tassert.equal(opSplitter.chunks.size, 1);\n\t\topSplitter.clearPartialChunks(\"noClient\");\n\t\tassert.equal(opSplitter.chunks.size, 1);\n\t\topSplitter.clearPartialChunks(\"testClient\");\n\t\tassert.equal(opSplitter.chunks.size, 0);\n\t});\n\n\tit(\"Throw when processing out-of-order chunks\", () => {\n\t\tconst chunks = wrapChunkedOps(\n\t\t\tsplitOp(generateChunkableOp(chunkSizeInBytes * 3), chunkSizeInBytes),\n\t\t\t\"testClient1\",\n\t\t);\n\t\tconst opSplitter = new OpSplitter(\n\t\t\t[],\n\t\t\tmockSubmitBatchFn,\n\t\t\t0,\n\t\t\tmaxBatchSizeInBytes,\n\t\t\tmockLogger,\n\t\t);\n\t\tassert.throws(() => opSplitter.processRemoteMessage(chunks[2]));\n\t});\n\n\tit(\"Don't accept non-chunked ops\", () => {\n\t\tconst chunks = wrapChunkedOps(\n\t\t\tsplitOp(generateChunkableOp(chunkSizeInBytes * 3), chunkSizeInBytes),\n\t\t\t\"testClient1\",\n\t\t).map((op) => ({ ...op, type: ContainerMessageType.FluidDataStoreOp }));\n\t\tconst opSplitter = new OpSplitter(\n\t\t\t[],\n\t\t\tmockSubmitBatchFn,\n\t\t\t0,\n\t\t\tmaxBatchSizeInBytes,\n\t\t\tmockLogger,\n\t\t);\n\t\tfor (const op of chunks) {\n\t\t\tassert.deepStrictEqual(opSplitter.processRemoteMessage(op), {\n\t\t\t\tmessage: op,\n\t\t\t\tstate: \"Skipped\",\n\t\t\t});\n\t\t}\n\t});\n\n\tit(\"Chunk metadata\", () => {\n\t\tconst originalOp = generateChunkableOp(chunkSizeInBytes * 4);\n\t\tconst chunks = splitOp(originalOp, chunkSizeInBytes);\n\t\tassert.equal(\n\t\t\tchunks\n\t\t\t\t.slice(0, -1)\n\t\t\t\t.every(\n\t\t\t\t\t(chunk) =>\n\t\t\t\t\t\tchunk.originalCompression === undefined &&\n\t\t\t\t\t\tchunk.originalMetadata === undefined,\n\t\t\t\t),\n\t\t\ttrue,\n\t\t);\n\n\t\tconst lastChunk = chunks[chunks.length - 1];\n\t\tassert.deepStrictEqual(lastChunk.originalMetadata, originalOp.metadata);\n\t\tassert.equal(lastChunk.originalCompression, originalOp.compression);\n\t});\n\n\tit(\"Batch split invariants\", () => {\n\t\tconst opSplitter = new OpSplitter(\n\t\t\t[],\n\t\t\tmockSubmitBatchFn,\n\t\t\t50,\n\t\t\tmaxBatchSizeInBytes,\n\t\t\tmockLogger,\n\t\t);\n\t\tconst regularMessage = generateChunkableOp(20);\n\t\tconst compressedMessage = { ...regularMessage, metadata: { compressed: true } };\n\n\t\t// Empty batch\n\t\tassert.throws(() =>\n\t\t\topSplitter.splitFirstBatchMessage({\n\t\t\t\tcontent: [compressedMessage],\n\t\t\t\tcontentSizeInBytes: 0,\n\t\t\t\treferenceSequenceNumber: 0,\n\t\t\t}),\n\t\t);\n\n\t\t// Empty batch\n\t\tassert.throws(() =>\n\t\t\topSplitter.splitFirstBatchMessage({\n\t\t\t\tcontent: [],\n\t\t\t\tcontentSizeInBytes: 1,\n\t\t\t\treferenceSequenceNumber: 0,\n\t\t\t}),\n\t\t);\n\n\t\t// Batch is too small to be chunked\n\t\tassert.throws(() =>\n\t\t\topSplitter.splitFirstBatchMessage({\n\t\t\t\tcontent: [compressedMessage],\n\t\t\t\tcontentSizeInBytes: 1,\n\t\t\t\treferenceSequenceNumber: 0,\n\t\t\t}),\n\t\t);\n\n\t\t// Batch is not compressed\n\t\tassert.throws(() =>\n\t\t\topSplitter.splitFirstBatchMessage({\n\t\t\t\tcontent: [regularMessage],\n\t\t\t\tcontentSizeInBytes: 3,\n\t\t\t\treferenceSequenceNumber: 0,\n\t\t\t}),\n\t\t);\n\n\t\t// Misconfigured op splitter\n\t\tassert.throws(() =>\n\t\t\tnew OpSplitter(\n\t\t\t\t[],\n\t\t\t\tmockSubmitBatchFn,\n\t\t\t\t0,\n\t\t\t\tmaxBatchSizeInBytes,\n\t\t\t\tmockLogger,\n\t\t\t).splitFirstBatchMessage({\n\t\t\t\tcontent: [compressedMessage],\n\t\t\t\tcontentSizeInBytes: 3,\n\t\t\t\treferenceSequenceNumber: 0,\n\t\t\t}),\n\t\t);\n\n\t\t// Old loader\n\t\tassert.throws(() =>\n\t\t\tnew OpSplitter(\n\t\t\t\t[],\n\t\t\t\tundefined,\n\t\t\t\t0,\n\t\t\t\tmaxBatchSizeInBytes,\n\t\t\t\tmockLogger,\n\t\t\t).splitFirstBatchMessage({\n\t\t\t\tcontent: [compressedMessage],\n\t\t\t\tcontentSizeInBytes: 3,\n\t\t\t\treferenceSequenceNumber: 0,\n\t\t\t}),\n\t\t);\n\n\t\t// Misconfigured op splitter\n\t\tassert.throws(() =>\n\t\t\tnew OpSplitter([], mockSubmitBatchFn, 2, 1, mockLogger).splitFirstBatchMessage({\n\t\t\t\tcontent: [compressedMessage],\n\t\t\t\tcontentSizeInBytes: 3,\n\t\t\t\treferenceSequenceNumber: 0,\n\t\t\t}),\n\t\t);\n\n\t\t// Not enabled\n\t\tassert.throws(() =>\n\t\t\tnew OpSplitter(\n\t\t\t\t[],\n\t\t\t\tmockSubmitBatchFn,\n\t\t\t\tNumber.POSITIVE_INFINITY,\n\t\t\t\tmaxBatchSizeInBytes,\n\t\t\t\tmockLogger,\n\t\t\t).splitFirstBatchMessage({\n\t\t\t\tcontent: [compressedMessage],\n\t\t\t\tcontentSizeInBytes: 3,\n\t\t\t\treferenceSequenceNumber: 0,\n\t\t\t}),\n\t\t);\n\t});\n\n\tdescribe(\"Compressed batches\", () => {\n\t\t[false, true].forEach((extraOp) => {\n\t\t\tit(`Split compressed batch with multiple messages with${\n\t\t\t\textraOp ? \"\" : \"out\"\n\t\t\t} extra empty op.`, () => {\n\t\t\t\tconst chunkSize = 20;\n\t\t\t\tconst opSplitter = new OpSplitter(\n\t\t\t\t\t[],\n\t\t\t\t\tmockSubmitBatchFn,\n\t\t\t\t\tchunkSize,\n\t\t\t\t\textraOp ? chunkSize * 2 : maxBatchSizeInBytes,\n\t\t\t\t\tmockLogger,\n\t\t\t\t);\n\t\t\t\tconst largeMessage = generateChunkableOp(100);\n\t\t\t\tconst emptyMessage = generateChunkableOp(0);\n\n\t\t\t\tconst result = opSplitter.splitFirstBatchMessage({\n\t\t\t\t\tcontent: [largeMessage, emptyMessage, emptyMessage, emptyMessage],\n\t\t\t\t\tcontentSizeInBytes: largeMessage.contents?.length ?? 0,\n\t\t\t\t\treferenceSequenceNumber: 0,\n\t\t\t\t});\n\n\t\t\t\tassert.equal(batchesSubmitted.length, 5 + (extraOp ? 1 : 0));\n\t\t\t\tfor (const batch of batchesSubmitted) {\n\t\t\t\t\tassert.equal(batch.messages.length, 1);\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t(batch.messages[0] as BatchMessage).type,\n\t\t\t\t\t\tContainerMessageType.ChunkedOp,\n\t\t\t\t\t);\n\t\t\t\t\tassert.equal(batch.referenceSequenceNumber, 0);\n\t\t\t\t}\n\n\t\t\t\tassert.equal(result.content.length, 4);\n\t\t\t\tconst lastChunk = JSON.parse(result.content[0].contents!).contents as IChunkedOp;\n\t\t\t\tassert.equal(lastChunk.chunkId, lastChunk.totalChunks);\n\t\t\t\tassert.deepStrictEqual(result.content.slice(1), new Array(3).fill(emptyMessage));\n\t\t\t\tassert.equal(\n\t\t\t\t\t!extraOp ||\n\t\t\t\t\t\tJSON.parse(result.content[0].contents!).contents?.contents?.length === 0,\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t\tassert.notEqual(result.contentSizeInBytes, largeMessage.contents?.length ?? 0);\n\t\t\t\tconst contentSentSeparately = batchesSubmitted.map(\n\t\t\t\t\t(x) =>\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\tJSON.parse((x.messages[0] as BatchMessage).contents!)\n\t\t\t\t\t\t\t\t.contents as IChunkedOp\n\t\t\t\t\t\t).contents,\n\t\t\t\t);\n\t\t\t\tconst sentContent = [...contentSentSeparately, lastChunk.contents].reduce(\n\t\t\t\t\t(accumulator, current) => `${accumulator}${current}`,\n\t\t\t\t);\n\t\t\t\tassert.equal(sentContent, largeMessage.contents);\n\n\t\t\t\tassert(\n\t\t\t\t\tmockLogger.matchEvents([\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\teventName: \"OpSplitter:CompressedChunkedBatch\",\n\t\t\t\t\t\t\tlength: result.content.length,\n\t\t\t\t\t\t\tchunks: 100 / 20 + 1 + (extraOp ? 1 : 0),\n\t\t\t\t\t\t\tchunkSizeInBytes: 20,\n\t\t\t\t\t\t},\n\t\t\t\t\t]),\n\t\t\t\t);\n\t\t\t});\n\n\t\t\tit(`Split compressed batch with single message with${\n\t\t\t\textraOp ? \"\" : \"out\"\n\t\t\t} extra empty op.`, () => {\n\t\t\t\tconst chunkSize = 20;\n\t\t\t\tconst opSplitter = new OpSplitter(\n\t\t\t\t\t[],\n\t\t\t\t\tmockSubmitBatchFn,\n\t\t\t\t\t20,\n\t\t\t\t\textraOp ? chunkSize * 2 : maxBatchSizeInBytes,\n\t\t\t\t\tmockLogger,\n\t\t\t\t);\n\t\t\t\tconst largeMessage = generateChunkableOp(100);\n\n\t\t\t\tconst result = opSplitter.splitFirstBatchMessage({\n\t\t\t\t\tcontent: [largeMessage],\n\t\t\t\t\tcontentSizeInBytes: largeMessage.contents?.length ?? 0,\n\t\t\t\t\treferenceSequenceNumber: 0,\n\t\t\t\t});\n\n\t\t\t\tassert.equal(batchesSubmitted.length, 5 + (extraOp ? 1 : 0));\n\t\t\t\tfor (const batch of batchesSubmitted) {\n\t\t\t\t\tassert.equal(batch.messages.length, 1);\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t(batch.messages[0] as BatchMessage).type,\n\t\t\t\t\t\tContainerMessageType.ChunkedOp,\n\t\t\t\t\t);\n\t\t\t\t\tassert.equal(batch.referenceSequenceNumber, 0);\n\t\t\t\t}\n\n\t\t\t\tassert.equal(result.content.length, 1);\n\t\t\t\tassert.notEqual(result.contentSizeInBytes, largeMessage.contents?.length ?? 0);\n\t\t\t\tconst lastChunk = JSON.parse(result.content[0].contents!).contents as IChunkedOp;\n\t\t\t\tassert.equal(lastChunk.chunkId, lastChunk.totalChunks);\n\t\t\t\tassert.equal(\n\t\t\t\t\t!extraOp ||\n\t\t\t\t\t\tJSON.parse(result.content[0].contents!).contents?.contents?.length === 0,\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t\tassert.notEqual(result.contentSizeInBytes, largeMessage.contents?.length ?? 0);\n\t\t\t\tconst contentSentSeparately = batchesSubmitted.map(\n\t\t\t\t\t(x) =>\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\tJSON.parse((x.messages[0] as BatchMessage).contents!)\n\t\t\t\t\t\t\t\t.contents as IChunkedOp\n\t\t\t\t\t\t).contents,\n\t\t\t\t);\n\t\t\t\tconst sentContent = [...contentSentSeparately, lastChunk.contents].reduce(\n\t\t\t\t\t(accumulator, current) => `${accumulator}${current}`,\n\t\t\t\t);\n\t\t\t\tassert.equal(sentContent, largeMessage.contents);\n\n\t\t\t\tassert(\n\t\t\t\t\tmockLogger.matchEvents([\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\teventName: \"OpSplitter:CompressedChunkedBatch\",\n\t\t\t\t\t\t\tlength: result.content.length,\n\t\t\t\t\t\t\tchunks: 100 / 20 + 1 + (extraOp ? 1 : 0),\n\t\t\t\t\t\t\tchunkSizeInBytes: 20,\n\t\t\t\t\t\t},\n\t\t\t\t\t]),\n\t\t\t\t);\n\t\t\t});\n\t\t});\n\t});\n\n\tconst assertSameMessage = (result: ISequencedDocumentMessage, original: BatchMessage) => {\n\t\tassert.deepStrictEqual(result.contents, JSON.parse(original.contents!));\n\t\tassert.strictEqual(result.type, original.type);\n\t\tassert.strictEqual(result.metadata, original.metadata);\n\t\tassert.strictEqual(result.compression, original.compression);\n\t};\n\n\tconst generateChunkableOp = (contentSizeInBytes: number): BatchMessage => {\n\t\tconst contents = { value: crypto.randomBytes(contentSizeInBytes / 2).toString(\"hex\") };\n\t\treturn {\n\t\t\tlocalOpMetadata: undefined,\n\t\t\ttype: ContainerMessageType.FluidDataStoreOp,\n\t\t\treferenceSequenceNumber: Infinity,\n\t\t\tmetadata: { meta: \"data\" },\n\t\t\tcompression: CompressionAlgorithms.lz4,\n\t\t\tcontents: JSON.stringify(contents),\n\t\t};\n\t};\n\n\tconst wrapChunkedOps = (ops: IChunkedOp[], clientId: string): ISequencedDocumentMessage[] =>\n\t\tops.map((op) => {\n\t\t\tconst result = {\n\t\t\t\tcontents: op,\n\t\t\t\tclientId,\n\t\t\t\ttype: ContainerMessageType.ChunkedOp,\n\t\t\t};\n\n\t\t\treturn result as ISequencedDocumentMessage;\n\t\t});\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"throttler.spec.js","sourceRoot":"","sources":["../../src/test/throttler.spec.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 */\nimport { strict as assert } from \"assert\";\nimport sinon from \"sinon\";\nimport {\n\tformExponentialFn,\n\tformExponentialFnWithAttemptOffset,\n\tformLinearFn,\n\tThrottler,\n} from \"../throttler.js\";\n\ndescribe(\"Throttler\", () => {\n\tlet throttler: Throttler;\n\tlet clock: sinon.SinonFakeTimers;\n\tbefore(() => {\n\t\tclock = sinon.useFakeTimers();\n\t});\n\tafter(() => clock.restore());\n\tafterEach(() => clock.reset());\n\n\tfunction assertAscending(array: readonly number[]) {\n\t\tif (array.length < 1) {\n\t\t\treturn;\n\t\t}\n\t\tlet prev = array[0];\n\t\tfor (const item of array) {\n\t\t\tassert(item >= prev, \"out of order\");\n\t\t\tprev = item;\n\t\t}\n\t}\n\n\tfunction getDelayAndTick(): number {\n\t\tconst delay = throttler.getDelay();\n\t\tclock.tick(delay);\n\t\tassert.strictEqual(\n\t\t\tthrottler.latestAttemptTime,\n\t\t\tDate.now(),\n\t\t\t\"getDelayAndTick should yield latestAttemptTime === now\",\n\t\t);\n\t\tassertAscending(throttler.getAttempts());\n\t\treturn delay;\n\t}\n\n\tfunction runTests({\n\t\tmessage,\n\t\tdelayWindowMs,\n\t\tmaxDelayMs,\n\t\tdelayFn,\n\t\texpectedDelays,\n\t}: {\n\t\tmessage: string;\n\t\tdelayWindowMs: number;\n\t\tmaxDelayMs: number;\n\t\tdelayFn: (numAttempts: number) => number;\n\t\texpectedDelays: number[];\n\t}) {\n\t\tdescribe(message, () => {\n\t\t\tbeforeEach(() => {\n\t\t\t\tthrottler = new Throttler(delayWindowMs, maxDelayMs, delayFn);\n\t\t\t});\n\t\t\tconst expectedMaxAttempts = expectedDelays.length;\n\t\t\tconst expectedDelayAt = (attempt: number) =>\n\t\t\t\tattempt >= expectedMaxAttempts ? maxDelayMs : expectedDelays[attempt];\n\n\t\t\tit(\"Should initially have zero delay\", () => {\n\t\t\t\tassert.strictEqual(throttler.getDelay(), 0);\n\t\t\t});\n\n\t\t\tit(\"Should increase as expected with instant failures\", () => {\n\t\t\t\tfor (const expectedDelay of expectedDelays.concat([\n\t\t\t\t\tmaxDelayMs,\n\t\t\t\t\tmaxDelayMs,\n\t\t\t\t\tmaxDelayMs,\n\t\t\t\t\tmaxDelayMs,\n\t\t\t\t])) {\n\t\t\t\t\tassert.strictEqual(getDelayAndTick(), expectedDelay);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tit(\"Should remain zero delay with long pauses between getDelay calls\", () => {\n\t\t\t\tfor (let i = 0; i < 5; i++) {\n\t\t\t\t\tassert.strictEqual(getDelayAndTick(), 0, `iteration ${i}`);\n\t\t\t\t\tclock.tick(delayWindowMs);\n\t\t\t\t}\n\t\t\t\tassert.strictEqual(getDelayAndTick(), 0);\n\n\t\t\t\t// This time barely keep it in the window, giving a delay.\n\t\t\t\tclock.tick(delayWindowMs - 1);\n\t\t\t\tassert.strictEqual(getDelayAndTick(), expectedDelayAt(1));\n\t\t\t});\n\n\t\t\tit(\"Should not increase with long pauses between getDelay calls\", () => {\n\t\t\t\tconst oneThirdTicks = Math.floor(delayWindowMs / 3);\n\t\t\t\tconst remainingTicks = delayWindowMs - 2 * oneThirdTicks;\n\n\t\t\t\t// Accumulate some attempts first.\n\t\t\t\tassert.strictEqual(getDelayAndTick(), 0);\n\t\t\t\tclock.tick(oneThirdTicks);\n\t\t\t\tassert.strictEqual(getDelayAndTick(), expectedDelayAt(1));\n\t\t\t\tclock.tick(oneThirdTicks);\n\t\t\t\tassert.strictEqual(getDelayAndTick(), expectedDelayAt(2));\n\t\t\t\tclock.tick(remainingTicks);\n\n\t\t\t\t// Loop through attempts periodically dropping off.\n\t\t\t\tfor (let i = 0; i < 100; i++) {\n\t\t\t\t\tassert.strictEqual(getDelayAndTick(), expectedDelays[2], `iteration ${i}`);\n\t\t\t\t\tclock.tick(i % 3 === 2 ? remainingTicks : oneThirdTicks);\n\t\t\t\t}\n\t\t\t\tassert.strictEqual(getDelayAndTick(), expectedDelayAt(2));\n\n\t\t\t\t// This time fail instantly, giving a later delay.\n\t\t\t\tassert.strictEqual(getDelayAndTick(), expectedDelayAt(3));\n\t\t\t});\n\n\t\t\tit(\"Should stop increasing number of attempts after max\", () => {\n\t\t\t\tfor (let i = 0; i < expectedMaxAttempts; i++) {\n\t\t\t\t\tgetDelayAndTick();\n\t\t\t\t\tassert.strictEqual(throttler.numAttempts, i + 1, `loop 1; iteration ${i}`);\n\t\t\t\t}\n\t\t\t\tfor (let i = 0; i < 100; i++) {\n\t\t\t\t\tgetDelayAndTick();\n\t\t\t\t\tassert.strictEqual(\n\t\t\t\t\t\tthrottler.numAttempts,\n\t\t\t\t\t\texpectedMaxAttempts,\n\t\t\t\t\t\t`loop 2; iteration ${i}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tit(\"State should be corrected if delay is bypassed\", () => {\n\t\t\t\t// First 2 attempts are allowed to be instant.\n\t\t\t\tassert.strictEqual(getDelayAndTick(), 0);\n\t\t\t\tassert.strictEqual(throttler.getDelay(), expectedDelayAt(1));\n\n\t\t\t\t// This attempt is too soon, since we have not delayed 20ms.\n\t\t\t\tassert.strictEqual(getDelayAndTick(), expectedDelayAt(2));\n\t\t\t});\n\t\t});\n\t}\n\n\trunTests({\n\t\tmessage: \"Exponential Delay\",\n\t\t// 60 second delay window. We ignore attempts that are more\n\t\t// than 60 seconds ago. We are always subtracting the actual\n\t\t// delay time for this window.\n\t\tdelayWindowMs: 60 * 1000,\n\t\t// 30 second maximum delay. After delays reach this length,\n\t\t// subsequent attempts will also use the max delay, unless\n\t\t// enough extra time passes between attempts for some of the\n\t\t// previous start times to drop off out of the window.\n\t\tmaxDelayMs: 30 * 1000,\n\t\t// Exponential delay: [prev x 2 + 20] (0ms, 20ms, 60ms, 140ms, etc)\n\t\t// Equivalent reduction with G = 1, F = 0:\n\t\t/** f(n) = C x (B^n - G) + F = C x B^n + (F - C x G) = C x B^n - C */\n\t\tdelayFn: formExponentialFn({ coefficient: 20, offset: -20 }),\n\t\texpectedDelays: [0, 20, 60, 140, 300, 620, 1260, 2540, 5100, 10220, 20460],\n\t});\n\n\trunTests({\n\t\tmessage: \"Exponential Delay with attempt offset\",\n\t\t// 60 second delay window. We ignore attempts that are more\n\t\t// than 60 seconds ago. We are always subtracting the actual\n\t\t// delay time for this window.\n\t\tdelayWindowMs: 60 * 1000,\n\t\t// 30 second maximum delay. After delays reach this length,\n\t\t// subsequent attempts will also use the max delay, unless\n\t\t// enough extra time passes between attempts for some of the\n\t\t// previous start times to drop off out of the window.\n\t\tmaxDelayMs: 30 * 1000,\n\t\t// Exponential delay: [0, 20, then prev x 2] (0ms, 20ms, 40ms, 80ms, etc)\n\t\t// # | calculation | delay | cumulative delay\n\t\t// ---|-------------------------------|-----------|-----------------\n\t\t// 1 | SPECIAL CASE: 0 = 0 x 20 = | 0 ms | 0 ms\n\t\t// 2 | 2^( 1 - 1) x 20 = 1 x 20 = | 20 ms | 20 ms\n\t\t// 3 | 2^( 2 - 1) x 20 = 2 x 20 = | 40 ms | 60 ms\n\t\t// 4 | 2^( 3 - 1) x 20 = 4 x 20 = | 80 ms | 140 ms\n\t\t// 5 | 2^( 4 - 1) x 20 = 8 x 20 = | 160 ms | 300 ms\n\t\t// 6 | 2^( 5 - 1) x 20 = 16 x 20 = | 320 ms | 620 ms\n\t\t// 7 | 2^( 6 - 1) x 20 = 32 x 20 = | 640 ms | 1,260 ms\n\t\t// 8 | 2^( 7 - 1) x 20 = 64 x 20 = | 1,280 ms | 2,540 ms\n\t\t// 9 | 2^( 8 - 1) x 20 = 128 x 20 = | 2,560 ms | 5,100 ms\n\t\t// 10 | 2^( 9 - 1) x 20 = 256 x 20 = | 5,120 ms | 10,220 ms\n\t\t// 11 | 2^(10 - 1) x 20 = 512 x 20 = | 10,240 ms | 20,460 ms\n\t\t// 12 | 2^(11 - 1) x 20 = 1024 x 20 = | 20,480 ms | 40,940 ms\n\t\t// 13 | 2^(12 - 1) x 20 = 2048 x 20 = | 30,000 ms | 70,940 ms (MAX)\n\t\t// 14 | 2^(13 - 1) x 20 = 5096 x 20 = | 30,000 ms |100,940 ms (MAX)\n\t\tdelayFn: formExponentialFnWithAttemptOffset(-1, {\n\t\t\tcoefficient: 20,\n\t\t\tinitialDelay: 0,\n\t\t}),\n\t\texpectedDelays: [0, 20, 40, 80, 160, 320, 640, 1280, 2560, 5120, 10240, 20480],\n\t});\n\n\trunTests({\n\t\tmessage: \"Linear Delay\",\n\t\t// 60 ms delay window. We ignore attempts that are more\n\t\t// than 60 ms ago. We are always subtracting the actual\n\t\t// delay time for this window.\n\t\tdelayWindowMs: 60,\n\t\t// 30 ms maximum delay. After delays reach this length,\n\t\t// subsequent attempts will also use the max delay, unless\n\t\t// enough extra time passes between attempts for some of the\n\t\t// previous start times to drop off out of the window.\n\t\tmaxDelayMs: 30,\n\t\t// Linear delay: (0ms, 10ms, 20ms, 30ms, etc)\n\t\t// # | calculation | delay | cumulative delay\n\t\t// ---|-------------|-------|-----------------\n\t\t// 1 | 10 x 0 = | 0 ms | 0 ms\n\t\t// 2 | 10 x 1 = | 10 ms | 10 ms\n\t\t// 3 | 10 x 2 = | 20 ms | 30 ms\n\t\t// 4 | 10 x 3 = | 30 ms | 60 ms (MAX)\n\t\t// 5 | 10 x 4 = | 30 ms | 90 ms (MAX)\n\t\tdelayFn: formLinearFn({ coefficient: 10 }),\n\t\texpectedDelays: [0, 10, 20],\n\t});\n});\n"]}
1
+ {"version":3,"file":"throttler.spec.js","sourceRoot":"","sources":["../../src/test/throttler.spec.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 { strict as assert } from \"assert\";\nimport sinon from \"sinon\";\nimport {\n\tformExponentialFn,\n\tformExponentialFnWithAttemptOffset,\n\tformLinearFn,\n\tThrottler,\n} from \"../throttler.js\";\n\ndescribe(\"Throttler\", () => {\n\tlet throttler: Throttler;\n\tlet clock: sinon.SinonFakeTimers;\n\tbefore(() => {\n\t\tclock = sinon.useFakeTimers();\n\t});\n\tafter(() => clock.restore());\n\tafterEach(() => clock.reset());\n\n\tfunction assertAscending(array: readonly number[]) {\n\t\tif (array.length < 1) {\n\t\t\treturn;\n\t\t}\n\t\tlet prev = array[0];\n\t\tfor (const item of array) {\n\t\t\tassert(item >= prev, \"out of order\");\n\t\t\tprev = item;\n\t\t}\n\t}\n\n\tfunction getDelayAndTick(): number {\n\t\tconst delay = throttler.getDelay();\n\t\tclock.tick(delay);\n\t\tassert.strictEqual(\n\t\t\tthrottler.latestAttemptTime,\n\t\t\tDate.now(),\n\t\t\t\"getDelayAndTick should yield latestAttemptTime === now\",\n\t\t);\n\t\tassertAscending(throttler.getAttempts());\n\t\treturn delay;\n\t}\n\n\tfunction runTests({\n\t\tmessage,\n\t\tdelayWindowMs,\n\t\tmaxDelayMs,\n\t\tdelayFn,\n\t\texpectedDelays,\n\t}: {\n\t\tmessage: string;\n\t\tdelayWindowMs: number;\n\t\tmaxDelayMs: number;\n\t\tdelayFn: (numAttempts: number) => number;\n\t\texpectedDelays: number[];\n\t}) {\n\t\tdescribe(message, () => {\n\t\t\tbeforeEach(() => {\n\t\t\t\tthrottler = new Throttler(delayWindowMs, maxDelayMs, delayFn);\n\t\t\t});\n\t\t\tconst expectedMaxAttempts = expectedDelays.length;\n\t\t\tconst expectedDelayAt = (attempt: number) =>\n\t\t\t\tattempt >= expectedMaxAttempts ? maxDelayMs : expectedDelays[attempt];\n\n\t\t\tit(\"Should initially have zero delay\", () => {\n\t\t\t\tassert.strictEqual(throttler.getDelay(), 0);\n\t\t\t});\n\n\t\t\tit(\"Should increase as expected with instant failures\", () => {\n\t\t\t\tfor (const expectedDelay of expectedDelays.concat([\n\t\t\t\t\tmaxDelayMs,\n\t\t\t\t\tmaxDelayMs,\n\t\t\t\t\tmaxDelayMs,\n\t\t\t\t\tmaxDelayMs,\n\t\t\t\t])) {\n\t\t\t\t\tassert.strictEqual(getDelayAndTick(), expectedDelay);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tit(\"Should remain zero delay with long pauses between getDelay calls\", () => {\n\t\t\t\tfor (let i = 0; i < 5; i++) {\n\t\t\t\t\tassert.strictEqual(getDelayAndTick(), 0, `iteration ${i}`);\n\t\t\t\t\tclock.tick(delayWindowMs);\n\t\t\t\t}\n\t\t\t\tassert.strictEqual(getDelayAndTick(), 0);\n\n\t\t\t\t// This time barely keep it in the window, giving a delay.\n\t\t\t\tclock.tick(delayWindowMs - 1);\n\t\t\t\tassert.strictEqual(getDelayAndTick(), expectedDelayAt(1));\n\t\t\t});\n\n\t\t\tit(\"Should not increase with long pauses between getDelay calls\", () => {\n\t\t\t\tconst oneThirdTicks = Math.floor(delayWindowMs / 3);\n\t\t\t\tconst remainingTicks = delayWindowMs - 2 * oneThirdTicks;\n\n\t\t\t\t// Accumulate some attempts first.\n\t\t\t\tassert.strictEqual(getDelayAndTick(), 0);\n\t\t\t\tclock.tick(oneThirdTicks);\n\t\t\t\tassert.strictEqual(getDelayAndTick(), expectedDelayAt(1));\n\t\t\t\tclock.tick(oneThirdTicks);\n\t\t\t\tassert.strictEqual(getDelayAndTick(), expectedDelayAt(2));\n\t\t\t\tclock.tick(remainingTicks);\n\n\t\t\t\t// Loop through attempts periodically dropping off.\n\t\t\t\tfor (let i = 0; i < 100; i++) {\n\t\t\t\t\tassert.strictEqual(getDelayAndTick(), expectedDelays[2], `iteration ${i}`);\n\t\t\t\t\tclock.tick(i % 3 === 2 ? remainingTicks : oneThirdTicks);\n\t\t\t\t}\n\t\t\t\tassert.strictEqual(getDelayAndTick(), expectedDelayAt(2));\n\n\t\t\t\t// This time fail instantly, giving a later delay.\n\t\t\t\tassert.strictEqual(getDelayAndTick(), expectedDelayAt(3));\n\t\t\t});\n\n\t\t\tit(\"Should stop increasing number of attempts after max\", () => {\n\t\t\t\tfor (let i = 0; i < expectedMaxAttempts; i++) {\n\t\t\t\t\tgetDelayAndTick();\n\t\t\t\t\tassert.strictEqual(throttler.numAttempts, i + 1, `loop 1; iteration ${i}`);\n\t\t\t\t}\n\t\t\t\tfor (let i = 0; i < 100; i++) {\n\t\t\t\t\tgetDelayAndTick();\n\t\t\t\t\tassert.strictEqual(\n\t\t\t\t\t\tthrottler.numAttempts,\n\t\t\t\t\t\texpectedMaxAttempts,\n\t\t\t\t\t\t`loop 2; iteration ${i}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tit(\"State should be corrected if delay is bypassed\", () => {\n\t\t\t\t// First 2 attempts are allowed to be instant.\n\t\t\t\tassert.strictEqual(getDelayAndTick(), 0);\n\t\t\t\tassert.strictEqual(throttler.getDelay(), expectedDelayAt(1));\n\n\t\t\t\t// This attempt is too soon, since we have not delayed 20ms.\n\t\t\t\tassert.strictEqual(getDelayAndTick(), expectedDelayAt(2));\n\t\t\t});\n\t\t});\n\t}\n\n\trunTests({\n\t\tmessage: \"Exponential Delay\",\n\t\t// 60 second delay window. We ignore attempts that are more\n\t\t// than 60 seconds ago. We are always subtracting the actual\n\t\t// delay time for this window.\n\t\tdelayWindowMs: 60 * 1000,\n\t\t// 30 second maximum delay. After delays reach this length,\n\t\t// subsequent attempts will also use the max delay, unless\n\t\t// enough extra time passes between attempts for some of the\n\t\t// previous start times to drop off out of the window.\n\t\tmaxDelayMs: 30 * 1000,\n\t\t// Exponential delay: [prev x 2 + 20] (0ms, 20ms, 60ms, 140ms, etc)\n\t\t// Equivalent reduction with G = 1, F = 0:\n\t\t/** f(n) = C x (B^n - G) + F = C x B^n + (F - C x G) = C x B^n - C */\n\t\tdelayFn: formExponentialFn({ coefficient: 20, offset: -20 }),\n\t\texpectedDelays: [0, 20, 60, 140, 300, 620, 1260, 2540, 5100, 10220, 20460],\n\t});\n\n\trunTests({\n\t\tmessage: \"Exponential Delay with attempt offset\",\n\t\t// 60 second delay window. We ignore attempts that are more\n\t\t// than 60 seconds ago. We are always subtracting the actual\n\t\t// delay time for this window.\n\t\tdelayWindowMs: 60 * 1000,\n\t\t// 30 second maximum delay. After delays reach this length,\n\t\t// subsequent attempts will also use the max delay, unless\n\t\t// enough extra time passes between attempts for some of the\n\t\t// previous start times to drop off out of the window.\n\t\tmaxDelayMs: 30 * 1000,\n\t\t// Exponential delay: [0, 20, then prev x 2] (0ms, 20ms, 40ms, 80ms, etc)\n\t\t// # | calculation | delay | cumulative delay\n\t\t// ---|-------------------------------|-----------|-----------------\n\t\t// 1 | SPECIAL CASE: 0 = 0 x 20 = | 0 ms | 0 ms\n\t\t// 2 | 2^( 1 - 1) x 20 = 1 x 20 = | 20 ms | 20 ms\n\t\t// 3 | 2^( 2 - 1) x 20 = 2 x 20 = | 40 ms | 60 ms\n\t\t// 4 | 2^( 3 - 1) x 20 = 4 x 20 = | 80 ms | 140 ms\n\t\t// 5 | 2^( 4 - 1) x 20 = 8 x 20 = | 160 ms | 300 ms\n\t\t// 6 | 2^( 5 - 1) x 20 = 16 x 20 = | 320 ms | 620 ms\n\t\t// 7 | 2^( 6 - 1) x 20 = 32 x 20 = | 640 ms | 1,260 ms\n\t\t// 8 | 2^( 7 - 1) x 20 = 64 x 20 = | 1,280 ms | 2,540 ms\n\t\t// 9 | 2^( 8 - 1) x 20 = 128 x 20 = | 2,560 ms | 5,100 ms\n\t\t// 10 | 2^( 9 - 1) x 20 = 256 x 20 = | 5,120 ms | 10,220 ms\n\t\t// 11 | 2^(10 - 1) x 20 = 512 x 20 = | 10,240 ms | 20,460 ms\n\t\t// 12 | 2^(11 - 1) x 20 = 1024 x 20 = | 20,480 ms | 40,940 ms\n\t\t// 13 | 2^(12 - 1) x 20 = 2048 x 20 = | 30,000 ms | 70,940 ms (MAX)\n\t\t// 14 | 2^(13 - 1) x 20 = 5096 x 20 = | 30,000 ms |100,940 ms (MAX)\n\t\tdelayFn: formExponentialFnWithAttemptOffset(-1, {\n\t\t\tcoefficient: 20,\n\t\t\tinitialDelay: 0,\n\t\t}),\n\t\texpectedDelays: [0, 20, 40, 80, 160, 320, 640, 1280, 2560, 5120, 10240, 20480],\n\t});\n\n\trunTests({\n\t\tmessage: \"Linear Delay\",\n\t\t// 60 ms delay window. We ignore attempts that are more\n\t\t// than 60 ms ago. We are always subtracting the actual\n\t\t// delay time for this window.\n\t\tdelayWindowMs: 60,\n\t\t// 30 ms maximum delay. After delays reach this length,\n\t\t// subsequent attempts will also use the max delay, unless\n\t\t// enough extra time passes between attempts for some of the\n\t\t// previous start times to drop off out of the window.\n\t\tmaxDelayMs: 30,\n\t\t// Linear delay: (0ms, 10ms, 20ms, 30ms, etc)\n\t\t// # | calculation | delay | cumulative delay\n\t\t// ---|-------------|-------|-----------------\n\t\t// 1 | 10 x 0 = | 0 ms | 0 ms\n\t\t// 2 | 10 x 1 = | 10 ms | 10 ms\n\t\t// 3 | 10 x 2 = | 20 ms | 30 ms\n\t\t// 4 | 10 x 3 = | 30 ms | 60 ms (MAX)\n\t\t// 5 | 10 x 4 = | 30 ms | 90 ms (MAX)\n\t\tdelayFn: formLinearFn({ coefficient: 10 }),\n\t\texpectedDelays: [0, 10, 20],\n\t});\n});\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/container-runtime",
3
- "version": "2.0.0-dev-rc.2.0.0.245554",
3
+ "version": "2.0.0-dev-rc.2.0.0.246488",
4
4
  "description": "Fluid container runtime",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -137,20 +137,20 @@
137
137
  "temp-directory": "nyc/.nyc_output"
138
138
  },
139
139
  "dependencies": {
140
- "@fluid-internal/client-utils": "2.0.0-dev-rc.2.0.0.245554",
140
+ "@fluid-internal/client-utils": "2.0.0-dev-rc.2.0.0.246488",
141
141
  "@fluidframework/common-definitions": "^1.1.0",
142
- "@fluidframework/container-definitions": "2.0.0-dev-rc.2.0.0.245554",
143
- "@fluidframework/container-runtime-definitions": "2.0.0-dev-rc.2.0.0.245554",
144
- "@fluidframework/core-interfaces": "2.0.0-dev-rc.2.0.0.245554",
145
- "@fluidframework/core-utils": "2.0.0-dev-rc.2.0.0.245554",
146
- "@fluidframework/datastore": "2.0.0-dev-rc.2.0.0.245554",
147
- "@fluidframework/driver-definitions": "2.0.0-dev-rc.2.0.0.245554",
148
- "@fluidframework/driver-utils": "2.0.0-dev-rc.2.0.0.245554",
149
- "@fluidframework/id-compressor": "2.0.0-dev-rc.2.0.0.245554",
142
+ "@fluidframework/container-definitions": "2.0.0-dev-rc.2.0.0.246488",
143
+ "@fluidframework/container-runtime-definitions": "2.0.0-dev-rc.2.0.0.246488",
144
+ "@fluidframework/core-interfaces": "2.0.0-dev-rc.2.0.0.246488",
145
+ "@fluidframework/core-utils": "2.0.0-dev-rc.2.0.0.246488",
146
+ "@fluidframework/datastore": "2.0.0-dev-rc.2.0.0.246488",
147
+ "@fluidframework/driver-definitions": "2.0.0-dev-rc.2.0.0.246488",
148
+ "@fluidframework/driver-utils": "2.0.0-dev-rc.2.0.0.246488",
149
+ "@fluidframework/id-compressor": "2.0.0-dev-rc.2.0.0.246488",
150
150
  "@fluidframework/protocol-definitions": "^3.2.0",
151
- "@fluidframework/runtime-definitions": "2.0.0-dev-rc.2.0.0.245554",
152
- "@fluidframework/runtime-utils": "2.0.0-dev-rc.2.0.0.245554",
153
- "@fluidframework/telemetry-utils": "2.0.0-dev-rc.2.0.0.245554",
151
+ "@fluidframework/runtime-definitions": "2.0.0-dev-rc.2.0.0.246488",
152
+ "@fluidframework/runtime-utils": "2.0.0-dev-rc.2.0.0.246488",
153
+ "@fluidframework/telemetry-utils": "2.0.0-dev-rc.2.0.0.246488",
154
154
  "@tylerbu/sorted-btree-es6": "^1.8.0",
155
155
  "double-ended-queue": "^2.1.0-0",
156
156
  "lz4js": "^0.2.0",
@@ -158,15 +158,15 @@
158
158
  },
159
159
  "devDependencies": {
160
160
  "@arethetypeswrong/cli": "^0.13.3",
161
- "@fluid-internal/mocha-test-setup": "2.0.0-dev-rc.2.0.0.245554",
162
- "@fluid-private/stochastic-test-utils": "2.0.0-dev-rc.2.0.0.245554",
161
+ "@fluid-internal/mocha-test-setup": "2.0.0-dev-rc.2.0.0.246488",
162
+ "@fluid-private/stochastic-test-utils": "2.0.0-dev-rc.2.0.0.246488",
163
163
  "@fluid-tools/benchmark": "^0.48.0",
164
164
  "@fluid-tools/build-cli": "^0.34.0",
165
165
  "@fluidframework/build-common": "^2.0.3",
166
166
  "@fluidframework/build-tools": "^0.34.0",
167
167
  "@fluidframework/container-runtime-previous": "npm:@fluidframework/container-runtime@2.0.0-internal.8.0.0",
168
168
  "@fluidframework/eslint-config-fluid": "^5.1.0",
169
- "@fluidframework/test-runtime-utils": "2.0.0-dev-rc.2.0.0.245554",
169
+ "@fluidframework/test-runtime-utils": "2.0.0-dev-rc.2.0.0.246488",
170
170
  "@microsoft/api-extractor": "^7.42.3",
171
171
  "@types/double-ended-queue": "^2.1.0",
172
172
  "@types/mocha": "^9.1.1",
@@ -182,7 +182,7 @@ export function wrapContext(context: IFluidParentContext): IFluidParentContext {
182
182
  return context.getCreateChildSummarizerNodeFn?.(...args);
183
183
  },
184
184
  deleteChildSummarizerNode: (...args) => {
185
- return context.deleteChildSummarizerNode?.(...args);
185
+ return context.deleteChildSummarizerNode(...args);
186
186
  },
187
187
  setChannelDirty: (address: string) => {
188
188
  return context.setChannelDirty(address);
@@ -679,7 +679,7 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable {
679
679
  case ContainerMessageType.FluidDataStoreOp:
680
680
  return this.reSubmitChannelOp(type, content, localOpMetadata);
681
681
  default:
682
- assert(false, "unknown op type");
682
+ assert(false, 0x907 /* unknown op type */);
683
683
  }
684
684
  }
685
685
 
@@ -730,7 +730,7 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable {
730
730
  case ContainerMessageType.FluidDataStoreOp:
731
731
  return this.applyStashedChannelChannelOp(opContents.contents);
732
732
  default:
733
- assert(false, "unknon type of op");
733
+ assert(false, 0x908 /* unknon type of op */);
734
734
  }
735
735
  }
736
736
 
@@ -1164,6 +1164,17 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable {
1164
1164
  }
1165
1165
  }
1166
1166
 
1167
+ public deleteChild(dataStoreId: string) {
1168
+ const dataStoreContext = this.contexts.get(dataStoreId);
1169
+ assert(dataStoreContext !== undefined, 0x2d7 /* No data store with specified id */);
1170
+
1171
+ dataStoreContext.delete();
1172
+ // Delete the contexts of unused data stores.
1173
+ this.contexts.delete(dataStoreId);
1174
+ // Delete the summarizer node of the unused data stores.
1175
+ this.parentContext.deleteChildSummarizerNode(dataStoreId);
1176
+ }
1177
+
1167
1178
  /**
1168
1179
  * Delete data stores and its objects that are sweep ready.
1169
1180
  * @param sweepReadyDataStoreRoutes - The routes of data stores and its objects that are sweep ready and should
@@ -1197,12 +1208,7 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable {
1197
1208
  continue;
1198
1209
  }
1199
1210
 
1200
- dataStoreContext.delete();
1201
-
1202
- // Delete the contexts of sweep ready data stores.
1203
- this.contexts.delete(dataStoreId);
1204
- // Delete the summarizer node of the sweep ready data stores.
1205
- this.parentContext.deleteChildSummarizerNode?.(dataStoreId);
1211
+ this.deleteChild(dataStoreId);
1206
1212
  }
1207
1213
  return Array.from(sweepReadyDataStoreRoutes);
1208
1214
  }
@@ -2,6 +2,7 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
+
5
6
  import {
6
7
  ITelemetryBaseLogger,
7
8
  FluidObject,
@@ -1570,7 +1571,10 @@ export class ContainerRuntime
1570
1571
  clientId: () => this.clientId,
1571
1572
  close: this.closeFn,
1572
1573
  connected: () => this.connected,
1573
- reSubmit: this.reSubmit.bind(this),
1574
+ reSubmit: (message: IPendingBatchMessage) => {
1575
+ this.reSubmit(message);
1576
+ this.flush();
1577
+ },
1574
1578
  reSubmitBatch: this.reSubmitBatch.bind(this),
1575
1579
  isActiveConnection: () => this.innerDeltaManager.active,
1576
1580
  isAttached: () => this.attachState !== AttachState.Detached,
@@ -1800,7 +1804,7 @@ export class ContainerRuntime
1800
1804
  }
1801
1805
 
1802
1806
  public setChannelDirty(address: string) {
1803
- assert(false, "should not be called");
1807
+ assert(false, 0x909 /* should not be called */);
1804
1808
  }
1805
1809
 
1806
1810
  /**
@@ -2150,14 +2154,8 @@ export class ContainerRuntime
2150
2154
  return this.consecutiveReconnects < this.maxConsecutiveReconnects;
2151
2155
  }
2152
2156
 
2153
- private resetReconnectCount(message?: ISequencedDocumentMessage) {
2154
- // Chunked ops don't count towards making progress as they are sent
2155
- // in their own batches before the originating batch is sent.
2156
- // Therefore, receiving them while attempting to send the originating batch
2157
- // does not mean that the container is making any progress.
2158
- if (message?.type !== ContainerMessageType.ChunkedOp) {
2159
- this.consecutiveReconnects = 0;
2160
- }
2157
+ private resetReconnectCount() {
2158
+ this.consecutiveReconnects = 0;
2161
2159
  }
2162
2160
 
2163
2161
  private replayPendingStates() {
@@ -2413,12 +2411,17 @@ export class ContainerRuntime
2413
2411
  this._processedClientSequenceNumber = message.clientSequenceNumber;
2414
2412
 
2415
2413
  try {
2414
+ // See commit that added this assert for more details.
2415
+ // These calls should be made for all but chunked ops:
2416
+ // 1) this.pendingStateManager.processPendingLocalMessage() below
2417
+ // 2) this.resetReconnectCount() below
2418
+ assert(
2419
+ message.type !== ContainerMessageType.ChunkedOp,
2420
+ "we should never get here with chunked ops",
2421
+ );
2422
+
2416
2423
  let localOpMetadata: unknown;
2417
- if (
2418
- local &&
2419
- messageWithContext.modernRuntimeMessage &&
2420
- message.type !== ContainerMessageType.ChunkedOp
2421
- ) {
2424
+ if (local && messageWithContext.modernRuntimeMessage) {
2422
2425
  localOpMetadata = this.pendingStateManager.processPendingLocalMessage(
2423
2426
  messageWithContext.message,
2424
2427
  );
@@ -2440,7 +2443,7 @@ export class ContainerRuntime
2440
2443
  // If we have processed a local op, this means that the container is
2441
2444
  // making progress and we can reset the counter for how many times
2442
2445
  // we have consecutively replayed the pending states
2443
- this.resetReconnectCount(message);
2446
+ this.resetReconnectCount();
2444
2447
  }
2445
2448
  } catch (e) {
2446
2449
  this.scheduleManager.afterOpProcessing(e, message);
@@ -2496,6 +2499,9 @@ export class ContainerRuntime
2496
2499
  this.garbageCollector.processMessage(messageWithContext.message, local);
2497
2500
  break;
2498
2501
  case ContainerMessageType.ChunkedOp:
2502
+ // From observability POV, we should not exppse the rest of the system (including "op" events on object) to these messages.
2503
+ // Also resetReconnectCount() would be wrong - see comment that was there before this change was made.
2504
+ assert(false, "should not even get here");
2499
2505
  case ContainerMessageType.Rejoin:
2500
2506
  break;
2501
2507
  default: {
@@ -2816,6 +2822,7 @@ export class ContainerRuntime
2816
2822
  }
2817
2823
  break;
2818
2824
  }
2825
+ case ContainerMessageType.IdAllocation:
2819
2826
  case ContainerMessageType.GC: {
2820
2827
  return false;
2821
2828
  }