1mod prelude;
16
17use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
18use std::fmt::Debug;
19use std::future::pending;
20use std::hash::Hash;
21use std::pin::Pin;
22use std::sync::Arc;
23use std::task::Poll;
24use std::vec;
25
26use await_tree::InstrumentAwait;
27use enum_as_inner::EnumAsInner;
28use futures::future::try_join_all;
29use futures::stream::{BoxStream, FusedStream, FuturesUnordered, StreamFuture};
30use futures::{FutureExt, Stream, StreamExt, TryStreamExt};
31use itertools::Itertools;
32use prometheus::core::{AtomicU64, GenericCounter};
33use risingwave_common::array::StreamChunk;
34use risingwave_common::bitmap::Bitmap;
35use risingwave_common::catalog::{Schema, TableId};
36use risingwave_common::config::StreamingConfig;
37use risingwave_common::metrics::LabelGuardedMetric;
38use risingwave_common::row::OwnedRow;
39use risingwave_common::types::{DataType, Datum, DefaultOrd, ScalarImpl};
40use risingwave_common::util::epoch::{Epoch, EpochPair};
41use risingwave_common::util::tracing::TracingContext;
42use risingwave_common::util::value_encoding::{DatumFromProtoExt, DatumToProtoExt};
43use risingwave_common_estimate_size::EstimateSize;
44use risingwave_connector::source::SplitImpl;
45use risingwave_expr::expr::NonStrictExpression;
46use risingwave_pb::data::PbEpoch;
47use risingwave_pb::expr::PbInputRef;
48use risingwave_pb::stream_plan::add_mutation::PbNewUpstreamSink;
49use risingwave_pb::stream_plan::barrier::BarrierKind;
50use risingwave_pb::stream_plan::barrier_mutation::Mutation as PbMutation;
51use risingwave_pb::stream_plan::stream_node::PbStreamKind;
52use risingwave_pb::stream_plan::throttle_mutation::ThrottleConfig;
53use risingwave_pb::stream_plan::update_mutation::{DispatcherUpdate, MergeUpdate};
54use risingwave_pb::stream_plan::{
55 PbBarrier, PbBarrierMutation, PbDispatcher, PbSinkSchemaChange, PbStreamMessageBatch,
56 PbWatermark, SubscriptionUpstreamInfo,
57};
58use smallvec::SmallVec;
59use tokio::sync::mpsc;
60use tokio::time::{Duration, Instant};
61
62use crate::error::StreamResult;
63use crate::executor::exchange::input::{
64 BoxedActorInput, BoxedInput, assert_equal_dispatcher_barrier, new_input,
65};
66use crate::executor::monitor::ActorInputMetrics;
67use crate::executor::prelude::StreamingMetrics;
68use crate::executor::watermark::BufferedWatermarks;
69use crate::task::{ActorId, FragmentId, LocalBarrierManager};
70
71mod actor;
72mod barrier_align;
73pub mod exchange;
74pub mod monitor;
75
76pub mod aggregate;
77pub mod asof_join;
78mod backfill;
79mod barrier_recv;
80mod batch_query;
81mod chain;
82mod changelog;
83mod dedup;
84mod dispatch;
85pub mod dml;
86mod dynamic_filter;
87pub mod eowc;
88pub mod error;
89mod expand;
90mod filter;
91mod gap_fill;
92pub mod hash_join;
93mod hop_window;
94pub(crate) mod iceberg_with_pk_index;
95mod join;
96pub mod locality_provider;
97mod lookup;
98mod lookup_union;
99mod merge;
100mod mview;
101mod nested_loop_temporal_join;
102mod no_op;
103mod now;
104mod over_window;
105pub mod project;
106mod receiver;
107pub mod row_id_gen;
108mod sink;
109pub mod source;
110mod stream_reader;
111pub mod subtask;
112mod temporal_join;
113mod top_n;
114mod troublemaker;
115mod union;
116mod upstream_sink_union;
117mod values;
118mod watermark;
119mod watermark_filter;
120mod wrapper;
121
122mod approx_percentile;
123
124mod row_merge;
125
126#[cfg(test)]
127mod integration_tests;
128mod sync_kv_log_store;
129#[cfg(any(test, feature = "test"))]
130pub mod test_utils;
131mod utils;
132mod vector;
133
134pub use actor::{Actor, ActorContext, ActorContextRef};
135use anyhow::{Context, anyhow};
136pub use approx_percentile::global::GlobalApproxPercentileExecutor;
137pub use approx_percentile::local::LocalApproxPercentileExecutor;
138pub use backfill::arrangement_backfill::*;
139pub use backfill::cdc::{
140 CdcBackfillExecutor, ExternalStorageTable, ParallelizedCdcBackfillExecutor,
141};
142pub use backfill::no_shuffle_backfill::*;
143pub use backfill::snapshot_backfill::*;
144pub use barrier_recv::BarrierRecvExecutor;
145pub use batch_query::BatchQueryExecutor;
146pub use chain::ChainExecutor;
147pub use changelog::ChangeLogExecutor;
148pub use dedup::AppendOnlyDedupExecutor;
149pub use dispatch::{DispatchExecutor, SyncLogStoreDispatchExecutor};
150pub use dynamic_filter::DynamicFilterExecutor;
151pub use error::{StreamExecutorError, StreamExecutorResult};
152pub use expand::ExpandExecutor;
153pub use filter::{FilterExecutor, UpsertFilterExecutor};
154pub use gap_fill::{GapFillExecutor, GapFillExecutorArgs};
155pub use hash_join::*;
156pub use hop_window::HopWindowExecutor;
157pub use iceberg_with_pk_index::{
158 IcebergWriterImpl, PositionDeleteHandlerImpl, PositionDeleteMergerExecutor, WriterExecutor,
159};
160pub use join::asof_join::{AsOfCpuEncoding, AsOfMemoryEncoding};
161pub use join::row::{CachedJoinRow, CpuEncoding, JoinEncoding, MemoryEncoding};
162pub use join::{AsOfDesc, AsOfJoinType, JoinType};
163pub use lookup::*;
164pub use lookup_union::LookupUnionExecutor;
165pub use merge::MergeExecutor;
166pub(crate) use merge::{MergeExecutorInput, MergeExecutorUpstream};
167pub use mview::{MaterializeExecutor, RefreshableMaterializeArgs};
168pub use nested_loop_temporal_join::NestedLoopTemporalJoinExecutor;
169pub use no_op::NoOpExecutor;
170pub use now::*;
171pub use over_window::*;
172pub use receiver::ReceiverExecutor;
173use risingwave_common::id::SourceId;
174pub use row_merge::RowMergeExecutor;
175pub use sink::SinkExecutor;
176pub use sync_kv_log_store::SyncedKvLogStoreExecutor;
177pub use sync_kv_log_store::metrics::SyncedKvLogStoreMetrics;
178pub use temporal_join::TemporalJoinExecutor;
179pub use top_n::{
180 AppendOnlyGroupTopNExecutor, AppendOnlyTopNExecutor, GroupTopNExecutor, TopNExecutor,
181};
182pub use troublemaker::TroublemakerExecutor;
183pub use union::UnionExecutor;
184pub use upstream_sink_union::{UpstreamFragmentInfo, UpstreamSinkUnionExecutor};
185pub use utils::DummyExecutor;
186pub use values::ValuesExecutor;
187pub use vector::*;
188pub use watermark_filter::{UpsertWatermarkFilterExecutor, WatermarkFilterExecutor};
189pub use wrapper::WrapperExecutor;
190
191use self::barrier_align::AlignedMessageStream;
192
193pub type MessageStreamItemInner<M> = StreamExecutorResult<MessageInner<M>>;
194pub type MessageStreamItem = MessageStreamItemInner<BarrierMutationType>;
195pub type DispatcherMessageStreamItem = StreamExecutorResult<DispatcherMessage>;
196pub type BoxedMessageStream = BoxStream<'static, MessageStreamItem>;
197
198pub use risingwave_common::util::epoch::task_local::{curr_epoch, epoch, prev_epoch};
199use risingwave_connector::sink::catalog::SinkId;
200use risingwave_connector::source::cdc::{
201 CdcTableSnapshotSplitAssignmentWithGeneration,
202 build_actor_cdc_table_snapshot_splits_with_generation,
203};
204use risingwave_pb::id::{ExecutorId, SubscriberId};
205use risingwave_pb::stream_plan::stream_message_batch::{BarrierBatch, StreamMessageBatch};
206
207pub trait MessageStreamInner<M> = Stream<Item = MessageStreamItemInner<M>> + Send;
208pub trait MessageStream = Stream<Item = MessageStreamItem> + Send;
209pub trait DispatcherMessageStream = Stream<Item = DispatcherMessageStreamItem> + Send;
210
211#[derive(Debug, Default, Clone)]
213pub struct ExecutorInfo {
214 pub schema: Schema,
216
217 pub stream_key: StreamKey,
219
220 pub stream_kind: PbStreamKind,
222
223 pub identity: String,
225
226 pub id: ExecutorId,
228}
229
230impl ExecutorInfo {
231 pub fn for_test(schema: Schema, stream_key: StreamKey, identity: String, id: u64) -> Self {
232 Self {
233 schema,
234 stream_key,
235 stream_kind: PbStreamKind::Retract, identity,
237 id: id.into(),
238 }
239 }
240}
241
242pub trait Execute: Send + 'static {
244 fn execute(self: Box<Self>) -> BoxedMessageStream;
245
246 fn boxed(self) -> Box<dyn Execute>
247 where
248 Self: Sized + Send + 'static,
249 {
250 Box::new(self)
251 }
252}
253
254pub struct Executor {
257 info: ExecutorInfo,
258 execute: Box<dyn Execute>,
259}
260
261impl Executor {
262 pub fn new(info: ExecutorInfo, execute: Box<dyn Execute>) -> Self {
263 Self { info, execute }
264 }
265
266 pub fn info(&self) -> &ExecutorInfo {
267 &self.info
268 }
269
270 pub fn schema(&self) -> &Schema {
271 &self.info.schema
272 }
273
274 pub fn stream_key(&self) -> StreamKeyRef<'_> {
275 &self.info.stream_key
276 }
277
278 pub fn stream_kind(&self) -> PbStreamKind {
279 self.info.stream_kind
280 }
281
282 pub fn identity(&self) -> &str {
283 &self.info.identity
284 }
285
286 pub fn execute(self) -> BoxedMessageStream {
287 self.execute.execute()
288 }
289}
290
291impl std::fmt::Debug for Executor {
292 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
293 f.write_str(self.identity())
294 }
295}
296
297impl From<(ExecutorInfo, Box<dyn Execute>)> for Executor {
298 fn from((info, execute): (ExecutorInfo, Box<dyn Execute>)) -> Self {
299 Self::new(info, execute)
300 }
301}
302
303impl<E> From<(ExecutorInfo, E)> for Executor
304where
305 E: Execute,
306{
307 fn from((info, execute): (ExecutorInfo, E)) -> Self {
308 Self::new(info, execute.boxed())
309 }
310}
311
312pub const INVALID_EPOCH: u64 = 0;
313
314type UpstreamFragmentId = FragmentId;
315type SplitAssignments = HashMap<ActorId, Vec<SplitImpl>>;
316
317#[derive(Debug, Clone)]
318#[cfg_attr(any(test, feature = "test"), derive(Default, PartialEq))]
319pub struct UpdateMutation {
320 pub dispatchers: HashMap<ActorId, Vec<DispatcherUpdate>>,
321 pub merges: HashMap<(ActorId, UpstreamFragmentId), MergeUpdate>,
322 pub vnode_bitmaps: HashMap<ActorId, Arc<Bitmap>>,
323 pub dropped_actors: HashSet<ActorId>,
324 pub actor_splits: SplitAssignments,
325 pub actor_new_dispatchers: HashMap<ActorId, Vec<PbDispatcher>>,
326 pub actor_cdc_table_snapshot_splits: CdcTableSnapshotSplitAssignmentWithGeneration,
327 pub sink_schema_change: HashMap<SinkId, PbSinkSchemaChange>,
328 pub subscriptions_to_drop: Vec<SubscriptionUpstreamInfo>,
329}
330
331#[derive(Debug, Clone)]
332#[cfg_attr(any(test, feature = "test"), derive(Default, PartialEq))]
333pub struct AddMutation {
334 pub adds: HashMap<ActorId, Vec<PbDispatcher>>,
335 pub added_actors: HashSet<ActorId>,
336 pub dropped_actors: HashSet<ActorId>,
337 pub splits: SplitAssignments,
339 pub pause: bool,
340 pub subscriptions_to_add: Vec<(TableId, SubscriberId)>,
342 pub backfill_nodes_to_pause: HashSet<FragmentId>,
344 pub actor_cdc_table_snapshot_splits: CdcTableSnapshotSplitAssignmentWithGeneration,
345 pub new_upstream_sinks: HashMap<FragmentId, PbNewUpstreamSink>,
346 pub sink_log_store_flush: HashSet<SinkId>,
347}
348
349#[derive(Debug, Clone)]
350#[cfg_attr(any(test, feature = "test"), derive(Default, PartialEq))]
351pub struct StopMutation {
352 pub dropped_actors: HashSet<ActorId>,
353 pub dropped_sink_fragments: HashSet<FragmentId>,
354}
355
356#[cfg_attr(any(test, feature = "test"), derive(PartialEq))]
358#[derive(Debug, Clone)]
359pub enum Mutation {
360 Stop(StopMutation),
361 Update(UpdateMutation),
362 Add(AddMutation),
363 SourceChangeSplit(SplitAssignments),
364 Pause,
365 Resume,
366 Throttle(HashMap<FragmentId, ThrottleConfig>),
367 ConnectorPropsChange(HashMap<u32, HashMap<String, String>>),
368 DropSubscriptions {
369 subscriptions_to_drop: Vec<SubscriptionUpstreamInfo>,
371 },
372 StartFragmentBackfill {
373 fragment_ids: HashSet<FragmentId>,
374 },
375 RefreshStart {
376 table_id: TableId,
377 associated_source_id: SourceId,
378 },
379 ListFinish {
380 associated_source_id: SourceId,
381 },
382 LoadFinish {
383 associated_source_id: SourceId,
384 },
385 ResetSource {
386 source_id: SourceId,
387 },
388 InjectSourceOffsets {
389 source_id: SourceId,
390 split_offsets: HashMap<String, String>,
392 },
393}
394
395#[derive(Debug, Clone)]
400pub struct BarrierInner<M> {
401 pub epoch: EpochPair,
402 pub mutation: M,
403 pub kind: BarrierKind,
404
405 pub tracing_context: TracingContext,
407}
408
409pub type BarrierMutationType = Option<Arc<Mutation>>;
410pub type Barrier = BarrierInner<BarrierMutationType>;
411pub type DispatcherBarrier = BarrierInner<()>;
412
413impl<M: Default> BarrierInner<M> {
414 pub fn new_test_barrier(epoch: u64) -> Self {
416 Self {
417 epoch: EpochPair::new_test_epoch(epoch),
418 kind: BarrierKind::Checkpoint,
419 tracing_context: TracingContext::none(),
420 mutation: Default::default(),
421 }
422 }
423
424 pub fn with_prev_epoch_for_test(epoch: u64, prev_epoch: u64) -> Self {
425 Self {
426 epoch: EpochPair::new(epoch, prev_epoch),
427 kind: BarrierKind::Checkpoint,
428 tracing_context: TracingContext::none(),
429 mutation: Default::default(),
430 }
431 }
432}
433
434impl Barrier {
435 pub fn into_dispatcher(self) -> DispatcherBarrier {
436 DispatcherBarrier {
437 epoch: self.epoch,
438 mutation: (),
439 kind: self.kind,
440 tracing_context: self.tracing_context,
441 }
442 }
443
444 #[must_use]
445 pub fn with_mutation(self, mutation: Mutation) -> Self {
446 Self {
447 mutation: Some(Arc::new(mutation)),
448 ..self
449 }
450 }
451
452 #[must_use]
453 pub fn with_stop(self) -> Self {
454 self.with_mutation(Mutation::Stop(StopMutation {
455 dropped_actors: Default::default(),
456 dropped_sink_fragments: Default::default(),
457 }))
458 }
459
460 pub fn is_with_stop_mutation(&self) -> bool {
462 matches!(self.mutation.as_deref(), Some(Mutation::Stop(_)))
463 }
464
465 pub fn is_stop(&self, actor_id: ActorId) -> bool {
467 self.all_stop_actors()
468 .is_some_and(|actors| actors.contains(&actor_id))
469 }
470
471 pub fn is_checkpoint(&self) -> bool {
472 self.kind == BarrierKind::Checkpoint
473 }
474
475 pub fn initial_split_assignment(&self, actor_id: ActorId) -> Option<&[SplitImpl]> {
485 match self.mutation.as_deref()? {
486 Mutation::Update(UpdateMutation { actor_splits, .. })
487 | Mutation::Add(AddMutation {
488 splits: actor_splits,
489 ..
490 }) => actor_splits.get(&actor_id),
491
492 _ => {
493 if cfg!(debug_assertions) {
494 panic!(
495 "the initial mutation of the barrier should not be {:?}",
496 self.mutation
497 );
498 }
499 None
500 }
501 }
502 .map(|s| s.as_slice())
503 }
504
505 pub fn all_stop_actors(&self) -> Option<&HashSet<ActorId>> {
507 self.mutation.as_deref()?.all_stop_actors()
508 }
509
510 pub fn is_newly_added(&self, actor_id: ActorId) -> bool {
516 match self.mutation.as_deref() {
517 Some(Mutation::Add(AddMutation { added_actors, .. })) => {
518 added_actors.contains(&actor_id)
519 }
520 _ => false,
521 }
522 }
523
524 pub fn should_start_fragment_backfill(&self, fragment_id: FragmentId) -> bool {
525 if let Some(Mutation::StartFragmentBackfill { fragment_ids }) = self.mutation.as_deref() {
526 fragment_ids.contains(&fragment_id)
527 } else {
528 false
529 }
530 }
531
532 pub fn has_more_downstream_fragments(&self, upstream_actor_id: ActorId) -> bool {
550 let Some(mutation) = self.mutation.as_deref() else {
551 return false;
552 };
553 match mutation {
554 Mutation::Add(AddMutation { adds, .. }) => adds.get(&upstream_actor_id).is_some(),
556 Mutation::Update(_)
557 | Mutation::Stop(_)
558 | Mutation::Pause
559 | Mutation::Resume
560 | Mutation::SourceChangeSplit(_)
561 | Mutation::Throttle { .. }
562 | Mutation::DropSubscriptions { .. }
563 | Mutation::ConnectorPropsChange(_)
564 | Mutation::StartFragmentBackfill { .. }
565 | Mutation::RefreshStart { .. }
566 | Mutation::ListFinish { .. }
567 | Mutation::LoadFinish { .. }
568 | Mutation::ResetSource { .. }
569 | Mutation::InjectSourceOffsets { .. } => false,
570 }
571 }
572
573 pub fn is_pause_on_startup(&self) -> bool {
575 match self.mutation.as_deref() {
576 Some(Mutation::Add(AddMutation { pause, .. })) => *pause,
577 _ => false,
578 }
579 }
580
581 pub fn is_backfill_pause_on_startup(&self, backfill_fragment_id: FragmentId) -> bool {
582 match self.mutation.as_deref() {
583 Some(Mutation::Add(AddMutation {
584 backfill_nodes_to_pause,
585 ..
586 })) => backfill_nodes_to_pause.contains(&backfill_fragment_id),
587 Some(Mutation::Update(_)) => false,
588 _ => {
589 tracing::warn!(
590 "expected an AddMutation or UpdateMutation on Startup, instead got {:?}",
591 self
592 );
593 false
594 }
595 }
596 }
597
598 pub fn is_resume(&self) -> bool {
600 matches!(self.mutation.as_deref(), Some(Mutation::Resume))
601 }
602
603 pub fn as_update_merge(
606 &self,
607 actor_id: ActorId,
608 upstream_fragment_id: UpstreamFragmentId,
609 ) -> Option<&MergeUpdate> {
610 self.mutation
611 .as_deref()
612 .and_then(|mutation| match mutation {
613 Mutation::Update(UpdateMutation { merges, .. }) => {
614 merges.get(&(actor_id, upstream_fragment_id))
615 }
616 _ => None,
617 })
618 }
619
620 pub fn as_new_upstream_sink(&self, fragment_id: FragmentId) -> Option<&PbNewUpstreamSink> {
623 self.mutation
624 .as_deref()
625 .and_then(|mutation| match mutation {
626 Mutation::Add(AddMutation {
627 new_upstream_sinks, ..
628 }) => new_upstream_sinks.get(&fragment_id),
629 _ => None,
630 })
631 }
632
633 pub fn as_dropped_upstream_sinks(&self) -> Option<&HashSet<FragmentId>> {
635 self.mutation
636 .as_deref()
637 .and_then(|mutation| match mutation {
638 Mutation::Stop(StopMutation {
639 dropped_sink_fragments,
640 ..
641 }) => Some(dropped_sink_fragments),
642 _ => None,
643 })
644 }
645
646 pub fn as_update_vnode_bitmap(&self, actor_id: ActorId) -> Option<Arc<Bitmap>> {
652 self.mutation
653 .as_deref()
654 .and_then(|mutation| match mutation {
655 Mutation::Update(UpdateMutation { vnode_bitmaps, .. }) => {
656 vnode_bitmaps.get(&actor_id).cloned()
657 }
658 _ => None,
659 })
660 }
661
662 pub fn assume_no_update_vnode_bitmap(&self, actor_id: ActorId) -> StreamExecutorResult<()> {
663 if self.as_update_vnode_bitmap(actor_id).is_some() {
664 return Err(anyhow!("updating vnode bitmap in place is not supported").into());
665 }
666 Ok(())
667 }
668
669 pub fn as_sink_schema_change(&self, sink_id: SinkId) -> Option<PbSinkSchemaChange> {
670 self.mutation
671 .as_deref()
672 .and_then(|mutation| match mutation {
673 Mutation::Update(UpdateMutation {
674 sink_schema_change, ..
675 }) => sink_schema_change.get(&sink_id).cloned(),
676 _ => None,
677 })
678 }
679
680 pub fn should_flush_sink_log_store(&self, sink_id: SinkId) -> bool {
681 self.mutation
682 .as_deref()
683 .is_some_and(|mutation| match mutation {
684 Mutation::Add(AddMutation {
685 sink_log_store_flush,
686 ..
687 }) => sink_log_store_flush.contains(&sink_id),
688 _ => false,
689 })
690 }
691
692 pub fn as_subscriptions_to_drop(&self) -> Option<&[SubscriptionUpstreamInfo]> {
693 match self.mutation.as_deref() {
694 Some(Mutation::DropSubscriptions {
695 subscriptions_to_drop,
696 })
697 | Some(Mutation::Update(UpdateMutation {
698 subscriptions_to_drop,
699 ..
700 })) => Some(subscriptions_to_drop.as_slice()),
701 _ => None,
702 }
703 }
704
705 pub fn get_curr_epoch(&self) -> Epoch {
706 Epoch(self.epoch.curr)
707 }
708
709 pub fn tracing_context(&self) -> &TracingContext {
711 &self.tracing_context
712 }
713
714 pub fn added_subscriber_on_mv_table(
715 &self,
716 mv_table_id: TableId,
717 ) -> impl Iterator<Item = SubscriberId> + '_ {
718 if let Some(Mutation::Add(add)) = self.mutation.as_deref() {
719 Some(add)
720 } else {
721 None
722 }
723 .into_iter()
724 .flat_map(move |add| {
725 add.subscriptions_to_add.iter().filter_map(
726 move |(upstream_mv_table_id, subscriber_id)| {
727 if *upstream_mv_table_id == mv_table_id {
728 Some(*subscriber_id)
729 } else {
730 None
731 }
732 },
733 )
734 })
735 }
736}
737
738impl<M: PartialEq> PartialEq for BarrierInner<M> {
739 fn eq(&self, other: &Self) -> bool {
740 self.epoch == other.epoch && self.mutation == other.mutation
741 }
742}
743
744impl Mutation {
745 pub fn all_stop_actors(&self) -> Option<&HashSet<ActorId>> {
747 match self {
748 Mutation::Stop(StopMutation { dropped_actors, .. })
749 | Mutation::Update(UpdateMutation { dropped_actors, .. })
750 | Mutation::Add(AddMutation { dropped_actors, .. }) => Some(dropped_actors),
751 _ => None,
752 }
753 }
754
755 pub fn is_stop(&self, actor_id: ActorId) -> bool {
757 self.all_stop_actors()
758 .is_some_and(|actors| actors.contains(&actor_id))
759 }
760
761 #[cfg(test)]
765 pub fn is_stop_mutation(&self) -> bool {
766 matches!(self, Mutation::Stop(_))
767 }
768
769 #[cfg(test)]
770 fn to_protobuf(&self) -> PbMutation {
771 use risingwave_pb::source::{
772 ConnectorSplit, ConnectorSplits, PbCdcTableSnapshotSplitsWithGeneration,
773 };
774 use risingwave_pb::stream_plan::connector_props_change_mutation::ConnectorPropsInfo;
775 use risingwave_pb::stream_plan::{
776 PbAddMutation, PbConnectorPropsChangeMutation, PbDispatchers,
777 PbDropSubscriptionsMutation, PbPauseMutation, PbResumeMutation,
778 PbSourceChangeSplitMutation, PbStartFragmentBackfillMutation, PbStopMutation,
779 PbThrottleMutation, PbUpdateMutation,
780 };
781 let actor_splits_to_protobuf = |actor_splits: &SplitAssignments| {
782 actor_splits
783 .iter()
784 .map(|(&actor_id, splits)| {
785 (
786 actor_id,
787 ConnectorSplits {
788 splits: splits.clone().iter().map(ConnectorSplit::from).collect(),
789 },
790 )
791 })
792 .collect::<HashMap<_, _>>()
793 };
794
795 match self {
796 Mutation::Stop(StopMutation {
797 dropped_actors,
798 dropped_sink_fragments,
799 }) => PbMutation::Stop(PbStopMutation {
800 actors: dropped_actors.iter().copied().collect(),
801 dropped_sink_fragments: dropped_sink_fragments.iter().copied().collect(),
802 }),
803 Mutation::Update(UpdateMutation {
804 dispatchers,
805 merges,
806 vnode_bitmaps,
807 dropped_actors,
808 actor_splits,
809 actor_new_dispatchers,
810 actor_cdc_table_snapshot_splits,
811 sink_schema_change,
812 subscriptions_to_drop,
813 }) => PbMutation::Update(PbUpdateMutation {
814 dispatcher_update: dispatchers.values().flatten().cloned().collect(),
815 merge_update: merges.values().cloned().collect(),
816 actor_vnode_bitmap_update: vnode_bitmaps
817 .iter()
818 .map(|(&actor_id, bitmap)| (actor_id, bitmap.to_protobuf()))
819 .collect(),
820 dropped_actors: dropped_actors.iter().copied().collect(),
821 actor_splits: actor_splits_to_protobuf(actor_splits),
822 actor_new_dispatchers: actor_new_dispatchers
823 .iter()
824 .map(|(&actor_id, dispatchers)| {
825 (
826 actor_id,
827 PbDispatchers {
828 dispatchers: dispatchers.clone(),
829 },
830 )
831 })
832 .collect(),
833 actor_cdc_table_snapshot_splits: Some(PbCdcTableSnapshotSplitsWithGeneration {
834 splits:actor_cdc_table_snapshot_splits.splits.iter().map(|(actor_id,(splits, generation))| {
835 (*actor_id, risingwave_pb::source::PbCdcTableSnapshotSplits {
836 splits: splits.iter().map(risingwave_connector::source::cdc::build_cdc_table_snapshot_split).collect(),
837 generation: *generation,
838 })
839 }).collect()
840 }),
841 sink_schema_change: sink_schema_change
842 .iter()
843 .map(|(sink_id, change)| ((*sink_id).as_raw_id(), change.clone()))
844 .collect(),
845 subscriptions_to_drop: subscriptions_to_drop.clone(),
846 }),
847 Mutation::Add(AddMutation {
848 adds,
849 added_actors,
850 dropped_actors,
851 splits,
852 pause,
853 subscriptions_to_add,
854 backfill_nodes_to_pause,
855 actor_cdc_table_snapshot_splits,
856 new_upstream_sinks,
857 sink_log_store_flush,
858 }) => PbMutation::Add(PbAddMutation {
859 actor_dispatchers: adds
860 .iter()
861 .map(|(&actor_id, dispatchers)| {
862 (
863 actor_id,
864 PbDispatchers {
865 dispatchers: dispatchers.clone(),
866 },
867 )
868 })
869 .collect(),
870 added_actors: added_actors.iter().copied().collect(),
871 actor_splits: actor_splits_to_protobuf(splits),
872 pause: *pause,
873 subscriptions_to_add: subscriptions_to_add
874 .iter()
875 .map(|(table_id, subscriber_id)| SubscriptionUpstreamInfo {
876 subscriber_id: *subscriber_id,
877 upstream_mv_table_id: *table_id,
878 })
879 .collect(),
880 backfill_nodes_to_pause: backfill_nodes_to_pause.iter().copied().collect(),
881 actor_cdc_table_snapshot_splits:
882 Some(PbCdcTableSnapshotSplitsWithGeneration {
883 splits:actor_cdc_table_snapshot_splits.splits.iter().map(|(actor_id,(splits, generation))| {
884 (*actor_id, risingwave_pb::source::PbCdcTableSnapshotSplits {
885 splits: splits.iter().map(risingwave_connector::source::cdc::build_cdc_table_snapshot_split).collect(),
886 generation: *generation,
887 })
888 }).collect()
889 }),
890 new_upstream_sinks: new_upstream_sinks
891 .iter()
892 .map(|(k, v)| (*k, v.clone()))
893 .collect(),
894 dropped_actors: dropped_actors.iter().copied().collect(),
895 sink_log_store_flush: sink_log_store_flush.iter().copied().collect(),
896 }),
897 Mutation::SourceChangeSplit(changes) => {
898 PbMutation::Splits(PbSourceChangeSplitMutation {
899 actor_splits: changes
900 .iter()
901 .map(|(&actor_id, splits)| {
902 (
903 actor_id,
904 ConnectorSplits {
905 splits: splits
906 .clone()
907 .iter()
908 .map(ConnectorSplit::from)
909 .collect(),
910 },
911 )
912 })
913 .collect(),
914 })
915 }
916 Mutation::Pause => PbMutation::Pause(PbPauseMutation {}),
917 Mutation::Resume => PbMutation::Resume(PbResumeMutation {}),
918 Mutation::Throttle (changes) => PbMutation::Throttle(PbThrottleMutation {
919 fragment_throttle: changes.clone(),
920 }),
921 Mutation::DropSubscriptions {
922 subscriptions_to_drop,
923 } => PbMutation::DropSubscriptions(PbDropSubscriptionsMutation {
924 info: subscriptions_to_drop.clone(),
925 }),
926 Mutation::ConnectorPropsChange(map) => {
927 PbMutation::ConnectorPropsChange(PbConnectorPropsChangeMutation {
928 connector_props_infos: map
929 .iter()
930 .map(|(actor_id, options)| {
931 (
932 *actor_id,
933 ConnectorPropsInfo {
934 connector_props_info: options
935 .iter()
936 .map(|(k, v)| (k.clone(), v.clone()))
937 .collect(),
938 },
939 )
940 })
941 .collect(),
942 })
943 }
944 Mutation::StartFragmentBackfill { fragment_ids } => {
945 PbMutation::StartFragmentBackfill(PbStartFragmentBackfillMutation {
946 fragment_ids: fragment_ids.iter().copied().collect(),
947 })
948 }
949 Mutation::RefreshStart {
950 table_id,
951 associated_source_id,
952 } => PbMutation::RefreshStart(risingwave_pb::stream_plan::RefreshStartMutation {
953 table_id: *table_id,
954 associated_source_id: *associated_source_id,
955 }),
956 Mutation::ListFinish {
957 associated_source_id,
958 } => PbMutation::ListFinish(risingwave_pb::stream_plan::ListFinishMutation {
959 associated_source_id: *associated_source_id,
960 }),
961 Mutation::LoadFinish {
962 associated_source_id,
963 } => PbMutation::LoadFinish(risingwave_pb::stream_plan::LoadFinishMutation {
964 associated_source_id: *associated_source_id,
965 }),
966 Mutation::ResetSource { source_id } => {
967 PbMutation::ResetSource(risingwave_pb::stream_plan::ResetSourceMutation {
968 source_id: source_id.as_raw_id(),
969 })
970 }
971 Mutation::InjectSourceOffsets {
972 source_id,
973 split_offsets,
974 } => PbMutation::InjectSourceOffsets(
975 risingwave_pb::stream_plan::InjectSourceOffsetsMutation {
976 source_id: source_id.as_raw_id(),
977 split_offsets: split_offsets.clone(),
978 },
979 ),
980 }
981 }
982
983 fn from_protobuf(prost: &PbMutation) -> StreamExecutorResult<Self> {
984 let mutation = match prost {
985 PbMutation::Stop(stop) => Mutation::Stop(StopMutation {
986 dropped_actors: stop.actors.iter().copied().collect(),
987 dropped_sink_fragments: stop.dropped_sink_fragments.iter().copied().collect(),
988 }),
989
990 PbMutation::Update(update) => Mutation::Update(UpdateMutation {
991 dispatchers: update
992 .dispatcher_update
993 .iter()
994 .map(|u| (u.actor_id, u.clone()))
995 .into_group_map(),
996 merges: update
997 .merge_update
998 .iter()
999 .map(|u| ((u.actor_id, u.upstream_fragment_id), u.clone()))
1000 .collect(),
1001 vnode_bitmaps: update
1002 .actor_vnode_bitmap_update
1003 .iter()
1004 .map(|(&actor_id, bitmap)| (actor_id, Arc::new(bitmap.into())))
1005 .collect(),
1006 dropped_actors: update.dropped_actors.iter().copied().collect(),
1007 actor_splits: update
1008 .actor_splits
1009 .iter()
1010 .map(|(&actor_id, splits)| {
1011 (
1012 actor_id,
1013 splits
1014 .splits
1015 .iter()
1016 .map(|split| split.try_into().unwrap())
1017 .collect(),
1018 )
1019 })
1020 .collect(),
1021 actor_new_dispatchers: update
1022 .actor_new_dispatchers
1023 .iter()
1024 .map(|(&actor_id, dispatchers)| (actor_id, dispatchers.dispatchers.clone()))
1025 .collect(),
1026 actor_cdc_table_snapshot_splits:
1027 build_actor_cdc_table_snapshot_splits_with_generation(
1028 update
1029 .actor_cdc_table_snapshot_splits
1030 .clone()
1031 .unwrap_or_default(),
1032 ),
1033 sink_schema_change: update
1034 .sink_schema_change
1035 .iter()
1036 .map(|(sink_id, change)| (SinkId::from(*sink_id), change.clone()))
1037 .collect(),
1038 subscriptions_to_drop: update.subscriptions_to_drop.clone(),
1039 }),
1040
1041 PbMutation::Add(add) => Mutation::Add(AddMutation {
1042 adds: add
1043 .actor_dispatchers
1044 .iter()
1045 .map(|(&actor_id, dispatchers)| (actor_id, dispatchers.dispatchers.clone()))
1046 .collect(),
1047 added_actors: add.added_actors.iter().copied().collect(),
1048 dropped_actors: add.dropped_actors.iter().copied().collect(),
1049 splits: add
1052 .actor_splits
1053 .iter()
1054 .map(|(&actor_id, splits)| {
1055 (
1056 actor_id,
1057 splits
1058 .splits
1059 .iter()
1060 .map(|split| split.try_into().unwrap())
1061 .collect(),
1062 )
1063 })
1064 .collect(),
1065 pause: add.pause,
1066 subscriptions_to_add: add
1067 .subscriptions_to_add
1068 .iter()
1069 .map(
1070 |SubscriptionUpstreamInfo {
1071 subscriber_id,
1072 upstream_mv_table_id,
1073 }| { (*upstream_mv_table_id, *subscriber_id) },
1074 )
1075 .collect(),
1076 backfill_nodes_to_pause: add.backfill_nodes_to_pause.iter().copied().collect(),
1077 actor_cdc_table_snapshot_splits:
1078 build_actor_cdc_table_snapshot_splits_with_generation(
1079 add.actor_cdc_table_snapshot_splits
1080 .clone()
1081 .unwrap_or_default(),
1082 ),
1083 new_upstream_sinks: add
1084 .new_upstream_sinks
1085 .iter()
1086 .map(|(k, v)| (*k, v.clone()))
1087 .collect(),
1088 sink_log_store_flush: add.sink_log_store_flush.iter().copied().collect(),
1089 }),
1090
1091 PbMutation::Splits(s) => {
1092 let mut change_splits: Vec<(ActorId, Vec<SplitImpl>)> =
1093 Vec::with_capacity(s.actor_splits.len());
1094 for (&actor_id, splits) in &s.actor_splits {
1095 if !splits.splits.is_empty() {
1096 change_splits.push((
1097 actor_id,
1098 splits
1099 .splits
1100 .iter()
1101 .map(SplitImpl::try_from)
1102 .try_collect()?,
1103 ));
1104 }
1105 }
1106 Mutation::SourceChangeSplit(change_splits.into_iter().collect())
1107 }
1108 PbMutation::Pause(_) => Mutation::Pause,
1109 PbMutation::Resume(_) => Mutation::Resume,
1110 PbMutation::Throttle(changes) => Mutation::Throttle(changes.fragment_throttle.clone()),
1111 PbMutation::DropSubscriptions(drop) => Mutation::DropSubscriptions {
1112 subscriptions_to_drop: drop.info.clone(),
1113 },
1114 PbMutation::ConnectorPropsChange(alter_connector_props) => {
1115 Mutation::ConnectorPropsChange(
1116 alter_connector_props
1117 .connector_props_infos
1118 .iter()
1119 .map(|(connector_id, options)| {
1120 (
1121 *connector_id,
1122 options
1123 .connector_props_info
1124 .iter()
1125 .map(|(k, v)| (k.clone(), v.clone()))
1126 .collect(),
1127 )
1128 })
1129 .collect(),
1130 )
1131 }
1132 PbMutation::StartFragmentBackfill(start_fragment_backfill) => {
1133 Mutation::StartFragmentBackfill {
1134 fragment_ids: start_fragment_backfill
1135 .fragment_ids
1136 .iter()
1137 .copied()
1138 .collect(),
1139 }
1140 }
1141 PbMutation::RefreshStart(refresh_start) => Mutation::RefreshStart {
1142 table_id: refresh_start.table_id,
1143 associated_source_id: refresh_start.associated_source_id,
1144 },
1145 PbMutation::ListFinish(list_finish) => Mutation::ListFinish {
1146 associated_source_id: list_finish.associated_source_id,
1147 },
1148 PbMutation::LoadFinish(load_finish) => Mutation::LoadFinish {
1149 associated_source_id: load_finish.associated_source_id,
1150 },
1151 PbMutation::ResetSource(reset_source) => Mutation::ResetSource {
1152 source_id: SourceId::from(reset_source.source_id),
1153 },
1154 PbMutation::InjectSourceOffsets(inject) => Mutation::InjectSourceOffsets {
1155 source_id: SourceId::from(inject.source_id),
1156 split_offsets: inject.split_offsets.clone(),
1157 },
1158 };
1159 Ok(mutation)
1160 }
1161}
1162
1163impl<M> BarrierInner<M> {
1164 fn to_protobuf_inner(&self, barrier_fn: impl FnOnce(&M) -> Option<PbMutation>) -> PbBarrier {
1165 let Self {
1166 epoch,
1167 mutation,
1168 kind,
1169 tracing_context,
1170 ..
1171 } = self;
1172
1173 PbBarrier {
1174 epoch: Some(PbEpoch {
1175 curr: epoch.curr,
1176 prev: epoch.prev,
1177 }),
1178 mutation: barrier_fn(mutation).map(|mutation| PbBarrierMutation {
1179 mutation: Some(mutation),
1180 }),
1181 tracing_context: tracing_context.to_protobuf(),
1182 kind: *kind as _,
1183 }
1184 }
1185
1186 fn from_protobuf_inner(
1187 prost: &PbBarrier,
1188 mutation_from_pb: impl FnOnce(Option<&PbMutation>) -> StreamExecutorResult<M>,
1189 ) -> StreamExecutorResult<Self> {
1190 let epoch = prost.get_epoch()?;
1191
1192 Ok(Self {
1193 kind: prost.kind(),
1194 epoch: EpochPair::new(epoch.curr, epoch.prev),
1195 mutation: mutation_from_pb(
1196 (prost.mutation.as_ref()).and_then(|mutation| mutation.mutation.as_ref()),
1197 )?,
1198 tracing_context: TracingContext::from_protobuf(&prost.tracing_context),
1199 })
1200 }
1201
1202 pub fn map_mutation<M2>(self, f: impl FnOnce(M) -> M2) -> BarrierInner<M2> {
1203 BarrierInner {
1204 epoch: self.epoch,
1205 mutation: f(self.mutation),
1206 kind: self.kind,
1207 tracing_context: self.tracing_context,
1208 }
1209 }
1210}
1211
1212impl DispatcherBarrier {
1213 pub fn to_protobuf(&self) -> PbBarrier {
1214 self.to_protobuf_inner(|_| None)
1215 }
1216}
1217
1218impl Barrier {
1219 #[cfg(test)]
1220 pub fn to_protobuf(&self) -> PbBarrier {
1221 self.to_protobuf_inner(|mutation| mutation.as_ref().map(|mutation| mutation.to_protobuf()))
1222 }
1223
1224 pub fn from_protobuf(prost: &PbBarrier) -> StreamExecutorResult<Self> {
1225 Self::from_protobuf_inner(prost, |mutation| {
1226 mutation
1227 .map(|m| Mutation::from_protobuf(m).map(Arc::new))
1228 .transpose()
1229 })
1230 }
1231}
1232
1233#[derive(Debug, PartialEq, Eq, Clone, EstimateSize)]
1234pub struct Watermark {
1235 pub col_idx: usize,
1236 #[estimate_size(ignore)]
1237 pub data_type: DataType,
1238 pub val: ScalarImpl,
1239}
1240
1241impl PartialOrd for Watermark {
1242 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
1243 Some(self.cmp(other))
1244 }
1245}
1246
1247impl Ord for Watermark {
1248 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
1249 self.val.default_cmp(&other.val)
1250 }
1251}
1252
1253impl Watermark {
1254 pub fn new(col_idx: usize, data_type: DataType, val: ScalarImpl) -> Self {
1255 Self {
1256 col_idx,
1257 data_type,
1258 val,
1259 }
1260 }
1261
1262 pub async fn transform_with_expr(
1263 self,
1264 expr: &NonStrictExpression,
1265 new_col_idx: usize,
1266 ) -> Option<Self> {
1267 let Self { col_idx, val, .. } = self;
1268 let row = {
1269 let mut row = vec![None; col_idx + 1];
1270 row[col_idx] = Some(val);
1271 OwnedRow::new(row)
1272 };
1273 let val = expr.eval_row_infallible(&row).await?;
1274 Some(Self::new(new_col_idx, expr.inner().return_type(), val))
1275 }
1276
1277 pub fn transform_with_indices(self, output_indices: &[usize]) -> Option<Self> {
1280 output_indices
1281 .iter()
1282 .position(|p| *p == self.col_idx)
1283 .map(|new_col_idx| self.with_idx(new_col_idx))
1284 }
1285
1286 pub fn to_protobuf(&self) -> PbWatermark {
1287 PbWatermark {
1288 column: Some(PbInputRef {
1289 index: self.col_idx as _,
1290 r#type: Some(self.data_type.to_protobuf()),
1291 }),
1292 val: Some(&self.val).to_protobuf().into(),
1293 }
1294 }
1295
1296 pub fn from_protobuf(prost: &PbWatermark) -> StreamExecutorResult<Self> {
1297 let col_ref = prost.get_column()?;
1298 let data_type = DataType::from(col_ref.get_type()?);
1299 let val = Datum::from_protobuf(prost.get_val()?, &data_type)?
1300 .expect("watermark value cannot be null");
1301 Ok(Self::new(col_ref.get_index() as _, data_type, val))
1302 }
1303
1304 pub fn with_idx(self, idx: usize) -> Self {
1305 Self::new(idx, self.data_type, self.val)
1306 }
1307}
1308
1309#[cfg_attr(any(test, feature = "test"), derive(PartialEq))]
1310#[derive(Debug, EnumAsInner, Clone)]
1311pub enum MessageInner<M> {
1312 Chunk(StreamChunk),
1313 Barrier(BarrierInner<M>),
1314 Watermark(Watermark),
1315}
1316
1317impl<M> MessageInner<M> {
1318 pub fn map_mutation<M2>(self, f: impl FnOnce(M) -> M2) -> MessageInner<M2> {
1319 match self {
1320 MessageInner::Chunk(chunk) => MessageInner::Chunk(chunk),
1321 MessageInner::Barrier(barrier) => MessageInner::Barrier(barrier.map_mutation(f)),
1322 MessageInner::Watermark(watermark) => MessageInner::Watermark(watermark),
1323 }
1324 }
1325}
1326
1327pub type Message = MessageInner<BarrierMutationType>;
1328pub type DispatcherMessage = MessageInner<()>;
1329
1330#[derive(Debug, EnumAsInner, Clone)]
1333pub enum MessageBatchInner<M> {
1334 Chunk(StreamChunk),
1335 BarrierBatch(Vec<BarrierInner<M>>),
1336 Watermark(Watermark),
1337}
1338pub type MessageBatch = MessageBatchInner<BarrierMutationType>;
1339pub type DispatcherBarriers = Vec<DispatcherBarrier>;
1340pub type DispatcherMessageBatch = MessageBatchInner<()>;
1341
1342impl<M> From<MessageInner<M>> for MessageBatchInner<M> {
1343 fn from(m: MessageInner<M>) -> Self {
1344 match m {
1345 MessageInner::Chunk(c) => Self::Chunk(c),
1346 MessageInner::Barrier(b) => Self::BarrierBatch(vec![b]),
1347 MessageInner::Watermark(w) => Self::Watermark(w),
1348 }
1349 }
1350}
1351
1352impl From<StreamChunk> for Message {
1353 fn from(chunk: StreamChunk) -> Self {
1354 Message::Chunk(chunk)
1355 }
1356}
1357
1358impl<'a> TryFrom<&'a Message> for &'a Barrier {
1359 type Error = ();
1360
1361 fn try_from(m: &'a Message) -> std::result::Result<Self, Self::Error> {
1362 match m {
1363 Message::Chunk(_) => Err(()),
1364 Message::Barrier(b) => Ok(b),
1365 Message::Watermark(_) => Err(()),
1366 }
1367 }
1368}
1369
1370impl Message {
1371 #[cfg(test)]
1376 pub fn is_stop(&self) -> bool {
1377 matches!(
1378 self,
1379 Message::Barrier(Barrier {
1380 mutation,
1381 ..
1382 }) if mutation.as_ref().unwrap().is_stop_mutation()
1383 )
1384 }
1385}
1386
1387impl DispatcherMessageBatch {
1388 pub fn to_protobuf(&self) -> PbStreamMessageBatch {
1389 let prost = match self {
1390 Self::Chunk(stream_chunk) => {
1391 let prost_stream_chunk = stream_chunk.to_protobuf();
1392 StreamMessageBatch::StreamChunk(prost_stream_chunk)
1393 }
1394 Self::BarrierBatch(barrier_batch) => StreamMessageBatch::BarrierBatch(BarrierBatch {
1395 barriers: barrier_batch.iter().map(|b| b.to_protobuf()).collect(),
1396 }),
1397 Self::Watermark(watermark) => StreamMessageBatch::Watermark(watermark.to_protobuf()),
1398 };
1399 PbStreamMessageBatch {
1400 stream_message_batch: Some(prost),
1401 }
1402 }
1403
1404 pub fn from_protobuf(prost: &PbStreamMessageBatch) -> StreamExecutorResult<Self> {
1405 let res = match prost.get_stream_message_batch()? {
1406 StreamMessageBatch::StreamChunk(chunk) => {
1407 Self::Chunk(StreamChunk::from_protobuf(chunk)?)
1408 }
1409 StreamMessageBatch::BarrierBatch(barrier_batch) => {
1410 let barriers = barrier_batch
1411 .barriers
1412 .iter()
1413 .map(|barrier| {
1414 DispatcherBarrier::from_protobuf_inner(barrier, |mutation| {
1415 if mutation.is_some() {
1416 if cfg!(debug_assertions) {
1417 panic!("should not receive message of barrier with mutation");
1418 } else {
1419 warn!(?barrier, "receive message of barrier with mutation");
1420 }
1421 }
1422 Ok(())
1423 })
1424 })
1425 .try_collect()?;
1426 Self::BarrierBatch(barriers)
1427 }
1428 StreamMessageBatch::Watermark(watermark) => {
1429 Self::Watermark(Watermark::from_protobuf(watermark)?)
1430 }
1431 };
1432 Ok(res)
1433 }
1434
1435 pub fn get_encoded_len(msg: &impl ::prost::Message) -> usize {
1436 ::prost::Message::encoded_len(msg)
1437 }
1438}
1439
1440pub type StreamKey = Vec<usize>;
1441pub type StreamKeyRef<'a> = &'a [usize];
1442pub type StreamKeyDataTypes = SmallVec<[DataType; 1]>;
1443
1444pub async fn expect_first_barrier<M: Debug>(
1446 stream: &mut (impl MessageStreamInner<M> + Unpin),
1447) -> StreamExecutorResult<BarrierInner<M>> {
1448 let message = stream
1449 .next()
1450 .instrument_await("expect_first_barrier")
1451 .await
1452 .context("failed to extract the first message: stream closed unexpectedly")??;
1453 let barrier = message
1454 .into_barrier()
1455 .expect("the first message must be a barrier");
1456 assert!(matches!(
1458 barrier.kind,
1459 BarrierKind::Checkpoint | BarrierKind::Initial
1460 ));
1461 Ok(barrier)
1462}
1463
1464pub async fn expect_first_barrier_from_aligned_stream(
1466 stream: &mut (impl AlignedMessageStream + Unpin),
1467) -> StreamExecutorResult<Barrier> {
1468 let message = stream
1469 .next()
1470 .instrument_await("expect_first_barrier")
1471 .await
1472 .context("failed to extract the first message: stream closed unexpectedly")??;
1473 let barrier = message
1474 .into_barrier()
1475 .expect("the first message must be a barrier");
1476 Ok(barrier)
1477}
1478
1479pub trait StreamConsumer: Send + 'static {
1481 type BarrierStream: Stream<Item = StreamResult<Barrier>> + Send;
1482
1483 fn execute(self: Box<Self>) -> Self::BarrierStream;
1484}
1485
1486type BoxedMessageInput<InputId, M> = BoxedInput<InputId, MessageStreamItemInner<M>>;
1487
1488pub struct DynamicReceivers<InputId, M> {
1492 barrier: Option<BarrierInner<M>>,
1494 start_ts: Option<Instant>,
1496 blocked: Vec<BoxedMessageInput<InputId, M>>,
1498 active: FuturesUnordered<StreamFuture<BoxedMessageInput<InputId, M>>>,
1500 buffered_watermarks: BTreeMap<usize, BufferedWatermarks<InputId>>,
1502 barrier_align_duration: Option<LabelGuardedMetric<GenericCounter<AtomicU64>>>,
1504 merge_barrier_align_duration: Option<LabelGuardedMetric<GenericCounter<AtomicU64>>>,
1506}
1507
1508impl<InputId: Clone + Ord + Hash + std::fmt::Debug + Unpin, M: Clone + Unpin> Stream
1509 for DynamicReceivers<InputId, M>
1510{
1511 type Item = MessageStreamItemInner<M>;
1512
1513 fn poll_next(
1514 mut self: Pin<&mut Self>,
1515 cx: &mut std::task::Context<'_>,
1516 ) -> Poll<Option<Self::Item>> {
1517 if self.is_empty() {
1518 return Poll::Ready(None);
1519 }
1520
1521 loop {
1522 match futures::ready!(self.active.poll_next_unpin(cx)) {
1523 Some((Some(Err(e)), _)) => {
1525 return Poll::Ready(Some(Err(e)));
1526 }
1527 Some((Some(Ok(message)), remaining)) => {
1529 let input_id = remaining.id();
1530 match message {
1531 MessageInner::Chunk(chunk) => {
1532 self.active.push(remaining.into_future());
1534 return Poll::Ready(Some(Ok(MessageInner::Chunk(chunk))));
1535 }
1536 MessageInner::Watermark(watermark) => {
1537 self.active.push(remaining.into_future());
1539 if let Some(watermark) = self.handle_watermark(input_id, watermark) {
1540 return Poll::Ready(Some(Ok(MessageInner::Watermark(watermark))));
1541 }
1542 }
1543 MessageInner::Barrier(barrier) => {
1544 if self.blocked.is_empty() {
1546 self.start_ts = Some(Instant::now());
1547 }
1548 self.blocked.push(remaining);
1549 if let Some(current_barrier) = self.barrier.as_ref() {
1550 if current_barrier.epoch != barrier.epoch {
1551 return Poll::Ready(Some(Err(
1552 StreamExecutorError::align_barrier(
1553 current_barrier.clone().map_mutation(|_| None),
1554 barrier.map_mutation(|_| None),
1555 ),
1556 )));
1557 }
1558 } else {
1559 self.barrier = Some(barrier);
1560 }
1561 }
1562 }
1563 }
1564 Some((None, remaining)) => {
1572 return Poll::Ready(Some(Err(StreamExecutorError::channel_closed(format!(
1573 "upstream input {:?} unexpectedly closed",
1574 remaining.id()
1575 )))));
1576 }
1577 None => {
1579 assert!(!self.blocked.is_empty());
1580
1581 let start_ts = self
1582 .start_ts
1583 .take()
1584 .expect("should have received at least one barrier");
1585 if let Some(barrier_align_duration) = &self.barrier_align_duration {
1586 barrier_align_duration.inc_by(start_ts.elapsed().as_nanos() as u64);
1587 }
1588 if let Some(merge_barrier_align_duration) = &self.merge_barrier_align_duration {
1589 merge_barrier_align_duration.inc_by(start_ts.elapsed().as_nanos() as u64);
1590 }
1591
1592 break;
1593 }
1594 }
1595 }
1596
1597 assert!(self.active.is_terminated());
1598
1599 let barrier = self.barrier.take().unwrap();
1600
1601 let upstreams = std::mem::take(&mut self.blocked);
1602 self.extend_active(upstreams);
1603 assert!(!self.active.is_terminated());
1604
1605 Poll::Ready(Some(Ok(MessageInner::Barrier(barrier))))
1606 }
1607}
1608
1609impl<InputId: Clone + Ord + Hash + std::fmt::Debug, M> DynamicReceivers<InputId, M> {
1610 pub fn new(
1611 upstreams: Vec<BoxedMessageInput<InputId, M>>,
1612 barrier_align_duration: Option<LabelGuardedMetric<GenericCounter<AtomicU64>>>,
1613 merge_barrier_align_duration: Option<LabelGuardedMetric<GenericCounter<AtomicU64>>>,
1614 ) -> Self {
1615 let mut this = Self {
1616 barrier: None,
1617 start_ts: None,
1618 blocked: Vec::with_capacity(upstreams.len()),
1619 active: Default::default(),
1620 buffered_watermarks: Default::default(),
1621 merge_barrier_align_duration,
1622 barrier_align_duration,
1623 };
1624 this.extend_active(upstreams);
1625 this
1626 }
1627
1628 pub fn extend_active(
1631 &mut self,
1632 upstreams: impl IntoIterator<Item = BoxedMessageInput<InputId, M>>,
1633 ) {
1634 assert!(self.blocked.is_empty() && self.barrier.is_none());
1635
1636 self.active
1637 .extend(upstreams.into_iter().map(|s| s.into_future()));
1638 }
1639
1640 pub fn handle_watermark(
1642 &mut self,
1643 input_id: InputId,
1644 watermark: Watermark,
1645 ) -> Option<Watermark> {
1646 let col_idx = watermark.col_idx;
1647 let upstream_ids: Vec<_> = self.upstream_input_ids().collect();
1649 let watermarks = self
1650 .buffered_watermarks
1651 .entry(col_idx)
1652 .or_insert_with(|| BufferedWatermarks::with_ids(upstream_ids));
1653 watermarks.handle_watermark(input_id, watermark)
1654 }
1655
1656 pub fn add_upstreams_from(
1659 &mut self,
1660 new_inputs: impl IntoIterator<Item = BoxedMessageInput<InputId, M>>,
1661 ) {
1662 assert!(self.blocked.is_empty() && self.barrier.is_none());
1663
1664 let new_inputs: Vec<_> = new_inputs.into_iter().collect();
1665 let input_ids = new_inputs.iter().map(|input| input.id());
1666 self.buffered_watermarks.values_mut().for_each(|buffers| {
1667 buffers.add_buffers(input_ids.clone());
1669 });
1670 self.active
1671 .extend(new_inputs.into_iter().map(|s| s.into_future()));
1672 }
1673
1674 pub fn remove_upstreams(&mut self, upstream_input_ids: &HashSet<InputId>) {
1678 assert!(self.blocked.is_empty() && self.barrier.is_none());
1679
1680 let new_upstreams = std::mem::take(&mut self.active)
1681 .into_iter()
1682 .map(|s| s.into_inner().unwrap())
1683 .filter(|u| !upstream_input_ids.contains(&u.id()));
1684 self.extend_active(new_upstreams);
1685 self.buffered_watermarks.values_mut().for_each(|buffers| {
1686 buffers.remove_buffer(upstream_input_ids.clone());
1689 });
1690 }
1691
1692 pub fn merge_barrier_align_duration(
1693 &self,
1694 ) -> Option<LabelGuardedMetric<GenericCounter<AtomicU64>>> {
1695 self.merge_barrier_align_duration.clone()
1696 }
1697
1698 pub fn flush_buffered_watermarks(&mut self) {
1699 self.buffered_watermarks
1700 .values_mut()
1701 .for_each(|buffers| buffers.clear());
1702 }
1703
1704 pub fn upstream_input_ids(&self) -> impl Iterator<Item = InputId> + '_ {
1705 self.blocked
1706 .iter()
1707 .map(|s| s.id())
1708 .chain(self.active.iter().map(|s| s.get_ref().unwrap().id()))
1709 }
1710
1711 pub fn is_empty(&self) -> bool {
1712 self.blocked.is_empty() && self.active.is_empty()
1713 }
1714}
1715
1716pub(crate) struct DispatchBarrierBuffer {
1737 buffer: VecDeque<(Barrier, Option<Vec<BoxedActorInput>>)>,
1738 barrier_rx: mpsc::UnboundedReceiver<Barrier>,
1739 recv_state: BarrierReceiverState,
1740 curr_upstream_fragment_id: FragmentId,
1741 actor_id: ActorId,
1742 build_input_ctx: Arc<BuildInputContext>,
1744}
1745
1746struct BuildInputContext {
1747 pub actor_id: ActorId,
1748 pub local_barrier_manager: LocalBarrierManager,
1749 pub metrics: Arc<StreamingMetrics>,
1750 pub fragment_id: FragmentId,
1751 pub actor_config: Arc<StreamingConfig>,
1752}
1753
1754type BoxedNewInputsFuture =
1755 Pin<Box<dyn Future<Output = StreamExecutorResult<Vec<BoxedActorInput>>> + Send>>;
1756
1757enum BarrierReceiverState {
1758 ReceivingBarrier,
1759 CreatingNewInput(Barrier, BoxedNewInputsFuture),
1760}
1761
1762impl DispatchBarrierBuffer {
1763 pub fn new(
1764 barrier_rx: mpsc::UnboundedReceiver<Barrier>,
1765 actor_id: ActorId,
1766 curr_upstream_fragment_id: FragmentId,
1767 local_barrier_manager: LocalBarrierManager,
1768 metrics: Arc<StreamingMetrics>,
1769 fragment_id: FragmentId,
1770 actor_config: Arc<StreamingConfig>,
1771 ) -> Self {
1772 Self {
1773 buffer: VecDeque::new(),
1774 barrier_rx,
1775 recv_state: BarrierReceiverState::ReceivingBarrier,
1776 curr_upstream_fragment_id,
1777 actor_id,
1778 build_input_ctx: Arc::new(BuildInputContext {
1779 actor_id,
1780 local_barrier_manager,
1781 metrics,
1782 fragment_id,
1783 actor_config,
1784 }),
1785 }
1786 }
1787
1788 pub async fn await_next_message(
1789 &mut self,
1790 stream: &mut (impl Stream<Item = StreamExecutorResult<DispatcherMessage>> + Unpin),
1791 metrics: &ActorInputMetrics,
1792 ) -> StreamExecutorResult<DispatcherMessage> {
1793 let mut start_time = Instant::now();
1794 let interval_duration = Duration::from_secs(15);
1795 let mut interval =
1796 tokio::time::interval_at(start_time + interval_duration, interval_duration);
1797
1798 loop {
1799 tokio::select! {
1800 biased;
1801 msg = stream.try_next() => {
1802 metrics
1803 .actor_input_buffer_blocking_duration_ns
1804 .inc_by(start_time.elapsed().as_nanos() as u64);
1805 return msg?.ok_or_else(
1806 || StreamExecutorError::channel_closed("upstream executor closed unexpectedly")
1807 );
1808 }
1809
1810 e = self.continuously_fetch_barrier_rx() => {
1811 return Err(e);
1812 }
1813
1814 _ = interval.tick() => {
1815 start_time = Instant::now();
1816 metrics.actor_input_buffer_blocking_duration_ns.inc_by(interval_duration.as_nanos() as u64);
1817 continue;
1818 }
1819 }
1820 }
1821 }
1822
1823 pub async fn pop_barrier_with_inputs(
1824 &mut self,
1825 barrier: DispatcherBarrier,
1826 ) -> StreamExecutorResult<(Barrier, Option<Vec<BoxedActorInput>>)> {
1827 while self.buffer.is_empty() {
1828 self.try_fetch_barrier_rx(false).await?;
1829 }
1830 let (recv_barrier, inputs) = self.buffer.pop_front().unwrap();
1831 assert_equal_dispatcher_barrier(&recv_barrier, &barrier);
1832
1833 Ok((recv_barrier, inputs))
1834 }
1835
1836 async fn continuously_fetch_barrier_rx(&mut self) -> StreamExecutorError {
1837 loop {
1838 if let Err(e) = self.try_fetch_barrier_rx(true).await {
1839 return e;
1840 }
1841 }
1842 }
1843
1844 async fn try_fetch_barrier_rx(&mut self, pending_on_end: bool) -> StreamExecutorResult<()> {
1845 match &mut self.recv_state {
1846 BarrierReceiverState::ReceivingBarrier => {
1847 let Some(barrier) = self.barrier_rx.recv().await else {
1848 if pending_on_end {
1849 return pending().await;
1850 } else {
1851 return Err(StreamExecutorError::channel_closed(
1852 "barrier channel closed unexpectedly",
1853 ));
1854 }
1855 };
1856 if let Some(fut) = self.pre_apply_barrier(&barrier) {
1857 self.recv_state = BarrierReceiverState::CreatingNewInput(barrier, fut);
1858 } else {
1859 self.buffer.push_back((barrier, None));
1860 }
1861 }
1862 BarrierReceiverState::CreatingNewInput(barrier, fut) => {
1863 let new_inputs = fut.await?;
1864 self.buffer.push_back((barrier.clone(), Some(new_inputs)));
1865 self.recv_state = BarrierReceiverState::ReceivingBarrier;
1866 }
1867 }
1868 Ok(())
1869 }
1870
1871 fn pre_apply_barrier(&mut self, barrier: &Barrier) -> Option<BoxedNewInputsFuture> {
1872 if let Some(update) = barrier.as_update_merge(self.actor_id, self.curr_upstream_fragment_id)
1873 && !update.added_upstream_actors.is_empty()
1874 {
1875 let upstream_fragment_id =
1877 if let Some(new_upstream_fragment_id) = update.new_upstream_fragment_id {
1878 self.curr_upstream_fragment_id = new_upstream_fragment_id;
1879 new_upstream_fragment_id
1880 } else {
1881 self.curr_upstream_fragment_id
1882 };
1883 let ctx = self.build_input_ctx.clone();
1884 let added_upstream_actors = update.added_upstream_actors.clone();
1885 let barrier = barrier.clone();
1886 let fut = async move {
1887 try_join_all(added_upstream_actors.iter().map(|upstream_actor| async {
1888 let mut new_input = new_input(
1889 &ctx.local_barrier_manager,
1890 ctx.metrics.clone(),
1891 ctx.actor_id,
1892 ctx.fragment_id,
1893 upstream_actor,
1894 upstream_fragment_id,
1895 ctx.actor_config.clone(),
1896 )
1897 .await?;
1898
1899 let first_barrier = expect_first_barrier(&mut new_input).await?;
1902 assert_equal_dispatcher_barrier(&barrier, &first_barrier);
1903
1904 StreamExecutorResult::Ok(new_input)
1905 }))
1906 .await
1907 }
1908 .boxed();
1909
1910 Some(fut)
1911 } else {
1912 None
1913 }
1914 }
1915}