[do not review] coordinator: forward merged dynamic filters to consumers - #637
Open
jayshrivastava wants to merge 2 commits into
Open
[do not review] coordinator: forward merged dynamic filters to consumers#637jayshrivastava wants to merge 2 commits into
jayshrivastava wants to merge 2 commits into
Conversation
This was referenced Aug 13, 2026
jayshrivastava
force-pushed
the
js/5-forward-dynamic-filters
branch
from
August 13, 2026 19:27
3229903 to
ad77338
Compare
jayshrivastava
force-pushed
the
js/5-forward-dynamic-filters
branch
from
August 17, 2026 18:54
ad77338 to
15e6602
Compare
jayshrivastava
force-pushed
the
js/5-forward-dynamic-filters
branch
2 times, most recently
from
August 17, 2026 19:38
56fee53 to
1572836
Compare
jayshrivastava
force-pushed
the
js/5-forward-dynamic-filters
branch
from
August 18, 2026 18:15
1572836 to
296026d
Compare
jayshrivastava
force-pushed
the
js/5-forward-dynamic-filters
branch
2 times, most recently
from
August 21, 2026 16:28
e04ceac to
e720301
Compare
jayshrivastava
force-pushed
the
js/5-forward-dynamic-filters
branch
from
August 21, 2026 16:48
e720301 to
7a74a70
Compare
jayshrivastava
force-pushed
the
js/5-forward-dynamic-filters
branch
from
August 21, 2026 20:58
7a74a70 to
c1b6398
Compare
jayshrivastava
force-pushed
the
js/5-forward-dynamic-filters
branch
from
August 22, 2026 15:00
c1b6398 to
6a70c73
Compare
jayshrivastava
force-pushed
the
js/5-forward-dynamic-filters
branch
2 times, most recently
from
August 23, 2026 15:27
0a68111 to
42cb2ac
Compare
jayshrivastava
force-pushed
the
js/5-forward-dynamic-filters
branch
from
August 23, 2026 15:35
42cb2ac to
f9c7c5d
Compare
jayshrivastava
force-pushed
the
js/5-forward-dynamic-filters
branch
from
August 23, 2026 19:07
f9c7c5d to
9a949f2
Compare
jayshrivastava
marked this pull request as ready for review
August 23, 2026 19:28
jayshrivastava
force-pushed
the
js/5-forward-dynamic-filters
branch
from
September 3, 2026 22:03
d0694d9 to
e77fd82
Compare
jayshrivastava
added a commit
that referenced
this pull request
Sep 8, 2026
## Stack This stack of PRs implements distributed dynamic filtering #528 1. #623 <- you are here 2. #634 3. #635 4. #636 5. #637 6. #639 Closes: #529 ## Problem Post df-55 upgrade, dynamic filters should work in the worker-local case. There's no way to observe them working other than looking at metrics. ``` ┌───── Stage 2 ── tasks=1 │ AggregateExec: Final COUNT(*) │ [Stage 1] => NetworkCoalesceExec └────────────────────────────────────────────────── ┌───── Stage 1 ── tasks=2 │ HashJoinExec: orders.customer_id = selected_customers.customer_id │ DistributedLeafExec: | ... │ DistributedLeafExec: │ t0: DataSourceExec: predicate=DynamicFilter [ empty ] │ t1: DataSourceExec: predicate=DynamicFilter [ empty ] └──────────────────────────────────────────────── ``` Ideally we want the final filters visible when displaying plans. ## Solution This PR adds a new protocol which is basically identical to the metrics protocol. Even the `MetricsStore` is now just `Store` and is generic over `TaskMetrics` and `TaskCompletedDynamicFilters` (contains completed dynamic filters for a task). ```rust pub(crate) type MetricsStore = Store<TaskMetrics>; pub(crate) type CompletedDynamicFilterStore = Store<TaskCompletedDynamicFilters>; ``` Similar to the metrics protocol, workers now collect completed dynamic filters and send them back to the coordinator. ``` Coordinator Worker ----------- ------ Create independent display copies | +-- SetPlan(task 0, filter IDs) -------> Decode plan | | | | execute | | | | | | | | | | task finishes | v |<----- TaskDynamicFilters ----- Serialize completed filters from the consumers | v ``` Then, at display time, we call `apply_reports_to_distributed_leaves` which traverses the `plan_for_viz` and updates the dynamic filters for all the variants: ``` DistributedLeafExec task 0: DynamicFilter [ key@0 >= 1 AND key@0 <= 10 ] task 1: DynamicFilter [ empty ] ``` ## Notes ### Duplicate RPC Messages We will eventually have more dynamic filter RPCs which manage the worker -> coordinator -> merge -> worker flow mentioned in #553. In theory, the coordinator will know at `merge` time what the completed filters are, making the `TaskCompletedDynamicFilters` and final worker -> coordinator message in this PR irrelevant. However, I think having these mechanisms be separate is good because a) it helps us validate that the dynamic filter coordinator -> worker flow work using external "oracle", and b) there's no guarantee that the coordinator -> worker propagation happens before the query is done (ex. the `DataSourceExec` may not block execution waiting for dynamic filters), so it's good to have a separate way to know if the final `DataSourceExec` applied a filter or not. ### `AND true` and empty filters ``` DynamicFilter [ sr_returned_date_sk@0 >= 2451545 AND sr_returned_date_sk@0 <= 2451910 AND true ] AND DynamicFilter [ empty ] ``` In this filter `AND true` occurs because of apache/datafusion#24277. The first `DynamicFilter` is active but we lose the `HashTableLookupExpr` when serializing it to send back to the coordinator. The 2nd filter is `DynamicFilter [ empty ]` because this is a dynamic filter produced by a remote producer, which does not get propagated to this node yet. This will be fixed later. ### Displaying Dynamic Filters Protocol is as similar to the metrics protocol as possible. Due to double wrapping (`MetricsWrapperExec` wraps `DistributedLeafExec`, it's tricky to do the dynamic filter rewrite after doing the metrics rewrite. So `rewrite_distributed_plan_with_dynamic_filters` has to be called **first**. ```rust let plan = rewrite_distributed_plan_with_dynamic_filters(plan).await?; let plan = rewrite_distributed_plan_with_metrics(plan, DistributedMetricsFormat::Aggregated).await?; println!("{}", display_plan_ascii(plan.as_ref(), true)); ``` ## Testing - Tests in `tests/dynamic_filtering.rs`
jayshrivastava
force-pushed
the
js/5-forward-dynamic-filters
branch
from
September 8, 2026 13:28
e77fd82 to
0abbbff
Compare
Route each completed coordinator merge over the existing query-scoped
task stream. Deliver updates at most once, keep runtime filtering fail-open,
and release retained senders before signaling query EOS.
producer reports --> coordinator merge
|
+---------+---------+
v v
consumer task 0 consumer task 1
jayshrivastava
force-pushed
the
js/5-forward-dynamic-filters
branch
from
September 9, 2026 02:03
0abbbff to
d027946
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stack
This stack of PRs implements distributed dynamic filtering #528
Details
Route each merged dynamic filter to the tasks that consume them using the existing
CoordinatorToWorkerchannels.