@fluidframework/azure-end-to-end-tests 2.70.0-361788 → 2.71.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @fluidframework/azure-end-to-end-tests
2
2
 
3
+ ## 2.71.0
4
+
5
+ Dependency updates only.
6
+
7
+ ## 2.70.0
8
+
9
+ Dependency updates only.
10
+
3
11
  ## 2.63.0
4
12
 
5
13
  Dependency updates only.
@@ -12,10 +12,10 @@ import { InsecureTokenProvider } from "@fluidframework/test-runtime-utils/intern
12
12
  import { timeoutPromise } from "@fluidframework/test-utils/internal";
13
13
  import { createAzureTokenProvider } from "../AzureTokenFactory.js";
14
14
  import { TestDataObject } from "../TestDataObject.js";
15
- const connectTimeoutMs = 10_000;
15
+ const testLabel = process.argv[2];
16
16
  // Identifier given to child process
17
- const process_id = process.argv[2];
18
- const verbosity = process.argv[3] ?? "";
17
+ const process_id = process.argv[3];
18
+ const verbosity = process.argv[4] ?? "";
19
19
  const useAzure = process.env.FLUID_CLIENT === "azure";
20
20
  const tenantId = useAzure
21
21
  ? process.env.azure__fluid__relay__service__tenantId
@@ -30,6 +30,9 @@ const containerSchema = {
30
30
  _unused: TestDataObject,
31
31
  },
32
32
  };
