Hello everyone! I'm creating an open-source SystemD daemon service for providing high availability to network backend applications. The idea is simple: you describe your services in a configuration file, and buzz-operator reads it and runs your service. It performs healthchecks, restarts your service if it exits with an error, performs rolling updates, and runs scripts for updating other configurations. For example, if you run multiple instances behind nginx and upload a new version to VPS, the daemon will gradually replace all instances, run a script to update the nginx config, and reload nginx.
I have several types here:
ServiceUnit
- represents one instance of a single serviceServiceBunch
- represents multiple instances of a single serviceServiceController
- represents multiple bunches
I created all of them in an asynchronous manner, and I use the tokio runtime for this purpose. ServiceUnit
runs and waits for one of two events: exit from the process or a message from ServiceBunch
to terminate this unit. Anyway, if the process is terminated, ServiceUnit
returns control.
ServiceBunch
runs multiple units and waits for all of them. Also, when a bunch creates one unit, it gives the receiver part of an async channel to send a termination message. ServiceController
also communicates between every bunch using tokio::sync::mpsc::channel
.
In my main function, I listen on a Unix socket for commands from the user (start service, stop service, reload, etc.) and send messages to the controller over the channel again. When I created this, I didn't find any option to communicate between tasks except channels because an async task wants to own its values. I'm not very experienced with manual Future implementation, but I know how Pin and stuff works.
Can you please advise me if there are more optimal options, or if using only channels is totally fine?