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