@fluidframework/azure-end-to-end-tests 2.70.0-361092 → 2.70.0-361788
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.
- package/lib/test/AzureClientFactory.js +2 -2
- package/lib/test/AzureClientFactory.js.map +1 -1
- package/lib/test/multiprocess/childClient.tool.js +218 -104
- package/lib/test/multiprocess/childClient.tool.js.map +1 -1
- package/lib/test/multiprocess/messageTypes.js.map +1 -1
- package/lib/test/multiprocess/orchestratorUtils.js +72 -17
- package/lib/test/multiprocess/orchestratorUtils.js.map +1 -1
- package/lib/test/multiprocess/presenceTest.spec.js +79 -23
- package/lib/test/multiprocess/presenceTest.spec.js.map +1 -1
- package/lib/test/utils.js +1 -1
- package/lib/test/utils.js.map +1 -1
- package/package.json +23 -23
- package/src/test/AzureClientFactory.ts +2 -2
- package/src/test/multiprocess/childClient.tool.ts +268 -131
- package/src/test/multiprocess/messageTypes.ts +36 -0
- package/src/test/multiprocess/orchestratorUtils.ts +121 -23
- package/src/test/multiprocess/presenceTest.spec.ts +103 -23
- package/src/test/utils.ts +1 -1
|
@@ -136,7 +136,7 @@ export function createAzureClientLegacy(userID, userName, logger) {
|
|
|
136
136
|
* currently these are mainly fetched from ephemeralSummaryTrees.ts
|
|
137
137
|
* @param userID - ID for the user creating the container
|
|
138
138
|
* @param userName - Name for the user creating the container
|
|
139
|
-
* @returns
|
|
139
|
+
* @returns An AxiosResponse containing the container ID(response.data.id)
|
|
140
140
|
*/
|
|
141
141
|
export async function createContainerFromPayload(requestPayload, userID, userName) {
|
|
142
142
|
const useAzure = process.env.FLUID_CLIENT === "azure";
|
|
@@ -195,7 +195,7 @@ export async function createContainerFromPayload(requestPayload, userID, userNam
|
|
|
195
195
|
* (Tinylicious has the ID stored at a different path than other services)
|
|
196
196
|
*
|
|
197
197
|
* @param response - A container creation response returned by createContainerFromPayload
|
|
198
|
-
* @returns
|
|
198
|
+
* @returns The ID of the container that was created by createContainerFromPayload
|
|
199
199
|
*/
|
|
200
200
|
export function getContainerIdFromPayloadResponse(response) {
|
|
201
201
|
const useAzure = process.env.FLUID_CLIENT === "azure";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AzureClientFactory.js","sourceRoot":"","sources":["../../src/test/AzureClientFactory.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 {\n\tAzureClient,\n\ttype AzureLocalConnectionConfig,\n\ttype AzureRemoteConnectionConfig,\n\ttype ITelemetryBaseLogger,\n} from \"@fluidframework/azure-client\";\n// eslint-disable-next-line import/no-internal-modules -- TODO consider a test exposure to avoid /internal\nimport type { AzureClientPropsInternal } from \"@fluidframework/azure-client/internal\";\nimport {\n\tAzureClient as AzureClientLegacy,\n\ttype AzureLocalConnectionConfig as AzureLocalConnectionConfigLegacy,\n\ttype AzureRemoteConnectionConfig as AzureRemoteConnectionConfigLegacy,\n\ttype ITelemetryBaseLogger as ITelemetryBaseLoggerLegacy,\n} from \"@fluidframework/azure-client-legacy\";\nimport type { IRuntimeFactory } from \"@fluidframework/container-definitions/legacy\";\nimport type { IConfigProviderBase } from \"@fluidframework/core-interfaces\";\nimport { ScopeType } from \"@fluidframework/driver-definitions/legacy\";\nimport type { CompatibilityMode, ContainerSchema } from \"@fluidframework/fluid-static\";\nimport {\n\ttype MockLogger,\n\tcreateChildLogger,\n\tcreateMultiSinkLogger,\n} from \"@fluidframework/telemetry-utils/internal\";\nimport { InsecureTokenProvider } from \"@fluidframework/test-runtime-utils/internal\";\nimport { default as Axios, type AxiosResponse, type AxiosRequestConfig } from \"axios\";\nimport { v4 as uuid } from \"uuid\";\n\nimport { createAzureTokenProvider } from \"./AzureTokenFactory.js\";\n\n// eslint-disable-next-line unicorn/prefer-export-from\nexport { ScopeType };\n\n/**\n * This function will determine if local or remote mode is required (based on FLUID_CLIENT), and return a new\n * {@link AzureClient} instance based on the mode by setting the Connection config accordingly.\n */\nexport function createAzureClient(\n\tid?: string,\n\tname?: string,\n\tlogger?: MockLogger,\n\tconfigProvider?: IConfigProviderBase,\n\tscopes?: ScopeType[],\n\tcreateContainerRuntimeFactory?: ({\n\t\tschema,\n\t\tcompatibilityMode,\n\t}: {\n\t\tschema: ContainerSchema;\n\t\tcompatibilityMode: CompatibilityMode;\n\t}) => IRuntimeFactory,\n): AzureClient {\n\tconst args = process.argv.slice(2);\n\n\tconst driverIndex = args.indexOf(\"--driver\");\n\tconst r11sEndpointNameIndex = args.indexOf(\"--r11sEndpointName\");\n\n\t// Get values associated with the flags\n\tconst driver = driverIndex === -1 ? undefined : args[driverIndex + 1];\n\tconst r11sEndpointName =\n\t\tr11sEndpointNameIndex === -1 ? undefined : args[r11sEndpointNameIndex + 1];\n\n\tconst useAzure = process.env.FLUID_CLIENT === \"azure\";\n\tconst tenantId = useAzure\n\t\t? (process.env.azure__fluid__relay__service__tenantId as string)\n\t\t: \"frs-client-tenant\";\n\tconst user = {\n\t\tid: id ?? uuid(),\n\t\tname: name ?? uuid(),\n\t};\n\tconst endPoint = process.env.azure__fluid__relay__service__endpoint as string;\n\tif (useAzure && endPoint === undefined) {\n\t\tthrow new Error(\"Azure Fluid Relay service endpoint is missing\");\n\t}\n\n\t// use AzureClient remote mode will run against live Azure Fluid Relay.\n\t// Default to running Tinylicious for PR validation\n\t// and local testing so it's not hindered by service availability\n\tconst connectionProps: AzureRemoteConnectionConfig | AzureLocalConnectionConfig = useAzure\n\t\t? {\n\t\t\t\ttenantId,\n\t\t\t\ttokenProvider: createAzureTokenProvider(id ?? \"foo\", name ?? \"bar\", scopes),\n\t\t\t\tendpoint: endPoint,\n\t\t\t\ttype: \"remote\",\n\t\t\t}\n\t\t: {\n\t\t\t\ttokenProvider: new InsecureTokenProvider(\"fooBar\", user, scopes),\n\t\t\t\tendpoint: \"http://localhost:7071\",\n\t\t\t\ttype: \"local\",\n\t\t\t};\n\tconst getLogger = (): ITelemetryBaseLogger | undefined => {\n\t\tconst testLogger = getTestLogger?.();\n\t\tif (!logger && !testLogger) {\n\t\t\treturn undefined;\n\t\t}\n\t\tif (logger && testLogger) {\n\t\t\treturn createMultiSinkLogger({ loggers: [logger, testLogger] });\n\t\t}\n\t\treturn logger ?? testLogger;\n\t};\n\n\tconst createLogger = createChildLogger({\n\t\tlogger: getLogger(),\n\t\tproperties: {\n\t\t\tall: {\n\t\t\t\tdriverType: useAzure ? r11sEndpointName : driver,\n\t\t\t\tdriverEndpointName: driver,\n\t\t\t},\n\t\t},\n\t});\n\n\tconst props: AzureClientPropsInternal = {\n\t\tconnection: connectionProps,\n\t\tlogger: createLogger,\n\t\tconfigProvider,\n\t\tcreateContainerRuntimeFactory,\n\t};\n\treturn new AzureClient(props);\n}\n\n/**\n * Copy of {@link createAzureClient} with legacy (LTS) AzureClient APIs.\n */\nexport function createAzureClientLegacy(\n\tuserID?: string,\n\tuserName?: string,\n\tlogger?: MockLogger,\n): AzureClientLegacy {\n\tconst useAzure = process.env.FLUID_CLIENT === \"azure\";\n\tconst tenantId = useAzure\n\t\t? (process.env.azure__fluid__relay__service__tenantId as string)\n\t\t: \"frs-client-tenant\";\n\tconst user = {\n\t\tid: userID ?? uuid(),\n\t\tname: userName ?? uuid(),\n\t};\n\tconst endPoint = process.env.azure__fluid__relay__service__endpoint as string;\n\tif (useAzure && endPoint === undefined) {\n\t\tthrow new Error(\"Azure Azure Fluid Relay service endpoint is missing\");\n\t}\n\n\t// use AzureClient remote mode will run against live Azure Fluid Relay.\n\t// Default to running Tinylicious for PR validation\n\t// and local testing so it's not hindered by service availability\n\tconst connectionProps: AzureRemoteConnectionConfigLegacy | AzureLocalConnectionConfigLegacy =\n\t\tuseAzure\n\t\t\t? {\n\t\t\t\t\ttenantId,\n\t\t\t\t\ttokenProvider: createAzureTokenProvider(userID ?? \"foo\", userName ?? \"bar\"),\n\t\t\t\t\tendpoint: endPoint,\n\t\t\t\t\ttype: \"remote\",\n\t\t\t\t}\n\t\t\t: {\n\t\t\t\t\ttokenProvider: new InsecureTokenProvider(\"fooBar\", user),\n\t\t\t\t\tendpoint: \"http://localhost:7071\",\n\t\t\t\t\ttype: \"local\",\n\t\t\t\t};\n\tconst getLogger = (): ITelemetryBaseLoggerLegacy | undefined => {\n\t\tconst testLogger = getTestLogger?.();\n\t\tif (!logger && !testLogger) {\n\t\t\treturn undefined;\n\t\t}\n\t\tif (logger && testLogger) {\n\t\t\treturn createMultiSinkLogger({ loggers: [logger, testLogger] });\n\t\t}\n\t\treturn logger ?? testLogger;\n\t};\n\treturn new AzureClientLegacy({\n\t\tconnection: connectionProps,\n\t\tlogger: getLogger(),\n\t});\n}\n\n/**\n * This function is used to create a container using any summary payload.\n * It is primary intended as a workaround to using the AzureClient, and\n * is only being used at the moment for ephemeral container E2E tests\n * since AzureClient does not currently support ephemeral containers.\n *\n * Usage of this function for anything other than ephemeral E2E tests is\n * not recommended.\n *\n * @param requestPayload - The summary payload used to create the container,\n * currently these are mainly fetched from ephemeralSummaryTrees.ts\n * @param userID - ID for the user creating the container\n * @param userName - Name for the user creating the container\n * @returns - An AxiosResponse containing the container ID(response.data.id)\n */\nexport async function createContainerFromPayload(\n\trequestPayload: object,\n\tuserID?: string,\n\tuserName?: string,\n): Promise<AxiosResponse> {\n\tconst useAzure = process.env.FLUID_CLIENT === \"azure\";\n\tconst tenantId = useAzure\n\t\t? (process.env.azure__fluid__relay__service__tenantId as string)\n\t\t: \"local\";\n\tconst user = {\n\t\tid: userID ?? uuid(),\n\t\tname: userName ?? uuid(),\n\t};\n\tconst endPoint = useAzure\n\t\t? (process.env.azure__fluid__relay__service__endpoint as string)\n\t\t: \"http://localhost:7071\";\n\tif (useAzure && endPoint === undefined) {\n\t\tthrow new Error(\"Azure Fluid Relay service endpoint is missing\");\n\t}\n\n\tconst tokenProvider = useAzure\n\t\t? createAzureTokenProvider(userID ?? \"foo\", userName ?? \"bar\")\n\t\t: new InsecureTokenProvider(\"fooBar\", user);\n\tconst ordererToken = await tokenProvider.fetchOrdererToken(tenantId, undefined, false);\n\n\tconst headers = {\n\t\t\"Authorization\": `Basic ${ordererToken.jwt}`,\n\t\t\"Content-Type\": \"application/json\",\n\t};\n\n\tconst url = `/documents/${tenantId}`;\n\n\tconst options: AxiosRequestConfig = {\n\t\tbaseURL: endPoint,\n\t\tdata: requestPayload,\n\t\theaders,\n\t\tmaxBodyLength: 1048576000,\n\t\tmaxContentLength: 1048576000,\n\t\tmethod: \"POST\",\n\t\turl,\n\t};\n\n\ttry {\n\t\tconst response: AxiosResponse = await Axios(options);\n\n\t\tif (response.status === 201) {\n\t\t\tconsole.log(\"Container created successfully\");\n\t\t} else {\n\t\t\tthrow new Error(`Error creating container. Status code: ${response.status}`);\n\t\t}\n\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\tif (response?.data === undefined || (useAzure && response?.data?.id === undefined)) {\n\t\t\tthrow new Error(`ID of the created container is undefined`);\n\t\t}\n\n\t\treturn response;\n\t} catch (error) {\n\t\tthrow new Error(`An error occurred: ${error}`);\n\t}\n}\n\n/**\n * This function takes an AxiosResponse returned by the createContainerFromPayload and returns the containerId.\n * A separate function is used for this, since the data path to the containerID is not always the same.\n * (Tinylicious has the ID stored at a different path than other services)\n *\n * @param response - A container creation response returned by createContainerFromPayload\n * @returns - The ID of the container that was created by createContainerFromPayload\n */\nexport function getContainerIdFromPayloadResponse(response: AxiosResponse): string {\n\tconst useAzure = process.env.FLUID_CLIENT === \"azure\";\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\treturn (useAzure ? response.data.id : response.data) as string;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"AzureClientFactory.js","sourceRoot":"","sources":["../../src/test/AzureClientFactory.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 {\n\tAzureClient,\n\ttype AzureLocalConnectionConfig,\n\ttype AzureRemoteConnectionConfig,\n\ttype ITelemetryBaseLogger,\n} from \"@fluidframework/azure-client\";\n// eslint-disable-next-line import/no-internal-modules -- TODO consider a test exposure to avoid /internal\nimport type { AzureClientPropsInternal } from \"@fluidframework/azure-client/internal\";\nimport {\n\tAzureClient as AzureClientLegacy,\n\ttype AzureLocalConnectionConfig as AzureLocalConnectionConfigLegacy,\n\ttype AzureRemoteConnectionConfig as AzureRemoteConnectionConfigLegacy,\n\ttype ITelemetryBaseLogger as ITelemetryBaseLoggerLegacy,\n} from \"@fluidframework/azure-client-legacy\";\nimport type { IRuntimeFactory } from \"@fluidframework/container-definitions/legacy\";\nimport type { IConfigProviderBase } from \"@fluidframework/core-interfaces\";\nimport { ScopeType } from \"@fluidframework/driver-definitions/legacy\";\nimport type { CompatibilityMode, ContainerSchema } from \"@fluidframework/fluid-static\";\nimport {\n\ttype MockLogger,\n\tcreateChildLogger,\n\tcreateMultiSinkLogger,\n} from \"@fluidframework/telemetry-utils/internal\";\nimport { InsecureTokenProvider } from \"@fluidframework/test-runtime-utils/internal\";\nimport { default as Axios, type AxiosResponse, type AxiosRequestConfig } from \"axios\";\nimport { v4 as uuid } from \"uuid\";\n\nimport { createAzureTokenProvider } from \"./AzureTokenFactory.js\";\n\n// eslint-disable-next-line unicorn/prefer-export-from\nexport { ScopeType };\n\n/**\n * This function will determine if local or remote mode is required (based on FLUID_CLIENT), and return a new\n * {@link AzureClient} instance based on the mode by setting the Connection config accordingly.\n */\nexport function createAzureClient(\n\tid?: string,\n\tname?: string,\n\tlogger?: MockLogger,\n\tconfigProvider?: IConfigProviderBase,\n\tscopes?: ScopeType[],\n\tcreateContainerRuntimeFactory?: ({\n\t\tschema,\n\t\tcompatibilityMode,\n\t}: {\n\t\tschema: ContainerSchema;\n\t\tcompatibilityMode: CompatibilityMode;\n\t}) => IRuntimeFactory,\n): AzureClient {\n\tconst args = process.argv.slice(2);\n\n\tconst driverIndex = args.indexOf(\"--driver\");\n\tconst r11sEndpointNameIndex = args.indexOf(\"--r11sEndpointName\");\n\n\t// Get values associated with the flags\n\tconst driver = driverIndex === -1 ? undefined : args[driverIndex + 1];\n\tconst r11sEndpointName =\n\t\tr11sEndpointNameIndex === -1 ? undefined : args[r11sEndpointNameIndex + 1];\n\n\tconst useAzure = process.env.FLUID_CLIENT === \"azure\";\n\tconst tenantId = useAzure\n\t\t? (process.env.azure__fluid__relay__service__tenantId as string)\n\t\t: \"frs-client-tenant\";\n\tconst user = {\n\t\tid: id ?? uuid(),\n\t\tname: name ?? uuid(),\n\t};\n\tconst endPoint = process.env.azure__fluid__relay__service__endpoint as string;\n\tif (useAzure && endPoint === undefined) {\n\t\tthrow new Error(\"Azure Fluid Relay service endpoint is missing\");\n\t}\n\n\t// use AzureClient remote mode will run against live Azure Fluid Relay.\n\t// Default to running Tinylicious for PR validation\n\t// and local testing so it's not hindered by service availability\n\tconst connectionProps: AzureRemoteConnectionConfig | AzureLocalConnectionConfig = useAzure\n\t\t? {\n\t\t\t\ttenantId,\n\t\t\t\ttokenProvider: createAzureTokenProvider(id ?? \"foo\", name ?? \"bar\", scopes),\n\t\t\t\tendpoint: endPoint,\n\t\t\t\ttype: \"remote\",\n\t\t\t}\n\t\t: {\n\t\t\t\ttokenProvider: new InsecureTokenProvider(\"fooBar\", user, scopes),\n\t\t\t\tendpoint: \"http://localhost:7071\",\n\t\t\t\ttype: \"local\",\n\t\t\t};\n\tconst getLogger = (): ITelemetryBaseLogger | undefined => {\n\t\tconst testLogger = getTestLogger?.();\n\t\tif (!logger && !testLogger) {\n\t\t\treturn undefined;\n\t\t}\n\t\tif (logger && testLogger) {\n\t\t\treturn createMultiSinkLogger({ loggers: [logger, testLogger] });\n\t\t}\n\t\treturn logger ?? testLogger;\n\t};\n\n\tconst createLogger = createChildLogger({\n\t\tlogger: getLogger(),\n\t\tproperties: {\n\t\t\tall: {\n\t\t\t\tdriverType: useAzure ? r11sEndpointName : driver,\n\t\t\t\tdriverEndpointName: driver,\n\t\t\t},\n\t\t},\n\t});\n\n\tconst props: AzureClientPropsInternal = {\n\t\tconnection: connectionProps,\n\t\tlogger: createLogger,\n\t\tconfigProvider,\n\t\tcreateContainerRuntimeFactory,\n\t};\n\treturn new AzureClient(props);\n}\n\n/**\n * Copy of {@link createAzureClient} with legacy (LTS) AzureClient APIs.\n */\nexport function createAzureClientLegacy(\n\tuserID?: string,\n\tuserName?: string,\n\tlogger?: MockLogger,\n): AzureClientLegacy {\n\tconst useAzure = process.env.FLUID_CLIENT === \"azure\";\n\tconst tenantId = useAzure\n\t\t? (process.env.azure__fluid__relay__service__tenantId as string)\n\t\t: \"frs-client-tenant\";\n\tconst user = {\n\t\tid: userID ?? uuid(),\n\t\tname: userName ?? uuid(),\n\t};\n\tconst endPoint = process.env.azure__fluid__relay__service__endpoint as string;\n\tif (useAzure && endPoint === undefined) {\n\t\tthrow new Error(\"Azure Azure Fluid Relay service endpoint is missing\");\n\t}\n\n\t// use AzureClient remote mode will run against live Azure Fluid Relay.\n\t// Default to running Tinylicious for PR validation\n\t// and local testing so it's not hindered by service availability\n\tconst connectionProps: AzureRemoteConnectionConfigLegacy | AzureLocalConnectionConfigLegacy =\n\t\tuseAzure\n\t\t\t? {\n\t\t\t\t\ttenantId,\n\t\t\t\t\ttokenProvider: createAzureTokenProvider(userID ?? \"foo\", userName ?? \"bar\"),\n\t\t\t\t\tendpoint: endPoint,\n\t\t\t\t\ttype: \"remote\",\n\t\t\t\t}\n\t\t\t: {\n\t\t\t\t\ttokenProvider: new InsecureTokenProvider(\"fooBar\", user),\n\t\t\t\t\tendpoint: \"http://localhost:7071\",\n\t\t\t\t\ttype: \"local\",\n\t\t\t\t};\n\tconst getLogger = (): ITelemetryBaseLoggerLegacy | undefined => {\n\t\tconst testLogger = getTestLogger?.();\n\t\tif (!logger && !testLogger) {\n\t\t\treturn undefined;\n\t\t}\n\t\tif (logger && testLogger) {\n\t\t\treturn createMultiSinkLogger({ loggers: [logger, testLogger] });\n\t\t}\n\t\treturn logger ?? testLogger;\n\t};\n\treturn new AzureClientLegacy({\n\t\tconnection: connectionProps,\n\t\tlogger: getLogger(),\n\t});\n}\n\n/**\n * This function is used to create a container using any summary payload.\n * It is primary intended as a workaround to using the AzureClient, and\n * is only being used at the moment for ephemeral container E2E tests\n * since AzureClient does not currently support ephemeral containers.\n *\n * Usage of this function for anything other than ephemeral E2E tests is\n * not recommended.\n *\n * @param requestPayload - The summary payload used to create the container,\n * currently these are mainly fetched from ephemeralSummaryTrees.ts\n * @param userID - ID for the user creating the container\n * @param userName - Name for the user creating the container\n * @returns An AxiosResponse containing the container ID(response.data.id)\n */\nexport async function createContainerFromPayload(\n\trequestPayload: object,\n\tuserID?: string,\n\tuserName?: string,\n): Promise<AxiosResponse> {\n\tconst useAzure = process.env.FLUID_CLIENT === \"azure\";\n\tconst tenantId = useAzure\n\t\t? (process.env.azure__fluid__relay__service__tenantId as string)\n\t\t: \"local\";\n\tconst user = {\n\t\tid: userID ?? uuid(),\n\t\tname: userName ?? uuid(),\n\t};\n\tconst endPoint = useAzure\n\t\t? (process.env.azure__fluid__relay__service__endpoint as string)\n\t\t: \"http://localhost:7071\";\n\tif (useAzure && endPoint === undefined) {\n\t\tthrow new Error(\"Azure Fluid Relay service endpoint is missing\");\n\t}\n\n\tconst tokenProvider = useAzure\n\t\t? createAzureTokenProvider(userID ?? \"foo\", userName ?? \"bar\")\n\t\t: new InsecureTokenProvider(\"fooBar\", user);\n\tconst ordererToken = await tokenProvider.fetchOrdererToken(tenantId, undefined, false);\n\n\tconst headers = {\n\t\t\"Authorization\": `Basic ${ordererToken.jwt}`,\n\t\t\"Content-Type\": \"application/json\",\n\t};\n\n\tconst url = `/documents/${tenantId}`;\n\n\tconst options: AxiosRequestConfig = {\n\t\tbaseURL: endPoint,\n\t\tdata: requestPayload,\n\t\theaders,\n\t\tmaxBodyLength: 1048576000,\n\t\tmaxContentLength: 1048576000,\n\t\tmethod: \"POST\",\n\t\turl,\n\t};\n\n\ttry {\n\t\tconst response: AxiosResponse = await Axios(options);\n\n\t\tif (response.status === 201) {\n\t\t\tconsole.log(\"Container created successfully\");\n\t\t} else {\n\t\t\tthrow new Error(`Error creating container. Status code: ${response.status}`);\n\t\t}\n\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\tif (response?.data === undefined || (useAzure && response?.data?.id === undefined)) {\n\t\t\tthrow new Error(`ID of the created container is undefined`);\n\t\t}\n\n\t\treturn response;\n\t} catch (error) {\n\t\tthrow new Error(`An error occurred: ${error}`);\n\t}\n}\n\n/**\n * This function takes an AxiosResponse returned by the createContainerFromPayload and returns the containerId.\n * A separate function is used for this, since the data path to the containerID is not always the same.\n * (Tinylicious has the ID stored at a different path than other services)\n *\n * @param response - A container creation response returned by createContainerFromPayload\n * @returns The ID of the container that was created by createContainerFromPayload\n */\nexport function getContainerIdFromPayloadResponse(response: AxiosResponse): string {\n\tconst useAzure = process.env.FLUID_CLIENT === \"azure\";\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\treturn (useAzure ? response.data.id : response.data) as string;\n}\n"]}
|
|
@@ -24,28 +24,42 @@ const endPoint = process.env.azure__fluid__relay__service__endpoint;
|
|
|
24
24
|
if (useAzure && endPoint === undefined) {
|
|
25
25
|
throw new Error("Azure Fluid Relay service endpoint is missing");
|
|
26
26
|
}
|
|
27
|
+
const containerSchema = {
|
|
28
|
+
initialObjects: {
|
|
29
|
+
// A DataObject is added as otherwise fluid-static complains "Container cannot be initialized without any DataTypes"
|
|
30
|
+
_unused: TestDataObject,
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
function telemetryEventInterestLevel(eventName) {
|
|
34
|
+
if (eventName.includes(":Signal") || eventName.includes(":Join")) {
|
|
35
|
+
return "details";
|
|
36
|
+
}
|
|
37
|
+
else if (eventName.includes(":Container:") || eventName.includes(":Presence:")) {
|
|
38
|
+
return "basic";
|
|
39
|
+
}
|
|
40
|
+
return "none";
|
|
41
|
+
}
|
|
27
42
|
function selectiveVerboseLog(event, logLevel) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
details: event.details,
|
|
32
|
-
containerConnectionState: event.containerConnectionState,
|
|
33
|
-
});
|
|
43
|
+
const interest = telemetryEventInterestLevel(event.eventName);
|
|
44
|
+
if (interest === "none") {
|
|
45
|
+
return;
|
|
34
46
|
}
|
|
35
|
-
|
|
36
|
-
event.eventName
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
47
|
+
const content = {
|
|
48
|
+
eventName: event.eventName,
|
|
49
|
+
containerConnectionState: event.containerConnectionState,
|
|
50
|
+
};
|
|
51
|
+
if (interest === "details") {
|
|
52
|
+
content.details = event.details;
|
|
41
53
|
}
|
|
54
|
+
console.log(`[${process_id}] [${logLevel ?? LogLevel.default}]`, content);
|
|
42
55
|
}
|
|
43
56
|
/**
|
|
44
|
-
* Get or create a Fluid container
|
|
57
|
+
* Get or create a Fluid container.
|
|
45
58
|
*/
|
|
46
|
-
const
|
|
59
|
+
const getOrCreateContainer = async (params) => {
|
|
47
60
|
let container;
|
|
48
|
-
let containerId;
|
|
61
|
+
let { containerId } = params;
|
|
62
|
+
const { logger, onDisconnected, user, scopes, createScopes } = params;
|
|
49
63
|
const connectionProps = useAzure
|
|
50
64
|
? {
|
|
51
65
|
tenantId,
|
|
@@ -60,40 +74,30 @@ const getOrCreatePresenceContainer = async (id, user, scopes, createScopes) => {
|
|
|
60
74
|
};
|
|
61
75
|
const client = new AzureClient({
|
|
62
76
|
connection: connectionProps,
|
|
63
|
-
logger
|
|
64
|
-
send: verbosity.includes("telem") ? selectiveVerboseLog : () => { },
|
|
65
|
-
},
|
|
77
|
+
logger,
|
|
66
78
|
});
|
|
67
|
-
const schema = {
|
|
68
|
-
initialObjects: {
|
|
69
|
-
// A DataObject is added as otherwise fluid-static complains "Container cannot be initialized without any DataTypes"
|
|
70
|
-
_unused: TestDataObject,
|
|
71
|
-
},
|
|
72
|
-
};
|
|
73
79
|
let services;
|
|
74
|
-
if (
|
|
75
|
-
({ container, services } = await client.createContainer(
|
|
80
|
+
if (containerId === undefined) {
|
|
81
|
+
({ container, services } = await client.createContainer(containerSchema, "2"));
|
|
76
82
|
containerId = await container.attach();
|
|
77
83
|
}
|
|
78
84
|
else {
|
|
79
|
-
|
|
80
|
-
({ container, services } = await client.getContainer(containerId, schema, "2"));
|
|
85
|
+
({ container, services } = await client.getContainer(containerId, containerSchema, "2"));
|
|
81
86
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
87
|
+
container.on("disconnected", onDisconnected);
|
|
88
|
+
const connected = container.connectionState === ConnectionState.Connected
|
|
89
|
+
? Promise.resolve()
|
|
90
|
+
: timeoutPromise((resolve) => container.once("connected", () => resolve()), {
|
|
85
91
|
durationMs: connectTimeoutMs,
|
|
86
92
|
errorMsg: "container connect() timeout",
|
|
87
93
|
});
|
|
88
|
-
}
|
|
89
94
|
assert.strictEqual(container.attachState, AttachState.Attached, "Container is not attached after attach is called");
|
|
90
|
-
const presence = getPresence(container);
|
|
91
95
|
return {
|
|
92
96
|
client,
|
|
93
97
|
container,
|
|
94
|
-
presence,
|
|
95
98
|
services,
|
|
96
99
|
containerId,
|
|
100
|
+
connected,
|
|
97
101
|
};
|
|
98
102
|
};
|
|
99
103
|
function createSendFunction() {
|
|
@@ -110,21 +114,6 @@ function createSendFunction() {
|
|
|
110
114
|
throw new Error("process.send is not defined");
|
|
111
115
|
}
|
|
112
116
|
const send = createSendFunction();
|
|
113
|
-
function sendAttendeeConnected(attendee) {
|
|
114
|
-
send({
|
|
115
|
-
event: "attendeeConnected",
|
|
116
|
-
attendeeId: attendee.attendeeId,
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
function sendAttendeeDisconnected(attendee) {
|
|
120
|
-
send({
|
|
121
|
-
event: "attendeeDisconnected",
|
|
122
|
-
attendeeId: attendee.attendeeId,
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
function isConnected(container) {
|
|
126
|
-
return container !== undefined && container.connectionState === ConnectionState.Connected;
|
|
127
|
-
}
|
|
128
117
|
function isStringOrNumberRecord(value) {
|
|
129
118
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
130
119
|
return false;
|
|
@@ -145,11 +134,58 @@ function isStringOrNumberRecord(value) {
|
|
|
145
134
|
const WorkspaceSchema = {};
|
|
146
135
|
class MessageHandler {
|
|
147
136
|
constructor() {
|
|
137
|
+
this.log = [];
|
|
148
138
|
this.workspaces = new Map();
|
|
139
|
+
this.sendAttendeeConnected = (attendee) => {
|
|
140
|
+
this.send({
|
|
141
|
+
event: "attendeeConnected",
|
|
142
|
+
attendeeId: attendee.attendeeId,
|
|
143
|
+
});
|
|
144
|
+
};
|
|
145
|
+
this.sendAttendeeDisconnected = (attendee) => {
|
|
146
|
+
this.send({
|
|
147
|
+
event: "attendeeDisconnected",
|
|
148
|
+
attendeeId: attendee.attendeeId,
|
|
149
|
+
});
|
|
150
|
+
};
|
|
151
|
+
this.logger = {
|
|
152
|
+
send: (event, logLevel) => {
|
|
153
|
+
const interest = telemetryEventInterestLevel(event.eventName);
|
|
154
|
+
if (interest === "none") {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
this.log.push({
|
|
158
|
+
timestamp: Date.now(),
|
|
159
|
+
agentId: process_id,
|
|
160
|
+
eventCategory: "telemetry",
|
|
161
|
+
eventName: event.eventName,
|
|
162
|
+
details: typeof event.details === "string" ? event.details : JSON.stringify(event.details),
|
|
163
|
+
});
|
|
164
|
+
if (verbosity.includes("telem")) {
|
|
165
|
+
selectiveVerboseLog(event, logLevel);
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
this.onDisconnected = () => {
|
|
170
|
+
// Test state is a bit fragile and does not account for reconnections.
|
|
171
|
+
this.send({ event: "error", error: `${process_id}: Container disconnected` });
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
send(msg) {
|
|
175
|
+
this.log.push({
|
|
176
|
+
timestamp: Date.now(),
|
|
177
|
+
agentId: process_id,
|
|
178
|
+
eventCategory: "messageSent",
|
|
179
|
+
eventName: msg.event,
|
|
180
|
+
details: msg.event === "debugReportComplete" && msg.log
|
|
181
|
+
? JSON.stringify({ logLength: msg.log.length })
|
|
182
|
+
: JSON.stringify(msg),
|
|
183
|
+
});
|
|
184
|
+
send(msg);
|
|
149
185
|
}
|
|
150
186
|
registerWorkspace(workspaceId, options) {
|
|
151
187
|
if (!this.presence) {
|
|
152
|
-
send({ event: "error", error: `${process_id} is not connected to presence` });
|
|
188
|
+
this.send({ event: "error", error: `${process_id} is not connected to presence` });
|
|
153
189
|
return;
|
|
154
190
|
}
|
|
155
191
|
const { latest, latestMap } = options;
|
|
@@ -160,7 +196,7 @@ class MessageHandler {
|
|
|
160
196
|
// TODO: AB#47518
|
|
161
197
|
const latestState = workspace.states.latest;
|
|
162
198
|
latestState.events.on("remoteUpdated", (update) => {
|
|
163
|
-
send({
|
|
199
|
+
this.send({
|
|
164
200
|
event: "latestValueUpdated",
|
|
165
201
|
workspaceId,
|
|
166
202
|
attendeeId: update.attendee.attendeeId,
|
|
@@ -168,7 +204,7 @@ class MessageHandler {
|
|
|
168
204
|
});
|
|
169
205
|
});
|
|
170
206
|
for (const remote of latestState.getRemotes()) {
|
|
171
|
-
send({
|
|
207
|
+
this.send({
|
|
172
208
|
event: "latestValueUpdated",
|
|
173
209
|
workspaceId,
|
|
174
210
|
attendeeId: remote.attendee.attendeeId,
|
|
@@ -185,7 +221,7 @@ class MessageHandler {
|
|
|
185
221
|
const latestMapState = workspace.states.latestMap;
|
|
186
222
|
latestMapState.events.on("remoteUpdated", (update) => {
|
|
187
223
|
for (const [key, valueWithMetadata] of update.items) {
|
|
188
|
-
send({
|
|
224
|
+
this.send({
|
|
189
225
|
event: "latestMapValueUpdated",
|
|
190
226
|
workspaceId,
|
|
191
227
|
attendeeId: update.attendee.attendeeId,
|
|
@@ -196,7 +232,7 @@ class MessageHandler {
|
|
|
196
232
|
});
|
|
197
233
|
for (const remote of latestMapState.getRemotes()) {
|
|
198
234
|
for (const [key, valueWithMetadata] of remote.items) {
|
|
199
|
-
send({
|
|
235
|
+
this.send({
|
|
200
236
|
event: "latestMapValueUpdated",
|
|
201
237
|
workspaceId,
|
|
202
238
|
attendeeId: remote.attendee.attendeeId,
|
|
@@ -207,7 +243,7 @@ class MessageHandler {
|
|
|
207
243
|
}
|
|
208
244
|
}
|
|
209
245
|
this.workspaces.set(workspaceId, workspace);
|
|
210
|
-
send({
|
|
246
|
+
this.send({
|
|
211
247
|
event: "workspaceRegistered",
|
|
212
248
|
workspaceId,
|
|
213
249
|
latest: latest ?? false,
|
|
@@ -216,15 +252,33 @@ class MessageHandler {
|
|
|
216
252
|
}
|
|
217
253
|
async onMessage(msg) {
|
|
218
254
|
if (verbosity.includes("msgs")) {
|
|
255
|
+
this.log.push({
|
|
256
|
+
timestamp: Date.now(),
|
|
257
|
+
agentId: process_id,
|
|
258
|
+
eventCategory: "messageReceived",
|
|
259
|
+
eventName: msg.command,
|
|
260
|
+
});
|
|
219
261
|
console.log(`[${process_id}] Received`, msg);
|
|
220
262
|
}
|
|
263
|
+
if (msg.command === "ping") {
|
|
264
|
+
this.handlePing();
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
if (msg.command === "connect") {
|
|
268
|
+
await this.handleConnect(msg);
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
// All other message must wait if connect is in progress
|
|
272
|
+
if (this.msgQueue !== undefined) {
|
|
273
|
+
this.msgQueue.push(msg);
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
this.processMessage(msg);
|
|
277
|
+
}
|
|
278
|
+
processMessage(msg) {
|
|
221
279
|
switch (msg.command) {
|
|
222
|
-
case "
|
|
223
|
-
this.
|
|
224
|
-
break;
|
|
225
|
-
}
|
|
226
|
-
case "connect": {
|
|
227
|
-
await this.handleConnect(msg);
|
|
280
|
+
case "debugReport": {
|
|
281
|
+
this.handleDebugReport(msg);
|
|
228
282
|
break;
|
|
229
283
|
}
|
|
230
284
|
case "disconnectSelf": {
|
|
@@ -255,74 +309,125 @@ class MessageHandler {
|
|
|
255
309
|
break;
|
|
256
310
|
}
|
|
257
311
|
default: {
|
|
258
|
-
console.error(`${process_id}: Unknown command
|
|
259
|
-
send({
|
|
312
|
+
console.error(`${process_id}: Unknown command:`, msg);
|
|
313
|
+
this.send({
|
|
314
|
+
event: "error",
|
|
315
|
+
error: `${process_id} Unknown command: ${JSON.stringify(msg)}`,
|
|
316
|
+
});
|
|
260
317
|
}
|
|
261
318
|
}
|
|
262
319
|
}
|
|
263
320
|
handlePing() {
|
|
264
|
-
send({ event: "ack" });
|
|
321
|
+
this.send({ event: "ack" });
|
|
265
322
|
}
|
|
266
323
|
async handleConnect(msg) {
|
|
267
324
|
if (!msg.user) {
|
|
268
|
-
send({ event: "error", error: `${process_id}: No azure user information given` });
|
|
325
|
+
this.send({ event: "error", error: `${process_id}: No azure user information given` });
|
|
269
326
|
return;
|
|
270
327
|
}
|
|
271
|
-
if (
|
|
272
|
-
send({ event: "error", error: `${process_id}:
|
|
328
|
+
if (this.container) {
|
|
329
|
+
this.send({ event: "error", error: `${process_id}: Container already loaded` });
|
|
273
330
|
return;
|
|
274
331
|
}
|
|
275
|
-
|
|
276
|
-
this.
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
332
|
+
// Prevent reentrance. Queue messages until after connect is fully processed.
|
|
333
|
+
this.msgQueue = [];
|
|
334
|
+
try {
|
|
335
|
+
const { container, containerId, connected } = await getOrCreateContainer({
|
|
336
|
+
...msg,
|
|
337
|
+
logger: this.logger,
|
|
338
|
+
onDisconnected: this.onDisconnected,
|
|
339
|
+
});
|
|
340
|
+
this.container = container;
|
|
341
|
+
const presence = getPresence(container);
|
|
342
|
+
this.presence = presence;
|
|
343
|
+
// wait for 'ConnectionState.Connected'
|
|
344
|
+
await connected;
|
|
345
|
+
// Acknowledge connection before sending current attendee information
|
|
346
|
+
this.send({
|
|
347
|
+
event: "connected",
|
|
348
|
+
containerId,
|
|
349
|
+
attendeeId: presence.attendees.getMyself().attendeeId,
|
|
350
|
+
});
|
|
351
|
+
// Send existing attendees excluding self to parent/orchestrator
|
|
352
|
+
const self = presence.attendees.getMyself();
|
|
353
|
+
for (const attendee of presence.attendees.getAttendees()) {
|
|
354
|
+
if (attendee !== self && attendee.getConnectionStatus() === "Connected") {
|
|
355
|
+
this.sendAttendeeConnected(attendee);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
// Listen for presence events to notify parent/orchestrator when a new attendee joins or leaves the session.
|
|
359
|
+
presence.attendees.events.on("attendeeConnected", this.sendAttendeeConnected);
|
|
360
|
+
presence.attendees.events.on("attendeeDisconnected", this.sendAttendeeDisconnected);
|
|
361
|
+
}
|
|
362
|
+
finally {
|
|
363
|
+
// Process any queued messages received while connecting
|
|
364
|
+
for (const queuedMsg of this.msgQueue) {
|
|
365
|
+
this.processMessage(queuedMsg);
|
|
366
|
+
}
|
|
367
|
+
this.msgQueue = undefined;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
handleDebugReport(msg) {
|
|
371
|
+
if (msg.reportAttendees) {
|
|
372
|
+
if (this.presence) {
|
|
373
|
+
const attendees = this.presence.attendees.getAttendees();
|
|
374
|
+
let connectedCount = 0;
|
|
375
|
+
for (const attendee of attendees) {
|
|
376
|
+
if (attendee.getConnectionStatus() === "Connected") {
|
|
377
|
+
connectedCount++;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
console.log(`[${process_id}] Report: ${attendees.size} attendees, ${connectedCount} connected`);
|
|
381
|
+
}
|
|
382
|
+
else {
|
|
383
|
+
this.send({ event: "error", error: `${process_id} is not connected to presence` });
|
|
290
384
|
}
|
|
291
385
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
386
|
+
const debugReport = {
|
|
387
|
+
event: "debugReportComplete",
|
|
388
|
+
};
|
|
389
|
+
if (msg.sendEventLog) {
|
|
390
|
+
debugReport.log = this.log;
|
|
391
|
+
}
|
|
392
|
+
this.send(debugReport);
|
|
295
393
|
}
|
|
296
394
|
handleDisconnectSelf() {
|
|
297
395
|
if (!this.container) {
|
|
298
|
-
send({ event: "error", error: `${process_id} is not connected to container` });
|
|
396
|
+
this.send({ event: "error", error: `${process_id} is not connected to container` });
|
|
299
397
|
return;
|
|
300
398
|
}
|
|
399
|
+
// There are no current scenarios where disconnect without presence is expected.
|
|
301
400
|
if (!this.presence) {
|
|
302
|
-
send({ event: "error", error: `${process_id} is not connected to presence` });
|
|
401
|
+
this.send({ event: "error", error: `${process_id} is not connected to presence` });
|
|
303
402
|
return;
|
|
304
403
|
}
|
|
404
|
+
// Disconnect event is treated as an error in normal handling.
|
|
405
|
+
// Remove listener as this disconnect is intentional.
|
|
406
|
+
this.container.off("disconnected", this.onDisconnected);
|
|
305
407
|
this.container.disconnect();
|
|
306
|
-
send({
|
|
408
|
+
this.send({
|
|
307
409
|
event: "disconnectedSelf",
|
|
308
410
|
attendeeId: this.presence.attendees.getMyself().attendeeId,
|
|
309
411
|
});
|
|
310
412
|
}
|
|
311
413
|
handleSetLatestValue(msg) {
|
|
312
414
|
if (!this.presence) {
|
|
313
|
-
send({ event: "error", error: `${process_id} is not connected to presence` });
|
|
415
|
+
this.send({ event: "error", error: `${process_id} is not connected to presence` });
|
|
314
416
|
return;
|
|
315
417
|
}
|
|
316
418
|
const workspace = this.workspaces.get(msg.workspaceId);
|
|
317
419
|
if (!workspace) {
|
|
318
|
-
send({
|
|
420
|
+
this.send({
|
|
421
|
+
event: "error",
|
|
422
|
+
error: `${process_id} workspace ${msg.workspaceId} not found`,
|
|
423
|
+
});
|
|
319
424
|
return;
|
|
320
425
|
}
|
|
321
426
|
// Cast required due to optional keys in WorkspaceSchema
|
|
322
427
|
// TODO: AB#47518
|
|
323
428
|
const latestState = workspace.states.latest;
|
|
324
429
|
if (!latestState) {
|
|
325
|
-
send({
|
|
430
|
+
this.send({
|
|
326
431
|
event: "error",
|
|
327
432
|
error: `${process_id} latest state not registered for workspace ${msg.workspaceId}`,
|
|
328
433
|
});
|
|
@@ -335,23 +440,26 @@ class MessageHandler {
|
|
|
335
440
|
}
|
|
336
441
|
handleSetLatestMapValue(msg) {
|
|
337
442
|
if (!this.presence) {
|
|
338
|
-
send({ event: "error", error: `${process_id} is not connected to presence` });
|
|
443
|
+
this.send({ event: "error", error: `${process_id} is not connected to presence` });
|
|
339
444
|
return;
|
|
340
445
|
}
|
|
341
446
|
if (typeof msg.key !== "string") {
|
|
342
|
-
send({ event: "error", error: `${process_id} invalid key type` });
|
|
447
|
+
this.send({ event: "error", error: `${process_id} invalid key type` });
|
|
343
448
|
return;
|
|
344
449
|
}
|
|
345
450
|
const workspace = this.workspaces.get(msg.workspaceId);
|
|
346
451
|
if (!workspace) {
|
|
347
|
-
send({
|
|
452
|
+
this.send({
|
|
453
|
+
event: "error",
|
|
454
|
+
error: `${process_id} workspace ${msg.workspaceId} not found`,
|
|
455
|
+
});
|
|
348
456
|
return;
|
|
349
457
|
}
|
|
350
458
|
// Cast required due to optional keys in WorkspaceSchema
|
|
351
459
|
// TODO: AB#47518
|
|
352
460
|
const latestMapState = workspace.states.latestMap;
|
|
353
461
|
if (!latestMapState) {
|
|
354
|
-
send({
|
|
462
|
+
this.send({
|
|
355
463
|
event: "error",
|
|
356
464
|
error: `${process_id} latestMap state not registered for workspace ${msg.workspaceId}`,
|
|
357
465
|
});
|
|
@@ -364,19 +472,22 @@ class MessageHandler {
|
|
|
364
472
|
}
|
|
365
473
|
handleGetLatestValue(msg) {
|
|
366
474
|
if (!this.presence) {
|
|
367
|
-
send({ event: "error", error: `${process_id} is not connected to presence` });
|
|
475
|
+
this.send({ event: "error", error: `${process_id} is not connected to presence` });
|
|
368
476
|
return;
|
|
369
477
|
}
|
|
370
478
|
const workspace = this.workspaces.get(msg.workspaceId);
|
|
371
479
|
if (!workspace) {
|
|
372
|
-
send({
|
|
480
|
+
this.send({
|
|
481
|
+
event: "error",
|
|
482
|
+
error: `${process_id} workspace ${msg.workspaceId} not found`,
|
|
483
|
+
});
|
|
373
484
|
return;
|
|
374
485
|
}
|
|
375
486
|
// Cast required due to optional keys in WorkspaceSchema
|
|
376
487
|
// TODO: AB#47518
|
|
377
488
|
const latestState = workspace.states.latest;
|
|
378
489
|
if (!latestState) {
|
|
379
|
-
send({
|
|
490
|
+
this.send({
|
|
380
491
|
event: "error",
|
|
381
492
|
error: `${process_id} latest state not registered for workspace ${msg.workspaceId}`,
|
|
382
493
|
});
|
|
@@ -391,7 +502,7 @@ class MessageHandler {
|
|
|
391
502
|
else {
|
|
392
503
|
value = latestState.local;
|
|
393
504
|
}
|
|
394
|
-
send({
|
|
505
|
+
this.send({
|
|
395
506
|
event: "latestValueGetResponse",
|
|
396
507
|
workspaceId: msg.workspaceId,
|
|
397
508
|
attendeeId: msg.attendeeId,
|
|
@@ -400,23 +511,26 @@ class MessageHandler {
|
|
|
400
511
|
}
|
|
401
512
|
handleGetLatestMapValue(msg) {
|
|
402
513
|
if (!this.presence) {
|
|
403
|
-
send({ event: "error", error: `${process_id} is not connected to presence` });
|
|
514
|
+
this.send({ event: "error", error: `${process_id} is not connected to presence` });
|
|
404
515
|
return;
|
|
405
516
|
}
|
|
406
517
|
if (typeof msg.key !== "string") {
|
|
407
|
-
send({ event: "error", error: `${process_id} invalid key type` });
|
|
518
|
+
this.send({ event: "error", error: `${process_id} invalid key type` });
|
|
408
519
|
return;
|
|
409
520
|
}
|
|
410
521
|
const workspace = this.workspaces.get(msg.workspaceId);
|
|
411
522
|
if (!workspace) {
|
|
412
|
-
send({
|
|
523
|
+
this.send({
|
|
524
|
+
event: "error",
|
|
525
|
+
error: `${process_id} workspace ${msg.workspaceId} not found`,
|
|
526
|
+
});
|
|
413
527
|
return;
|
|
414
528
|
}
|
|
415
529
|
// Cast required due to optional keys in WorkspaceSchema
|
|
416
530
|
// TODO: AB#47518
|
|
417
531
|
const latestMapState = workspace.states.latestMap;
|
|
418
532
|
if (!latestMapState) {
|
|
419
|
-
send({
|
|
533
|
+
this.send({
|
|
420
534
|
event: "error",
|
|
421
535
|
error: `${process_id} latestMap state not registered for workspace ${msg.workspaceId}`,
|
|
422
536
|
});
|
|
@@ -432,7 +546,7 @@ class MessageHandler {
|
|
|
432
546
|
else {
|
|
433
547
|
value = latestMapState.local.get(msg.key);
|
|
434
548
|
}
|
|
435
|
-
send({
|
|
549
|
+
this.send({
|
|
436
550
|
event: "latestMapValueGetResponse",
|
|
437
551
|
workspaceId: msg.workspaceId,
|
|
438
552
|
attendeeId: msg.attendeeId,
|