|
34 | 34 | import org.apache.iotdb.confignode.rpc.thrift.TShowTopicResp; |
35 | 35 | import org.apache.iotdb.mpp.rpc.thrift.TTopicOwnerLeaseEntry; |
36 | 36 | import org.apache.iotdb.rpc.TSStatusCode; |
| 37 | +import org.apache.iotdb.rpc.subscription.config.ConsumerConstant; |
37 | 38 | import org.apache.iotdb.rpc.subscription.config.TopicConstant; |
38 | 39 |
|
39 | 40 | import org.junit.Assert; |
| 41 | +import org.junit.Rule; |
40 | 42 | import org.junit.Test; |
| 43 | +import org.junit.rules.TemporaryFolder; |
41 | 44 |
|
42 | 45 | import java.nio.ByteBuffer; |
43 | 46 | import java.util.Collections; |
|
49 | 52 |
|
50 | 53 | public class SubscriptionInfoTest { |
51 | 54 |
|
| 55 | + @Rule public final TemporaryFolder temporaryFolder = new TemporaryFolder(); |
| 56 | + |
| 57 | + @Test |
| 58 | + public void testLastConsumerClosePreservesConfiguredProgressAcrossSnapshot() throws Exception { |
| 59 | + for (final boolean tableModel : new boolean[] {false, true}) { |
| 60 | + for (final boolean unsubscribeFirst : new boolean[] {false, true}) { |
| 61 | + assertLastConsumerClosePreservesProgress(tableModel, unsubscribeFirst); |
| 62 | + } |
| 63 | + } |
| 64 | + } |
| 65 | + |
| 66 | + private void assertLastConsumerClosePreservesProgress( |
| 67 | + final boolean tableModel, final boolean unsubscribeFirst) throws Exception { |
| 68 | + final SubscriptionInfo info = new SubscriptionInfo(); |
| 69 | + final Map<String, String> attributes = new HashMap<>(); |
| 70 | + attributes.put(TopicConstant.MODE_KEY, TopicConstant.MODE_INCREMENTAL_VALUE); |
| 71 | + attributes.put(TopicConstant.RETAIN_PROGRESS_AFTER_UNSUBSCRIBE_KEY, "true"); |
| 72 | + attributes.put(SystemConstant.SQL_DIALECT_KEY, tableModel ? "table" : "tree"); |
| 73 | + info.createTopic(new CreateTopicPlan(new TopicMeta("kept", 1L, attributes))); |
| 74 | + final Map<String, String> discardedAttributes = new HashMap<>(attributes); |
| 75 | + discardedAttributes.put(TopicConstant.RETAIN_PROGRESS_AFTER_UNSUBSCRIBE_KEY, "false"); |
| 76 | + info.createTopic(new CreateTopicPlan(new TopicMeta("discarded", 1L, discardedAttributes))); |
| 77 | + final ConsumerGroupMeta group = |
| 78 | + new ConsumerGroupMeta( |
| 79 | + "group", |
| 80 | + 1L, |
| 81 | + new ConsumerMeta( |
| 82 | + "consumer", |
| 83 | + 1L, |
| 84 | + Collections.singletonMap( |
| 85 | + ConsumerConstant.SQL_DIALECT_KEY, tableModel ? "table" : "tree"))); |
| 86 | + group.addSubscription( |
| 87 | + "consumer", new java.util.HashSet<>(java.util.Arrays.asList("kept", "discarded"))); |
| 88 | + info.alterConsumerGroup(new AlterConsumerGroupPlan(group)); |
| 89 | + final String keptKey = CommitProgressKeeper.generateKey("group", "kept", "DataRegion[1]", 1); |
| 90 | + final String legacyKey = |
| 91 | + CommitProgressKeeper.generateLegacyKey("group", "kept", "DataRegion[1]", 2); |
| 92 | + final String discardedKey = |
| 93 | + CommitProgressKeeper.generateKey("group", "discarded", "DataRegion[1]", 1); |
| 94 | + for (final String key : new String[] {keptKey, legacyKey, discardedKey}) { |
| 95 | + info.getCommitProgressKeeper().updateRegionProgress(key, ByteBuffer.wrap(new byte[] {1})); |
| 96 | + } |
| 97 | + final ConsumerGroupMeta updated = group.deepCopy(); |
| 98 | + if (unsubscribeFirst) { |
| 99 | + updated.removeSubscription( |
| 100 | + "consumer", new java.util.HashSet<>(java.util.Arrays.asList("kept", "discarded"))); |
| 101 | + info.alterConsumerGroup(new AlterConsumerGroupPlan(updated.deepCopy())); |
| 102 | + } |
| 103 | + updated.removeConsumer("consumer"); |
| 104 | + info.alterConsumerGroup(new AlterConsumerGroupPlan(updated)); |
| 105 | + Assert.assertNotNull( |
| 106 | + "tableModel=" + tableModel + ", unsubscribeFirst=" + unsubscribeFirst, |
| 107 | + info.getCommitProgressKeeper().getRegionProgress(keptKey)); |
| 108 | + Assert.assertNotNull(info.getCommitProgressKeeper().getRegionProgress(legacyKey)); |
| 109 | + Assert.assertNull(info.getCommitProgressKeeper().getRegionProgress(discardedKey)); |
| 110 | + Assert.assertTrue(info.getConsumerGroupMeta("group").isEmpty()); |
| 111 | + Assert.assertTrue(info.getConsumerGroupMeta("group").visibleUnder(tableModel)); |
| 112 | + |
| 113 | + final java.io.File snapshotDir = temporaryFolder.newFolder(); |
| 114 | + Assert.assertTrue(info.processTakeSnapshot(snapshotDir)); |
| 115 | + final SubscriptionInfo restored = new SubscriptionInfo(); |
| 116 | + restored.processLoadSnapshot(snapshotDir); |
| 117 | + Assert.assertNotNull(restored.getCommitProgressKeeper().getRegionProgress(keptKey)); |
| 118 | + final ConsumerGroupMeta restoredGroup = restored.deepCopyConsumerGroupMeta("group"); |
| 119 | + Assert.assertTrue(restoredGroup.isEmpty()); |
| 120 | + Assert.assertTrue(restoredGroup.visibleUnder(tableModel)); |
| 121 | + final ConsumerMeta replacement = |
| 122 | + new ConsumerMeta( |
| 123 | + "replacement", |
| 124 | + 2L, |
| 125 | + Collections.singletonMap( |
| 126 | + ConsumerConstant.SQL_DIALECT_KEY, tableModel ? "table" : "tree")); |
| 127 | + restoredGroup.checkAuthorityBeforeJoinConsumerGroup(replacement); |
| 128 | + restoredGroup.addConsumer(replacement); |
| 129 | + restored.alterConsumerGroup(new AlterConsumerGroupPlan(restoredGroup)); |
| 130 | + Assert.assertNotNull(restored.getCommitProgressKeeper().getRegionProgress(keptKey)); |
| 131 | + restoredGroup.removeConsumer("replacement"); |
| 132 | + restored.alterConsumerGroup(new AlterConsumerGroupPlan(restoredGroup)); |
| 133 | + |
| 134 | + // Same-name topics in the other model must not remove this retained group's progress. |
| 135 | + final Map<String, String> otherAttributes = new HashMap<>(attributes); |
| 136 | + otherAttributes.put(SystemConstant.SQL_DIALECT_KEY, tableModel ? "tree" : "table"); |
| 137 | + restored.createTopic(new CreateTopicPlan(new TopicMeta("kept", 2L, otherAttributes))); |
| 138 | + restored.dropTopic(new DropTopicPlan("kept", !tableModel)); |
| 139 | + Assert.assertNotNull(restored.getCommitProgressKeeper().getRegionProgress(keptKey)); |
| 140 | + if (unsubscribeFirst) { |
| 141 | + attributes.put(TopicConstant.RETAIN_PROGRESS_AFTER_UNSUBSCRIBE_KEY, "false"); |
| 142 | + restored.alterTopic(new AlterTopicPlan(new TopicMeta("kept", 2L, attributes))); |
| 143 | + } else { |
| 144 | + restored.dropTopic(new DropTopicPlan("kept", tableModel)); |
| 145 | + } |
| 146 | + Assert.assertNull(restored.getCommitProgressKeeper().getRegionProgress(keptKey)); |
| 147 | + Assert.assertNull(restored.getCommitProgressKeeper().getRegionProgress(legacyKey)); |
| 148 | + Assert.assertFalse(restored.isConsumerGroupExisted("group")); |
| 149 | + } |
| 150 | + |
52 | 151 | @Test |
53 | 152 | public void testSameNameTreeAndTableTopicsCanBeManagedIndependently() { |
54 | 153 | final String topicName = "same-name-topic"; |
|
0 commit comments