2020package org .apache .iotdb .confignode .procedure .impl .pipe .task ;
2121
2222import org .apache .iotdb .common .rpc .thrift .TConsensusGroupType ;
23+ import org .apache .iotdb .common .rpc .thrift .TPipeHeartbeatResp ;
2324import org .apache .iotdb .common .rpc .thrift .TSStatus ;
25+ import org .apache .iotdb .commons .consensus .index .ProgressIndex ;
2426import org .apache .iotdb .commons .consensus .index .impl .MinimumProgressIndex ;
2527import org .apache .iotdb .commons .pipe .agent .task .PipeTaskAgent ;
2628import org .apache .iotdb .commons .pipe .agent .task .meta .PipeMeta ;
3335import org .apache .iotdb .confignode .conf .ConfigNodeDescriptor ;
3436import org .apache .iotdb .confignode .consensus .request .write .pipe .task .AlterPipePlanV2 ;
3537import org .apache .iotdb .confignode .manager .pipe .coordinator .PipeManager ;
38+ import org .apache .iotdb .confignode .manager .pipe .coordinator .runtime .heartbeat .PipeHeartbeat ;
3639import org .apache .iotdb .confignode .procedure .env .ConfigNodeProcedureEnv ;
3740import org .apache .iotdb .confignode .procedure .impl .pipe .AbstractOperatePipeProcedureV2 ;
3841import org .apache .iotdb .confignode .procedure .impl .pipe .PipeTaskOperation ;
4952import java .io .DataOutputStream ;
5053import java .io .IOException ;
5154import java .nio .ByteBuffer ;
55+ import java .util .Collections ;
5256import java .util .HashMap ;
57+ import java .util .HashSet ;
5358import java .util .Map ;
5459import java .util .Objects ;
60+ import java .util .Set ;
5561import java .util .concurrent .ConcurrentHashMap ;
5662import java .util .concurrent .ConcurrentMap ;
5763
@@ -138,6 +144,16 @@ public void executeFromCalculateInfoForTask(ConfigNodeProcedureEnv env) {
138144 new HashMap <>(alterPipeRequest .getProcessorAttributes ()),
139145 new HashMap <>(alterPipeRequest .getConnectorAttributes ()));
140146
147+ // The periodic heartbeat may not have reached ConfigNode immediately before this alter. Pull
148+ // the current leader checkpoints first so a leader migration does not make the replacement
149+ // task start from an older coordinator checkpoint.
150+ final Map <Integer , ProgressIndex > latestProgressIndexMap =
151+ PipeTaskAgent .isRealtimeOnlyPipe (currentPipeStaticMeta .getExtractorParameters ())
152+ == PipeTaskAgent .isRealtimeOnlyPipe (updatedPipeStaticMeta .getExtractorParameters ())
153+ ? collectLatestProgressIndexes (
154+ env , currentPipeStaticMeta , currentConsensusGroupId2PipeTaskMeta )
155+ : Collections .emptyMap ();
156+
141157 final ConcurrentMap <Integer , PipeTaskMeta > updatedConsensusGroupIdToTaskMetaMap =
142158 new ConcurrentHashMap <>();
143159
@@ -167,8 +183,7 @@ public void executeFromCalculateInfoForTask(ConfigNodeProcedureEnv env) {
167183 // then it will extract all existing data now, not existing data since the
168184 // original pipe was created
169185 // Similar for "pure realtime"
170- updatedConsensusGroupIdToTaskMetaMap .put (
171- regionGroupId .getId (),
186+ final PipeTaskMeta updatedPipeTaskMeta =
172187 new PipeTaskMeta (
173188 PipeTaskAgent .isRealtimeOnlyPipe (
174189 currentPipeStaticMeta .getExtractorParameters ())
@@ -186,7 +201,14 @@ public void executeFromCalculateInfoForTask(ConfigNodeProcedureEnv env) {
186201 && PipeTaskAgent .isRealtimeOnlyPipe (
187202 updatedPipeStaticMeta .getExtractorParameters ()))
188203 ? PipeTaskMeta .getRevertedLeader (regionLeaderNodeId )
189- : regionLeaderNodeId ));
204+ : regionLeaderNodeId );
205+ final ProgressIndex latestProgressIndex =
206+ latestProgressIndexMap .get (regionGroupId .getId ());
207+ if (latestProgressIndex != null ) {
208+ updatedPipeTaskMeta .updateProgressIndex (latestProgressIndex );
209+ }
210+ updatedConsensusGroupIdToTaskMetaMap .put (
211+ regionGroupId .getId (), updatedPipeTaskMeta );
190212 }
191213 });
192214
@@ -213,6 +235,61 @@ public void executeFromCalculateInfoForTask(ConfigNodeProcedureEnv env) {
213235 }
214236 }
215237
238+ private Map <Integer , ProgressIndex > collectLatestProgressIndexes (
239+ final ConfigNodeProcedureEnv env ,
240+ final PipeStaticMeta pipeStaticMeta ,
241+ final Map <Integer , PipeTaskMeta > taskMetaMap ) {
242+ final Set <Integer > leaderNodeIds = new HashSet <>();
243+ final Set <Integer > registeredDataNodeIds =
244+ env .getConfigManager ().getNodeManager ().getRegisteredDataNodeLocations ().keySet ();
245+ taskMetaMap .forEach (
246+ (consensusGroupId , taskMeta ) -> {
247+ // The ConfigRegion task is led by a ConfigNode, not by a DataNode.
248+ if (consensusGroupId != Integer .MIN_VALUE
249+ && registeredDataNodeIds .contains (taskMeta .getLeaderNodeId ())) {
250+ leaderNodeIds .add (taskMeta .getLeaderNodeId ());
251+ }
252+ });
253+
254+ if (leaderNodeIds .isEmpty ()) {
255+ return Collections .emptyMap ();
256+ }
257+
258+ final Map <Integer , TPipeHeartbeatResp > responseMap =
259+ env .collectPipeMetaFromDataNodes (leaderNodeIds );
260+ final Map <Integer , ProgressIndex > latestProgressIndexMap = new HashMap <>();
261+ responseMap .forEach (
262+ (dataNodeId , response ) -> {
263+ if (response == null || !response .isSetPipeMetaList ()) {
264+ return ;
265+ }
266+
267+ final PipeMeta pipeMetaFromDataNode =
268+ new PipeHeartbeat (response .getPipeMetaList (), null , null , null )
269+ .getPipeMeta (pipeStaticMeta );
270+ if (pipeMetaFromDataNode == null ) {
271+ return ;
272+ }
273+
274+ pipeMetaFromDataNode
275+ .getRuntimeMeta ()
276+ .getConsensusGroupId2TaskMetaMap ()
277+ .forEach (
278+ (consensusGroupId , taskMetaFromDataNode ) -> {
279+ final PipeTaskMeta taskMetaFromCoordinator = taskMetaMap .get (consensusGroupId );
280+ if (taskMetaFromCoordinator == null
281+ || taskMetaFromCoordinator .getLeaderNodeId () != dataNodeId ) {
282+ return ;
283+ }
284+ latestProgressIndexMap .merge (
285+ consensusGroupId ,
286+ taskMetaFromDataNode .getProgressIndex (),
287+ ProgressIndex ::updateToMinimumEqualOrIsAfterProgressIndex );
288+ });
289+ });
290+ return latestProgressIndexMap ;
291+ }
292+
216293 @ Override
217294 public void executeFromWriteConfigNodeConsensus (ConfigNodeProcedureEnv env ) throws PipeException {
218295 LOGGER .info (
0 commit comments