-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add service manager infrastructure #14150
Conversation
✅ Deploy Preview for frigate-docs canceled.
|
I think it would be great to see what the other maintainers think, but I'll leave my thoughts: I like this idea. Personally, I think it would work best to implement the framework first and then gradually move some of the processes over as it makes sense (as opposed to converting lots of the current processes at once). This approach seems like it would be a great way to go about implementing #1911 in which case we will sometimes deliberately want the service to stop indefinitely before it starts again at some point in the future. |
Looks great to me. Really appreciate the detailed explanation and thoughtful staging of the changes. |
e9e1bd7
to
8462414
Compare
8462414
to
d3d92aa
Compare
The changes are (This will be a bit long): - A ServiceManager class that spawns a background thread and deals with service lifecycle management. The idea is that service lifecycle code will run in async functions, so a single thread is enough to manage any (reasonable) amount of services. - A Service class, that offers start(), stop() and restart() methods that simply notify the service manager to... well. Start, stop or restart a service. (!) Warning: Note that this differs from mp.Process.start/stop in that the service commands are sent asynchronously and will complete "eventually". This is good because it means that business logic is fast when booting up and shutting down, but we need to make sure that code does not rely on start() and stop() being instant (Mainly pid assignments). Subclasses of the Service class should use the on_start and on_stop methods to monitor for service events. These will be run by the service manager thread, so we need to be careful not to block execution here. Standard async stuff. (!) Note on service names: Service names should be unique within a ServiceManager. Make sure that you pass the name you want to super().__init__(name="...") if you plan to spawn multiple instances of a service. - A ServiceProcess class: A Service that wraps a multiprocessing.Process into a Service. It offers a run() method subclasses can override and can support in-place restarting using the service manager. And finally, I lied a bit about this whole thing using a single thread. I can't find any way to run python multiprocessing in async, so there is a MultiprocessingWaiter thread that waits for multiprocessing events and notifies any pending futures. This was uhhh... fun? No, not really. But it works. Using this part of the code just involves calling the provided wait method. See the implementation of ServiceProcess for more details. Mirror util.Process hooks onto service process Remove Service.__name attribute Do not serialize process object on ServiceProcess start. asd
d3d92aa
to
57c2818
Compare
Okay, this is done basically done as far as the service manager is concerned. I've converted the audio processor to use the new service manager since it seemed easy to do, but I'm leaving the rest for later PRs. I haven't done the heartbeat part of the TODO, since I'd like to delay it until I can see where and how it'll be used exactly. So it can wait. |
This is still very much a work in progress. Please don't merge just yet. I'm posting the PR now so we can discuss the approach. The code I've added is still (intentionally) not called from anywhere.
I'm making the PR now since it's getting big again so it doesn't come out of nowhere. But this time it can wait for 0.16 however long it needs to since I haven't touched anything outside of the new
frigate/service_manager/
folder (Well, I did changemypy.ini
, but I can live with merging that).TODO
Add service heartbeat. If a service does not send a heartbeat often enough, it is restarted.This can wait for another PR.High level overview
Add a service class that can spawn and tear down processes blazingly 🔥 fast (Sorry, I had to).
In more detail
I'll just paste the singular commit message here for now.
Type of change
Toy example to put into main if you wanna play with the service manager: