You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We can't actually merge an upgrade yet because the version has not been published in crates.io yet. We can start testing in the meantime and then merge the upgrade once the new version is in crates.io.
│ +---------+-----------+
│ | MinTemp | RainToday |
│ +---------+-----------+
│ | 20.9 | No |
│+| 20.9 | No |
│+| 20.9 | No |
+---------+-----------+
We see 3 results when there should be 1, this only happens in distributed execution. Talking with @gabotechs the suspicion is that this breaks PartitionIsolatorExec assumption that each ExecutionPlan partition only reads its corresponding files. With #21351 the parquet files are pulled from a shared queue all partitions share. In distributed mode, because each task gets its own DataSourceExec instance, it can read a file that was already read by another DataSourceExec, resulting in duplicated results.
If ScalarSubqueryExec and the node holding the ScalarSubqueryExpr are in different stages, the query fails during deserialization with the following error Internal("ScalarSubqueryExpr can only be deserialized as part of a surrounding ScalarSubqueryExec") . Even if we edited the decoder to create a fresh ScalarSubqueryResults on the worker, the result wouldn't be correct I think, the worker's slots are a different Arc from the coordinator, so the writer would never fill them. This looks like a similar problem to Dynamic Filtering -- although DynamicFilterPhysicalExpr does not fail on serialization and we will never see correctness issues since it's an optimization.
We also found the issue described in the following revert PR: DataDog/datafusion#135 -- not really sure what's going on, I will open a follow-up issue soon
We also found the issue described in the following revert PR: DataDog/datafusion#135 -- not really sure what's going on, I will open a follow-up issue soon
I managed to get this fixed I think, it's not really an upstream bug, it's in this codebase, will post a PR soon
When a partitioned HashJoinExec partition has an empty build side it now short-circuits to Completed and drops its probe-side input without ever polling it. When that probe is a NetworkShuffleExec, the remote request is issued lazily on first poll — so dropping it before the first poll means the request is never sent, the upstream worker never execute()s that partition of its shared RepartitionExec, that output channel is never drained, the distributor latches its global gate (closes once all output channels are non-empty), the pump blocks, and every sibling consumer of that shared RepartitionExec deadlocks.
This is distinct from the demux fix in #473: that keeps an already-running demux alive when a receiver drops; here the demux for the abandoned partition never starts.
Activity
LiaCastaneda commentedon May 25, 2026
Testing new version in #465
There are some issues we are investigating now
LiaCastaneda commentedon May 25, 2026
After bisecting, we found two breaking changes not compatible with some assumptions we make in DDF:
custom_extension_codecwith correctness issues :We see 3 results when there should be 1, this only happens in distributed execution. Talking with @gabotechs the suspicion is that this breaks
PartitionIsolatorExecassumption that eachExecutionPlanpartition only reads its corresponding files. With #21351 the parquet files are pulled from a shared queue all partitions share. In distributed mode, because each task gets its ownDataSourceExecinstance, it can read a file that was already read by anotherDataSourceExec, resulting in duplicated results.ScalarSubqueryExecwhich structure holds a shared state:where the a given subquery has an index to fill it's corresponding slot at runtime:
If
ScalarSubqueryExecand the node holding theScalarSubqueryExprare in different stages, the query fails during deserialization with the following errorInternal("ScalarSubqueryExpr can only be deserialized as part of a surrounding ScalarSubqueryExec"). Even if we edited the decoder to create a freshScalarSubqueryResultson the worker, the result wouldn't be correct I think, the worker's slots are a differentArcfrom the coordinator, so the writer would never fill them. This looks like a similar problem to Dynamic Filtering -- althoughDynamicFilterPhysicalExprdoes not fail on serialization and we will never see correctness issues since it's an optimization.LiaCastaneda commentedon May 26, 2026
Opened apache/datafusion#22530 for point 2.
LiaCastaneda commentedon May 27, 2026
We also found the issue described in the following revert PR: DataDog/datafusion#135 -- not really sure what's going on, I will open a follow-up issue soon
Introduce DistributedLeafExec (#467)
LiaCastaneda commentedon May 28, 2026
Opened an issue to solve permanently point 2 #471
gabotechs commentedon May 28, 2026
I managed to get this fixed I think, it's not really an upstream bug, it's in this codebase, will post a PR soon
gabotechs commentedon May 28, 2026
Fixed!
Gate new ScalarSubqueryExec node behind session property (apache#22530)
Gate new ScalarSubqueryExec node behind session property (apache#22530)
gabotechs commentedon Jun 2, 2026
Upgrade branch is green now #465 🎉 . Once DataFusion releases 54, I think we are done here.
gabotechs commentedon Jun 3, 2026
I'm seeing some deadlocks in the CI...
I verified that
maindoes not deadlock, so it must be something related to the upgrade...gabotechs commentedon Jun 3, 2026
Root-caused the deadlocks (
task_estimator_test::custom_routing_join*and friends): it's DataFusion #21068 — "Skip probe-side consumption when hash join build side is empty", new in branch-54.When a partitioned
HashJoinExecpartition has an empty build side it now short-circuits toCompletedand drops its probe-side input without ever polling it. When that probe is aNetworkShuffleExec, the remote request is issued lazily on first poll — so dropping it before the first poll means the request is never sent, the upstream worker neverexecute()s that partition of its sharedRepartitionExec, that output channel is never drained, the distributor latches its global gate (closes once all output channels are non-empty), the pump blocks, and every sibling consumer of that sharedRepartitionExecdeadlocks.This is distinct from the demux fix in #473: that keeps an already-running demux alive when a receiver drops; here the demux for the abandoned partition never starts.
gabotechs commentedon Jun 3, 2026
This should solve it: #482 (comment)
I don't love that approach though, it feels a bit like a workaround, but I don't have a better idea
Upgrade DF to v54 (#465)