|
21 | 21 |
|
22 | 22 | import org.apache.iotdb.commons.conf.CommonDescriptor; |
23 | 23 | import org.apache.iotdb.commons.consensus.index.impl.MinimumProgressIndex; |
| 24 | +import org.apache.iotdb.commons.consensus.index.impl.RecoverProgressIndex; |
| 25 | +import org.apache.iotdb.commons.consensus.index.impl.SimpleProgressIndex; |
24 | 26 | import org.apache.iotdb.commons.exception.pipe.PipeRuntimeCriticalException; |
25 | 27 | import org.apache.iotdb.commons.exception.pipe.PipeRuntimeSinkCriticalException; |
26 | 28 | import org.apache.iotdb.commons.pipe.agent.task.meta.PipeMeta; |
|
55 | 57 | import java.util.concurrent.atomic.AtomicBoolean; |
56 | 58 | import java.util.concurrent.atomic.AtomicReference; |
57 | 59 |
|
| 60 | +import static org.junit.Assert.assertEquals; |
58 | 61 | import static org.mockito.ArgumentMatchers.any; |
59 | 62 | import static org.mockito.ArgumentMatchers.anyBoolean; |
60 | 63 | import static org.mockito.Mockito.never; |
@@ -134,6 +137,82 @@ public void testParseHeartbeatKeepsPendingFlagsWhenProcedureSubmissionFails() th |
134 | 137 | verify(context.procedureManager, times(2)).pipeHandleMetaChange(true, false); |
135 | 138 | } |
136 | 139 |
|
| 140 | + @Test |
| 141 | + public void testParseHeartbeatSkipsConsensusWriteWhenCoordinatorProgressCoversAgent() |
| 142 | + throws Exception { |
| 143 | + CommonDescriptor.getInstance().getConfig().setSeperatedPipeHeartbeatEnabled(false); |
| 144 | + |
| 145 | + final PipeTaskInfo pipeTaskInfo = new PipeTaskInfo(); |
| 146 | + final PipeMeta coordinatorPipeMeta = createPipeMeta(); |
| 147 | + final RecoverProgressIndex coordinatorProgressIndex = createRecoverProgressIndex(10, 10); |
| 148 | + coordinatorPipeMeta |
| 149 | + .getRuntimeMeta() |
| 150 | + .getConsensusGroupId2TaskMetaMap() |
| 151 | + .get(DATA_NODE_ID) |
| 152 | + .updateProgressIndex(coordinatorProgressIndex); |
| 153 | + pipeTaskInfo.createPipe( |
| 154 | + new CreatePipePlanV2( |
| 155 | + coordinatorPipeMeta.getStaticMeta(), coordinatorPipeMeta.getRuntimeMeta())); |
| 156 | + |
| 157 | + final PipeMeta agentPipeMeta = createPipeMeta(); |
| 158 | + agentPipeMeta |
| 159 | + .getRuntimeMeta() |
| 160 | + .getConsensusGroupId2TaskMetaMap() |
| 161 | + .get(DATA_NODE_ID) |
| 162 | + .updateProgressIndex(createRecoverProgressIndex(10, 5)); |
| 163 | + |
| 164 | + final ParserTestContext context = createParserTestContext(1, pipeTaskInfo); |
| 165 | + context.parser.parseHeartbeat(DATA_NODE_ID, createPipeHeartbeat(agentPipeMeta, false)); |
| 166 | + |
| 167 | + assertEquals( |
| 168 | + coordinatorProgressIndex, |
| 169 | + pipeTaskInfo |
| 170 | + .getPipeMetaByPipeName("test_pipe") |
| 171 | + .getRuntimeMeta() |
| 172 | + .getConsensusGroupId2TaskMetaMap() |
| 173 | + .get(DATA_NODE_ID) |
| 174 | + .getProgressIndex()); |
| 175 | + verify(context.procedureManager, never()).pipeHandleMetaChange(anyBoolean(), anyBoolean()); |
| 176 | + } |
| 177 | + |
| 178 | + @Test |
| 179 | + public void testParseHeartbeatWritesConsensusWhenAgentProgressAdvancesCoordinator() |
| 180 | + throws Exception { |
| 181 | + CommonDescriptor.getInstance().getConfig().setSeperatedPipeHeartbeatEnabled(false); |
| 182 | + |
| 183 | + final PipeTaskInfo pipeTaskInfo = new PipeTaskInfo(); |
| 184 | + final PipeMeta coordinatorPipeMeta = createPipeMeta(); |
| 185 | + coordinatorPipeMeta |
| 186 | + .getRuntimeMeta() |
| 187 | + .getConsensusGroupId2TaskMetaMap() |
| 188 | + .get(DATA_NODE_ID) |
| 189 | + .updateProgressIndex(createRecoverProgressIndex(10, 10)); |
| 190 | + pipeTaskInfo.createPipe( |
| 191 | + new CreatePipePlanV2( |
| 192 | + coordinatorPipeMeta.getStaticMeta(), coordinatorPipeMeta.getRuntimeMeta())); |
| 193 | + |
| 194 | + final PipeMeta agentPipeMeta = createPipeMeta(); |
| 195 | + final RecoverProgressIndex agentProgressIndex = createRecoverProgressIndex(10, 11); |
| 196 | + agentPipeMeta |
| 197 | + .getRuntimeMeta() |
| 198 | + .getConsensusGroupId2TaskMetaMap() |
| 199 | + .get(DATA_NODE_ID) |
| 200 | + .updateProgressIndex(agentProgressIndex); |
| 201 | + |
| 202 | + final ParserTestContext context = createParserTestContext(1, pipeTaskInfo); |
| 203 | + context.parser.parseHeartbeat(DATA_NODE_ID, createPipeHeartbeat(agentPipeMeta, false)); |
| 204 | + |
| 205 | + assertEquals( |
| 206 | + agentProgressIndex, |
| 207 | + pipeTaskInfo |
| 208 | + .getPipeMetaByPipeName("test_pipe") |
| 209 | + .getRuntimeMeta() |
| 210 | + .getConsensusGroupId2TaskMetaMap() |
| 211 | + .get(DATA_NODE_ID) |
| 212 | + .getProgressIndex()); |
| 213 | + verify(context.procedureManager, times(1)).pipeHandleMetaChange(true, false); |
| 214 | + } |
| 215 | + |
137 | 216 | @Test |
138 | 217 | public void testParseHeartbeatIgnoresExceptionsBeforeClearTime() throws Exception { |
139 | 218 | CommonDescriptor.getInstance().getConfig().setSeperatedPipeHeartbeatEnabled(false); |
@@ -428,6 +507,30 @@ private PipeHeartbeat createPipeHeartbeat( |
428 | 507 | Collections.singletonList(recentFailures)); |
429 | 508 | } |
430 | 509 |
|
| 510 | + private PipeHeartbeat createPipeHeartbeat(final PipeMeta pipeMeta, final boolean ignored) |
| 511 | + throws Exception { |
| 512 | + return createPipeHeartbeat(pipeMeta, Collections.emptyMap()); |
| 513 | + } |
| 514 | + |
| 515 | + private PipeMeta createPipeMeta() { |
| 516 | + final PipeRuntimeMeta pipeRuntimeMeta = new PipeRuntimeMeta(); |
| 517 | + pipeRuntimeMeta |
| 518 | + .getConsensusGroupId2TaskMetaMap() |
| 519 | + .put(DATA_NODE_ID, new PipeTaskMeta(MinimumProgressIndex.INSTANCE, DATA_NODE_ID)); |
| 520 | + return new PipeMeta( |
| 521 | + new PipeStaticMeta( |
| 522 | + "test_pipe", 1L, Collections.emptyMap(), new HashMap<>(), new HashMap<>()), |
| 523 | + pipeRuntimeMeta); |
| 524 | + } |
| 525 | + |
| 526 | + private RecoverProgressIndex createRecoverProgressIndex( |
| 527 | + final long firstDataNodeIndex, final long secondDataNodeIndex) { |
| 528 | + final Map<Integer, SimpleProgressIndex> dataNodeId2LocalIndex = new HashMap<>(); |
| 529 | + dataNodeId2LocalIndex.put(1, new SimpleProgressIndex(0, firstDataNodeIndex)); |
| 530 | + dataNodeId2LocalIndex.put(2, new SimpleProgressIndex(0, secondDataNodeIndex)); |
| 531 | + return new RecoverProgressIndex(dataNodeId2LocalIndex); |
| 532 | + } |
| 533 | + |
431 | 534 | private static class ParserTestContext { |
432 | 535 | private final PipeHeartbeatParser parser; |
433 | 536 | private final ProcedureManager procedureManager; |
|
0 commit comments