… and I think I just wrote it.
For years, I have wanted a Python TCP server framework with the following features.
- Multi-process: I want the framework to be able to use all available processors and cores with no GIL (global interpreter lock) contention. This is important for CPU-bound applications.
- Multi-threaded: Each process should have a fixed number of threads so it can multiplex tasks. This is important for I/O-bound applications.
- Graceful shutdown: when I issue the kill signal, I want the server to close its server socket immediately, but I want existing connections to have a chance to finish their work. This is important if the connections are involved in transactions.
- Graceful code reloading and reconfiguration: when I issue the HUP (hangup) signal, I want the server reload its configuration, spin up new processes, and tell the old processes to stop accepting new connections and shut down only when finished. Also, the server should only load application code in child processes, so that loading new code is simply a matter of issuing a HUP signal.
- Transaction integration, including two-phase commit: If the connection dies, I want to roll back the associated transaction automatically, unless the connection dies after the first phase of two-phase commit, in which case I want to leave the transaction in a partially committed state and sort out the issue at a higher level.
- No proxying: I don’t want all traffic to flow through the master process, which would be bad for both reliability and performance. Linux (and maybe any Unix system) allows multiple processes to listen on the same server socket; I want to use that feature.
What I have described is well beyond what the Python standard library provides. In theory, it will let me have all the joys of transactions and zero-downtime updates in a high performance environment. I have been searching for an implementation of this design for years. This week, I have been reworking some WingCash code to make better use of transactions and I realized I really need this design.
So, on Monday, I wrote my dream server framework and tried it out… and to my surprise, it actually worked! I was surprised because I thought that some Python hacker, somewhere, must have tried this experiment by now, and must have failed; otherwise the experiment results would surely be published or mentioned somewhere. Perhaps my requirements are not very common, the design is not obvious, or I did not type the right search terms.
I am now writing tests for the new server framework, which I am tentatively calling fdtserver (forking distributed transaction server). I won’t put it into production until it has 100% statement coverage like the rest of WingCash. I wonder whether fdtserver should be open source. Doesn’t the need for all those features, particularly graceful code reloading, exist elsewhere?