cucumber / cucumber-js

Cucumber for JavaScript
https://cucumber.io
MIT License
5.05k stars 1.09k forks source link

Concurrency: Allow IPC between workers and coordinator, and/or custom Runtime impls #2417

Open tristanzander opened 2 months ago

tristanzander commented 2 months ago

πŸ€” What's the problem you're trying to solve?

I recently found myself in a bit of a predicament when trying to log specific environment information during Cucumber tests.

Our usecase:

Since each worker process is its own forked node process and doesn't allow for overriding the default IPC channel handlers, it's really difficult to find a way to communicate to a parent "coordinator" that can orchestrate situations that have concurrency limitations that aren't tied to test case execution.

There are also other situations that require us to adjust concurrency, such as when multiple worker processes need to change singletons in the systems that we test. If any other tests utilize those features in opposing states, they can't run in parallel. We can set parallelCanAssign rules for those, but we can't coordinate between threads to see how tests change the environment for testing purposes.

✨ What's your proposed solution?

In the WIP plugins API, it would be very helpful if plugins could declare their own runtime implementations for coordinating parallel workers, or for a plugin to be able to send/receive custom events on behalf of a worker to other workers/parent process. This would give us the flexibility and utility to orchestrate all of our asynchronous tasks and log the additional information that we need to monitor our test execution environments.

Such a format is up to debate, which I'm hoping that y'all have some opinions for how you think this can be handled. If there are no objections, I could come up with a more fleshed-out POC.

⛏ Have you considered any alternatives or workarounds?

My current workaround is to use a filesystem lock mechanism to ensure that only one cucumber worker has access to the file at a time, which is working well.

I initially tried to use a BroadcastChannel between the workers to communicate this information, but worker threads fork the parent process, and thus can't communicate over this API.

I also attempted to spawn a separate process that handled IPC over sockets with an RPC protocol, but that ended up being more complex than I wanted it to be for our solution.

πŸ“š Any additional context?

πŸ₯’

tristanzander commented 2 months ago

Relates to #2419

davidjgoss commented 2 months ago

Thanks for raising @tristanzander.

This is definitely on the list for plugins. We had a rough idea of what it could look like in the discussion here https://github.com/cucumber/cucumber-js/discussions/2357#discussioncomment-7850298 but not final.

To unlock this piece of work I first need to finish #2419 as you spotted, so that we can put the plugin hooks into both serial and parallel runners. Once that is done (this week or next I'm hoping) then the IPC use case should be up for grabs if you want to take a run at it!

tristanzander commented 2 months ago

@davidjgoss Thanks for pointing that out for me. I'm happy with the way the plugin example looks on your discussion so I'll patiently await your changes until I can do my part. Thanks for your hard work πŸ₯‡

tristanzander commented 2 months ago

As long as workers and coordinators can both respond to message via an on("myplugin:event") message, we can emit events directly to the workers, and if we can prevent the default messages from going to the workers, all of our use-cases should be covered.