Description
Hello,
Sorry for being a bit late to this party. I just saw that #41163 got merged into 5.4 and I think it needs a bit more polish. The main issue I found with it is that IMHO it's way too agressive. If reset_on_message
is enabled on a transport, the services in ServicesResetter
(which are quite a few) will get reset
while (true) {
// worker tick
foreach (transport) {
if (message) {
reset (success/failed)
reset again (worker running) <-- actually, this would throw
}
}
if (idle) {
reset again
}
usleep
Isn't this too aggresive? While resetting after each message (success/failure) makes some sense (though there's an argument to be made for a userland implementation), resetting multiple times per worker tick can't be all right. It also reset on each tick if idle. Depending on the configuration, it can happen multiple times per second.
ServicesResetter was meant for resetting state on request boundaries. It was never meant to hide memory leaks. Sure, it does help cover the memory leaks, but covering them is not a viable long term solution.
The original PR pointed out at least 2 legitimate issues: The FingersCrossedHandler
keeps on flushing logs after a single error and the Profiler infrastructure is leaking memory. While the monolog issue should be fixed, I don't find the Profiler argument convincing. I do believe the profiler should not leak memory, but I think the Profiler should do its own housekeeping in a messenger context.
Another issue with the current implementation is the fact the it subscribes to WorkerRunningEvent
and then it calls getReceiverName()
on it. WorkerRunningEvent::getReceiverName()
does not exist. That's because WorkerRunningEvent
doesn't extend AbstractWorkerMessageEvent
(which ResetServicesListener::resetServices()
expects).
Last but not least, there's the semantic issue -- right now, the configuration reset_on_message
is misleading.
Some ideas that would improve the situation would be:
- reset the services only on message handled (success or failed)
- maybe even reset on idle, but do it a lot less often (and toggleable separately, or at least make it clear to the developer that
reset_on_message_also_resets_on_idle
) - just like there is
cache.app
and acache.system
, maybe theServicesResetter
should have separate service groups for app and system. The framework would do its own housekeeping, while userland that has no other choice would tag their services to get reset as well as part of theapp
group) - I know it's a long shot, but if we extended the profiler to work for CLI usecases (like messenger), it would give us a chance to mitigate some of the leaks. The profiler would
collect()
the data and the Collectors (likeTraceableEventDispatcher
) would have their buffers cleared.
So... what do you guys think?
/cc @lyrixx (please forgive me 😁 )