1use std::collections::BTreeMap;
19use std::marker::PhantomData;
20use std::ops::{Bound, RangeInclusive};
21
22use delta_btree_map::{Change, DeltaBTreeMap};
23use educe::Educe;
24use futures::StreamExt;
25use futures_async_stream::for_await;
26use risingwave_common::array::stream_record::Record;
27use risingwave_common::config::streaming::OverWindowCachePolicy as CachePolicy;
28use risingwave_common::row::{OwnedRow, Row, RowExt};
29use risingwave_common::types::{Datum, DefaultOrd, ScalarImpl, Sentinelled};
30use risingwave_common::util::iter_util::ZipEqFast;
31use risingwave_expr::window_function::{StateKey, WindowStates, create_window_state};
32use risingwave_storage::StateStore;
33use risingwave_storage::store::PrefetchOptions;
34
35use super::general::{Calls, RowConverter, StateCleaning};
36use super::range_cache::{CacheKey, PartitionCache};
37use crate::common::table::state_table::{BoxedRowStream, StateTable};
38use crate::consistency::{consistency_error, enable_strict_consistency};
39use crate::executor::StreamExecutorResult;
40use crate::executor::over_window::frame_finder::*;
41
42pub(super) type PartitionDelta = BTreeMap<CacheKey, Change<OwnedRow>>;
44
45#[derive(Default, Debug)]
46pub(super) struct OverPartitionStats {
47 pub lookup_count: u64,
49 pub left_miss_count: u64,
50 pub right_miss_count: u64,
51
52 pub accessed_entry_count: u64,
54 pub compute_count: u64,
55 pub same_output_count: u64,
56}
57
58#[derive(Debug, Educe)]
68#[educe(Clone, Copy)]
69pub(super) struct AffectedRange<'a> {
70 pub first_frame_start: &'a CacheKey,
71 pub first_curr_key: &'a CacheKey,
72 pub last_curr_key: &'a CacheKey,
73 pub last_frame_end: &'a CacheKey,
74}
75
76impl<'a> AffectedRange<'a> {
77 fn new(
78 first_frame_start: &'a CacheKey,
79 first_curr_key: &'a CacheKey,
80 last_curr_key: &'a CacheKey,
81 last_frame_end: &'a CacheKey,
82 ) -> Self {
83 Self {
84 first_frame_start,
85 first_curr_key,
86 last_curr_key,
87 last_frame_end,
88 }
89 }
90}
91
92pub(super) struct OverPartition<'a, S: StateStore> {
96 deduped_part_key: &'a OwnedRow,
97 range_cache: &'a mut PartitionCache,
98 cache_policy: CachePolicy,
99
100 calls: &'a Calls,
101 row_conv: RowConverter<'a>,
102
103 stats: OverPartitionStats,
104
105 _phantom: PhantomData<S>,
106}
107
108const MAGIC_BATCH_SIZE: usize = 512;
109
110const MAX_STALE_ROWS_TO_DELETE_PER_ROUND: usize = 1 << 16;
113
114impl<'a, S: StateStore> OverPartition<'a, S> {
115 pub fn new(
116 deduped_part_key: &'a OwnedRow,
117 cache: &'a mut PartitionCache,
118 cache_policy: CachePolicy,
119 calls: &'a Calls,
120 row_conv: RowConverter<'a>,
121 ) -> Self {
122 Self {
123 deduped_part_key,
124 range_cache: cache,
125 cache_policy,
126
127 calls,
128 row_conv,
129
130 stats: Default::default(),
131
132 _phantom: PhantomData,
133 }
134 }
135
136 pub fn summarize(self) -> OverPartitionStats {
139 self.stats
141 }
142
143 pub fn cache_real_len(&self) -> usize {
145 self.range_cache.normal_len()
146 }
147
148 pub async fn build_changes(
151 &mut self,
152 table: &StateTable<S>,
153 mut delta: PartitionDelta,
154 ) -> StreamExecutorResult<(
155 BTreeMap<StateKey, Record<OwnedRow>>,
156 Option<RangeInclusive<StateKey>>,
157 )> {
158 let calls = self.calls;
159 let input_schema_len = table.get_data_types().len() - calls.len();
160 let numbering_only = calls.numbering_only;
161 let has_rank = calls.has_rank;
162
163 let mut part_changes = BTreeMap::new();
165 let mut accessed_range: Option<RangeInclusive<StateKey>> = None;
166
167 let mut accessed_entry_count = 0;
169 let mut compute_count = 0;
170 let mut same_output_count = 0;
171
172 let (part_with_delta, affected_ranges) =
174 self.find_affected_ranges(table, &mut delta).await?;
175
176 let snapshot = part_with_delta.snapshot();
177 let delta = part_with_delta.delta();
178 let last_delta_key = delta.last_key_value().map(|(k, _)| k.as_normal_expect());
179
180 for (key, change) in delta {
183 if change.is_delete() {
184 part_changes.insert(
185 key.as_normal_expect().clone(),
186 Record::Delete {
187 old_row: snapshot.get(key).unwrap().clone(),
188 },
189 );
190 }
191 }
192
193 for AffectedRange {
194 first_frame_start,
195 first_curr_key,
196 last_curr_key,
197 last_frame_end,
198 } in affected_ranges
199 {
200 assert!(first_frame_start <= first_curr_key);
201 assert!(first_curr_key <= last_curr_key);
202 assert!(last_curr_key <= last_frame_end);
203 assert!(first_frame_start.is_normal());
204 assert!(first_curr_key.is_normal());
205 assert!(last_curr_key.is_normal());
206 assert!(last_frame_end.is_normal());
207
208 let last_delta_key = last_delta_key.unwrap();
209
210 if let Some(accessed_range) = accessed_range.as_mut() {
211 let min_start = first_frame_start
212 .as_normal_expect()
213 .min(accessed_range.start())
214 .clone();
215 let max_end = last_frame_end
216 .as_normal_expect()
217 .max(accessed_range.end())
218 .clone();
219 *accessed_range = min_start..=max_end;
220 } else {
221 accessed_range = Some(
222 first_frame_start.as_normal_expect().clone()
223 ..=last_frame_end.as_normal_expect().clone(),
224 );
225 }
226
227 let mut states =
228 WindowStates::new(calls.iter().map(create_window_state).try_collect()?);
229
230 {
232 let mut cursor = part_with_delta
233 .before(first_frame_start)
234 .expect("first frame start key must exist");
235
236 while let Some((key, row)) = cursor.next() {
237 accessed_entry_count += 1;
238
239 for (call, state) in calls.iter().zip_eq_fast(states.iter_mut()) {
240 state.append(
243 key.as_normal_expect().clone(),
244 row.project(call.args.val_indices())
245 .into_owned_row()
246 .as_inner()
247 .into(),
248 );
249 }
250
251 if key == last_frame_end {
252 break;
253 }
254 }
255 }
256
257 states.just_slide_to(first_curr_key.as_normal_expect())?;
260 let mut curr_key_cursor = part_with_delta.before(first_curr_key).unwrap();
261 assert_eq!(
262 states.curr_key(),
263 curr_key_cursor
264 .peek_next()
265 .map(|(k, _)| k)
266 .map(CacheKey::as_normal_expect)
267 );
268
269 while let Some((key, row)) = curr_key_cursor.next() {
271 let mut should_stop = false;
272
273 let output = states.slide_no_evict_hint()?;
274 compute_count += 1;
275
276 let old_output = &row.as_inner()[input_schema_len..];
277 if !old_output.is_empty() && old_output == output {
278 same_output_count += 1;
279
280 if numbering_only {
281 if has_rank {
282 if key.as_normal_expect().order_key > last_delta_key.order_key {
285 should_stop = true;
287 }
288 } else if key.as_normal_expect() >= last_delta_key {
289 should_stop = true;
291 }
292 }
293 }
294
295 let new_row = OwnedRow::new(
296 row.as_inner()
297 .iter()
298 .take(input_schema_len)
299 .cloned()
300 .chain(output)
301 .collect(),
302 );
303
304 if let Some(old_row) = snapshot.get(key).cloned() {
305 if old_row != new_row {
307 part_changes.insert(
308 key.as_normal_expect().clone(),
309 Record::Update { old_row, new_row },
310 );
311 }
312 } else {
313 part_changes.insert(key.as_normal_expect().clone(), Record::Insert { new_row });
315 }
316
317 if should_stop || key == last_curr_key {
318 break;
319 }
320 }
321 }
322
323 self.stats.accessed_entry_count += accessed_entry_count;
324 self.stats.compute_count += compute_count;
325 self.stats.same_output_count += same_output_count;
326
327 Ok((part_changes, accessed_range))
328 }
329
330 pub fn write_record(
334 &mut self,
335 table: &mut StateTable<S>,
336 key: StateKey,
337 record: Record<OwnedRow>,
338 ) {
339 table.write_record(record.as_ref());
340 match record {
341 Record::Insert { new_row } | Record::Update { new_row, .. } => {
342 self.range_cache.insert(CacheKey::from(key), new_row);
343 }
344 Record::Delete { .. } => {
345 self.range_cache.remove(&CacheKey::from(key));
346
347 if self.range_cache.normal_len() == 0 && self.range_cache.len() == 1 {
348 self.range_cache
350 .insert(CacheKey::Smallest, OwnedRow::empty());
351 self.range_cache
352 .insert(CacheKey::Largest, OwnedRow::empty());
353 }
354 }
355 }
356 }
357
358 pub async fn clean_stale_rows(
365 &mut self,
366 table: &mut StateTable<S>,
367 cleaning: &StateCleaning,
368 watermark: &ScalarImpl,
369 ) -> StreamExecutorResult<(usize, bool)> {
370 let watermark_ref = watermark.as_scalar_ref_impl();
371 let is_stale = |row: &OwnedRow| match row.datum_at(cleaning.watermark_col_idx) {
372 Some(value) => value.default_cmp(&watermark_ref).is_lt(),
373 None => false, };
375 let max_to_collect = MAX_STALE_ROWS_TO_DELETE_PER_ROUND.saturating_add(cleaning.n_retain);
380
381 let cache_covers_stale_end = if cleaning.stale_rows_at_front {
382 !self.range_cache.left_is_sentinel()
383 } else {
384 !self.range_cache.right_is_sentinel()
385 };
386
387 let mut stale_rows: Vec<(CacheKey, OwnedRow)> = Vec::new();
388 if cache_covers_stale_end {
389 let entries: Box<dyn Iterator<Item = (&CacheKey, &OwnedRow)> + '_> =
391 if cleaning.stale_rows_at_front {
392 Box::new(self.range_cache.inner().iter())
393 } else {
394 Box::new(self.range_cache.inner().iter().rev())
395 };
396 stale_rows.extend(
397 entries
398 .take_while(|(key, row)| key.is_normal() && is_stale(row))
399 .take(max_to_collect)
400 .map(|(key, row)| (key.clone(), row.clone())),
401 );
402 } else {
403 let watermark_row = OwnedRow::new(vec![Some(watermark.clone())]);
405 let sub_range: (Bound<OwnedRow>, Bound<OwnedRow>) = if cleaning.stale_rows_at_front {
406 (Bound::Unbounded, Bound::Excluded(watermark_row))
407 } else {
408 (Bound::Excluded(watermark_row), Bound::Unbounded)
409 };
410 let stream: BoxedRowStream<'_> = if cleaning.stale_rows_at_front {
411 table
412 .iter_with_prefix(
413 self.deduped_part_key,
414 &sub_range,
415 PrefetchOptions::default(),
416 )
417 .await?
418 .boxed()
419 } else {
420 table
421 .rev_iter_with_prefix(
422 self.deduped_part_key,
423 &sub_range,
424 PrefetchOptions::default(),
425 )
426 .await?
427 .boxed()
428 };
429
430 #[for_await]
431 for row in stream {
432 let row: OwnedRow = row?.into_owned_row();
433 if !is_stale(&row) {
434 break;
435 }
436 let key = self.row_conv.row_to_state_key(&row)?;
437 stale_rows.push((CacheKey::from(key), row));
438 if stale_rows.len() >= max_to_collect {
439 break;
440 }
441 }
442 }
443
444 let has_more = stale_rows.len() >= max_to_collect;
445 let n_to_delete = if has_more {
446 MAX_STALE_ROWS_TO_DELETE_PER_ROUND
447 } else {
448 stale_rows.len().saturating_sub(cleaning.n_retain)
449 };
450 for (key, row) in stale_rows.into_iter().take(n_to_delete) {
451 table.delete(row);
452 self.range_cache.remove(&key);
453 }
454 if n_to_delete > 0 && self.range_cache.normal_len() == 0 && self.range_cache.len() == 1 {
455 self.range_cache
457 .insert(CacheKey::Smallest, OwnedRow::empty());
458 self.range_cache
459 .insert(CacheKey::Largest, OwnedRow::empty());
460 }
461
462 tracing::trace!(
463 partition=?self.deduped_part_key,
464 n_deleted=n_to_delete,
465 has_more,
466 "cleaned stale rows in the partition"
467 );
468
469 Ok((n_to_delete, has_more))
470 }
471
472 async fn find_affected_ranges<'s, 'delta>(
476 &'s mut self,
477 table: &StateTable<S>,
478 delta: &'delta mut PartitionDelta,
479 ) -> StreamExecutorResult<(
480 DeltaBTreeMap<'delta, CacheKey, OwnedRow>,
481 Vec<AffectedRange<'delta>>,
482 )>
483 where
484 'a: 'delta,
485 's: 'delta,
486 {
487 if delta.is_empty() {
488 return Ok((DeltaBTreeMap::new(self.range_cache.inner(), delta), vec![]));
489 }
490
491 self.ensure_delta_in_cache(table, delta).await?;
492 let delta = &*delta; let delta_first = delta.first_key_value().unwrap().0.as_normal_expect();
495 let delta_last = delta.last_key_value().unwrap().0.as_normal_expect();
496
497 let range_frame_logical_curr =
498 calc_logical_curr_for_range_frames(&self.calls.range_frames, delta_first, delta_last);
499
500 loop {
501 let cache_inner = unsafe { &*(self.range_cache.inner() as *const _) };
510 let part_with_delta = DeltaBTreeMap::new(cache_inner, delta);
511
512 self.stats.lookup_count += 1;
513 let res = self
514 .find_affected_ranges_readonly(part_with_delta, range_frame_logical_curr.as_ref());
515
516 let (need_extend_leftward, need_extend_rightward) = match res {
517 Ok(ranges) => return Ok((part_with_delta, ranges)),
518 Err(cache_extend_hint) => cache_extend_hint,
519 };
520
521 if need_extend_leftward {
522 self.stats.left_miss_count += 1;
523 tracing::trace!(partition=?self.deduped_part_key, "partition cache left extension triggered");
524 let left_most = self
525 .range_cache
526 .first_normal_key()
527 .unwrap_or(delta_first)
528 .clone();
529 self.extend_cache_leftward_by_n(table, &left_most).await?;
530 }
531 if need_extend_rightward {
532 self.stats.right_miss_count += 1;
533 tracing::trace!(partition=?self.deduped_part_key, "partition cache right extension triggered");
534 let right_most = self
535 .range_cache
536 .last_normal_key()
537 .unwrap_or(delta_last)
538 .clone();
539 self.extend_cache_rightward_by_n(table, &right_most).await?;
540 }
541 tracing::trace!(partition=?self.deduped_part_key, "partition cache extended");
542 }
543 }
544
545 async fn ensure_delta_in_cache(
546 &mut self,
547 table: &StateTable<S>,
548 delta: &mut PartitionDelta,
549 ) -> StreamExecutorResult<()> {
550 if delta.is_empty() {
551 return Ok(());
552 }
553
554 let delta_first = delta.first_key_value().unwrap().0.as_normal_expect();
555 let delta_last = delta.last_key_value().unwrap().0.as_normal_expect();
556
557 if self.cache_policy.is_full() {
558 self.extend_cache_to_boundary(table).await?;
560 } else {
561 self.extend_cache_by_range(table, delta_first..=delta_last)
566 .await?;
567 }
568
569 if !enable_strict_consistency() {
570 let cache = self.range_cache.inner();
572 delta.retain(|key, change| match &*change {
573 Change::Insert(_) => {
574 true
577 }
578 Change::Delete => {
579 let consistent = cache.contains_key(key);
581 if !consistent {
582 consistency_error!(?key, "removing a row with non-existing key");
583 }
584 consistent
585 }
586 });
587 }
588
589 Ok(())
590 }
591
592 fn find_affected_ranges_readonly<'delta>(
601 &self,
602 part_with_delta: DeltaBTreeMap<'delta, CacheKey, OwnedRow>,
603 range_frame_logical_curr: Option<&(Sentinelled<Datum>, Sentinelled<Datum>)>,
604 ) -> std::result::Result<Vec<AffectedRange<'delta>>, (bool, bool)> {
605 if part_with_delta.first_key().is_none() {
606 return Ok(vec![]);
608 }
609
610 let delta_first_key = part_with_delta.delta().first_key_value().unwrap().0;
611 let delta_last_key = part_with_delta.delta().last_key_value().unwrap().0;
612 let cache_key_pk_len = delta_first_key.as_normal_expect().pk.len();
613
614 if part_with_delta.snapshot().is_empty() {
615 return Ok(vec![AffectedRange::new(
617 delta_first_key,
618 delta_first_key,
619 delta_last_key,
620 delta_last_key,
621 )]);
622 }
623
624 let first_key = part_with_delta.first_key().unwrap();
625 let last_key = part_with_delta.last_key().unwrap();
626
627 let first_curr_key = if self.calls.end_is_unbounded || delta_first_key == first_key {
628 first_key
631 } else {
632 let mut key = find_first_curr_for_rows_frame(
633 &self.calls.super_rows_frame_bounds,
634 part_with_delta,
635 delta_first_key,
636 );
637
638 if let Some((logical_first_curr, _)) = range_frame_logical_curr {
639 let logical_curr = logical_first_curr.as_normal_expect(); let new_key = find_left_for_range_frames(
641 &self.calls.range_frames,
642 part_with_delta,
643 logical_curr,
644 cache_key_pk_len,
645 );
646 key = std::cmp::min(key, new_key);
647 }
648
649 key
650 };
651
652 let last_curr_key = if self.calls.start_is_unbounded || delta_last_key == last_key {
653 last_key
655 } else {
656 let mut key = find_last_curr_for_rows_frame(
657 &self.calls.super_rows_frame_bounds,
658 part_with_delta,
659 delta_last_key,
660 );
661
662 if let Some((_, logical_last_curr)) = range_frame_logical_curr {
663 let logical_curr = logical_last_curr.as_normal_expect(); let new_key = find_right_for_range_frames(
665 &self.calls.range_frames,
666 part_with_delta,
667 logical_curr,
668 cache_key_pk_len,
669 );
670 key = std::cmp::max(key, new_key);
671 }
672
673 key
674 };
675
676 {
677 let mut need_extend_leftward = false;
680 let mut need_extend_rightward = false;
681 for key in [first_curr_key, last_curr_key] {
682 if key.is_smallest() {
683 need_extend_leftward = true;
684 } else if key.is_largest() {
685 need_extend_rightward = true;
686 }
687 }
688 if need_extend_leftward || need_extend_rightward {
689 return Err((need_extend_leftward, need_extend_rightward));
690 }
691 }
692
693 if first_curr_key > last_curr_key {
696 return Ok(vec![]);
703 }
704
705 let range_frame_logical_boundary = calc_logical_boundary_for_range_frames(
706 &self.calls.range_frames,
707 first_curr_key.as_normal_expect(),
708 last_curr_key.as_normal_expect(),
709 );
710
711 let first_frame_start = if self.calls.start_is_unbounded || first_curr_key == first_key {
712 first_key
715 } else {
716 let mut key = find_frame_start_for_rows_frame(
717 &self.calls.super_rows_frame_bounds,
718 part_with_delta,
719 first_curr_key,
720 );
721
722 if let Some((logical_first_start, _)) = range_frame_logical_boundary.as_ref() {
723 let logical_boundary = logical_first_start.as_normal_expect(); let new_key = find_left_for_range_frames(
725 &self.calls.range_frames,
726 part_with_delta,
727 logical_boundary,
728 cache_key_pk_len,
729 );
730 key = std::cmp::min(key, new_key);
731 }
732
733 key
734 };
735 assert!(first_frame_start <= first_curr_key);
736
737 let last_frame_end = if self.calls.end_is_unbounded || last_curr_key == last_key {
738 last_key
740 } else {
741 let mut key = find_frame_end_for_rows_frame(
742 &self.calls.super_rows_frame_bounds,
743 part_with_delta,
744 last_curr_key,
745 );
746
747 if let Some((_, logical_last_end)) = range_frame_logical_boundary.as_ref() {
748 let logical_boundary = logical_last_end.as_normal_expect(); let new_key = find_right_for_range_frames(
750 &self.calls.range_frames,
751 part_with_delta,
752 logical_boundary,
753 cache_key_pk_len,
754 );
755 key = std::cmp::max(key, new_key);
756 }
757
758 key
759 };
760 assert!(last_frame_end >= last_curr_key);
761
762 let mut need_extend_leftward = false;
763 let mut need_extend_rightward = false;
764 for key in [
765 first_curr_key,
766 last_curr_key,
767 first_frame_start,
768 last_frame_end,
769 ] {
770 if key.is_smallest() {
771 need_extend_leftward = true;
772 } else if key.is_largest() {
773 need_extend_rightward = true;
774 }
775 }
776
777 if need_extend_leftward || need_extend_rightward {
778 Err((need_extend_leftward, need_extend_rightward))
779 } else {
780 Ok(vec![AffectedRange::new(
781 first_frame_start,
782 first_curr_key,
783 last_curr_key,
784 last_frame_end,
785 )])
786 }
787 }
788
789 async fn extend_cache_to_boundary(
790 &mut self,
791 table: &StateTable<S>,
792 ) -> StreamExecutorResult<()> {
793 if self.range_cache.normal_len() == self.range_cache.len() {
794 return Ok(());
796 }
797
798 tracing::trace!(partition=?self.deduped_part_key, "loading the whole partition into cache");
799
800 let mut new_cache = PartitionCache::new_without_sentinels(); let sub_range: &(Bound<OwnedRow>, Bound<OwnedRow>) = &(Bound::Unbounded, Bound::Unbounded);
802 let table_iter = table
803 .iter_with_prefix(self.deduped_part_key, sub_range, PrefetchOptions::default())
804 .await?;
805
806 #[for_await]
807 for row in table_iter {
808 let row: OwnedRow = row?.into_owned_row();
809 new_cache.insert(self.row_conv.row_to_state_key(&row)?.into(), row);
810 }
811 *self.range_cache = new_cache;
812
813 Ok(())
814 }
815
816 async fn extend_cache_by_range(
820 &mut self,
821 table: &StateTable<S>,
822 range: RangeInclusive<&StateKey>,
823 ) -> StreamExecutorResult<()> {
824 if self.range_cache.normal_len() == self.range_cache.len() {
825 return Ok(());
827 }
828 assert!(self.range_cache.len() >= 2);
829
830 let cache_first_normal_key = self.range_cache.first_normal_key();
831 let cache_last_normal_key = self.range_cache.last_normal_key();
832
833 if cache_first_normal_key.is_some() && *range.end() < cache_first_normal_key.unwrap()
834 || cache_last_normal_key.is_some() && *range.start() > cache_last_normal_key.unwrap()
835 {
836 tracing::debug!(
838 partition=?self.deduped_part_key,
839 cache_first=?cache_first_normal_key,
840 cache_last=?cache_last_normal_key,
841 range=?range,
842 "modified range is completely non-overlapping with the cached range, re-initializing the cache"
843 );
844 *self.range_cache = PartitionCache::new();
845 }
846
847 if self.cache_real_len() == 0 {
848 let table_sub_range = (
850 Bound::Included(self.row_conv.state_key_to_table_sub_pk(range.start())?),
851 Bound::Included(self.row_conv.state_key_to_table_sub_pk(range.end())?),
852 );
853 tracing::debug!(
854 partition=?self.deduped_part_key,
855 table_sub_range=?table_sub_range,
856 "cache is empty, just loading the given range"
857 );
858 return self
859 .extend_cache_by_range_inner(table, table_sub_range)
860 .await;
861 }
862
863 let cache_real_first_key = self
864 .range_cache
865 .first_normal_key()
866 .expect("cache real len is not 0");
867 if self.range_cache.left_is_sentinel() && *range.start() < cache_real_first_key {
868 let table_sub_range = (
870 Bound::Included(self.row_conv.state_key_to_table_sub_pk(range.start())?),
871 Bound::Excluded(
872 self.row_conv
873 .state_key_to_table_sub_pk(cache_real_first_key)?,
874 ),
875 );
876 tracing::trace!(
877 partition=?self.deduped_part_key,
878 table_sub_range=?table_sub_range,
879 "loading the left half of given range"
880 );
881 self.extend_cache_by_range_inner(table, table_sub_range)
882 .await?;
883 }
884
885 let cache_real_last_key = self
886 .range_cache
887 .last_normal_key()
888 .expect("cache real len is not 0");
889 if self.range_cache.right_is_sentinel() && *range.end() > cache_real_last_key {
890 let table_sub_range = (
892 Bound::Excluded(
893 self.row_conv
894 .state_key_to_table_sub_pk(cache_real_last_key)?,
895 ),
896 Bound::Included(self.row_conv.state_key_to_table_sub_pk(range.end())?),
897 );
898 tracing::trace!(
899 partition=?self.deduped_part_key,
900 table_sub_range=?table_sub_range,
901 "loading the right half of given range"
902 );
903 self.extend_cache_by_range_inner(table, table_sub_range)
904 .await?;
905 }
906
907 self.extend_cache_leftward_by_n(table, range.start())
909 .await?;
910
911 self.extend_cache_rightward_by_n(table, range.end()).await
913 }
914
915 async fn extend_cache_leftward_by_n(
916 &mut self,
917 table: &StateTable<S>,
918 hint_key: &StateKey,
919 ) -> StreamExecutorResult<()> {
920 if self.range_cache.normal_len() == self.range_cache.len() {
921 return Ok(());
923 }
924 assert!(self.range_cache.len() >= 2);
925
926 let left_second = {
927 let mut iter = self.range_cache.inner().iter();
928 let left_first = iter.next().unwrap().0;
929 if left_first.is_normal() {
930 return Ok(());
932 }
933 iter.next().unwrap().0
934 };
935 let range_to_exclusive = match left_second {
936 CacheKey::Normal(smallest_in_cache) => smallest_in_cache,
937 CacheKey::Largest => hint_key, _ => unreachable!(),
939 }
940 .clone();
941
942 self.extend_cache_leftward_by_n_inner(table, &range_to_exclusive)
943 .await?;
944
945 if self.cache_real_len() == 0 {
946 self.extend_cache_rightward_by_n_inner(table, hint_key)
949 .await?;
950 if self.cache_real_len() == 0 {
951 self.range_cache.remove(&CacheKey::Smallest);
953 self.range_cache.remove(&CacheKey::Largest);
954 }
955 }
956
957 Ok(())
958 }
959
960 async fn extend_cache_rightward_by_n(
961 &mut self,
962 table: &StateTable<S>,
963 hint_key: &StateKey,
964 ) -> StreamExecutorResult<()> {
965 if self.range_cache.normal_len() == self.range_cache.len() {
966 return Ok(());
968 }
969 assert!(self.range_cache.len() >= 2);
970
971 let right_second = {
972 let mut iter = self.range_cache.inner().iter();
973 let right_first = iter.next_back().unwrap().0;
974 if right_first.is_normal() {
975 return Ok(());
977 }
978 iter.next_back().unwrap().0
979 };
980 let range_from_exclusive = match right_second {
981 CacheKey::Normal(largest_in_cache) => largest_in_cache,
982 CacheKey::Smallest => hint_key, _ => unreachable!(),
984 }
985 .clone();
986
987 self.extend_cache_rightward_by_n_inner(table, &range_from_exclusive)
988 .await?;
989
990 if self.cache_real_len() == 0 {
991 self.extend_cache_leftward_by_n_inner(table, hint_key)
994 .await?;
995 if self.cache_real_len() == 0 {
996 self.range_cache.remove(&CacheKey::Smallest);
998 self.range_cache.remove(&CacheKey::Largest);
999 }
1000 }
1001
1002 Ok(())
1003 }
1004
1005 async fn extend_cache_by_range_inner(
1006 &mut self,
1007 table: &StateTable<S>,
1008 table_sub_range: (Bound<impl Row>, Bound<impl Row>),
1009 ) -> StreamExecutorResult<()> {
1010 let stream = table
1011 .iter_with_prefix(
1012 self.deduped_part_key,
1013 &table_sub_range,
1014 PrefetchOptions::default(),
1015 )
1016 .await?;
1017
1018 #[for_await]
1019 for row in stream {
1020 let row: OwnedRow = row?.into_owned_row();
1021 let key = self.row_conv.row_to_state_key(&row)?;
1022 self.range_cache.insert(CacheKey::from(key), row);
1023 }
1024
1025 Ok(())
1026 }
1027
1028 async fn extend_cache_leftward_by_n_inner(
1029 &mut self,
1030 table: &StateTable<S>,
1031 range_to_exclusive: &StateKey,
1032 ) -> StreamExecutorResult<()> {
1033 let mut n_extended = 0usize;
1034 {
1035 let sub_range = (
1036 Bound::<OwnedRow>::Unbounded,
1037 Bound::Excluded(
1038 self.row_conv
1039 .state_key_to_table_sub_pk(range_to_exclusive)?,
1040 ),
1041 );
1042 let rev_stream = table
1043 .rev_iter_with_prefix(
1044 self.deduped_part_key,
1045 &sub_range,
1046 PrefetchOptions::default(),
1047 )
1048 .await?;
1049
1050 #[for_await]
1051 for row in rev_stream {
1052 let row: OwnedRow = row?.into_owned_row();
1053
1054 let key = self.row_conv.row_to_state_key(&row)?;
1055 self.range_cache.insert(CacheKey::from(key), row);
1056
1057 n_extended += 1;
1058 if n_extended == MAGIC_BATCH_SIZE {
1059 break;
1060 }
1061 }
1062 }
1063
1064 if n_extended < MAGIC_BATCH_SIZE && self.cache_real_len() > 0 {
1065 self.range_cache.remove(&CacheKey::Smallest);
1067 }
1068
1069 Ok(())
1070 }
1071
1072 async fn extend_cache_rightward_by_n_inner(
1073 &mut self,
1074 table: &StateTable<S>,
1075 range_from_exclusive: &StateKey,
1076 ) -> StreamExecutorResult<()> {
1077 let mut n_extended = 0usize;
1078 {
1079 let sub_range = (
1080 Bound::Excluded(
1081 self.row_conv
1082 .state_key_to_table_sub_pk(range_from_exclusive)?,
1083 ),
1084 Bound::<OwnedRow>::Unbounded,
1085 );
1086 let stream = table
1087 .iter_with_prefix(
1088 self.deduped_part_key,
1089 &sub_range,
1090 PrefetchOptions::default(),
1091 )
1092 .await?;
1093
1094 #[for_await]
1095 for row in stream {
1096 let row: OwnedRow = row?.into_owned_row();
1097
1098 let key = self.row_conv.row_to_state_key(&row)?;
1099 self.range_cache.insert(CacheKey::from(key), row);
1100
1101 n_extended += 1;
1102 if n_extended == MAGIC_BATCH_SIZE {
1103 break;
1104 }
1105 }
1106 }
1107
1108 if n_extended < MAGIC_BATCH_SIZE && self.cache_real_len() > 0 {
1109 self.range_cache.remove(&CacheKey::Largest);
1111 }
1112
1113 Ok(())
1114 }
1115}