refactor: SessionConfig.extensions instead ConfigOptions.extensions#550
refactor: SessionConfig.extensions instead ConfigOptions.extensions#550Rich-T-kid wants to merge 11 commits into
Conversation
Rich-T-kid
left a comment
There was a problem hiding this comment.
left some comments for reviewers on some of my rational in case it helps 🚀
d393923 to
302551b
Compare
|
🤔 I think you might have misunderstood the issue description in #538. The scope is not to move Citing the issue description
Here, |
e066089 to
aa5231b
Compare
56b6672 to
93990e6
Compare
|
| /// Gets the [DistributedConfig] from the [ConfigOptions]'s extensions. | ||
| pub fn from_config_options_mut(cfg: &mut ConfigOptions) -> Result<&mut Self, DataFusionError> { | ||
| let Some(distributed_cfg) = cfg.extensions.get_mut::<DistributedConfig>() else { | ||
| return plan_err!("DistributedConfig is not in ConfigOptions.extensions"); | ||
| }; | ||
| Ok(distributed_cfg) | ||
| /// Gets the [DistributedConfig] from the [SessionConfig], inserting a default if not present. | ||
| /// Always registers the `"distributed"` propagation prefix so coordinator-side settings are | ||
| /// included in gRPC headers sent to workers, regardless of call ordering. | ||
| pub fn from_session_config_mut(cfg: &mut SessionConfig) -> Result<&mut Self, DataFusionError> { | ||
| if cfg | ||
| .options() | ||
| .extensions | ||
| .get::<DistributedConfig>() | ||
| .is_none() | ||
| { | ||
| set_distributed_option_extension(cfg, DistributedConfig::default()); | ||
| } else { | ||
| register_config_extension_prefix(cfg, DistributedConfig::PREFIX); | ||
| } | ||
| Ok(cfg | ||
| .options_mut() | ||
| .extensions | ||
| .get_mut::<DistributedConfig>() | ||
| .unwrap()) | ||
| } |
There was a problem hiding this comment.
This change also seems unrelated to this PR, ca we keep the from_config_options_mut method?
There was a problem hiding this comment.
Also, that way of injecting DistributedConfig in the config.extensions... looks a bit too LLMy, it's overall pretty convoluted and unnecessary.
For ensuring that the DistributedConfig is always present in the SessionConfig, rather than doing on each from_session_config_mut, I'd instead just put in in SessionStateBuilderExt, because that's the only mandatory place people should go enable distributed-datafusion:
impl SessionStateBuilderExt for SessionStateBuilder {
fn with_distributed_planner(mut self) -> Self {
let config = self.config().get_or_insert_default().options_mut();
config
.optimizer
.enable_physical_uncorrelated_scalar_subquery = false;
if config.extensions.get::<DistributedConfig>().is_none() {
config.extensions.insert(DistributedConfig::default());
}
let prev = std::mem::take(self.query_planner());
self.with_query_planner(Arc::new(DistributedQueryPlanner { prev }))
}
}But not sure if this is necessary.
There was a problem hiding this comment.
Reverted this change. There were some test breaking due to this but I resolved them by adding
.with_distributed_option_extension(DistributedConfig::default()) to the sessionState builder
There was a problem hiding this comment.
I'm afraid we cannot do that, because that means that in the same way this is blowing up in our tests here, it will blow up in other people's codebase, se we need to find an alternative.
15a9f98 to
efb8121
Compare
| let d_cfg = DistributedConfig::from_task_context(&ctx.task_ctx)?; | ||
| let available_urls = d_cfg.worker_resolver().get_urls()?; | ||
| let available_urls = | ||
| get_distributed_worker_resolver(ctx.task_ctx.session_config())?.get_urls()?; |
There was a problem hiding this comment.
🤔 Damn... this is actually how people are expected to access their worker resolver, and the API is taking a hit on usability now...
There was a problem hiding this comment.
What comes to mind is, in the same way that we have the DistributedExt::with_distributed_worker_resolver and DistributedExt::set_distributed_worker_resolver, we can have the DistributedExt::get_distributed_worker_resolver for retrieving the worker resolver.
How does that sound?
| /// Gets the [DistributedConfig] from the [ConfigOptions]'s extensions. | ||
| pub fn from_config_options_mut(cfg: &mut ConfigOptions) -> Result<&mut Self, DataFusionError> { | ||
| let Some(distributed_cfg) = cfg.extensions.get_mut::<DistributedConfig>() else { | ||
| return plan_err!("DistributedConfig is not in ConfigOptions.extensions"); | ||
| }; | ||
| Ok(distributed_cfg) | ||
| /// Gets the [DistributedConfig] from the [SessionConfig], inserting a default if not present. | ||
| /// Always registers the `"distributed"` propagation prefix so coordinator-side settings are | ||
| /// included in gRPC headers sent to workers, regardless of call ordering. | ||
| pub fn from_session_config_mut(cfg: &mut SessionConfig) -> Result<&mut Self, DataFusionError> { | ||
| if cfg | ||
| .options() | ||
| .extensions | ||
| .get::<DistributedConfig>() | ||
| .is_none() | ||
| { | ||
| set_distributed_option_extension(cfg, DistributedConfig::default()); | ||
| } else { | ||
| register_config_extension_prefix(cfg, DistributedConfig::PREFIX); | ||
| } | ||
| Ok(cfg | ||
| .options_mut() | ||
| .extensions | ||
| .get_mut::<DistributedConfig>() | ||
| .unwrap()) | ||
| } |
There was a problem hiding this comment.
I'm afraid we cannot do that, because that means that in the same way this is blowing up in our tests here, it will blow up in other people's codebase, se we need to find an alternative.
| @@ -116,14 +118,15 @@ impl QueryPlanner for DistributedQueryPlanner { | |||
| } | |||
|
|
|||
| // Compute per-node task counts and inject `Network*Exec` nodes at the stage boundaries. | |||
| plan = inject_network_boundaries(plan, CardinalityBasedNetworkBoundaryBuilder, cfg).await?; | |||
| plan = inject_network_boundaries(plan, CardinalityBasedNetworkBoundaryBuilder, session_cfg) | |||
| .await?; | |||
|
|
|||
| plan = prepare_network_boundaries(plan)?; | |||
| if !plan.exists(|plan| Ok(plan.is_network_boundary()))? { | |||
| return Ok(original_plan); | |||
| } | |||
|
|
|||
| let plan = partial_reduce_below_network_shuffles(plan, cfg)?; | |||
| let plan = partial_reduce_below_network_shuffles(plan, session_config_opt)?; | |||
| let plan = push_fetch_into_network_coalesce(plan)?; | |||
|
|
|||
There was a problem hiding this comment.
Can we leave this unrelated variable name changes out of the PR? Not that there's a problem with the new names, but if for some reason we need to revert this PR in the future, not changing unrelated things will yield less chances of conflicts with other PRs.
|
|
||
| /// Gets the [DistributedConfig] from the [ConfigOptions]'s extensions. | ||
| pub fn from_config_options_mut(cfg: &mut ConfigOptions) -> Result<&mut Self, DataFusionError> { | ||
| let Some(distributed_cfg) = cfg.extensions.get_mut::<DistributedConfig>() else { |
There was a problem hiding this comment.
Any reason for removing the docs in this function?
| if options.extensions.get::<DistributedConfig>().is_none() { | ||
| options.extensions.insert(DistributedConfig::default()); | ||
| } | ||
| } |
There was a problem hiding this comment.
I'm realizing that setting it like this is not going to be enough, it's not registered as distributed config, it's registered as a normal config, so it will not make it through worker jumps.
There was a problem hiding this comment.
We can do here something like this:
pub(crate) fn set_distributed_worker_resolver(
cfg: &mut SessionConfig,
worker_resolver: impl WorkerResolver + 'static,
) {
DistributedConfig::ensure_in_config(cfg);
cfg.set_extension(Arc::new(WorkerResolverExtension(Arc::new(worker_resolver))));
}And let the ensure_in_config method be like this:
pub(crate) fn ensure_in_config(cfg: &mut SessionConfig) {
if cfg
.options()
.extensions
.get::<DistributedConfig>()
.is_none()
{
set_distributed_option_extension(cfg, DistributedConfig::default())
}
}We'll need to call the ensure_in_config method here, in set_distributed_channel_resolver and in SessionStateBuilderExt::with_distributed_planner
closes #538
What Changed
Move 4 non-serializable DistributedConfig fields to SessionConfig.extensions
__private_task_estimator,__private_channel_resolver,__private_worker_resolver, and__private_work_unit_feed_registryno longer live inConfigOptions.extensions. They are stored directly inSessionConfig.extensionsvia set_extension/get_extension, which removes all the hollow ConfigField + Debug stub impls these types required.The main structural change is
inject_network_boundariestaking &SessionConfig instead of &ConfigOptions so it can reach the AnyMap. All other changes are mechanical callsite updates.