listener, srds, rds, vhds: replace FactoryContext with ServerFactoryContext in router/... #9779
Conversation
…t SRDS/RDS/VHDS subscription could outlive their creator listener Signed-off-by: Xin Zhuang <stevenzzz@google.com>
htuch
left a comment
There was a problem hiding this comment.
General approach looks good, thanks, but I think there's still some issues around validation visitor inference with this PR.
/wait
|
|
||
| ConfigSubscriptionCommonBase::~ConfigSubscriptionCommonBase() { | ||
| init_target_.ready(); | ||
|
|
There was a problem hiding this comment.
Nit: please avoid gratuitous whitespace changes.
source/common/router/rds_impl.cc
Outdated
| : config_(new ConfigImpl(config, factory_context.getServerFactoryContext(), | ||
| factory_context.messageValidationVisitor(), true)), | ||
| : config_(new ConfigImpl(config, factory_context, | ||
| factory_context.messageValidationContext().staticValidationVisitor(), |
There was a problem hiding this comment.
I think this still might not be correct; what if you have an inline route in an HCM that is delivered via a Listener in a LDS message? The validation should be dynamic.
There was a problem hiding this comment.
revert it. This PR is supposed to be a child PR of #9621.
But we can also work on this PR to solve the problem in one shot. :)
There was a problem hiding this comment.
if we don't want FactoryContext to contain a messageValidationVisitor() method, I can do another cleanup PR which will pipe the validator from ListenerImpl --> ... --> HCM::Config.
source/common/router/rds_impl.cc
Outdated
| parent_init_target_(fmt::format("RdsRouteConfigSubscription init {}", route_config_name_), | ||
| [this]() { local_init_manager_.initialize(init_watcher_); }), | ||
| init_watcher_(fmt::format("RDS local-init-watcher {}", rds.route_config_name()), | ||
| [this]() { parent_init_target_.ready(); }), |
There was a problem hiding this comment.
This makes sense to me and is roughly how I was envisaging transitive init managers working. @mergeconflict @lambdai did you have any thoughts here?
There was a problem hiding this comment.
LGTM. Based on my understanding this field initialization order doesn't introduce initialized-after-detroy
There was a problem hiding this comment.
I think it's fine, if it's needed.
source/server/listener_impl.h
Outdated
| std::unique_ptr<Init::WatcherImpl> init_watcher_; | ||
| // A target is added to Server's InitManager if workers_started_ is false. | ||
| std::unique_ptr<Init::TargetImpl> listener_init_target_; |
There was a problem hiding this comment.
When the ListenerImpl is in destroyed, listener_init_target_ is destroyed prior to init_watcher_
Is it possible it triggered init_watcher_ in between?
There was a problem hiding this comment.
ListenerImpl destruction is supposed to be an "atomic" operation in master thread, same as listener_init_target_'s triggering. I think it's fine here?
There was a problem hiding this comment.
Sorry for the churn. I agree it's fine. Although for different reason :)
On top of ~ListenerImpl() there might be ListenerManagerImpl::startWorkers() if this listener is the last uninitialized listener. It's fine because this destroying listener won't in the start list
mergeconflict
left a comment
There was a problem hiding this comment.
I just left a few comments here regarding init manager / target / handle usage (I didn't pay attention to anything else).
source/server/listener_impl.h
Outdated
|
|
||
| // This init watcher, if available, notifies the "parent" listener manager when listener | ||
| // initialization is complete. It may be reset to cancel interest. | ||
| std::unique_ptr<Init::WatcherImpl> init_watcher_; |
There was a problem hiding this comment.
I know it was already like this, but I don't think this needs to be a unique_ptr.
source/server/listener_impl.h
Outdated
| // initialization is complete. It may be reset to cancel interest. | ||
| std::unique_ptr<Init::WatcherImpl> init_watcher_; | ||
| // A target is added to Server's InitManager if workers_started_ is false. | ||
| std::unique_ptr<Init::TargetImpl> listener_init_target_; |
There was a problem hiding this comment.
This doesn't really need to be a unique_ptr either. I'd recommend always creating the target, so that you don't have to worry about ASSERT(listener_init_target_ != nullptr), and just add it to the parent's server's init manager if workers haven't been started.
source/common/router/rds_impl.h
Outdated
| Init::SharedTargetImpl parent_init_target_; | ||
|
|
||
| // Init watcher on RDS and VHDS ready event. This watcher marks parent_init_target_ ready. | ||
| Init::WatcherImpl init_watcher_; |
There was a problem hiding this comment.
Might want to call this parent_init_watcher_ or local_init_watcher_ (I'm not sure which) for consistency.
There was a problem hiding this comment.
moved to config-provider-framework now. named to local_init_watcher_.
There was a problem hiding this comment.
latest init manager related changes still lgtm
Thanks!
source/common/router/rds_impl.cc
Outdated
| parent_init_target_(fmt::format("RdsRouteConfigSubscription init {}", route_config_name_), | ||
| [this]() { local_init_manager_.initialize(init_watcher_); }), | ||
| init_watcher_(fmt::format("RDS local-init-watcher {}", rds.route_config_name()), | ||
| [this]() { parent_init_target_.ready(); }), |
There was a problem hiding this comment.
I think it's fine, if it's needed.
Signed-off-by: Xin Zhuang <stevenzzz@google.com>
abc80ba to
e8de6c1
Compare
Signed-off-by: Xin Zhuang <stevenzzz@google.com>
mergeconflict
left a comment
There was a problem hiding this comment.
init manager related changes lgtm, thanks!
Signed-off-by: Xin Zhuang <stevenzzz@google.com>
Signed-off-by: Xin Zhuang <stevenzzz@google.com>
Signed-off-by: Xin Zhuang <stevenzzz@google.com>
mergeconflict
left a comment
There was a problem hiding this comment.
latest init manager related changes still lgtm
Signed-off-by: Xin Zhuang <stevenzzz@google.com>
|
@stevenzzzz sorry for the delay here. I have been a bit swamped these days. Will prioritize taking a look tomorrow. |
junr03
left a comment
There was a problem hiding this comment.
thanks for working on this. A few comments
include/envoy/server/filter_config.h
Outdated
| virtual const LocalInfo::LocalInfo& localInfo() const PURE; | ||
|
|
||
| /** | ||
| * @return ProtobufMessage::ValidationContext& validation visitor for xDS&static configuration |
There was a problem hiding this comment.
| * @return ProtobufMessage::ValidationContext& validation visitor for xDS&static configuration | |
| * @return ProtobufMessage::ValidationContext& validation visitor for xDS and static configuration |
| createStaticRouteConfigProvider(const envoy::config::route::v3::RouteConfiguration& route_config, | ||
| Server::Configuration::FactoryContext& factory_context) PURE; | ||
| Server::Configuration::ServerFactoryContext& factory_context, | ||
| ProtobufMessage::ValidationVisitor& validator) PURE; |
There was a problem hiding this comment.
I need to read the rest of the PR, but given the change below which add messageValidationVisitor() to the CommonFactoryContext, why is this function also taking a validator as a parameter?
There was a problem hiding this comment.
sorry, missed this comment. I think you mean "add a validation visitor context"?
It's because we can't tell from the current ServerFactoryContext if the static validator or the dynamic validator should be used.
For example, a static Route config provider could be put into a dynamic(LDS) listener's config, in which case we should use the dynamic validator instead (per Harvey).
For that, we will have to pass validator alongside the Serverfatorycontext.
There was a problem hiding this comment.
I see, so only the code that is building the config provider knows if it should be using the static or dynamic visitor, but the constructor itself does not. Hence why the caller of createStaticRouteConfigProvider needs to pass the intended visitor.
Not to bike shed, but it seems that we have gone in one direction here, and the opposite in the ListernerImpl constructor where we used to pass the validator reference but now we decide inside the constructor. Should we pass an added_via_api boolean here and have the constructor decide?
There was a problem hiding this comment.
IMHO, I'd like the validator choice made as close to the consumer entity(in this case, the listenerImpl) as possible, which provides better modularity.
The listener could make the decision by itself as there is a somewhat hacky paramter add_via_api in its constructor, the added_via_api information could be deducted by any RDS-config-provider or any subscription-initiated config-provider,
but not in static config provider: its context doesn't provide enough information for making the choice.
There was a problem hiding this comment.
Should we pass an added_via_api boolean here and have the constructor decide?
Right, that is why I was suggesting if we should hint the static config provider as well (albeit I have not looked if we have access to the same hint when we create this config provider, but my intuition tells me we do). I am not sure what the right answer here is. My point is that we seem to have gone in opposite directions where we could have the same setup.
Perhaps the next reviewer can state their preference.
There was a problem hiding this comment.
discussed this w/ Harvey before, passing the correct validator is preferred over hinting (passing the added_via_api signal). Agreed it's a preference thing as to if we want to keep all the places have the same interface.
| Init::TargetImpl parent_init_target_; | ||
| // Watcher that marks parent_init_target_ ready when the local init manager is ready. | ||
| Init::WatcherImpl local_init_watcher_; | ||
| // Local manager that tracks the subscription's sub-resources(RDS subscriptions) initialization. |
There was a problem hiding this comment.
| // Local manager that tracks the subscription's sub-resources(RDS subscriptions) initialization. | |
| // Local manager that tracks the subscription's sub-resources initialization. For example, RDS in LDS. |
Because RDS is just one example, right?
source/common/router/scoped_rds.h
Outdated
| // ScopedRouteInfo by scope name. | ||
| ScopedRouteMap scoped_route_map_; | ||
| // For creating RDS subscriptions. | ||
| Server::Configuration::ServerFactoryContext& factory_context_; |
There was a problem hiding this comment.
revert it. It's unnecessary now.
There was a problem hiding this comment.
pong.
I think I updated this in another backup branch, oops.
source/server/listener_impl.cc
Outdated
| if (workers_started_) { | ||
| dynamic_init_manager_.initialize(*init_watcher_); | ||
| // If workers_started_ is true, dynamic_init_manager_ should be initialized by listener manager | ||
| // directly.. |
There was a problem hiding this comment.
| // directly.. | |
| // directly. |
source/server/listener_impl.cc
Outdated
| @@ -309,7 +326,6 @@ ListenerImpl::~ListenerImpl() { | |||
| // a local init manager we should block the notification from trying to move us from warming to | |||
There was a problem hiding this comment.
Ok, I think I follow what happened here in terms of changing having different init managers and resetting this watch, vs having the new target and arrangement of firings.
However, there are some outdated comments throughout this file. The above for instance, as this destructor does not any longer reset the init_watcher_. Do you mind going through the file and deleting and updating comments. I think the process here is tricky and being extra crisp on what is going on would make the next person reading this have an easier time.
There was a problem hiding this comment.
oops, this is back!
I have a major git sync problem with master and had to resolve w/ upstream master one by one. I will do a around of comment cleanup.
Signed-off-by: Xin Zhuang <stevenzzz@google.com>
Signed-off-by: Xin Zhuang <stevenzzz@google.com>
Signed-off-by: Xin Zhuang <stevenzzz@google.com>
PTAL |
Signed-off-by: Xin Zhuang <stevenzzz@google.com>
mattklein123
left a comment
There was a problem hiding this comment.
Thanks for a ton for adding the integration test, nice work. Small comment nit and needs a format fix.
/wait
| INSTANTIATE_TEST_SUITE_P(IpVersionsAndGrpcTypes, ListenerIntegrationTest, | ||
| GRPC_CLIENT_INTEGRATION_PARAMS); | ||
|
|
||
| // Tests that a LDS deletion before Server initManager been initialized will block the Server from |
There was a problem hiding this comment.
s/will block/will not block ?
There was a problem hiding this comment.
aah, that's the whole point of this test. :0
Signed-off-by: Xin Zhuang <stevenzzz@google.com>
|
Thanks! |
|
CI issue looks legit. Can you merge master and take a look? /wait |
…al-look-longlive-srds Signed-off-by: Xin Zhuang <stevenzzz@google.com>
Signed-off-by: Xin Zhuang <stevenzzz@google.com>
Signed-off-by: Xin Zhuang <stevenzzz@google.com>
|
probably because of difference between libc++ and libstdc++, can't reproduce the error on my local box. |
|
/retest |
|
🤷♀️ nothing to rebuild. |
|
thank you.
…On Tue, Mar 3, 2020 at 7:44 PM Matt Klein ***@***.***> wrote:
Merged #9779 <#9779> into master.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#9779?email_source=notifications&email_token=AA2I6TBYKXLZQ7UU3X5JRCLRFWP5LA5CNFSM4KKLLZD2YY3PNVWWK3TUL52HS4DFWZEXG43VMVCXMZLOORHG65DJMZUWGYLUNFXW5KTDN5WW2ZLOORPWSZGOXBY23DQ#event-3094457742>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AA2I6TF6PDNZP5I43GPD2QTRFWP5LANCNFSM4KKLLZDQ>
.
--
Xin Zhuang
|
replace FactoryContext with ServerFactoryContext in router/..., So that SRDS/RDS/VHDS subscription could outlive their creator listener.
Signed-off-by: Xin Zhuang stevenzzz@google.com
Description:replace FactoryContext with ServerFactoryContext in router/..., So that SRDS/RDS/VHDS subscription could outlive their creator listener.
This PR:
Risk Level: Med
There is one behavior change, that previously during a listenerImpl's initManager initializing [which could be either Server::initManager or Listener::initManager], if there are multiple SRDS or RDS responses that contains sub-resource, their targets are added to the listener::initManager() and will bar on the listerner::initManager() ready. With this modification, the sub-resources contains in the second response of a SRDS/RDS may not be able to bar the local-init-manager's ready(), if the first response's sub-resources are initialized and called ready on the SRDS's local init-manger ready() aheader of the second's response's arrival.
before==> SRDS(A, B, C) bar Listener::initManager(),
now ===> SRDS::local_init_manager bars Listener::initManager(), and (A, B) bars on local_init_manager, (C) in a second response may or may not bar on Listener::initManager() depending on if (A,B) finish initialization before (C)'s arrival.
Testing: unit test
Docs Changes:
Release Notes:
[Optional Fixes #Issue]
[Optional Deprecated:]