solid_queue
solid_queue copied to clipboard
For discussion: add in-process `async` mode to Puma plugin
First, let me apologize for dropping what is essentially a spike; I figured it was simplest to share some real code.
I wanted to see how difficult it would be to add an "async" mode to the puma plugin that would run the workers/dispatchers in the same process rather than forking. Not difficult at all! 🤞🏻
Working on this did expose a few questions that I had about what an ideal implementation would be:
Configuration
I added a new "mode" to the Puma plugin, and also overloaded the worker configuration to make "processes: 0" mean something new. I think they're somewhat redundant.
processes: 0 is not great (maybe someone wants to disable a worker but retain the configuration; this would make that more difficult). I went with 0 because I didn't want to mix integers and strings (e.g. processes: async) and...
In this implementation, it's not possible to mix both async and forking, and I think that could be nice (or maybe too complicated!). I could imagine async as general mode of SolidQueue rather than specific to the Puma plugin to allow mixing-and-matching async and forked workers through the CLI too.
Supervision
I made a new object called AsyncSupervisor which is overloading the concept of Supervisor a bit. It also made me think, if async and forked workers could be operated simultaneously there would need to be an object (a "Director"?) that managed both an AsyncSupervisor and Supervisor ... and that was the point where I figured I should just share where I'm at 😊
Slimming down workers
Lastly, I think this naive spike still leaves the Worker objects with some behavior that maybe isn't necessary (process registration, each having their own heartbeat) or possibly bad (e.g. setting the procline). It might be as simple as adding a few more if supervised? checks because I didn't see anything that strongly-strongly implied that Workers must run in a subprocess.
Lastly, I wanted to try this just to dig into SolidQueue, so please feel free to disregard/dispose of it if you already have completely different ideas for how to implement this functionality. I'm excited regardless 🎉
Hey @bensheldon, thank you so much for this! I really want to have this feature so really appreciate you doing the work!
I could imagine async as general mode of SolidQueue rather than specific to the Puma plugin to allow mixing-and-matching async and forked workers through the CLI too.
Yeah, I'd like this too. I think I'd like to get rid of mode as it is now for the Supervisor (work, dispatch), leaving that to the configuration (if you have dispatchers there or workers, just work/dispatch based on that), and have that mean the same as for workers and dispatchers. Maybe it'd make sense to have async, fork for modes 🤔 And maybe that'd make sense for workers and dispatchers too, instead of supervised, they could have forked or fork mode, and we could slim them down when they're not in fork mode. They'd be "supervised" in a sense when running in this new async mode you introduced. Then the configuration would know the difference between these and would ignore processes altogether when going in async mode, so we wouldn't need processes: 0.
I'll continue thinking about this, let me know if you have any thoughts about the above, and thanks again for this, I love it.
It's been quite a long time but I'm finally working on this. Ported your changes to the Puma plugin over a different branch: https://github.com/rails/solid_queue/commit/6601a54f6f3f0346c8e3ce09d8a6db285d4bbf36. I'll open a PR this week.
@rosa awesome! thank you for picking it up 🙇🏻
Going to close this PR in favour of #269. Again, thanks so much @bensheldon for starting this one and inspiring the whole idea!