TL;DR: This may be a rather big effort, but also bring a bunch opportunities.
With Django 4.2 comes the possibility to deploy apps as ASGI instead of WSGI (the “A” stands for “asynchronous” and means “event driven non-blocking single threaded code” in this context). In practice, a single daphne (this is what replaces the “gunicorn” worker) process can handle multiple hundreds of requests simultaneously even if they individually take rather long, as e.g. streaming an artifact to the user. So far this streaming need is what warranted the original design choice to use aiohttp for the content-app, while the pulp-api still ran as a native Django app. But this mix of technology (the content app still needs to access the Django ORM and storage technology in non-trivial ways) is a constant source of friction. The most prominent example being the db-disconnection bug chasing us over years, we may or may not have solved by now, but certainly with a lack of confidence.
The proposal I want to outline here pursues the goal to bring the content app back onto the same technology stack as the rest of the Pulp components.
The benefits I see from the top of my mind are:
- The ORM fits naturally into the request handling.
- Exceptions flow naturally between the abstraction layers without translating.
- One less HTTP stack to keep in mind.
As much as the envisioned result looks like the promised land, there are significant challenges on the way:
- You can only run either technology in the same process.
- Plugins have the opportunity to hook into the content app for so called live APIs.
- You can most certainly not use the same (plugin-) codepaths for both versions of the content app.
To allow for a smooth transition (including zero downtime upgrades), we could exert a phased approach. We would design the new type content app side by side to the old one (we did a similar thing to replace the tasking system), and ask plugins to start provide equivalent codepaths for both implementations, reporting their availablility with the PluginConfig
object. We would then properly deprecate the old implementation and eventually remove it for good.
As for the new implementation, I’d like to see a design, where the main app would route the request up to the distribution, from where the plugin takes over responsibility. For most plugins, Pulpcore should provide convenience classes that simply route pass-through publications or such with published artifacts.