1use std::any::Any;
16use std::sync::Arc;
17
18use common_query::request::{
19 DynFilterPayload, INITIAL_REMOTE_DYN_FILTER_REGISTRATIONS_EXTENSION_KEY, InitialDynFilterReg,
20 InitialDynFilterRegs, InitialDynFilterSnapshot, REMOTE_DYN_FILTER_PAYLOAD_MAX_BYTES,
21};
22use datafusion_common::Result;
23use datafusion_physical_expr::PhysicalExpr;
24use datafusion_physical_expr::expressions::DynamicFilterPhysicalExpr;
25use session::context::{QueryContext, QueryContextRef};
26use store_api::storage::RegionId;
27
28use crate::dist_plan::filter_id::build_remote_dyn_filter_id;
29use crate::dist_plan::{FilterId, QueryDynFilterRegistry, RemoteDynFilterProducerId, Subscriber};
30
31#[derive(Debug, Clone)]
32pub(crate) struct CapturedDynFilter {
33 filter_id: FilterId,
34 initial_registration: InitialDynFilterReg,
35 pub(crate) alive_dyn_filter: Arc<DynamicFilterPhysicalExpr>,
36}
37
38#[derive(Debug, Clone)]
39pub(crate) struct RemoteDynFilterPushdown {
40 pub(crate) captured_dyn_filters: Vec<CapturedDynFilter>,
41 pub(crate) pushed_down: Vec<bool>,
43}
44
45pub(crate) fn capture_remote_dyn_filters_for_pushdown(
46 remote_dyn_filter_producer_id: RemoteDynFilterProducerId,
47 parent_filters: Vec<Arc<dyn datafusion::physical_plan::PhysicalExpr>>,
48) -> RemoteDynFilterPushdown {
49 let mut pushed_down = Vec::with_capacity(parent_filters.len());
50 let mut captured_dyn_filters = Vec::new();
51
52 for (producer_local_ordinal, filter) in parent_filters.into_iter().enumerate() {
53 let Some(alive_dyn_filter) = downcast_dynamic_filter(filter) else {
54 pushed_down.push(false);
55 continue;
56 };
57
58 match build_captured_dyn_filter(
59 remote_dyn_filter_producer_id,
60 producer_local_ordinal,
61 alive_dyn_filter,
62 ) {
63 Ok(captured_dyn_filter) => {
64 pushed_down.push(true);
65 captured_dyn_filters.push(captured_dyn_filter);
66 }
67 Err(error) => {
68 common_telemetry::warn!(error; "Remote dyn filter is not pushed down because initial registration cannot be built");
69 pushed_down.push(false);
70 }
71 }
72 }
73
74 if let Err(error) = validate_initial_registrations_for_pushdown(&captured_dyn_filters) {
75 common_telemetry::warn!(error; "Remote dyn filters are not pushed down because initial registrations are invalid");
76 return RemoteDynFilterPushdown {
77 captured_dyn_filters: Vec::new(),
78 pushed_down: vec![false; pushed_down.len()],
79 };
80 }
81
82 RemoteDynFilterPushdown {
83 captured_dyn_filters,
84 pushed_down,
85 }
86}
87
88fn downcast_dynamic_filter(
89 expr: Arc<dyn datafusion::physical_plan::PhysicalExpr>,
90) -> Option<Arc<DynamicFilterPhysicalExpr>> {
91 (expr as Arc<dyn Any + Send + Sync + 'static>)
92 .downcast::<DynamicFilterPhysicalExpr>()
93 .ok()
94}
95
96pub(crate) fn register_dyn_filters_for_region(
97 registry: &QueryDynFilterRegistry,
98 region_id: RegionId,
99 captured_dyn_filters: &[CapturedDynFilter],
100) {
101 for captured_dyn_filter in captured_dyn_filters {
102 let _ = registry.register_remote_dyn_filter(
103 captured_dyn_filter.filter_id.clone(),
104 captured_dyn_filter.alive_dyn_filter.clone(),
105 );
106 let _ = registry
107 .register_subscriber(&captured_dyn_filter.filter_id, Subscriber::new(region_id));
108 }
109}
110
111fn build_captured_dyn_filter(
112 remote_dyn_filter_producer_id: RemoteDynFilterProducerId,
113 producer_local_ordinal: usize,
114 alive_dyn_filter: Arc<DynamicFilterPhysicalExpr>,
115) -> Result<CapturedDynFilter> {
116 let children = alive_dyn_filter
117 .children()
118 .into_iter()
119 .cloned()
120 .collect::<Vec<_>>();
121 let filter_id = build_remote_dyn_filter_id(
122 remote_dyn_filter_producer_id,
123 producer_local_ordinal,
124 &children,
125 )?;
126 let initial_registration =
127 InitialDynFilterReg::from_filter_id_and_children(filter_id.to_string(), &children)?;
128
129 Ok(CapturedDynFilter {
130 filter_id,
131 initial_registration: attach_initial_snapshot(initial_registration, &alive_dyn_filter),
132 alive_dyn_filter,
133 })
134}
135
136fn validate_initial_registrations_for_pushdown(
137 captured_dyn_filters: &[CapturedDynFilter],
138) -> std::result::Result<(), String> {
139 let regs = build_initial_dyn_filter_regs_for_region(captured_dyn_filters);
140 regs.validate_default_bounds()?;
141 regs.to_extension_value()
142 .map_err(|error| error.to_string())?;
143 Ok(())
144}
145
146fn attach_initial_snapshot(
147 initial_registration: InitialDynFilterReg,
148 alive_dyn_filter: &DynamicFilterPhysicalExpr,
149) -> InitialDynFilterReg {
150 let Some(initial_snapshot) = initial_snapshot(alive_dyn_filter) else {
151 return initial_registration;
152 };
153
154 initial_registration.with_initial_snapshot(initial_snapshot)
155}
156
157fn initial_snapshot(
158 alive_dyn_filter: &DynamicFilterPhysicalExpr,
159) -> Option<InitialDynFilterSnapshot> {
160 let generation = alive_dyn_filter.snapshot_generation();
161 let current = match alive_dyn_filter.current() {
162 Ok(current) => current,
163 Err(error) => {
164 common_telemetry::warn!(error; "Failed to read remote dyn filter initial snapshot");
165 return None;
166 }
167 };
168
169 let payload = match DynFilterPayload::from_datafusion_expr(
170 ¤t,
171 REMOTE_DYN_FILTER_PAYLOAD_MAX_BYTES,
172 ) {
173 Ok(payload) => payload,
174 Err(error) => {
175 common_telemetry::warn!(error; "Failed to encode remote dyn filter initial snapshot");
176 return None;
177 }
178 };
179
180 let is_complete = false;
182 Some(InitialDynFilterSnapshot::new(
183 payload,
184 generation,
185 is_complete,
186 ))
187}
188
189fn build_initial_dyn_filter_regs_for_region(
190 captured_dyn_filters: &[CapturedDynFilter],
191) -> InitialDynFilterRegs {
192 InitialDynFilterRegs::new(
193 captured_dyn_filters
194 .iter()
195 .map(|captured| captured.initial_registration.clone())
196 .collect(),
197 )
198}
199
200pub(crate) fn query_context_with_initial_dyn_filter_regs(
201 query_ctx: &QueryContextRef,
202 region_id: RegionId,
203 captured_dyn_filters: &[CapturedDynFilter],
204) -> QueryContext {
205 let mut region_query_ctx = query_ctx.as_ref().clone();
206 let regs = build_initial_dyn_filter_regs_for_region(captured_dyn_filters);
207 if regs.is_empty() {
208 return region_query_ctx;
209 }
210
211 if let Err(error) = regs.validate_default_bounds() {
212 common_telemetry::warn!(error; "Dropping initial remote dyn filter registrations for region {} that exceed configured bounds", region_id);
213 return region_query_ctx;
214 }
215
216 match regs.to_extension_value() {
217 Ok(serialized) => region_query_ctx.set_extension(
218 INITIAL_REMOTE_DYN_FILTER_REGISTRATIONS_EXTENSION_KEY,
219 serialized,
220 ),
221 Err(error) => {
222 common_telemetry::warn!(error; "Failed to serialize initial remote dyn filter registrations");
223 }
224 }
225
226 region_query_ctx
227}
228
229#[cfg(test)]
230mod tests {
231 use std::fmt;
232 use std::hash::{Hash, Hasher};
233
234 use datafusion::execution::TaskContext;
235 use datafusion_common::ScalarValue;
236 use datafusion_expr::ColumnarValue;
237 use datafusion_physical_expr::expressions::{Column, lit};
238 use session::query_id::QueryId;
239 use uuid::Uuid;
240
241 use super::*;
242
243 #[derive(Debug)]
244 struct UnserializableExpr;
245
246 impl fmt::Display for UnserializableExpr {
247 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
248 write!(f, "unserializable_expr")
249 }
250 }
251
252 impl Hash for UnserializableExpr {
253 fn hash<H: Hasher>(&self, state: &mut H) {
254 "unserializable_expr".hash(state);
255 }
256 }
257
258 impl PartialEq for UnserializableExpr {
259 fn eq(&self, _other: &Self) -> bool {
260 true
261 }
262 }
263
264 impl Eq for UnserializableExpr {}
265
266 impl datafusion_physical_expr::PhysicalExpr for UnserializableExpr {
267 fn as_any(&self) -> &dyn Any {
268 self
269 }
270
271 fn data_type(
272 &self,
273 _input_schema: &arrow_schema::Schema,
274 ) -> datafusion_common::Result<arrow_schema::DataType> {
275 Ok(arrow_schema::DataType::Boolean)
276 }
277
278 fn nullable(
279 &self,
280 _input_schema: &arrow_schema::Schema,
281 ) -> datafusion_common::Result<bool> {
282 Ok(false)
283 }
284
285 fn evaluate(
286 &self,
287 _batch: &common_recordbatch::DfRecordBatch,
288 ) -> datafusion_common::Result<ColumnarValue> {
289 Ok(ColumnarValue::Scalar(ScalarValue::Boolean(Some(true))))
290 }
291
292 fn children(&self) -> Vec<&Arc<dyn datafusion_physical_expr::PhysicalExpr>> {
293 Vec::new()
294 }
295
296 fn with_new_children(
297 self: Arc<Self>,
298 _children: Vec<Arc<dyn datafusion_physical_expr::PhysicalExpr>>,
299 ) -> datafusion_common::Result<Arc<dyn datafusion_physical_expr::PhysicalExpr>> {
300 Ok(self)
301 }
302
303 fn fmt_sql(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
304 write!(f, "{self}")
305 }
306 }
307
308 fn test_query_id(value: u128) -> QueryId {
309 QueryId::from(Uuid::from_u128(value))
310 }
311
312 fn test_remote_dyn_filter_producer_id(value: u64) -> RemoteDynFilterProducerId {
313 RemoteDynFilterProducerId::new(value)
314 }
315
316 fn test_captured_dyn_filter(
317 remote_dyn_filter_producer_id: RemoteDynFilterProducerId,
318 producer_local_ordinal: usize,
319 column_name: &str,
320 column_index: usize,
321 ) -> CapturedDynFilter {
322 build_captured_dyn_filter(
323 remote_dyn_filter_producer_id,
324 producer_local_ordinal,
325 Arc::new(DynamicFilterPhysicalExpr::new(
326 vec![Arc::new(Column::new(column_name, column_index)) as Arc<_>],
327 lit(true) as _,
328 )),
329 )
330 .unwrap()
331 }
332
333 fn test_dyn_filter_with_snapshot_payload(
334 column_name: &str,
335 column_index: usize,
336 payload_bytes: usize,
337 ) -> Arc<DynamicFilterPhysicalExpr> {
338 let dyn_filter = Arc::new(DynamicFilterPhysicalExpr::new(
339 vec![Arc::new(Column::new(column_name, column_index)) as Arc<_>],
340 lit(true) as _,
341 ));
342 dyn_filter
343 .update(lit(ScalarValue::Utf8(Some("x".repeat(payload_bytes)))) as _)
344 .unwrap();
345 dyn_filter
346 }
347
348 #[test]
349 fn capture_remote_dyn_filters_for_pushdown_preserves_parent_filter_ordinals() {
350 let parent_filters = vec![
351 Arc::new(Column::new("service", 0)) as Arc<dyn datafusion::physical_plan::PhysicalExpr>,
352 Arc::new(DynamicFilterPhysicalExpr::new(
353 vec![Arc::new(Column::new("host", 1)) as Arc<_>],
354 lit(true) as _,
355 )) as Arc<dyn datafusion::physical_plan::PhysicalExpr>,
356 Arc::new(Column::new("zone", 2)) as Arc<dyn datafusion::physical_plan::PhysicalExpr>,
357 Arc::new(DynamicFilterPhysicalExpr::new(
358 vec![Arc::new(Column::new("pod", 3)) as Arc<_>],
359 lit(true) as _,
360 )) as Arc<dyn datafusion::physical_plan::PhysicalExpr>,
361 ];
362
363 let remote_dyn_filter_producer_id = test_remote_dyn_filter_producer_id(42);
364 let captured =
365 capture_remote_dyn_filters_for_pushdown(remote_dyn_filter_producer_id, parent_filters)
366 .captured_dyn_filters;
367
368 assert_eq!(captured.len(), 2);
369 assert_eq!(
370 captured[0].filter_id.remote_dyn_filter_producer_id(),
371 remote_dyn_filter_producer_id
372 );
373 assert_eq!(
374 captured[1].filter_id.remote_dyn_filter_producer_id(),
375 remote_dyn_filter_producer_id
376 );
377 assert_eq!(captured[0].filter_id.producer_ordinal(), 1);
378 assert_eq!(captured[1].filter_id.producer_ordinal(), 3);
379 }
380
381 #[test]
382 fn capture_remote_dyn_filters_for_pushdown_marks_only_valid_initial_regs() {
383 let parent_filters = vec![
384 Arc::new(Column::new("service", 0)) as Arc<dyn datafusion::physical_plan::PhysicalExpr>,
385 Arc::new(DynamicFilterPhysicalExpr::new(
386 vec![Arc::new(Column::new("host", 1)) as Arc<_>],
387 lit(true) as _,
388 )) as Arc<dyn datafusion::physical_plan::PhysicalExpr>,
389 Arc::new(Column::new("zone", 2)) as Arc<dyn datafusion::physical_plan::PhysicalExpr>,
390 ];
391
392 let remote_dyn_filter_producer_id = test_remote_dyn_filter_producer_id(42);
393 let pushdown =
394 capture_remote_dyn_filters_for_pushdown(remote_dyn_filter_producer_id, parent_filters);
395
396 assert_eq!(pushdown.pushed_down, vec![false, true, false]);
397 assert_eq!(pushdown.captured_dyn_filters.len(), 1);
398 assert_eq!(
399 pushdown.captured_dyn_filters[0]
400 .filter_id
401 .remote_dyn_filter_producer_id(),
402 remote_dyn_filter_producer_id
403 );
404 assert_eq!(
405 pushdown.captured_dyn_filters[0]
406 .filter_id
407 .producer_ordinal(),
408 1
409 );
410 assert!(
411 pushdown.captured_dyn_filters[0]
412 .initial_registration
413 .initial_snapshot
414 .is_some()
415 );
416 }
417
418 #[test]
419 fn capture_remote_dyn_filters_for_pushdown_rejects_unencodable_registration() {
420 let parent_filters = vec![Arc::new(DynamicFilterPhysicalExpr::new(
421 vec![Arc::new(UnserializableExpr) as Arc<_>],
422 lit(true) as _,
423 ))
424 as Arc<dyn datafusion::physical_plan::PhysicalExpr>];
425
426 let pushdown = capture_remote_dyn_filters_for_pushdown(
427 test_remote_dyn_filter_producer_id(42),
428 parent_filters,
429 );
430
431 assert_eq!(pushdown.pushed_down, vec![false]);
432 assert!(pushdown.captured_dyn_filters.is_empty());
433 }
434
435 #[test]
436 fn capture_remote_dyn_filters_for_pushdown_attaches_initial_snapshot() {
437 let parent_filters = vec![Arc::new(DynamicFilterPhysicalExpr::new(
438 vec![Arc::new(Column::new("host", 1)) as Arc<_>],
439 lit(true) as _,
440 ))
441 as Arc<dyn datafusion::physical_plan::PhysicalExpr>];
442
443 let pushdown = capture_remote_dyn_filters_for_pushdown(
444 test_remote_dyn_filter_producer_id(42),
445 parent_filters,
446 );
447
448 assert_eq!(pushdown.pushed_down, vec![true]);
449 assert!(
450 pushdown.captured_dyn_filters[0]
451 .initial_registration
452 .initial_snapshot
453 .is_some()
454 );
455 }
456
457 #[test]
458 fn capture_remote_dyn_filters_for_pushdown_attaches_initial_snapshot_after_update() {
459 let dyn_filter = Arc::new(DynamicFilterPhysicalExpr::new(
460 vec![Arc::new(Column::new("host", 1)) as Arc<_>],
461 lit(true) as _,
462 ));
463 dyn_filter.update(lit(false) as _).unwrap();
464 let parent_filters = vec![dyn_filter as Arc<dyn datafusion::physical_plan::PhysicalExpr>];
465
466 let pushdown = capture_remote_dyn_filters_for_pushdown(
467 test_remote_dyn_filter_producer_id(42),
468 parent_filters,
469 );
470
471 assert_eq!(pushdown.pushed_down, vec![true]);
472 let snapshot = pushdown.captured_dyn_filters[0]
473 .initial_registration
474 .initial_snapshot
475 .as_ref()
476 .unwrap();
477 assert_eq!(snapshot.generation, 2);
478 assert!(!snapshot.is_complete);
479 assert!(matches!(
480 snapshot.payload,
481 DynFilterPayload::Datafusion(ref bytes) if !bytes.is_empty()
482 ));
483 }
484
485 #[test]
486 fn capture_remote_dyn_filters_for_pushdown_rejects_oversized_snapshots() {
487 let oversized_total_snapshot_bytes = REMOTE_DYN_FILTER_PAYLOAD_MAX_BYTES * 3 / 5;
488 let parent_filters = vec![
489 test_dyn_filter_with_snapshot_payload("host", 0, oversized_total_snapshot_bytes)
490 as Arc<dyn datafusion::physical_plan::PhysicalExpr>,
491 test_dyn_filter_with_snapshot_payload("pod", 1, oversized_total_snapshot_bytes)
492 as Arc<dyn datafusion::physical_plan::PhysicalExpr>,
493 ];
494
495 let pushdown = capture_remote_dyn_filters_for_pushdown(
496 test_remote_dyn_filter_producer_id(42),
497 parent_filters,
498 );
499
500 assert_eq!(pushdown.pushed_down, vec![false, false]);
501 assert!(pushdown.captured_dyn_filters.is_empty());
502 }
503
504 #[test]
505 fn capture_remote_dyn_filters_for_pushdown_rejects_too_many_regs_with_snapshots() {
506 const TOO_MANY_INITIAL_REGS: usize = 65;
507
508 let parent_filters = (0..TOO_MANY_INITIAL_REGS)
509 .map(|ordinal| {
510 test_dyn_filter_with_snapshot_payload(&format!("host_{ordinal}"), ordinal, 1)
511 as Arc<dyn datafusion::physical_plan::PhysicalExpr>
512 })
513 .collect::<Vec<_>>();
514
515 let pushdown = capture_remote_dyn_filters_for_pushdown(
516 test_remote_dyn_filter_producer_id(42),
517 parent_filters,
518 );
519
520 assert!(pushdown.captured_dyn_filters.is_empty());
521 assert_eq!(pushdown.pushed_down, vec![false; TOO_MANY_INITIAL_REGS]);
522 }
523
524 #[test]
525 fn capture_remote_dyn_filters_for_pushdown_rejects_regs_exceeding_bounds() {
526 const TOO_MANY_INITIAL_REGS: usize = 65;
527
528 let parent_filters = (0..TOO_MANY_INITIAL_REGS)
529 .map(|_| {
530 Arc::new(DynamicFilterPhysicalExpr::new(
531 vec![Arc::new(Column::new("host", 0)) as Arc<_>],
532 lit(true) as _,
533 )) as Arc<dyn datafusion::physical_plan::PhysicalExpr>
534 })
535 .collect::<Vec<_>>();
536
537 let pushdown = capture_remote_dyn_filters_for_pushdown(
538 test_remote_dyn_filter_producer_id(42),
539 parent_filters,
540 );
541
542 assert!(pushdown.captured_dyn_filters.is_empty());
543 assert_eq!(pushdown.pushed_down, vec![false; TOO_MANY_INITIAL_REGS]);
544 }
545
546 #[test]
547 fn register_dyn_filters_for_region_reuses_existing_entry() {
548 let registry = QueryDynFilterRegistry::new(test_query_id(1));
549 let captured_dyn_filters = vec![test_captured_dyn_filter(
550 test_remote_dyn_filter_producer_id(42),
551 2,
552 "host",
553 0,
554 )];
555 let first_region_id = RegionId::new(1024, 7);
556 let second_region_id = RegionId::new(1024, 8);
557
558 register_dyn_filters_for_region(®istry, first_region_id, &captured_dyn_filters);
559 register_dyn_filters_for_region(®istry, second_region_id, &captured_dyn_filters);
560
561 assert_eq!(registry.entry_count(), 1);
562 let entry = registry.entries().pop().unwrap();
563 assert_eq!(
564 entry.filter_id().remote_dyn_filter_producer_id(),
565 test_remote_dyn_filter_producer_id(42)
566 );
567 assert_eq!(entry.filter_id().producer_ordinal(), 2);
568 let subscribers = entry.subscribers();
569 assert_eq!(subscribers.len(), 2);
570 assert!(
571 subscribers
572 .iter()
573 .any(|subscriber| subscriber.region_id() == first_region_id)
574 );
575 assert!(
576 subscribers
577 .iter()
578 .any(|subscriber| subscriber.region_id() == second_region_id)
579 );
580 }
581
582 #[test]
583 fn register_dyn_filters_for_region_keeps_independent_producer_ids_distinct() {
584 let registry = QueryDynFilterRegistry::new(test_query_id(1));
585 let region_id = RegionId::new(1024, 7);
586 let make_filter = |remote_dyn_filter_producer_id| {
587 test_captured_dyn_filter(remote_dyn_filter_producer_id, 2, "host", 0)
588 };
589
590 register_dyn_filters_for_region(
591 ®istry,
592 region_id,
593 &[make_filter(test_remote_dyn_filter_producer_id(42))],
594 );
595 register_dyn_filters_for_region(
596 ®istry,
597 region_id,
598 &[make_filter(test_remote_dyn_filter_producer_id(43))],
599 );
600
601 assert_eq!(registry.entry_count(), 2);
602 }
603
604 #[test]
605 fn query_context_includes_region_initial_dyn_filter_regs() {
606 let captured_dyn_filters = vec![test_captured_dyn_filter(
607 test_remote_dyn_filter_producer_id(42),
608 2,
609 "host",
610 0,
611 )];
612 let region_id = RegionId::new(1024, 7);
613 let query_ctx = QueryContext::arc();
614
615 let region_query_ctx = query_context_with_initial_dyn_filter_regs(
616 &query_ctx,
617 region_id,
618 &captured_dyn_filters,
619 );
620 let extension = region_query_ctx
621 .extension(INITIAL_REMOTE_DYN_FILTER_REGISTRATIONS_EXTENSION_KEY)
622 .unwrap();
623 let regs = InitialDynFilterRegs::from_extension_value(extension).unwrap();
624 let decoded_children = regs.regs[0]
625 .decode_children(
626 &TaskContext::default(),
627 &arrow_schema::Schema::new(vec![arrow_schema::Field::new(
628 "host",
629 arrow_schema::DataType::Utf8,
630 false,
631 )]),
632 1024,
633 )
634 .unwrap();
635 assert_eq!(regs.regs.len(), 1);
636 assert_eq!(
637 regs.regs[0].filter_id,
638 captured_dyn_filters[0].filter_id.to_string()
639 );
640 assert_eq!(decoded_children.len(), 1);
641 assert!(decoded_children[0].as_any().is::<Column>());
642 }
643
644 #[test]
645 fn query_context_drops_initial_regs_when_duplicate_filter_ids_exceed_bounds() {
646 let captured_dyn_filters = vec![
647 test_captured_dyn_filter(test_remote_dyn_filter_producer_id(42), 2, "host", 0),
648 test_captured_dyn_filter(test_remote_dyn_filter_producer_id(42), 2, "host", 0),
649 ];
650 let region_id = RegionId::new(1024, 7);
651 let query_ctx = QueryContext::arc();
652
653 let region_query_ctx = query_context_with_initial_dyn_filter_regs(
654 &query_ctx,
655 region_id,
656 &captured_dyn_filters,
657 );
658
659 assert!(
660 region_query_ctx
661 .extension(INITIAL_REMOTE_DYN_FILTER_REGISTRATIONS_EXTENSION_KEY)
662 .is_none()
663 );
664 }
665}