Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(client-presence): Example multi-process E2E test #23305

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

WillieHabi
Copy link
Contributor

@WillieHabi WillieHabi commented Dec 11, 2024

Not meant to merge

Description

This PR is an example setup of a multi-process end to end test could potentially look like. Each client has their own separate process. There is a client in the parent process who creates the container and child processes that fork from the parent process that get the same container. Through IPC (inter-process communication) calls parent process acts as an orchestrator to its child processes, giving commands about what actions to perform. The child then performs these actions and responds with any information needed to verify correctness. The parent can interact with each child and each child only interacts with the parent.

This was written as an AzureClient E2E test to avoid the complexity of the existing cross-compat in the root e2e test package.

Learnings

This pattern follows something close to the actor model in which the parent process is the only actor that creates other actors. From this experience I realize this concurrent programming model is very different from the traditional single process tests we write now. It would be difficult to integrate this pattern into our current e2e compat test suite. If we build out a new test suite using this actor model for multi-process testing, we'd have to develop new abstractions to make it easy for developers to write tests simply (Actor, Orchestrator, Command/Action, etc.)

Next Steps

We should look into other potential JS frameworks that we could leverage here

@github-actions github-actions bot added dependencies Pull requests that update a dependency file base: main PRs targeted against main branch labels Dec 11, 2024
Copy link
Contributor

@scottn12 scottn12 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work Willie, this looks great! I left some suggestions/questions, but overall this looks like a great start. I agree we should look into other options/frameworks to see what fits our tests best

afterEach(async () => {
// kill all child processes after each test
for (const child of children) {
if (!child.killed) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would probably make more sense to reset the array after each test. Something like -

let children: ChildProcess[] = [];
afterEach(async () => {
  // kill all child processes after each test
  for (const child of children) {
    child.kill();
  }
  children = [];
}

if (attendee !== presence.getMyself()) {
count++;
attendeesJoined.push(attendee.sessionId);
if (count === numClients) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: You could get rid of count by comparing attendeesJoined.length === numClients instead

await timeoutPromise(
(resolve) => {
let count = 0;
presence.events.on("attendeeJoined", (attendee) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to turn off this listener after we are done with it? I'm not sure if it gets cleaned up automatically

const waitForDisconnected = children.map(async (child, index) =>
timeoutPromise(
(resolve) =>
child.on("message", (msg: MessageFromChild) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question as above (re: turning off listeners)

};
};

process.on("message", (msg: MessageFromParent) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since I commented on the below listeners I just want to note I think we don't need to turn this listener off since the process will get killed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
base: main PRs targeted against main branch dependencies Pull requests that update a dependency file
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants