lide-reed opened a new pull request, #68002:
URL: https://github.com/apache/doris/pull/68002

   ### Proposed changes
   
   Fix #67997
   
   **Problem**
   
   `RuntimeFilter::serialize()` marks the outgoing filter as `disabled` for any 
state other
   than `READY`:
   
   ```cpp
   auto state = _wrapper->get_state();
   if (state != RuntimeFilterWrapper::State::READY) {
       request->set_disabled(true);
       return Status::OK();
   }
   ```
   
   `UNINITED` means "no filter content has been produced yet", not "this filter 
was
   cancelled", but the consumer cannot distinguish the two. It treats 
`disabled` as an
   absorbing state (`set_state(DISABLED, "get disabled from remote")`) and 
permanently gives
   up the filter, so the probe side degrades to a full scan.
   
   The merger decides readiness only by producer count, which is independent of 
whether any
   producer really produced content:
   
   ```cpp
   // RuntimeFilterMerger::merge_from()
   *ready = _received_producer_num == _expected_producer_num;
   if (_received_producer_num == _expected_producer_num) {
       _rf_state = State::READY;
   }
   if (_wrapper->get_state() == RuntimeFilterWrapper::State::UNINITED) {
       _wrapper = other->_wrapper;   // may still be UNINITED
       return Status::OK();
   }
   ```
   
   So when all producers report without content, `merge_from()` returns `ready 
== true` while
   the merged wrapper is still `UNINITED`, and the caller publishes it as 
`disabled` to every
   consumer.
   
   **Fix**
   
   Align with the legacy (branch-3.1) semantics: only a really disabled filter
   (`max_in_num` / join spill / rpc error -> `State::DISABLED`) is published as 
`disabled`; a
   filter that is simply not ready is skipped and consumers wait until
   `runtime_filter_wait_time_ms`.
   
   | File | Change |
   | --- | --- |
   | `runtime_filter.h` | `serialize()`: only `DISABLED` sets `disabled=true`; 
`UNINITED` publishes nothing (DCHECK + WARNING + `OK`) |
   | `runtime_filter_merger.h` | new `is_wrapper_uninited()` helper |
   | `runtime_filter_producer.cpp` | `do_merge`: skip send when merged wrapper 
is `UNINITED` |
   | `runtime_filter_mgr.cpp` | `_send_rf_to_target()`: skip broadcast when 
merged wrapper is `UNINITED` |
   
   **Why `UNINITED` returns `OK` instead of `InternalError`**
   
   The old behavior for `UNINITED` was a silent performance degradation (filter 
disabled),
   not an error. Turning it into `InternalError` would escalate a performance 
issue into a
   query failure. Publishing nothing keeps the failure mode conservative: the 
filter is lost,
   the consumer times out, and at worst the probe side falls back to a full 
scan. `DCHECK` is
   kept so unexpected paths still fail fast in debug builds.
   
   ### Checklist
   
   - [ ] Issue is created and linked
   - [ ] No new configuration or user-facing interface
   - [ ] No behavior change for correctly produced filters
   
   ### Further comments
   
   Silent performance regression is hard to notice in production; the fix 
restores the
   previous (branch-3.1) semantics and makes the worst case a filter timeout 
rather than a
   permanently disabled filter.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to