33
+ function log(...data) {
34
+ console.log(`[${testLabel}] [${new Date().toISOString()}] [${process_id}]`, ...data);
35
+ }
33
36
  function telemetryEventInterestLevel(eventName) {
34
37
  if (eventName.includes(":Signal") || eventName.includes(":Join")) {
35
38
  return "details";
@@ -51,7 +54,7 @@ function selectiveVerboseLog(event, logLevel) {
51
54
  if (interest === "details") {
52
55
  content.details = event.details;
53
56
  }
54
- console.log(`[${process_id}] [${logLevel ?? LogLevel.default}]`, content);
57
+ log(`[${logLevel ?? LogLevel.default}]`, content);
55
58
  }
56
59
  /**
57
60
  * Get or create a Fluid container.
@@ -59,7 +62,7 @@ function selectiveVerboseLog(event, logLevel) {
59
62
  const getOrCreateContainer = async (params) => {
60
63
  let container;
61
64
  let { containerId } = params;
62
- const { logger, onDisconnected, user, scopes, createScopes } = params;
65
+ const { logger, onDisconnected, user, scopes, createScopes, connectTimeoutMs } = params;
63
66
  const connectionProps = useAzure
64
67
  ? {
65
68
  tenantId,
@@ -105,7 +108,7 @@ function createSendFunction() {
105
108
  const sendFn = process.send.bind(process);
106
109
  if (verbosity.includes("msgs")) {
107
110
  return (msg) => {
108
- console.log(`[${process_id}] Sending`, msg);
111
+ log(`Sending`, msg);
109
112
  sendFn(msg);
110
113
  };
111
114
  }
@@ -150,6 +153,19 @@ class MessageHandler {
150
153
  };
151
154
  this.logger = {
152
155
  send: (event, logLevel) => {
156
+ // Filter out non-interactive client telemetry
157
+ const clientType = event.clientType;
158
+ if (typeof clientType === "string" && clientType.startsWith("noninteractive")) {
159
+ return;
160
+ }
161
+ // Special case unexpected telemetry event
162
+ if (event.eventName.endsWith(":JoinResponseWhenAlone")) {
163
+ this.send({
164
+ event: "error",
165
+ error: `Unexpected ClientJoin response. Details: ${JSON.stringify(event.details)}\nLog: ${JSON.stringify(this.log)}`,
166
+ });
167
+ // Keep going
168
+ }
153
169
  const interest = telemetryEventInterestLevel(event.eventName);
154
170
  if (interest === "none") {
155
171
  return;
@@ -258,7 +274,7 @@ class MessageHandler {
258
274
  eventCategory: "messageReceived",
259
275
  eventName: msg.command,
260
276
  });
261
- console.log(`[${process_id}] Received`, msg);
277
+ log(`Received`, msg);
262
278
  }
263
279
  if (msg.command === "ping") {
264
280
  this.handlePing();
@@ -341,7 +357,10 @@ class MessageHandler {
341
357
  const presence = getPresence(container);
342
358
  this.presence = presence;
343
359
  // wait for 'ConnectionState.Connected'
344
- await connected;
360
+ await connected.catch((error) => {
361
+ error.message += `\nLog: ${JSON.stringify(this.log)}`;
362
+ throw error;
363
+ });
345
364
  // Acknowledge connection before sending current attendee information
346
365
  this.send({
347
366
  event: "connected",
@@ -377,7 +396,7 @@ class MessageHandler {
377
396
  connectedCount++;
378
397
  }
379
398
  }
380
- console.log(`[${process_id}] Report: ${attendees.size} attendees, ${connectedCount} connected`);
399
+ log(`Report: ${attendees.size} attendees, ${connectedCount} connected`);
381
400
  }
382
401
  else {
383
402
  this.send({ event: "error", error: `${process_id} is not connected to presence` });
@@ -559,7 +578,7 @@ function setupMessageHandler() {
559
578
  const messageHandler = new MessageHandler();
560
579
  process.on("message", (msg) => {
561
580
  messageHandler.onMessage(msg).catch((error) => {
562
- console.error(`Error in client ${process_id}`, error);
581
+ console.error(`[${testLabel}] Error in client ${process_id}`, error);
563
582
  send({ event: "error", error: `${process_id}: ${error.message}` });
564
583
  });
565
584
  });
@@ -1 +1 @@
1
- {"version":3,"file":"childClient.tool.js","sourceRoot":"","sources":["../../../src/test/multiprocess/childClient.tool.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 \"node:assert\";\n\nimport {\n\tAzureClient,\n\ttype AzureContainerServices,\n\ttype AzureLocalConnectionConfig,\n\ttype AzureRemoteConnectionConfig,\n\ttype ITelemetryBaseEvent,\n} from \"@fluidframework/azure-client\";\nimport { AttachState } from \"@fluidframework/container-definitions\";\nimport { ConnectionState } from \"@fluidframework/container-loader\";\nimport type { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { LogLevel } from \"@fluidframework/core-interfaces\";\nimport type { ScopeType } from \"@fluidframework/driver-definitions/legacy\";\nimport type { ContainerSchema, IFluidContainer } from \"@fluidframework/fluid-static\";\nimport {\n\tgetPresence,\n\ttype Attendee,\n\ttype Presence,\n\tStateFactory,\n\ttype LatestRaw,\n\ttype LatestMapRaw,\n\ttype StatesWorkspace,\n} from \"@fluidframework/presence/beta\";\nimport { InsecureTokenProvider } from \"@fluidframework/test-runtime-utils/internal\";\nimport { timeoutPromise } from \"@fluidframework/test-utils/internal\";\n\nimport { createAzureTokenProvider } from \"../AzureTokenFactory.js\";\nimport { TestDataObject } from \"../TestDataObject.js\";\n\nimport type {\n\tMessageFromChild as MessageToParent,\n\tMessageToChild as MessageFromParent,\n\tUserIdAndName,\n\tEventEntry,\n} from \"./messageTypes.js\";\n\nconst connectTimeoutMs = 10_000;\n// Identifier given to child process\nconst process_id = process.argv[2];\nconst verbosity = process.argv[3] ?? \"\";\n\nconst useAzure = process.env.FLUID_CLIENT === \"azure\";\nconst tenantId = useAzure\n\t? (process.env.azure__fluid__relay__service__tenantId as string)\n\t: \"frs-client-tenant\";\nconst endPoint = process.env.azure__fluid__relay__service__endpoint as string;\nif (useAzure && endPoint === undefined) {\n\tthrow new Error(\"Azure Fluid Relay service endpoint is missing\");\n}\n\nconst containerSchema = {\n\tinitialObjects: {\n\t\t// A DataObject is added as otherwise fluid-static complains \"Container cannot be initialized without any DataTypes\"\n\t\t_unused: TestDataObject,\n\t},\n} as const satisfies ContainerSchema;\n\nfunction telemetryEventInterestLevel(eventName: string): \"none\" | \"basic\" | \"details\" {\n\tif (eventName.includes(\":Signal\") || eventName.includes(\":Join\")) {\n\t\treturn \"details\";\n\t} else if (eventName.includes(\":Container:\") || eventName.includes(\":Presence:\")) {\n\t\treturn \"basic\";\n\t}\n\treturn \"none\";\n}\n\nfunction selectiveVerboseLog(event: ITelemetryBaseEvent, logLevel?: LogLevel): void {\n\tconst interest = telemetryEventInterestLevel(event.eventName);\n\tif (interest === \"none\") {\n\t\treturn;\n\t}\n\tconst content: Record<string, unknown> = {\n\t\teventName: event.eventName,\n\t\tcontainerConnectionState: event.containerConnectionState,\n\t};\n\tif (interest === \"details\") {\n\t\tcontent.details = event.details;\n\t}\n\tconsole.log(`[${process_id}] [${logLevel ?? LogLevel.default}]`, content);\n}\n\n/**\n * Get or create a Fluid container.\n */\nconst getOrCreateContainer = async (params: {\n\tlogger: ITelemetryBaseLogger;\n\tonDisconnected: () => void;\n\tcontainerId?: string;\n\tuser: UserIdAndName;\n\tscopes?: ScopeType[];\n\tcreateScopes?: ScopeType[];\n}): Promise<{\n\tcontainer: IFluidContainer<typeof containerSchema>;\n\tservices: AzureContainerServices;\n\tclient: AzureClient;\n\tcontainerId: string;\n\tconnected: Promise<void>;\n}> => {\n\tlet container: IFluidContainer<typeof containerSchema>;\n\tlet { containerId } = params;\n\tconst { logger, onDisconnected, user, scopes, createScopes } = params;\n\tconst connectionProps: AzureRemoteConnectionConfig | AzureLocalConnectionConfig = useAzure\n\t\t? {\n\t\t\t\ttenantId,\n\t\t\t\ttokenProvider: createAzureTokenProvider(\n\t\t\t\t\tuser.id ?? \"foo\",\n\t\t\t\t\tuser.name ?? \"bar\",\n\t\t\t\t\tscopes,\n\t\t\t\t\tcreateScopes,\n\t\t\t\t),\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, createScopes),\n\t\t\t\tendpoint: \"http://localhost:7071\",\n\t\t\t\ttype: \"local\",\n\t\t\t};\n\tconst client = new AzureClient({\n\t\tconnection: connectionProps,\n\t\tlogger,\n\t});\n\tlet services: AzureContainerServices;\n\tif (containerId === undefined) {\n\t\t({ container, services } = await client.createContainer(containerSchema, \"2\"));\n\t\tcontainerId = await container.attach();\n\t} else {\n\t\t({ container, services } = await client.getContainer(containerId, containerSchema, \"2\"));\n\t}\n\tcontainer.on(\"disconnected\", onDisconnected);\n\n\tconst connected =\n\t\tcontainer.connectionState === ConnectionState.Connected\n\t\t\t? Promise.resolve()\n\t\t\t: timeoutPromise((resolve) => container.once(\"connected\", () => resolve()), {\n\t\t\t\t\tdurationMs: connectTimeoutMs,\n\t\t\t\t\terrorMsg: \"container connect() timeout\",\n\t\t\t\t});\n\n\tassert.strictEqual(\n\t\tcontainer.attachState,\n\t\tAttachState.Attached,\n\t\t\"Container is not attached after attach is called\",\n\t);\n\n\treturn {\n\t\tclient,\n\t\tcontainer,\n\t\tservices,\n\t\tcontainerId,\n\t\tconnected,\n\t};\n};\n\nfunction createSendFunction(): (msg: MessageToParent) => void {\n\tif (process.send) {\n\t\tconst sendFn = process.send.bind(process);\n\t\tif (verbosity.includes(\"msgs\")) {\n\t\t\treturn (msg: MessageToParent) => {\n\t\t\t\tconsole.log(`[${process_id}] Sending`, msg);\n\t\t\t\tsendFn(msg);\n\t\t\t};\n\t\t}\n\t\treturn sendFn;\n\t}\n\tthrow new Error(\"process.send is not defined\");\n}\n\nconst send = createSendFunction();\n\nfunction isStringOrNumberRecord(value: unknown): value is Record<string, string | number> {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n\t\treturn false;\n\t}\n\n\tconst stringKeys = Object.keys(value);\n\tconst allKeys = Reflect.ownKeys(value);\n\n\tif (stringKeys.length !== allKeys.length) {\n\t\t// If there are non-string/symbol keys, return false\n\t\treturn false;\n\t}\n\tfor (const key of stringKeys) {\n\t\tif (!(typeof value[key] === \"string\" || typeof value[key] === \"number\")) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n// NOTE:\n// - This schema intentionally uses optional keys (latest?, latestMap?) so tests can register\n// states conditionally at runtime.\n// - Optional keys are not explicitly supported in StatesWorkspace typing today, which means\n// workspace.states.<key> is typed as any. As a result, usages below require casts\n// (e.g., to LatestRaw / LatestMapRaw) to recover concrete types.\n// - Track adding proper optional-key support to Presence state workspace typing here:\n// Work item: AB#47518\n// - Fallout: Until the above is addressed, keep the casts in place and document new usages accordingly.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\ntype WorkspaceSchema = {\n\tlatest?: ReturnType<typeof StateFactory.latest<{ value: string }>>;\n\tlatestMap?: ReturnType<\n\t\ttypeof StateFactory.latestMap<{ value: Record<string, string | number> }, string>\n\t>;\n};\nconst WorkspaceSchema: WorkspaceSchema = {};\n\nclass MessageHandler {\n\tprivate readonly log: EventEntry[] = [];\n\tprivate msgQueue: undefined | Exclude<MessageFromParent, { command: \"ping\" | \"connect\" }>[];\n\tprivate container: IFluidContainer | undefined;\n\tprivate presence: Presence | undefined;\n\tprivate readonly workspaces = new Map<string, StatesWorkspace<WorkspaceSchema>>();\n\n\tprivate send(msg: MessageToParent): void {\n\t\tthis.log.push({\n\t\t\ttimestamp: Date.now(),\n\t\t\tagentId: process_id,\n\t\t\teventCategory: \"messageSent\",\n\t\t\teventName: msg.event,\n\t\t\tdetails:\n\t\t\t\tmsg.event === \"debugReportComplete\" && msg.log\n\t\t\t\t\t? JSON.stringify({ logLength: msg.log.length })\n\t\t\t\t\t: JSON.stringify(msg),\n\t\t});\n\t\tsend(msg);\n\t}\n\n\tprivate readonly sendAttendeeConnected = (attendee: Attendee): void => {\n\t\tthis.send({\n\t\t\tevent: \"attendeeConnected\",\n\t\t\tattendeeId: attendee.attendeeId,\n\t\t});\n\t};\n\tprivate readonly sendAttendeeDisconnected = (attendee: Attendee): void => {\n\t\tthis.send({\n\t\t\tevent: \"attendeeDisconnected\",\n\t\t\tattendeeId: attendee.attendeeId,\n\t\t});\n\t};\n\n\tprivate readonly logger: ITelemetryBaseLogger = {\n\t\tsend: (event: ITelemetryBaseEvent, logLevel?: LogLevel) => {\n\t\t\tconst interest = telemetryEventInterestLevel(event.eventName);\n\t\t\tif (interest === \"none\") {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.log.push({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tagentId: process_id,\n\t\t\t\teventCategory: \"telemetry\",\n\t\t\t\teventName: event.eventName,\n\t\t\t\tdetails:\n\t\t\t\t\ttypeof event.details === \"string\" ? event.details : JSON.stringify(event.details),\n\t\t\t});\n\t\t\tif (verbosity.includes(\"telem\")) {\n\t\t\t\tselectiveVerboseLog(event, logLevel);\n\t\t\t}\n\t\t},\n\t};\n\n\tprivate readonly onDisconnected = (): void => {\n\t\t// Test state is a bit fragile and does not account for reconnections.\n\t\tthis.send({ event: \"error\", error: `${process_id}: Container disconnected` });\n\t};\n\n\tprivate registerWorkspace(\n\t\tworkspaceId: string,\n\t\toptions: { latest?: boolean; latestMap?: boolean },\n\t): void {\n\t\tif (!this.presence) {\n\t\t\tthis.send({ event: \"error\", error: `${process_id} is not connected to presence` });\n\t\t\treturn;\n\t\t}\n\t\tconst { latest, latestMap } = options;\n\t\tconst workspace: StatesWorkspace<WorkspaceSchema> = this.presence.states.getWorkspace(\n\t\t\t`test:${workspaceId}`,\n\t\t\tWorkspaceSchema,\n\t\t);\n\n\t\tif (latest && !workspace.states.latest) {\n\t\t\tworkspace.add(\n\t\t\t\t\"latest\",\n\t\t\t\tStateFactory.latest<{ value: string }>({ local: { value: \"initial\" } }),\n\t\t\t);\n\t\t\t// Cast required due to optional keys in WorkspaceSchema\n\t\t\t// TODO: AB#47518\n\t\t\tconst latestState = workspace.states.latest as LatestRaw<{ value: string }>;\n\t\t\tlatestState.events.on(\"remoteUpdated\", (update) => {\n\t\t\t\tthis.send({\n\t\t\t\t\tevent: \"latestValueUpdated\",\n\t\t\t\t\tworkspaceId,\n\t\t\t\t\tattendeeId: update.attendee.attendeeId,\n\t\t\t\t\tvalue: update.value.value,\n\t\t\t\t});\n\t\t\t});\n\t\t\tfor (const remote of latestState.getRemotes()) {\n\t\t\t\tthis.send({\n\t\t\t\t\tevent: \"latestValueUpdated\",\n\t\t\t\t\tworkspaceId,\n\t\t\t\t\tattendeeId: remote.attendee.attendeeId,\n\t\t\t\t\tvalue: remote.value.value,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tif (latestMap && !workspace.states.latestMap) {\n\t\t\tworkspace.add(\n\t\t\t\t\"latestMap\",\n\t\t\t\tStateFactory.latestMap<{ value: Record<string, string | number> }, string>({\n\t\t\t\t\tlocal: {},\n\t\t\t\t}),\n\t\t\t);\n\t\t\t// Cast required due to optional keys in WorkspaceSchema\n\t\t\t// TODO: AB#47518\n\t\t\tconst latestMapState = workspace.states.latestMap as LatestMapRaw<\n\t\t\t\t{ value: Record<string, string | number> },\n\t\t\t\tstring\n\t\t\t>;\n\t\t\tlatestMapState.events.on(\"remoteUpdated\", (update) => {\n\t\t\t\tfor (const [key, valueWithMetadata] of update.items) {\n\t\t\t\t\tthis.send({\n\t\t\t\t\t\tevent: \"latestMapValueUpdated\",\n\t\t\t\t\t\tworkspaceId,\n\t\t\t\t\t\tattendeeId: update.attendee.attendeeId,\n\t\t\t\t\t\tkey: String(key),\n\t\t\t\t\t\tvalue: valueWithMetadata.value.value,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t\tfor (const remote of latestMapState.getRemotes()) {\n\t\t\t\tfor (const [key, valueWithMetadata] of remote.items) {\n\t\t\t\t\tthis.send({\n\t\t\t\t\t\tevent: \"latestMapValueUpdated\",\n\t\t\t\t\t\tworkspaceId,\n\t\t\t\t\t\tattendeeId: remote.attendee.attendeeId,\n\t\t\t\t\t\tkey: String(key),\n\t\t\t\t\t\tvalue: valueWithMetadata.value.value,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.workspaces.set(workspaceId, workspace);\n\t\tthis.send({\n\t\t\tevent: \"workspaceRegistered\",\n\t\t\tworkspaceId,\n\t\t\tlatest: latest ?? false,\n\t\t\tlatestMap: latestMap ?? false,\n\t\t});\n\t}\n\n\tpublic async onMessage(msg: MessageFromParent): Promise<void> {\n\t\tif (verbosity.includes(\"msgs\")) {\n\t\t\tthis.log.push({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tagentId: process_id,\n\t\t\t\teventCategory: \"messageReceived\",\n\t\t\t\teventName: msg.command,\n\t\t\t});\n\t\t\tconsole.log(`[${process_id}] Received`, msg);\n\t\t}\n\n\t\tif (msg.command === \"ping\") {\n\t\t\tthis.handlePing();\n\t\t\treturn;\n\t\t}\n\n\t\tif (msg.command === \"connect\") {\n\t\t\tawait this.handleConnect(msg);\n\t\t\treturn;\n\t\t}\n\n\t\t// All other message must wait if connect is in progress\n\t\tif (this.msgQueue !== undefined) {\n\t\t\tthis.msgQueue.push(msg);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.processMessage(msg);\n\t}\n\n\tprivate processMessage(\n\t\tmsg: Exclude<MessageFromParent, { command: \"ping\" | \"connect\" }>,\n\t): void {\n\t\tswitch (msg.command) {\n\t\t\tcase \"debugReport\": {\n\t\t\t\tthis.handleDebugReport(msg);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"disconnectSelf\": {\n\t\t\t\tthis.handleDisconnectSelf();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"setLatestValue\": {\n\t\t\t\tthis.handleSetLatestValue(msg);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"setLatestMapValue\": {\n\t\t\t\tthis.handleSetLatestMapValue(msg);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"getLatestValue\": {\n\t\t\t\tthis.handleGetLatestValue(msg);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"getLatestMapValue\": {\n\t\t\t\tthis.handleGetLatestMapValue(msg);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"registerWorkspace\": {\n\t\t\t\tthis.registerWorkspace(msg.workspaceId, {\n\t\t\t\t\tlatest: msg.latest,\n\t\t\t\t\tlatestMap: msg.latestMap,\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tconsole.error(`${process_id}: Unknown command:`, msg);\n\t\t\t\tthis.send({\n\t\t\t\t\tevent: \"error\",\n\t\t\t\t\terror: `${process_id} Unknown command: ${JSON.stringify(msg)}`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate handlePing(): void {\n\t\tthis.send({ event: \"ack\" });\n\t}\n\n\tprivate async handleConnect(\n\t\tmsg: Extract<MessageFromParent, { command: \"connect\" }>,\n\t): Promise<void> {\n\t\tif (!msg.user) {\n\t\t\tthis.send({ event: \"error\", error: `${process_id}: No azure user information given` });\n\t\t\treturn;\n\t\t}\n\t\tif (this.container) {\n\t\t\tthis.send({ event: \"error\", error: `${process_id}: Container already loaded` });\n\t\t\treturn;\n\t\t}\n\n\t\t// Prevent reentrance. Queue messages until after connect is fully processed.\n\t\tthis.msgQueue = [];\n\n\t\ttry {\n\t\t\tconst { container, containerId, connected } = await getOrCreateContainer({\n\t\t\t\t...msg,\n\t\t\t\tlogger: this.logger,\n\t\t\t\tonDisconnected: this.onDisconnected,\n\t\t\t});\n\t\t\tthis.container = container;\n\t\t\tconst presence = getPresence(container);\n\t\t\tthis.presence = presence;\n\n\t\t\t// wait for 'ConnectionState.Connected'\n\t\t\tawait connected;\n\n\t\t\t// Acknowledge connection before sending current attendee information\n\t\t\tthis.send({\n\t\t\t\tevent: \"connected\",\n\t\t\t\tcontainerId,\n\t\t\t\tattendeeId: presence.attendees.getMyself().attendeeId,\n\t\t\t});\n\n\t\t\t// Send existing attendees excluding self to parent/orchestrator\n\t\t\tconst self = presence.attendees.getMyself();\n\t\t\tfor (const attendee of presence.attendees.getAttendees()) {\n\t\t\t\tif (attendee !== self && attendee.getConnectionStatus() === \"Connected\") {\n\t\t\t\t\tthis.sendAttendeeConnected(attendee);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Listen for presence events to notify parent/orchestrator when a new attendee joins or leaves the session.\n\t\t\tpresence.attendees.events.on(\"attendeeConnected\", this.sendAttendeeConnected);\n\t\t\tpresence.attendees.events.on(\"attendeeDisconnected\", this.sendAttendeeDisconnected);\n\t\t} finally {\n\t\t\t// Process any queued messages received while connecting\n\t\t\tfor (const queuedMsg of this.msgQueue) {\n\t\t\t\tthis.processMessage(queuedMsg);\n\t\t\t}\n\t\t\tthis.msgQueue = undefined;\n\t\t}\n\t}\n\n\tprivate handleDebugReport(\n\t\tmsg: Extract<MessageFromParent, { command: \"debugReport\" }>,\n\t): void {\n\t\tif (msg.reportAttendees) {\n\t\t\tif (this.presence) {\n\t\t\t\tconst attendees = this.presence.attendees.getAttendees();\n\t\t\t\tlet connectedCount = 0;\n\t\t\t\tfor (const attendee of attendees) {\n\t\t\t\t\tif (attendee.getConnectionStatus() === \"Connected\") {\n\t\t\t\t\t\tconnectedCount++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[${process_id}] Report: ${attendees.size} attendees, ${connectedCount} connected`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tthis.send({ event: \"error\", error: `${process_id} is not connected to presence` });\n\t\t\t}\n\t\t}\n\n\t\tconst debugReport: Extract<MessageToParent, { event: \"debugReportComplete\" }> = {\n\t\t\tevent: \"debugReportComplete\",\n\t\t};\n\t\tif (msg.sendEventLog) {\n\t\t\tdebugReport.log = this.log;\n\t\t}\n\t\tthis.send(debugReport);\n\t}\n\n\tprivate handleDisconnectSelf(): void {\n\t\tif (!this.container) {\n\t\t\tthis.send({ event: \"error\", error: `${process_id} is not connected to container` });\n\t\t\treturn;\n\t\t}\n\t\t// There are no current scenarios where disconnect without presence is expected.\n\t\tif (!this.presence) {\n\t\t\tthis.send({ event: \"error\", error: `${process_id} is not connected to presence` });\n\t\t\treturn;\n\t\t}\n\t\t// Disconnect event is treated as an error in normal handling.\n\t\t// Remove listener as this disconnect is intentional.\n\t\tthis.container.off(\"disconnected\", this.onDisconnected);\n\t\tthis.container.disconnect();\n\t\tthis.send({\n\t\t\tevent: \"disconnectedSelf\",\n\t\t\tattendeeId: this.presence.attendees.getMyself().attendeeId,\n\t\t});\n\t}\n\n\tprivate handleSetLatestValue(\n\t\tmsg: Extract<MessageFromParent, { command: \"setLatestValue\" }>,\n\t): void {\n\t\tif (!this.presence) {\n\t\t\tthis.send({ event: \"error\", error: `${process_id} is not connected to presence` });\n\t\t\treturn;\n\t\t}\n\t\tconst workspace = this.workspaces.get(msg.workspaceId);\n\t\tif (!workspace) {\n\t\t\tthis.send({\n\t\t\t\tevent: \"error\",\n\t\t\t\terror: `${process_id} workspace ${msg.workspaceId} not found`,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\t// Cast required due to optional keys in WorkspaceSchema\n\t\t// TODO: AB#47518\n\t\tconst latestState = workspace.states.latest as LatestRaw<{ value: string }> | undefined;\n\t\tif (!latestState) {\n\t\t\tthis.send({\n\t\t\t\tevent: \"error\",\n\t\t\t\terror: `${process_id} latest state not registered for workspace ${msg.workspaceId}`,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tif (typeof msg.value !== \"string\") {\n\t\t\treturn;\n\t\t}\n\t\tlatestState.local = { value: msg.value };\n\t}\n\n\tprivate handleSetLatestMapValue(\n\t\tmsg: Extract<MessageFromParent, { command: \"setLatestMapValue\" }>,\n\t): void {\n\t\tif (!this.presence) {\n\t\t\tthis.send({ event: \"error\", error: `${process_id} is not connected to presence` });\n\t\t\treturn;\n\t\t}\n\t\tif (typeof msg.key !== \"string\") {\n\t\t\tthis.send({ event: \"error\", error: `${process_id} invalid key type` });\n\t\t\treturn;\n\t\t}\n\t\tconst workspace = this.workspaces.get(msg.workspaceId);\n\t\tif (!workspace) {\n\t\t\tthis.send({\n\t\t\t\tevent: \"error\",\n\t\t\t\terror: `${process_id} workspace ${msg.workspaceId} not found`,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\t// Cast required due to optional keys in WorkspaceSchema\n\t\t// TODO: AB#47518\n\t\tconst latestMapState = workspace.states.latestMap as\n\t\t\t| LatestMapRaw<{ value: Record<string, string | number> }, string>\n\t\t\t| undefined;\n\t\tif (!latestMapState) {\n\t\t\tthis.send({\n\t\t\t\tevent: \"error\",\n\t\t\t\terror: `${process_id} latestMap state not registered for workspace ${msg.workspaceId}`,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tif (!isStringOrNumberRecord(msg.value)) {\n\t\t\treturn;\n\t\t}\n\t\tlatestMapState.local.set(msg.key, { value: msg.value });\n\t}\n\n\tprivate handleGetLatestValue(\n\t\tmsg: Extract<MessageFromParent, { command: \"getLatestValue\" }>,\n\t): void {\n\t\tif (!this.presence) {\n\t\t\tthis.send({ event: \"error\", error: `${process_id} is not connected to presence` });\n\t\t\treturn;\n\t\t}\n\t\tconst workspace = this.workspaces.get(msg.workspaceId);\n\t\tif (!workspace) {\n\t\t\tthis.send({\n\t\t\t\tevent: \"error\",\n\t\t\t\terror: `${process_id} workspace ${msg.workspaceId} not found`,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\t// Cast required due to optional keys in WorkspaceSchema\n\t\t// TODO: AB#47518\n\t\tconst latestState = workspace.states.latest as LatestRaw<{ value: string }> | undefined;\n\t\tif (!latestState) {\n\t\t\tthis.send({\n\t\t\t\tevent: \"error\",\n\t\t\t\terror: `${process_id} latest state not registered for workspace ${msg.workspaceId}`,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tlet value: { value: string };\n\t\tif (msg.attendeeId) {\n\t\t\tconst attendee = this.presence.attendees.getAttendee(msg.attendeeId);\n\t\t\tconst remoteData = latestState.getRemote(attendee);\n\t\t\tvalue = remoteData.value;\n\t\t} else {\n\t\t\tvalue = latestState.local;\n\t\t}\n\t\tthis.send({\n\t\t\tevent: \"latestValueGetResponse\",\n\t\t\tworkspaceId: msg.workspaceId,\n\t\t\tattendeeId: msg.attendeeId,\n\t\t\tvalue: value.value,\n\t\t});\n\t}\n\n\tprivate handleGetLatestMapValue(\n\t\tmsg: Extract<MessageFromParent, { command: \"getLatestMapValue\" }>,\n\t): void {\n\t\tif (!this.presence) {\n\t\t\tthis.send({ event: \"error\", error: `${process_id} is not connected to presence` });\n\t\t\treturn;\n\t\t}\n\t\tif (typeof msg.key !== \"string\") {\n\t\t\tthis.send({ event: \"error\", error: `${process_id} invalid key type` });\n\t\t\treturn;\n\t\t}\n\t\tconst workspace = this.workspaces.get(msg.workspaceId);\n\t\tif (!workspace) {\n\t\t\tthis.send({\n\t\t\t\tevent: \"error\",\n\t\t\t\terror: `${process_id} workspace ${msg.workspaceId} not found`,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\t// Cast required due to optional keys in WorkspaceSchema\n\t\t// TODO: AB#47518\n\t\tconst latestMapState = workspace.states.latestMap as\n\t\t\t| LatestMapRaw<{ value: Record<string, string | number> }, string>\n\t\t\t| undefined;\n\t\tif (!latestMapState) {\n\t\t\tthis.send({\n\t\t\t\tevent: \"error\",\n\t\t\t\terror: `${process_id} latestMap state not registered for workspace ${msg.workspaceId}`,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tlet value: { value: Record<string, string | number> } | undefined;\n\t\tif (msg.attendeeId) {\n\t\t\tconst attendee = this.presence.attendees.getAttendee(msg.attendeeId);\n\t\t\tconst remoteData = latestMapState.getRemote(attendee);\n\t\t\tconst keyData = remoteData.get(msg.key);\n\t\t\tvalue = keyData?.value;\n\t\t} else {\n\t\t\tvalue = latestMapState.local.get(msg.key);\n\t\t}\n\t\tthis.send({\n\t\t\tevent: \"latestMapValueGetResponse\",\n\t\t\tworkspaceId: msg.workspaceId,\n\t\t\tattendeeId: msg.attendeeId,\n\t\t\tkey: msg.key,\n\t\t\tvalue: value?.value,\n\t\t});\n\t}\n}\n\nfunction setupMessageHandler(): void {\n\tconst messageHandler = new MessageHandler();\n\tprocess.on(\"message\", (msg: MessageFromParent) => {\n\t\tmessageHandler.onMessage(msg).catch((error: Error) => {\n\t\t\tconsole.error(`Error in client ${process_id}`, error);\n\t\t\tsend({ event: \"error\", error: `${process_id}: ${error.message}` });\n\t\t});\n\t});\n}\n\nsetupMessageHandler();\n"]}
1
+ {"version":3,"file":"childClient.tool.js","sourceRoot":"","sources":["../../../src/test/multiprocess/childClient.tool.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 \"node:assert\";\n\nimport {\n\tAzureClient,\n\ttype AzureContainerServices,\n\ttype AzureLocalConnectionConfig,\n\ttype AzureRemoteConnectionConfig,\n\ttype ITelemetryBaseEvent,\n} from \"@fluidframework/azure-client\";\nimport { AttachState } from \"@fluidframework/container-definitions\";\nimport { ConnectionState } from \"@fluidframework/container-loader\";\nimport type { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { LogLevel } from \"@fluidframework/core-interfaces\";\nimport type { ScopeType } from \"@fluidframework/driver-definitions/legacy\";\nimport type { ContainerSchema, IFluidContainer } from \"@fluidframework/fluid-static\";\nimport {\n\tgetPresence,\n\ttype Attendee,\n\ttype Presence,\n\tStateFactory,\n\ttype LatestRaw,\n\ttype LatestMapRaw,\n\ttype StatesWorkspace,\n} from \"@fluidframework/presence/beta\";\nimport { InsecureTokenProvider } from \"@fluidframework/test-runtime-utils/internal\";\nimport { timeoutPromise } from \"@fluidframework/test-utils/internal\";\n\nimport { createAzureTokenProvider } from \"../AzureTokenFactory.js\";\nimport { TestDataObject } from \"../TestDataObject.js\";\n\nimport type {\n\tMessageFromChild as MessageToParent,\n\tMessageToChild as MessageFromParent,\n\tUserIdAndName,\n\tEventEntry,\n} from \"./messageTypes.js\";\n\nconst testLabel = process.argv[2];\n// Identifier given to child process\nconst process_id = process.argv[3];\nconst verbosity = process.argv[4] ?? \"\";\n\nconst useAzure = process.env.FLUID_CLIENT === \"azure\";\nconst tenantId = useAzure\n\t? (process.env.azure__fluid__relay__service__tenantId as string)\n\t: \"frs-client-tenant\";\nconst endPoint = process.env.azure__fluid__relay__service__endpoint as string;\nif (useAzure && endPoint === undefined) {\n\tthrow new Error(\"Azure Fluid Relay service endpoint is missing\");\n}\n\nconst containerSchema = {\n\tinitialObjects: {\n\t\t// A DataObject is added as otherwise fluid-static complains \"Container cannot be initialized without any DataTypes\"\n\t\t_unused: TestDataObject,\n\t},\n} as const satisfies ContainerSchema;\n\nfunction log(...data: unknown[]): void {\n\tconsole.log(`[${testLabel}] [${new Date().toISOString()}] [${process_id}]`, ...data);\n}\n\nfunction telemetryEventInterestLevel(eventName: string): \"none\" | \"basic\" | \"details\" {\n\tif (eventName.includes(\":Signal\") || eventName.includes(\":Join\")) {\n\t\treturn \"details\";\n\t} else if (eventName.includes(\":Container:\") || eventName.includes(\":Presence:\")) {\n\t\treturn \"basic\";\n\t}\n\treturn \"none\";\n}\n\nfunction selectiveVerboseLog(event: ITelemetryBaseEvent, logLevel?: LogLevel): void {\n\tconst interest = telemetryEventInterestLevel(event.eventName);\n\tif (interest === \"none\") {\n\t\treturn;\n\t}\n\tconst content: Record<string, unknown> = {\n\t\teventName: event.eventName,\n\t\tcontainerConnectionState: event.containerConnectionState,\n\t};\n\tif (interest === \"details\") {\n\t\tcontent.details = event.details;\n\t}\n\tlog(`[${logLevel ?? LogLevel.default}]`, content);\n}\n\n/**\n * Get or create a Fluid container.\n */\nconst getOrCreateContainer = async (params: {\n\tlogger: ITelemetryBaseLogger;\n\tonDisconnected: () => void;\n\tcontainerId?: string;\n\tuser: UserIdAndName;\n\tscopes?: ScopeType[];\n\tcreateScopes?: ScopeType[];\n\tconnectTimeoutMs: number;\n}): Promise<{\n\tcontainer: IFluidContainer<typeof containerSchema>;\n\tservices: AzureContainerServices;\n\tclient: AzureClient;\n\tcontainerId: string;\n\tconnected: Promise<void>;\n}> => {\n\tlet container: IFluidContainer<typeof containerSchema>;\n\tlet { containerId } = params;\n\tconst { logger, onDisconnected, user, scopes, createScopes, connectTimeoutMs } = params;\n\tconst connectionProps: AzureRemoteConnectionConfig | AzureLocalConnectionConfig = useAzure\n\t\t? {\n\t\t\t\ttenantId,\n\t\t\t\ttokenProvider: createAzureTokenProvider(\n\t\t\t\t\tuser.id ?? \"foo\",\n\t\t\t\t\tuser.name ?? \"bar\",\n\t\t\t\t\tscopes,\n\t\t\t\t\tcreateScopes,\n\t\t\t\t),\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, createScopes),\n\t\t\t\tendpoint: \"http://localhost:7071\",\n\t\t\t\ttype: \"local\",\n\t\t\t};\n\tconst client = new AzureClient({\n\t\tconnection: connectionProps,\n\t\tlogger,\n\t});\n\tlet services: AzureContainerServices;\n\tif (containerId === undefined) {\n\t\t({ container, services } = await client.createContainer(containerSchema, \"2\"));\n\t\tcontainerId = await container.attach();\n\t} else {\n\t\t({ container, services } = await client.getContainer(containerId, containerSchema, \"2\"));\n\t}\n\tcontainer.on(\"disconnected\", onDisconnected);\n\n\tconst connected =\n\t\tcontainer.connectionState === ConnectionState.Connected\n\t\t\t? Promise.resolve()\n\t\t\t: timeoutPromise((resolve) => container.once(\"connected\", () => resolve()), {\n\t\t\t\t\tdurationMs: connectTimeoutMs,\n\t\t\t\t\terrorMsg: \"container connect() timeout\",\n\t\t\t\t});\n\n\tassert.strictEqual(\n\t\tcontainer.attachState,\n\t\tAttachState.Attached,\n\t\t\"Container is not attached after attach is called\",\n\t);\n\n\treturn {\n\t\tclient,\n\t\tcontainer,\n\t\tservices,\n\t\tcontainerId,\n\t\tconnected,\n\t};\n};\n\nfunction createSendFunction(): (msg: MessageToParent) => void {\n\tif (process.send) {\n\t\tconst sendFn = process.send.bind(process);\n\t\tif (verbosity.includes(\"msgs\")) {\n\t\t\treturn (msg: MessageToParent) => {\n\t\t\t\tlog(`Sending`, msg);\n\t\t\t\tsendFn(msg);\n\t\t\t};\n\t\t}\n\t\treturn sendFn;\n\t}\n\tthrow new Error(\"process.send is not defined\");\n}\n\nconst send = createSendFunction();\n\nfunction isStringOrNumberRecord(value: unknown): value is Record<string, string | number> {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n\t\treturn false;\n\t}\n\n\tconst stringKeys = Object.keys(value);\n\tconst allKeys = Reflect.ownKeys(value);\n\n\tif (stringKeys.length !== allKeys.length) {\n\t\t// If there are non-string/symbol keys, return false\n\t\treturn false;\n\t}\n\tfor (const key of stringKeys) {\n\t\tif (!(typeof value[key] === \"string\" || typeof value[key] === \"number\")) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n// NOTE:\n// - This schema intentionally uses optional keys (latest?, latestMap?) so tests can register\n// states conditionally at runtime.\n// - Optional keys are not explicitly supported in StatesWorkspace typing today, which means\n// workspace.states.<key> is typed as any. As a result, usages below require casts\n// (e.g., to LatestRaw / LatestMapRaw) to recover concrete types.\n// - Track adding proper optional-key support to Presence state workspace typing here:\n// Work item: AB#47518\n// - Fallout: Until the above is addressed, keep the casts in place and document new usages accordingly.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\ntype WorkspaceSchema = {\n\tlatest?: ReturnType<typeof StateFactory.latest<{ value: string }>>;\n\tlatestMap?: ReturnType<\n\t\ttypeof StateFactory.latestMap<{ value: Record<string, string | number> }, string>\n\t>;\n};\nconst WorkspaceSchema: WorkspaceSchema = {};\n\nclass MessageHandler {\n\tprivate readonly log: EventEntry[] = [];\n\tprivate msgQueue: undefined | Exclude<MessageFromParent, { command: \"ping\" | \"connect\" }>[];\n\tprivate container: IFluidContainer | undefined;\n\tprivate presence: Presence | undefined;\n\tprivate readonly workspaces = new Map<string, StatesWorkspace<WorkspaceSchema>>();\n\n\tprivate send(msg: MessageToParent): void {\n\t\tthis.log.push({\n\t\t\ttimestamp: Date.now(),\n\t\t\tagentId: process_id,\n\t\t\teventCategory: \"messageSent\",\n\t\t\teventName: msg.event,\n\t\t\tdetails:\n\t\t\t\tmsg.event === \"debugReportComplete\" && msg.log\n\t\t\t\t\t? JSON.stringify({ logLength: msg.log.length })\n\t\t\t\t\t: JSON.stringify(msg),\n\t\t});\n\t\tsend(msg);\n\t}\n\n\tprivate readonly sendAttendeeConnected = (attendee: Attendee): void => {\n\t\tthis.send({\n\t\t\tevent: \"attendeeConnected\",\n\t\t\tattendeeId: attendee.attendeeId,\n\t\t});\n\t};\n\tprivate readonly sendAttendeeDisconnected = (attendee: Attendee): void => {\n\t\tthis.send({\n\t\t\tevent: \"attendeeDisconnected\",\n\t\t\tattendeeId: attendee.attendeeId,\n\t\t});\n\t};\n\n\tprivate readonly logger: ITelemetryBaseLogger = {\n\t\tsend: (event: ITelemetryBaseEvent, logLevel?: LogLevel) => {\n\t\t\t// Filter out non-interactive client telemetry\n\t\t\tconst clientType = event.clientType;\n\t\t\tif (typeof clientType === \"string\" && clientType.startsWith(\"noninteractive\")) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Special case unexpected telemetry event\n\t\t\tif (event.eventName.endsWith(\":JoinResponseWhenAlone\")) {\n\t\t\t\tthis.send({\n\t\t\t\t\tevent: \"error\",\n\t\t\t\t\terror: `Unexpected ClientJoin response. Details: ${JSON.stringify(event.details)}\\nLog: ${JSON.stringify(this.log)}`,\n\t\t\t\t});\n\t\t\t\t// Keep going\n\t\t\t}\n\n\t\t\tconst interest = telemetryEventInterestLevel(event.eventName);\n\t\t\tif (interest === \"none\") {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.log.push({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tagentId: process_id,\n\t\t\t\teventCategory: \"telemetry\",\n\t\t\t\teventName: event.eventName,\n\t\t\t\tdetails:\n\t\t\t\t\ttypeof event.details === \"string\" ? event.details : JSON.stringify(event.details),\n\t\t\t});\n\t\t\tif (verbosity.includes(\"telem\")) {\n\t\t\t\tselectiveVerboseLog(event, logLevel);\n\t\t\t}\n\t\t},\n\t};\n\n\tprivate readonly onDisconnected = (): void => {\n\t\t// Test state is a bit fragile and does not account for reconnections.\n\t\tthis.send({ event: \"error\", error: `${process_id}: Container disconnected` });\n\t};\n\n\tprivate registerWorkspace(\n\t\tworkspaceId: string,\n\t\toptions: { latest?: boolean; latestMap?: boolean },\n\t): void {\n\t\tif (!this.presence) {\n\t\t\tthis.send({ event: \"error\", error: `${process_id} is not connected to presence` });\n\t\t\treturn;\n\t\t}\n\t\tconst { latest, latestMap } = options;\n\t\tconst workspace: StatesWorkspace<WorkspaceSchema> = this.presence.states.getWorkspace(\n\t\t\t`test:${workspaceId}`,\n\t\t\tWorkspaceSchema,\n\t\t);\n\n\t\tif (latest && !workspace.states.latest) {\n\t\t\tworkspace.add(\n\t\t\t\t\"latest\",\n\t\t\t\tStateFactory.latest<{ value: string }>({ local: { value: \"initial\" } }),\n\t\t\t);\n\t\t\t// Cast required due to optional keys in WorkspaceSchema\n\t\t\t// TODO: AB#47518\n\t\t\tconst latestState = workspace.states.latest as LatestRaw<{ value: string }>;\n\t\t\tlatestState.events.on(\"remoteUpdated\", (update) => {\n\t\t\t\tthis.send({\n\t\t\t\t\tevent: \"latestValueUpdated\",\n\t\t\t\t\tworkspaceId,\n\t\t\t\t\tattendeeId: update.attendee.attendeeId,\n\t\t\t\t\tvalue: update.value.value,\n\t\t\t\t});\n\t\t\t});\n\t\t\tfor (const remote of latestState.getRemotes()) {\n\t\t\t\tthis.send({\n\t\t\t\t\tevent: \"latestValueUpdated\",\n\t\t\t\t\tworkspaceId,\n\t\t\t\t\tattendeeId: remote.attendee.attendeeId,\n\t\t\t\t\tvalue: remote.value.value,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tif (latestMap && !workspace.states.latestMap) {\n\t\t\tworkspace.add(\n\t\t\t\t\"latestMap\",\n\t\t\t\tStateFactory.latestMap<{ value: Record<string, string | number> }, string>({\n\t\t\t\t\tlocal: {},\n\t\t\t\t}),\n\t\t\t);\n\t\t\t// Cast required due to optional keys in WorkspaceSchema\n\t\t\t// TODO: AB#47518\n\t\t\tconst latestMapState = workspace.states.latestMap as LatestMapRaw<\n\t\t\t\t{ value: Record<string, string | number> },\n\t\t\t\tstring\n\t\t\t>;\n\t\t\tlatestMapState.events.on(\"remoteUpdated\", (update) => {\n\t\t\t\tfor (const [key, valueWithMetadata] of update.items) {\n\t\t\t\t\tthis.send({\n\t\t\t\t\t\tevent: \"latestMapValueUpdated\",\n\t\t\t\t\t\tworkspaceId,\n\t\t\t\t\t\tattendeeId: update.attendee.attendeeId,\n\t\t\t\t\t\tkey: String(key),\n\t\t\t\t\t\tvalue: valueWithMetadata.value.value,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t\tfor (const remote of latestMapState.getRemotes()) {\n\t\t\t\tfor (const [key, valueWithMetadata] of remote.items) {\n\t\t\t\t\tthis.send({\n\t\t\t\t\t\tevent: \"latestMapValueUpdated\",\n\t\t\t\t\t\tworkspaceId,\n\t\t\t\t\t\tattendeeId: remote.attendee.attendeeId,\n\t\t\t\t\t\tkey: String(key),\n\t\t\t\t\t\tvalue: valueWithMetadata.value.value,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.workspaces.set(workspaceId, workspace);\n\t\tthis.send({\n\t\t\tevent: \"workspaceRegistered\",\n\t\t\tworkspaceId,\n\t\t\tlatest: latest ?? false,\n\t\t\tlatestMap: latestMap ?? false,\n\t\t});\n\t}\n\n\tpublic async onMessage(msg: MessageFromParent): Promise<void> {\n\t\tif (verbosity.includes(\"msgs\")) {\n\t\t\tthis.log.push({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tagentId: process_id,\n\t\t\t\teventCategory: \"messageReceived\",\n\t\t\t\teventName: msg.command,\n\t\t\t});\n\t\t\tlog(`Received`, msg);\n\t\t}\n\n\t\tif (msg.command === \"ping\") {\n\t\t\tthis.handlePing();\n\t\t\treturn;\n\t\t}\n\n\t\tif (msg.command === \"connect\") {\n\t\t\tawait this.handleConnect(msg);\n\t\t\treturn;\n\t\t}\n\n\t\t// All other message must wait if connect is in progress\n\t\tif (this.msgQueue !== undefined) {\n\t\t\tthis.msgQueue.push(msg);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.processMessage(msg);\n\t}\n\n\tprivate processMessage(\n\t\tmsg: Exclude<MessageFromParent, { command: \"ping\" | \"connect\" }>,\n\t): void {\n\t\tswitch (msg.command) {\n\t\t\tcase \"debugReport\": {\n\t\t\t\tthis.handleDebugReport(msg);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"disconnectSelf\": {\n\t\t\t\tthis.handleDisconnectSelf();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"setLatestValue\": {\n\t\t\t\tthis.handleSetLatestValue(msg);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"setLatestMapValue\": {\n\t\t\t\tthis.handleSetLatestMapValue(msg);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"getLatestValue\": {\n\t\t\t\tthis.handleGetLatestValue(msg);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"getLatestMapValue\": {\n\t\t\t\tthis.handleGetLatestMapValue(msg);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"registerWorkspace\": {\n\t\t\t\tthis.registerWorkspace(msg.workspaceId, {\n\t\t\t\t\tlatest: msg.latest,\n\t\t\t\t\tlatestMap: msg.latestMap,\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tconsole.error(`${process_id}: Unknown command:`, msg);\n\t\t\t\tthis.send({\n\t\t\t\t\tevent: \"error\",\n\t\t\t\t\terror: `${process_id} Unknown command: ${JSON.stringify(msg)}`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate handlePing(): void {\n\t\tthis.send({ event: \"ack\" });\n\t}\n\n\tprivate async handleConnect(\n\t\tmsg: Extract<MessageFromParent, { command: \"connect\" }>,\n\t): Promise<void> {\n\t\tif (!msg.user) {\n\t\t\tthis.send({ event: \"error\", error: `${process_id}: No azure user information given` });\n\t\t\treturn;\n\t\t}\n\t\tif (this.container) {\n\t\t\tthis.send({ event: \"error\", error: `${process_id}: Container already loaded` });\n\t\t\treturn;\n\t\t}\n\n\t\t// Prevent reentrance. Queue messages until after connect is fully processed.\n\t\tthis.msgQueue = [];\n\n\t\ttry {\n\t\t\tconst { container, containerId, connected } = await getOrCreateContainer({\n\t\t\t\t...msg,\n\t\t\t\tlogger: this.logger,\n\t\t\t\tonDisconnected: this.onDisconnected,\n\t\t\t});\n\t\t\tthis.container = container;\n\t\t\tconst presence = getPresence(container);\n\t\t\tthis.presence = presence;\n\n\t\t\t// wait for 'ConnectionState.Connected'\n\t\t\tawait connected.catch((error) => {\n\t\t\t\t(error as Error).message += `\\nLog: ${JSON.stringify(this.log)}`;\n\t\t\t\tthrow error;\n\t\t\t});\n\n\t\t\t// Acknowledge connection before sending current attendee information\n\t\t\tthis.send({\n\t\t\t\tevent: \"connected\",\n\t\t\t\tcontainerId,\n\t\t\t\tattendeeId: presence.attendees.getMyself().attendeeId,\n\t\t\t});\n\n\t\t\t// Send existing attendees excluding self to parent/orchestrator\n\t\t\tconst self = presence.attendees.getMyself();\n\t\t\tfor (const attendee of presence.attendees.getAttendees()) {\n\t\t\t\tif (attendee !== self && attendee.getConnectionStatus() === \"Connected\") {\n\t\t\t\t\tthis.sendAttendeeConnected(attendee);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Listen for presence events to notify parent/orchestrator when a new attendee joins or leaves the session.\n\t\t\tpresence.attendees.events.on(\"attendeeConnected\", this.sendAttendeeConnected);\n\t\t\tpresence.attendees.events.on(\"attendeeDisconnected\", this.sendAttendeeDisconnected);\n\t\t} finally {\n\t\t\t// Process any queued messages received while connecting\n\t\t\tfor (const queuedMsg of this.msgQueue) {\n\t\t\t\tthis.processMessage(queuedMsg);\n\t\t\t}\n\t\t\tthis.msgQueue = undefined;\n\t\t}\n\t}\n\n\tprivate handleDebugReport(\n\t\tmsg: Extract<MessageFromParent, { command: \"debugReport\" }>,\n\t): void {\n\t\tif (msg.reportAttendees) {\n\t\t\tif (this.presence) {\n\t\t\t\tconst attendees = this.presence.attendees.getAttendees();\n\t\t\t\tlet connectedCount = 0;\n\t\t\t\tfor (const attendee of attendees) {\n\t\t\t\t\tif (attendee.getConnectionStatus() === \"Connected\") {\n\t\t\t\t\t\tconnectedCount++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlog(`Report: ${attendees.size} attendees, ${connectedCount} connected`);\n\t\t\t} else {\n\t\t\t\tthis.send({ event: \"error\", error: `${process_id} is not connected to presence` });\n\t\t\t}\n\t\t}\n\n\t\tconst debugReport: Extract<MessageToParent, { event: \"debugReportComplete\" }> = {\n\t\t\tevent: \"debugReportComplete\",\n\t\t};\n\t\tif (msg.sendEventLog) {\n\t\t\tdebugReport.log = this.log;\n\t\t}\n\t\tthis.send(debugReport);\n\t}\n\n\tprivate handleDisconnectSelf(): void {\n\t\tif (!this.container) {\n\t\t\tthis.send({ event: \"error\", error: `${process_id} is not connected to container` });\n\t\t\treturn;\n\t\t}\n\t\t// There are no current scenarios where disconnect without presence is expected.\n\t\tif (!this.presence) {\n\t\t\tthis.send({ event: \"error\", error: `${process_id} is not connected to presence` });\n\t\t\treturn;\n\t\t}\n\t\t// Disconnect event is treated as an error in normal handling.\n\t\t// Remove listener as this disconnect is intentional.\n\t\tthis.container.off(\"disconnected\", this.onDisconnected);\n\t\tthis.container.disconnect();\n\t\tthis.send({\n\t\t\tevent: \"disconnectedSelf\",\n\t\t\tattendeeId: this.presence.attendees.getMyself().attendeeId,\n\t\t});\n\t}\n\n\tprivate handleSetLatestValue(\n\t\tmsg: Extract<MessageFromParent, { command: \"setLatestValue\" }>,\n\t): void {\n\t\tif (!this.presence) {\n\t\t\tthis.send({ event: \"error\", error: `${process_id} is not connected to presence` });\n\t\t\treturn;\n\t\t}\n\t\tconst workspace = this.workspaces.get(msg.workspaceId);\n\t\tif (!workspace) {\n\t\t\tthis.send({\n\t\t\t\tevent: \"error\",\n\t\t\t\terror: `${process_id} workspace ${msg.workspaceId} not found`,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\t// Cast required due to optional keys in WorkspaceSchema\n\t\t// TODO: AB#47518\n\t\tconst latestState = workspace.states.latest as LatestRaw<{ value: string }> | undefined;\n\t\tif (!latestState) {\n\t\t\tthis.send({\n\t\t\t\tevent: \"error\",\n\t\t\t\terror: `${process_id} latest state not registered for workspace ${msg.workspaceId}`,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tif (typeof msg.value !== \"string\") {\n\t\t\treturn;\n\t\t}\n\t\tlatestState.local = { value: msg.value };\n\t}\n\n\tprivate handleSetLatestMapValue(\n\t\tmsg: Extract<MessageFromParent, { command: \"setLatestMapValue\" }>,\n\t): void {\n\t\tif (!this.presence) {\n\t\t\tthis.send({ event: \"error\", error: `${process_id} is not connected to presence` });\n\t\t\treturn;\n\t\t}\n\t\tif (typeof msg.key !== \"string\") {\n\t\t\tthis.send({ event: \"error\", error: `${process_id} invalid key type` });\n\t\t\treturn;\n\t\t}\n\t\tconst workspace = this.workspaces.get(msg.workspaceId);\n\t\tif (!workspace) {\n\t\t\tthis.send({\n\t\t\t\tevent: \"error\",\n\t\t\t\terror: `${process_id} workspace ${msg.workspaceId} not found`,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\t// Cast required due to optional keys in WorkspaceSchema\n\t\t// TODO: AB#47518\n\t\tconst latestMapState = workspace.states.latestMap as\n\t\t\t| LatestMapRaw<{ value: Record<string, string | number> }, string>\n\t\t\t| undefined;\n\t\tif (!latestMapState) {\n\t\t\tthis.send({\n\t\t\t\tevent: \"error\",\n\t\t\t\terror: `${process_id} latestMap state not registered for workspace ${msg.workspaceId}`,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tif (!isStringOrNumberRecord(msg.value)) {\n\t\t\treturn;\n\t\t}\n\t\tlatestMapState.local.set(msg.key, { value: msg.value });\n\t}\n\n\tprivate handleGetLatestValue(\n\t\tmsg: Extract<MessageFromParent, { command: \"getLatestValue\" }>,\n\t): void {\n\t\tif (!this.presence) {\n\t\t\tthis.send({ event: \"error\", error: `${process_id} is not connected to presence` });\n\t\t\treturn;\n\t\t}\n\t\tconst workspace = this.workspaces.get(msg.workspaceId);\n\t\tif (!workspace) {\n\t\t\tthis.send({\n\t\t\t\tevent: \"error\",\n\t\t\t\terror: `${process_id} workspace ${msg.workspaceId} not found`,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\t// Cast required due to optional keys in WorkspaceSchema\n\t\t// TODO: AB#47518\n\t\tconst latestState = workspace.states.latest as LatestRaw<{ value: string }> | undefined;\n\t\tif (!latestState) {\n\t\t\tthis.send({\n\t\t\t\tevent: \"error\",\n\t\t\t\terror: `${process_id} latest state not registered for workspace ${msg.workspaceId}`,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tlet value: { value: string };\n\t\tif (msg.attendeeId) {\n\t\t\tconst attendee = this.presence.attendees.getAttendee(msg.attendeeId);\n\t\t\tconst remoteData = latestState.getRemote(attendee);\n\t\t\tvalue = remoteData.value;\n\t\t} else {\n\t\t\tvalue = latestState.local;\n\t\t}\n\t\tthis.send({\n\t\t\tevent: \"latestValueGetResponse\",\n\t\t\tworkspaceId: msg.workspaceId,\n\t\t\tattendeeId: msg.attendeeId,\n\t\t\tvalue: value.value,\n\t\t});\n\t}\n\n\tprivate handleGetLatestMapValue(\n\t\tmsg: Extract<MessageFromParent, { command: \"getLatestMapValue\" }>,\n\t): void {\n\t\tif (!this.presence) {\n\t\t\tthis.send({ event: \"error\", error: `${process_id} is not connected to presence` });\n\t\t\treturn;\n\t\t}\n\t\tif (typeof msg.key !== \"string\") {\n\t\t\tthis.send({ event: \"error\", error: `${process_id} invalid key type` });\n\t\t\treturn;\n\t\t}\n\t\tconst workspace = this.workspaces.get(msg.workspaceId);\n\t\tif (!workspace) {\n\t\t\tthis.send({\n\t\t\t\tevent: \"error\",\n\t\t\t\terror: `${process_id} workspace ${msg.workspaceId} not found`,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\t// Cast required due to optional keys in WorkspaceSchema\n\t\t// TODO: AB#47518\n\t\tconst latestMapState = workspace.states.latestMap as\n\t\t\t| LatestMapRaw<{ value: Record<string, string | number> }, string>\n\t\t\t| undefined;\n\t\tif (!latestMapState) {\n\t\t\tthis.send({\n\t\t\t\tevent: \"error\",\n\t\t\t\terror: `${process_id} latestMap state not registered for workspace ${msg.workspaceId}`,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tlet value: { value: Record<string, string | number> } | undefined;\n\t\tif (msg.attendeeId) {\n\t\t\tconst attendee = this.presence.attendees.getAttendee(msg.attendeeId);\n\t\t\tconst remoteData = latestMapState.getRemote(attendee);\n\t\t\tconst keyData = remoteData.get(msg.key);\n\t\t\tvalue = keyData?.value;\n\t\t} else {\n\t\t\tvalue = latestMapState.local.get(msg.key);\n\t\t}\n\t\tthis.send({\n\t\t\tevent: \"latestMapValueGetResponse\",\n\t\t\tworkspaceId: msg.workspaceId,\n\t\t\tattendeeId: msg.attendeeId,\n\t\t\tkey: msg.key,\n\t\t\tvalue: value?.value,\n\t\t});\n\t}\n}\n\nfunction setupMessageHandler(): void {\n\tconst messageHandler = new MessageHandler();\n\tprocess.on(\"message\", (msg: MessageFromParent) => {\n\t\tmessageHandler.onMessage(msg).catch((error: Error) => {\n\t\t\tconsole.error(`[${testLabel}] Error in client ${process_id}`, error);\n\t\t\tsend({ event: \"error\", error: `${process_id}: ${error.message}` });\n\t\t});\n\t});\n}\n\nsetupMessageHandler();\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"messageTypes.js","sourceRoot":"","sources":["../../../src/test/multiprocess/messageTypes.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n// eslint-disable-next-line import/no-internal-modules\nimport type { JsonSerializable } from \"@fluidframework/core-interfaces/internal\";\nimport type { ScopeType } from \"@fluidframework/driver-definitions/legacy\";\nimport type { AttendeeId } from \"@fluidframework/presence/beta\";\n\nexport interface UserIdAndName {\n\tid: string;\n\tname: string;\n}\n\nexport interface EventEntry {\n\ttimestamp: number;\n\tagentId: string;\n\teventCategory: string;\n\teventName: string;\n\tdetails?: string;\n}\n\n/**\n * Message types sent from the orchestrator to the child processes\n */\nexport type MessageToChild =\n\t| ConnectCommand\n\t| DebugReportCommand\n\t| DisconnectSelfCommand\n\t| RegisterWorkspaceCommand\n\t| GetLatestValueCommand\n\t| GetLatestMapValueCommand\n\t| SetLatestValueCommand\n\t| SetLatestMapValueCommand\n\t| PingCommand;\n\n/**\n * Can be sent to check child responsiveness.\n * An {@link AcknowledgeEvent} should be expected in response.\n */\ninterface PingCommand {\n\tcommand: \"ping\";\n}\n\n/**\n * Instructs a child process to connect to a Fluid container.\n * A {@link ConnectedEvent} should be expected in response.\n */\nexport interface ConnectCommand {\n\tcommand: \"connect\";\n\tuser: UserIdAndName;\n\tscopes: ScopeType[];\n\tcreateScopes?: ScopeType[];\n\t/**\n\t * The ID of the Fluid container to connect to.\n\t * If not provided, a new Fluid container will be created.\n\t */\n\tcontainerId?: string;\n}\n\n/**\n * Instructs a child process to report debug information.\n *\n * @privateRemarks\n * This can be expanded over time to include more options.\n */\ninterface DebugReportCommand {\n\tcommand: \"debugReport\";\n\t/**\n\t * Send event log entries.\n\t */\n\tsendEventLog?: true;\n\t/**\n\t * Send basic attendee statistics (like count of connected).\n\t */\n\treportAttendees?: true;\n}\n\n/**\n * Instructs a child process to disconnect from a Fluid container.\n * A {@link DisconnectedSelfEvent} should be expected in response.\n */\ninterface DisconnectSelfCommand {\n\tcommand: \"disconnectSelf\";\n}\n\n/**\n * Instructs a child process to register for state objects in a workspace given a workspaceId\n * A {@link WorkspaceRegisteredEvent} should be expected in response.\n */\ninterface RegisterWorkspaceCommand {\n\tcommand: \"registerWorkspace\";\n\tworkspaceId: string;\n\t/**\n\t * Register a Latest state for this workspace.\n\t */\n\tlatest?: true;\n\t/**\n\t * Register a LatestMap state for this workspace.\n\t */\n\tlatestMap?: true;\n}\n\n/**\n * Instructs a child process to set the latest value.\n * We then can wait for {@link LatestValueUpdatedEvent} from other clients to know when an update occurs that represents this change.\n * Note: The client doesn't guarantee that the update message is directly related to this set command.\n */\ninterface SetLatestValueCommand {\n\tcommand: \"setLatestValue\";\n\tworkspaceId: string;\n\tvalue: JsonSerializable<unknown>;\n}\n\n/**\n * Instructs a child process to set the latest map value.\n * We then can wait for {@link LatestMapValueUpdatedEvent} from other clients to know when an update occurs that represents this change.\n * Note: The client doesn't guarantee that the update message is directly related to this set command.\n */\ninterface SetLatestMapValueCommand {\n\tcommand: \"setLatestMapValue\";\n\tworkspaceId: string;\n\tkey: string;\n\tvalue: JsonSerializable<unknown>;\n}\n\n/**\n * Instructs a child process to get the latest value.\n * A {@link LatestValueGetResponseEvent} should be expected in response.\n */\ninterface GetLatestValueCommand {\n\tcommand: \"getLatestValue\";\n\tworkspaceId: string;\n\tattendeeId?: AttendeeId;\n}\n\n/**\n * Instructs a child process to get the latest map value.\n * A {@link LatestMapValueGetResponseEvent} should be expected in response.\n */\ninterface GetLatestMapValueCommand {\n\tcommand: \"getLatestMapValue\";\n\tworkspaceId: string;\n\tkey: string;\n\tattendeeId?: AttendeeId;\n}\n\n/**\n * Message types sent from the child processes to the orchestrator\n */\nexport type MessageFromChild =\n\t| AcknowledgeEvent\n\t| AttendeeConnectedEvent\n\t| AttendeeDisconnectedEvent\n\t| ConnectedEvent\n\t| DebugReportCompleteEvent\n\t| DisconnectedSelfEvent\n\t| ErrorEvent\n\t| LatestMapValueGetResponseEvent\n\t| LatestMapValueUpdatedEvent\n\t| LatestValueGetResponseEvent\n\t| LatestValueUpdatedEvent\n\t| WorkspaceRegisteredEvent;\n\n/**\n * Sent from the child processes to the orchestrator in response to a {@link PingCommand}.\n */\ninterface AcknowledgeEvent {\n\tevent: \"ack\";\n}\n\n/**\n * Sent arbitrarily to indicate a new attendee has connected.\n */\ninterface AttendeeConnectedEvent {\n\tevent: \"attendeeConnected\";\n\tattendeeId: AttendeeId;\n}\n\n/**\n * Sent arbitrarily to indicate an attendee has disconnected.\n */\ninterface AttendeeDisconnectedEvent {\n\tevent: \"attendeeDisconnected\";\n\tattendeeId: AttendeeId;\n}\n\n/**\n * Sent from the child processes to the orchestrator in response to a {@link ConnectCommand}.\n */\ninterface ConnectedEvent {\n\tevent: \"connected\";\n\tcontainerId: string;\n\tattendeeId: AttendeeId;\n}\n\n/**\n * Sent from the child processes to the orchestrator in response to a {@link DebugReportCommand}.\n */\ninterface DebugReportCompleteEvent {\n\tevent: \"debugReportComplete\";\n\tlog?: EventEntry[];\n}\n\n/**\n * Sent from the child processes to the orchestrator in response to a {@link DisconnectSelfCommand}.\n */\ninterface DisconnectedSelfEvent {\n\tevent: \"disconnectedSelf\";\n\tattendeeId: AttendeeId;\n}\n\n/**\n * Sent from the child processes to the orchestrator in response to latest value update.\n */\nexport interface LatestValueUpdatedEvent {\n\tevent: \"latestValueUpdated\";\n\tworkspaceId: string;\n\tattendeeId: AttendeeId;\n\tvalue: unknown;\n}\n\n/**\n * Sent from the child processes to the orchestrator in response to latest map value update.\n */\nexport interface LatestMapValueUpdatedEvent {\n\tevent: \"latestMapValueUpdated\";\n\tworkspaceId: string;\n\tattendeeId: AttendeeId;\n\tkey: string;\n\tvalue: unknown;\n}\n\n/**\n * Sent from the child processes to the orchestrator in response to a {@link GetLatestValueCommand}.\n */\nexport interface LatestValueGetResponseEvent {\n\tevent: \"latestValueGetResponse\";\n\tworkspaceId: string;\n\tattendeeId: AttendeeId | undefined;\n\tvalue: unknown;\n}\n\n/**\n * Sent from the child processes to the orchestrator in response to a {@link GetLatestMapValueCommand}.\n */\nexport interface LatestMapValueGetResponseEvent {\n\tevent: \"latestMapValueGetResponse\";\n\tworkspaceId: string;\n\tattendeeId: AttendeeId | undefined;\n\tkey: string;\n\tvalue: unknown;\n}\n\n/**\n * Sent from the child process to acknowledge workspace registration.\n */\ninterface WorkspaceRegisteredEvent {\n\tevent: \"workspaceRegistered\";\n\tworkspaceId: string;\n\tlatest?: boolean;\n\tlatestMap?: boolean;\n}\n\n/**\n * Sent at any time to indicate an error.\n */\ninterface ErrorEvent {\n\tevent: \"error\";\n\terror: string;\n}\n"]}
1
+ {"version":3,"file":"messageTypes.js","sourceRoot":"","sources":["../../../src/test/multiprocess/messageTypes.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n// eslint-disable-next-line import/no-internal-modules\nimport type { JsonSerializable } from \"@fluidframework/core-interfaces/internal\";\nimport type { ScopeType } from \"@fluidframework/driver-definitions/legacy\";\nimport type { AttendeeId } from \"@fluidframework/presence/beta\";\n\nexport interface UserIdAndName {\n\tid: string;\n\tname: string;\n}\n\nexport interface EventEntry {\n\ttimestamp: number;\n\tagentId: string;\n\teventCategory: string;\n\teventName: string;\n\tdetails?: string;\n}\n\n/**\n * Message types sent from the orchestrator to the child processes\n */\nexport type MessageToChild =\n\t| ConnectCommand\n\t| DebugReportCommand\n\t| DisconnectSelfCommand\n\t| RegisterWorkspaceCommand\n\t| GetLatestValueCommand\n\t| GetLatestMapValueCommand\n\t| SetLatestValueCommand\n\t| SetLatestMapValueCommand\n\t| PingCommand;\n\n/**\n * Can be sent to check child responsiveness.\n * An {@link AcknowledgeEvent} should be expected in response.\n */\ninterface PingCommand {\n\tcommand: \"ping\";\n}\n\n/**\n * Instructs a child process to connect to a Fluid container.\n * A {@link ConnectedEvent} should be expected in response.\n */\nexport interface ConnectCommand {\n\tcommand: \"connect\";\n\tuser: UserIdAndName;\n\tscopes: ScopeType[];\n\tcreateScopes?: ScopeType[];\n\t/**\n\t * The ID of the Fluid container to connect to.\n\t * If not provided, a new Fluid container will be created.\n\t */\n\tcontainerId?: string;\n\tconnectTimeoutMs: number;\n}\n\n/**\n * Instructs a child process to report debug information.\n *\n * @privateRemarks\n * This can be expanded over time to include more options.\n */\ninterface DebugReportCommand {\n\tcommand: \"debugReport\";\n\t/**\n\t * Send event log entries.\n\t */\n\tsendEventLog?: true;\n\t/**\n\t * Send basic attendee statistics (like count of connected).\n\t */\n\treportAttendees?: true;\n}\n\n/**\n * Instructs a child process to disconnect from a Fluid container.\n * A {@link DisconnectedSelfEvent} should be expected in response.\n */\ninterface DisconnectSelfCommand {\n\tcommand: \"disconnectSelf\";\n}\n\n/**\n * Instructs a child process to register for state objects in a workspace given a workspaceId\n * A {@link WorkspaceRegisteredEvent} should be expected in response.\n */\ninterface RegisterWorkspaceCommand {\n\tcommand: \"registerWorkspace\";\n\tworkspaceId: string;\n\t/**\n\t * Register a Latest state for this workspace.\n\t */\n\tlatest?: true;\n\t/**\n\t * Register a LatestMap state for this workspace.\n\t */\n\tlatestMap?: true;\n}\n\n/**\n * Instructs a child process to set the latest value.\n * We then can wait for {@link LatestValueUpdatedEvent} from other clients to know when an update occurs that represents this change.\n * Note: The client doesn't guarantee that the update message is directly related to this set command.\n */\ninterface SetLatestValueCommand {\n\tcommand: \"setLatestValue\";\n\tworkspaceId: string;\n\tvalue: JsonSerializable<unknown>;\n}\n\n/**\n * Instructs a child process to set the latest map value.\n * We then can wait for {@link LatestMapValueUpdatedEvent} from other clients to know when an update occurs that represents this change.\n * Note: The client doesn't guarantee that the update message is directly related to this set command.\n */\ninterface SetLatestMapValueCommand {\n\tcommand: \"setLatestMapValue\";\n\tworkspaceId: string;\n\tkey: string;\n\tvalue: JsonSerializable<unknown>;\n}\n\n/**\n * Instructs a child process to get the latest value.\n * A {@link LatestValueGetResponseEvent} should be expected in response.\n */\ninterface GetLatestValueCommand {\n\tcommand: \"getLatestValue\";\n\tworkspaceId: string;\n\tattendeeId?: AttendeeId;\n}\n\n/**\n * Instructs a child process to get the latest map value.\n * A {@link LatestMapValueGetResponseEvent} should be expected in response.\n */\ninterface GetLatestMapValueCommand {\n\tcommand: \"getLatestMapValue\";\n\tworkspaceId: string;\n\tkey: string;\n\tattendeeId?: AttendeeId;\n}\n\n/**\n * Message types sent from the child processes to the orchestrator\n */\nexport type MessageFromChild =\n\t| AcknowledgeEvent\n\t| AttendeeConnectedEvent\n\t| AttendeeDisconnectedEvent\n\t| ConnectedEvent\n\t| DebugReportCompleteEvent\n\t| DisconnectedSelfEvent\n\t| ErrorEvent\n\t| LatestMapValueGetResponseEvent\n\t| LatestMapValueUpdatedEvent\n\t| LatestValueGetResponseEvent\n\t| LatestValueUpdatedEvent\n\t| WorkspaceRegisteredEvent;\n\n/**\n * Sent from the child processes to the orchestrator in response to a {@link PingCommand}.\n */\ninterface AcknowledgeEvent {\n\tevent: \"ack\";\n}\n\n/**\n * Sent arbitrarily to indicate a new attendee has connected.\n */\ninterface AttendeeConnectedEvent {\n\tevent: \"attendeeConnected\";\n\tattendeeId: AttendeeId;\n}\n\n/**\n * Sent arbitrarily to indicate an attendee has disconnected.\n */\ninterface AttendeeDisconnectedEvent {\n\tevent: \"attendeeDisconnected\";\n\tattendeeId: AttendeeId;\n}\n\n/**\n * Sent from the child processes to the orchestrator in response to a {@link ConnectCommand}.\n */\ninterface ConnectedEvent {\n\tevent: \"connected\";\n\tcontainerId: string;\n\tattendeeId: AttendeeId;\n}\n\n/**\n * Sent from the child processes to the orchestrator in response to a {@link DebugReportCommand}.\n */\ninterface DebugReportCompleteEvent {\n\tevent: \"debugReportComplete\";\n\tlog?: EventEntry[];\n}\n\n/**\n * Sent from the child processes to the orchestrator in response to a {@link DisconnectSelfCommand}.\n */\ninterface DisconnectedSelfEvent {\n\tevent: \"disconnectedSelf\";\n\tattendeeId: AttendeeId;\n}\n\n/**\n * Sent from the child processes to the orchestrator in response to latest value update.\n */\nexport interface LatestValueUpdatedEvent {\n\tevent: \"latestValueUpdated\";\n\tworkspaceId: string;\n\tattendeeId: AttendeeId;\n\tvalue: unknown;\n}\n\n/**\n * Sent from the child processes to the orchestrator in response to latest map value update.\n */\nexport interface LatestMapValueUpdatedEvent {\n\tevent: \"latestMapValueUpdated\";\n\tworkspaceId: string;\n\tattendeeId: AttendeeId;\n\tkey: string;\n\tvalue: unknown;\n}\n\n/**\n * Sent from the child processes to the orchestrator in response to a {@link GetLatestValueCommand}.\n */\nexport interface LatestValueGetResponseEvent {\n\tevent: \"latestValueGetResponse\";\n\tworkspaceId: string;\n\tattendeeId: AttendeeId | undefined;\n\tvalue: unknown;\n}\n\n/**\n * Sent from the child processes to the orchestrator in response to a {@link GetLatestMapValueCommand}.\n */\nexport interface LatestMapValueGetResponseEvent {\n\tevent: \"latestMapValueGetResponse\";\n\tworkspaceId: string;\n\tattendeeId: AttendeeId | undefined;\n\tkey: string;\n\tvalue: unknown;\n}\n\n/**\n * Sent from the child process to acknowledge workspace registration.\n */\ninterface WorkspaceRegisteredEvent {\n\tevent: \"workspaceRegistered\";\n\tworkspaceId: string;\n\tlatest?: boolean;\n\tlatestMap?: boolean;\n}\n\n/**\n * Sent at any time to indicate an error.\n */\ninterface ErrorEvent {\n\tevent: \"error\";\n\terror: string;\n}\n"]}
@@ -35,12 +35,13 @@ export const testConsole = {
35
35
  * @param cleanUpAccumulator - An array to accumulate cleanup functions for each child.
36
36
  * @returns A collection of child processes and a promise that rejects on the first child error.
37
37
  */
38
- export async function forkChildProcesses(numProcesses, cleanUpAccumulator) {
38
+ export async function forkChildProcesses(testLabel, numProcesses, cleanUpAccumulator) {
39
39
  const children = [];
40
40
  const childReadyPromises = [];
41
41
  const childErrorPromises = [];
42
42
  for (let i = 0; i < numProcesses; i++) {
43
43
  const child = fork("./lib/test/multiprocess/childClient.tool.js", [
44
+ testLabel,
44
45
  `child ${i}` /* identifier passed to child process */,
45
46
  childLoggingVerbosity /* console logging verbosity */,
46
47
  ]);
@@ -108,7 +109,7 @@ export async function executeDebugReports(childrenRequestedToReport) {
108
109
  *
109
110
  * @param id - Suffix used to construct stable test user identity.
110
111
  */
111
- function composeConnectMessage(id, scopes = [ScopeType.DocRead]) {
112
+ function composeConnectMessage(id, scopes = [ScopeType.DocRead], connectTimeoutMs) {
112
113
  return {
113
114
  command: "connect",
114
115
  user: {
@@ -117,6 +118,7 @@ function composeConnectMessage(id, scopes = [ScopeType.DocRead]) {
117
118
  },
118
119
  scopes,
119
120
  createScopes: [ScopeType.DocWrite, ScopeType.DocRead],
121
+ connectTimeoutMs,
120
122
  };
121
123
  }
122
124
  /**
@@ -172,12 +174,16 @@ export async function connectChildProcesses(childProcesses, { writeClients, read
172
174
  // Note that DocWrite is used to have this attendee be the "leader".
173
175
  // DocRead would also be valid as DocWrite is specified for attach when there
174
176
  // is no document id (container id).
175
- const connectContainerCreator = composeConnectMessage(0, writeClients > 0 ? [ScopeType.DocWrite, ScopeType.DocRead] : [ScopeType.DocRead]);
177
+ const connectContainerCreator = composeConnectMessage(0, writeClients > 0 ? [ScopeType.DocWrite, ScopeType.DocRead] : [ScopeType.DocRead],
178
+ /* connectTimeoutMs */ readyTimeoutMs);
176
179
  firstChild.send(connectContainerCreator);
177
180
  }
178
181
  const { containerCreatorAttendeeId, containerId } = await timeoutAwait(containerReadyPromise, {
179
182
  durationMs: readyTimeoutMs,
180
183
  errorMsg: "did not receive 'connected' from child process",
184
+ }).catch(async (error) => {
185
+ await executeDebugReports([firstChild]);
186
+ throw error;
181
187
  });
182
188
  const attendeeIdPromises = [];
183
189
  for (const [index, child] of childProcesses.entries()) {
@@ -185,7 +191,8 @@ export async function connectChildProcesses(childProcesses, { writeClients, read
185
191
  attendeeIdPromises.push(Promise.resolve(containerCreatorAttendeeId));
186
192
  continue;
187
193
  }
188
- const message = composeConnectMessage(index, index < writeClients ? [ScopeType.DocWrite, ScopeType.DocRead] : [ScopeType.DocRead]);
194
+ const message = composeConnectMessage(index, index < writeClients ? [ScopeType.DocWrite, ScopeType.DocRead] : [ScopeType.DocRead],
195
+ /* connectTimeoutMs */ readyTimeoutMs);
189
196
  message.containerId = containerId;
190
197
  attendeeIdPromises.push(new Promise((resolve, reject) => listenForConnectedResponse({
191
198
  child,
@@ -225,6 +232,10 @@ export async function connectAndListenForAttendees(children, { writeClients, att
225
232
  writeClients,
226
233
  readyTimeoutMs: childConnectTimeoutMs,
227
234
  });
235
+ // These actions are not awaited. They are here to provide additional logging.
236
+ // It is up to the caller to await attendeeIdPromises if desired. This can mean
237
+ // An "error" message is output, but the caller does not care about attendee
238
+ // ids and proceeds.
228
239
  Promise.all(connectResult.attendeeIdPromises)
229
240
  .then(() => console.log("All attendees connected."))
230
241
  .catch((error) => {