@@ -102,6 +102,7 @@ class TDqComputeActorBase : public NActors::TActorBootstrapped<TDerived>
102102 struct TEvPrivate {
103103 enum EEv : ui32 {
104104 EvAsyncOutputError = EventSpaceBegin (NActors::TEvents::ES_PRIVATE),
105+ EvCheckIdleness,
105106 EvEnd
106107 };
107108
@@ -116,6 +117,14 @@ class TDqComputeActorBase : public NActors::TActorBootstrapped<TDerived>
116117 NYql::NDqProto::StatusIds::StatusCode StatusCode;
117118 NYql::TIssues Issues;
118119 };
120+
121+ struct TEvCheckIdleness : public NActors ::TEventLocal<TEvCheckIdleness, EvCheckIdleness> {
122+ TEvCheckIdleness (TInstant checkTime)
123+ : CheckTime(checkTime)
124+ {}
125+
126+ TInstant CheckTime;
127+ };
119128 };
120129
121130protected:
@@ -137,6 +146,8 @@ class TDqComputeActorBase : public NActors::TActorBootstrapped<TDerived>
137146 RuntimeSettings.StatsMode , MemoryLimits.ChannelBufferSize , this , this ->GetActivityType ());
138147 this ->RegisterWithSameMailbox (Channels);
139148
149+ InitializeWatermarks ();
150+
140151 if (RuntimeSettings.Timeout ) {
141152 CA_LOG_D (" Set execution timeout " << *RuntimeSettings.Timeout );
142153 this ->Schedule (*RuntimeSettings.Timeout , new NActors::TEvents::TEvWakeup (EEvWakeupTag::TimeoutTag));
@@ -317,6 +328,7 @@ class TDqComputeActorBase : public NActors::TActorBootstrapped<TDerived>
317328 hFunc (IDqComputeActorAsyncInput::TEvNewAsyncInputDataArrived, OnNewAsyncInputDataArrived);
318329 hFunc (IDqComputeActorAsyncInput::TEvAsyncInputError, OnAsyncInputError);
319330 hFunc (TEvPrivate::TEvAsyncOutputError, HandleAsyncOutputError);
331+ hFunc (TEvPrivate::TEvCheckIdleness, HandleCheckIdleness);
320332 default : {
321333 CA_LOG_C (" TDqComputeActorBase, unexpected event: " << ev->GetTypeRewrite () << " (" << GetEventTypeString (ev) << " )" );
322334 InternalError (NYql::NDqProto::StatusIds::INTERNAL_ERROR, TIssuesIds::DEFAULT_ERROR, TStringBuilder () << " Unexpected event: " << ev->GetTypeRewrite () << " (" << GetEventTypeString (ev) << " )" );
@@ -843,6 +855,7 @@ class TDqComputeActorBase : public NActors::TActorBootstrapped<TDerived>
843855 IDqInputChannel::TPtr Channel;
844856 bool HasPeer = false ;
845857 const NDqProto::EWatermarksMode WatermarksMode;
858+ const TDuration WatermarksIdleTimeout = TDuration::Max();
846859 std::optional<NDqProto::TCheckpoint> PendingCheckpoint;
847860 const NDqProto::ECheckpointingMode CheckpointingMode;
848861 i64 FreeSpace = 0 ;
@@ -852,11 +865,13 @@ class TDqComputeActorBase : public NActors::TActorBootstrapped<TDerived>
852865 ui64 channelId,
853866 ui32 srcStageId,
854867 NDqProto::EWatermarksMode watermarksMode,
855- NDqProto::ECheckpointingMode checkpointingMode)
868+ NDqProto::ECheckpointingMode checkpointingMode,
869+ TDuration watermarksIdleTimeout)
856870 : LogPrefix(logPrefix)
857871 , ChannelId(channelId)
858872 , SrcStageId(srcStageId)
859873 , WatermarksMode(watermarksMode)
874+ , WatermarksIdleTimeout(watermarksIdleTimeout)
860875 , CheckpointingMode(checkpointingMode)
861876 {
862877 }
@@ -1587,6 +1602,25 @@ class TDqComputeActorBase : public NActors::TActorBootstrapped<TDerived>
15871602 InternalError (ev->Get ()->StatusCode , ev->Get ()->Issues );
15881603 }
15891604
1605+ void HandleCheckIdleness (const TEvPrivate::TEvCheckIdleness::TPtr& ev) {
1606+ auto checkTime = Max (ev->Get ()->CheckTime , TInstant::Now ());
1607+ if (WatermarksTracker.ProcessIdlenessCheck (checkTime)) {
1608+ auto idleWatermark = WatermarksTracker.HandleIdleness (checkTime);
1609+ if (idleWatermark) {
1610+ CA_LOG_T (" Idleness watermark " << idleWatermark);
1611+ ResumeExecution (EResumeSource::CAWatermarkIdleness);
1612+ }
1613+ }
1614+ ScheduleIdlenessCheck ();
1615+ }
1616+
1617+ void ScheduleIdlenessCheck () {
1618+ if (auto checkTime = WatermarksTracker.PrepareIdlenessCheck ()) {
1619+ CA_LOG_T (" Schedule next idleness check at " << checkTime);
1620+ this ->Schedule (*checkTime, new TEvPrivate::TEvCheckIdleness (*checkTime));
1621+ }
1622+ }
1623+
15901624 bool AllAsyncOutputsFinished () const {
15911625 for (const auto & [outputIndex, sinkInfo] : SinksMap) {
15921626 if (!sinkInfo.FinishIsAcknowledged ) {
@@ -1618,26 +1652,36 @@ class TDqComputeActorBase : public NActors::TActorBootstrapped<TDerived>
16181652 Y_ABORT_UNLESS (!inputDesc.HasSource () || inputDesc.ChannelsSize () == 0 ); // HasSource => no channels
16191653
16201654 if (inputDesc.HasSource ()) {
1621- watermarksMode = inputDesc.GetSource ().GetWatermarksMode ();
1655+ auto & source = inputDesc.GetSource ();
1656+ watermarksMode = source.GetWatermarksMode ();
1657+ TDuration watermarksIdleTimeout = TDuration::Max ();
1658+ if (source.HasWatermarksIdleTimeoutUs ()) {
1659+ watermarksIdleTimeout = TDuration::MicroSeconds (source.GetWatermarksIdleTimeoutUs ());
1660+ }
16221661 auto result = SourcesMap.emplace (
16231662 i,
1624- static_cast <TDerived*>(this )->CreateInputHelper (LogPrefix, i, watermarksMode)
1663+ static_cast <TDerived*>(this )->CreateInputHelper (LogPrefix, i, watermarksMode, watermarksIdleTimeout )
16251664 );
16261665 YQL_ENSURE (result.second );
16271666 } else {
16281667 for (auto & channel : inputDesc.GetChannels ()) {
16291668 auto channelWatermarksMode = channel.GetWatermarksMode ();
1669+ TDuration watermarksIdleTimeout = TDuration::Max ();
16301670 if (channelWatermarksMode != NDqProto::EWatermarksMode::WATERMARKS_MODE_DISABLED) {
16311671 watermarksMode = channelWatermarksMode;
16321672 }
1673+ if (channel.HasWatermarksIdleTimeoutUs ()) {
1674+ watermarksIdleTimeout = TDuration::MicroSeconds (channel.GetWatermarksIdleTimeoutUs ());
1675+ }
16331676 auto result = InputChannelsMap.emplace (
16341677 channel.GetId (),
16351678 TInputChannelInfo (
16361679 LogPrefix,
16371680 channel.GetId (),
16381681 channel.GetSrcStageId (),
16391682 channelWatermarksMode,
1640- channel.GetCheckpointingMode ())
1683+ channel.GetCheckpointingMode (),
1684+ watermarksIdleTimeout)
16411685 );
16421686 YQL_ENSURE (result.second );
16431687 }
@@ -1646,8 +1690,9 @@ class TDqComputeActorBase : public NActors::TActorBootstrapped<TDerived>
16461690 if (inputDesc.HasTransform ()) {
16471691 auto result = InputTransformsMap.emplace (
16481692 i,
1649- TAsyncInputTransformHelper (LogPrefix, i, watermarksMode)
1693+ TAsyncInputTransformHelper (LogPrefix, i, watermarksMode, TDuration::Max () )
16501694 );
1695+ // TODO: watermarksIdleTimeout (currently unused)
16511696 YQL_ENSURE (result.second );
16521697 }
16531698 }
@@ -1687,21 +1732,21 @@ class TDqComputeActorBase : public NActors::TActorBootstrapped<TDerived>
16871732
16881733 RequestContext = MakeIntrusive<NYql::NDq::TRequestContext>(Task.GetRequestContext ());
16891734
1690- InitializeWatermarks ();
16911735 InitializeLogPrefix (); // note: SelfId is not initialized here
16921736 }
16931737
16941738private:
16951739 void InitializeWatermarks () {
1740+ TInstant now = TInstant::Now ();
16961741 for (const auto & [id, source] : SourcesMap) {
16971742 if (source.WatermarksMode == NDqProto::EWatermarksMode::WATERMARKS_MODE_DEFAULT) {
1698- WatermarksTracker.RegisterAsyncInput (id);
1743+ WatermarksTracker.RegisterAsyncInput (id, source. WatermarksIdleTimeout , now );
16991744 }
17001745 }
17011746
17021747 for (const auto & [id, channel] : InputChannelsMap) {
17031748 if (channel.WatermarksMode == NDqProto::EWatermarksMode::WATERMARKS_MODE_DEFAULT) {
1704- WatermarksTracker.RegisterInputChannel (id);
1749+ WatermarksTracker.RegisterInputChannel (id, channel. WatermarksIdleTimeout , now );
17051750 }
17061751 }
17071752 }
0 commit comments