-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Refactor Envoy's Dispatcher abstraction #14401
Comments
Consider using the Scheduler interface in include/envoy/event/timer.h to create low-level timers and thus resolve the circular dependency on dispatcher. Other methods you're using from the dispatcher interface: Both of these could be added to the Scheduler interface. |
Thanks, that'll solve my scaled timer issue. I'm still wondering if it's worth splitting up the Dispatcher, though, since it seems to export abstractions that could be built entirely using some of the lower-level abstractions it also exports. |
Possibly, but we would need to make sure to limit use of the lower level interface. Most code should interact with the full dispatcher interface. |
Actually, the Scheduler interface doesn't resolve the circular dependency since Scheduler::createTimer's second argument is a Dispatcher& 🤦 |
...though it looks like that might be easy enough to remove since the scheduler comes from the dispatcher. |
Could be resolved by adding setTrackedObject to the scheduler interface, or some new interface related to tracking current state in the event of a crash. |
Seems reasonable, but this could also be an opportunity to move some things out of dispatcher that might be concept/scope creep. For example, I'm not sure if the DNS resolver really needs to live there. Ultimately some of the API choices may have been influenced by the use of |
I think this is accurate. In general I think the idea of a low level interface that is very thin (and for example might allow us to completely swap out libevent for libuv/libev/etc. more easily) and then a high layer interface on top makes sense to me. In practice I don't have a good feel for how difficult that would be, but no major objection from me. |
I'm drafting a change right now to see what it would look like. Basically, remove the Dispatcher argument from the Schedulable::createTimer API, move a few useful methods to Scheduler and making Dispatcher a subclass of Scheduler. Methods to move to Scheduler: We could consider moving fileevent and friends to Scheduler in the future. |
I have two possible drafts: My thoughts on antoniovicente:dispatcher_base:
My thoughts so far on antoniovicente:dispatcher_interface:
|
dispatcher_base addresses the basic need, which is separating out low-level stuff that the dispatcher implements from higher-level stuff built on top, yeah. |
Do remember that higher level constructs like connections depend on ScaledTimer and are also created through the dispatcher. ScaledTimers are relatively low level. |
Sounds like we need a DAG :D Fair. Here's a crazy idea: get rid of createScaledTimer and just add an optional ScaledTimerMinimum argument to createTimer. If it's ScaledMinimum(1), return a regular timer; otherwise return a scaled timer. (I don't recommend this because scaled timers are actually not that efficient unless there are very few distinct timeouts) |
I think this would create a circular dependency between ScaledTimer and the createTimer method that may itself create a scaled timer. |
This issue has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed in the next 7 days unless it is tagged "help wanted" or "no stalebot" or other activity occurs. Thank you for your contributions. |
This issue has been automatically closed because it has not had activity in the last 37 days. If this issue is still valid, please ping a maintainer and ask them to label it as "help wanted" or "no stalebot". Thank you for your contributions. |
This FR was initiated by a discussion on moving scaled timer creation into the Dispatcher interface (#13800 (comment)). I've been working on exactly that, but was having some trouble with testing that scaled timer creation was occurring without duplicating the tests for the ScaledRangeTimerManager. The problem is that ScaledRangeTimerManager is built on top of the existing Dispatcher interface. In the name of efficiency, we could merge the impl into the already-bloated dispatcher (getting rid of virtual function calls and eliminating layering concerns), but that seems counterproductive.
Instead, I'm proposing that the existing Dispatcher be split into a lower-level class that handles files, sockets, timers, and other things that deal directly with events, and an upper-level class that wraps the lower to provide nice abstractions like scaled timers, the DNS resolver, stats, and whatever else is built on top of the low-level abstractions. Implementing the high-level stuff purely in terms of the low-level abstractions makes testing easier (since we can inject mocks) and reduces the amount of code that deals directly with libevent.
@mattklein123 @htuch WDYT?
The text was updated successfully, but these errors were encountered: