diff --git a/app/src/main/java/org/astraea/app/admin/Admin.java b/app/src/main/java/org/astraea/app/admin/Admin.java index bd70beec05..f4fc50b79f 100644 --- a/app/src/main/java/org/astraea/app/admin/Admin.java +++ b/app/src/main/java/org/astraea/app/admin/Admin.java @@ -48,6 +48,9 @@ default Map topics() { /** @return the topic name and its configurations. */ Map topics(Set topicNames); + /** delete topics by topic names */ + void deleteTopics(Set topicNames); + /** @return all partitions */ default Set partitions() { return partitions(topicNames()); diff --git a/app/src/main/java/org/astraea/app/admin/Builder.java b/app/src/main/java/org/astraea/app/admin/Builder.java index 0c1611fde6..6cb7a37f5f 100644 --- a/app/src/main/java/org/astraea/app/admin/Builder.java +++ b/app/src/main/java/org/astraea/app/admin/Builder.java @@ -272,6 +272,11 @@ public Set topicNames() { () -> admin.listTopics(new ListTopicsOptions().listInternal(true)).names().get()); } + @Override + public void deleteTopics(Set topicNames) { + Utils.packException(() -> admin.deleteTopics(topicNames).all().get()); + } + @Override public Map brokers(Set brokerIds) { return Utils.packException( diff --git a/app/src/main/java/org/astraea/app/web/TopicHandler.java b/app/src/main/java/org/astraea/app/web/TopicHandler.java index 591b01ef0f..ddd87c0911 100644 --- a/app/src/main/java/org/astraea/app/web/TopicHandler.java +++ b/app/src/main/java/org/astraea/app/web/TopicHandler.java @@ -113,6 +113,12 @@ public Response post(PostRequest request) { return new TopicInfo(request.value(TOPIC_NAME_KEY), List.of(), Map.of()); } + @Override + public Response delete(String topic, Map queries) { + admin.deleteTopics(Set.of(topic)); + return Response.OK; + } + static class Topics implements Response { final Collection topics; diff --git a/app/src/test/java/org/astraea/app/admin/AdminTest.java b/app/src/test/java/org/astraea/app/admin/AdminTest.java index ee96bbdc8a..f7781498c4 100644 --- a/app/src/test/java/org/astraea/app/admin/AdminTest.java +++ b/app/src/test/java/org/astraea/app/admin/AdminTest.java @@ -1134,4 +1134,27 @@ void testDeleteRecord() { Assertions.assertEquals(0, offsets.get(TopicPartition.of(topicName, 2)).earliest()); } } + + @Test + void testDeleteTopic() { + var topicNames = + IntStream.range(0, 4).mapToObj(x -> Utils.randomString(10)).collect(Collectors.toList()); + + try (var admin = Admin.of(bootstrapServers())) { + topicNames.forEach( + x -> admin.creator().topic(x).numberOfPartitions(3).numberOfReplicas((short) 3).create()); + + admin.deleteTopics(Set.of(topicNames.get(0), topicNames.get(1))); + var latestTopicNames = admin.topicNames(); + Assertions.assertFalse(latestTopicNames.contains(topicNames.get(0))); + Assertions.assertFalse(latestTopicNames.contains(topicNames.get(1))); + Assertions.assertTrue(latestTopicNames.contains(topicNames.get(2))); + Assertions.assertTrue(latestTopicNames.contains(topicNames.get(3))); + + admin.deleteTopics(Set.of(topicNames.get(3))); + latestTopicNames = admin.topicNames(); + Assertions.assertFalse(latestTopicNames.contains(topicNames.get(3))); + Assertions.assertTrue(latestTopicNames.contains(topicNames.get(2))); + } + } } diff --git a/app/src/test/java/org/astraea/app/web/TopicHandlerTest.java b/app/src/test/java/org/astraea/app/web/TopicHandlerTest.java index 9663ba172c..d3b051fb2b 100644 --- a/app/src/test/java/org/astraea/app/web/TopicHandlerTest.java +++ b/app/src/test/java/org/astraea/app/web/TopicHandlerTest.java @@ -21,6 +21,8 @@ import java.util.NoSuchElementException; import java.util.Optional; import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.IntStream; import org.astraea.app.admin.Admin; import org.astraea.app.common.Utils; import org.astraea.app.service.RequireBrokerCluster; @@ -193,4 +195,26 @@ void testRemainingConfigs() { PostRequest.of(Map.of(TopicHandler.TOPIC_NAME_KEY, "abc", "key", "value"))) .size()); } + + @Test + void testDeleteTopic() { + var topicNames = + IntStream.range(0, 3).mapToObj(x -> Utils.randomString(10)).collect(Collectors.toList()); + try (Admin admin = Admin.of(bootstrapServers())) { + var handler = new TopicHandler(admin); + topicNames.forEach( + x -> admin.creator().topic(x).numberOfPartitions(3).numberOfReplicas((short) 3).create()); + + handler.delete(topicNames.get(0), Map.of()); + var latestTopicNames = admin.topicNames(); + Assertions.assertFalse(latestTopicNames.contains(topicNames.get(0))); + Assertions.assertTrue(latestTopicNames.contains(topicNames.get(1))); + Assertions.assertTrue(latestTopicNames.contains(topicNames.get(2))); + + handler.delete(topicNames.get(2), Map.of()); + latestTopicNames = admin.topicNames(); + Assertions.assertFalse(latestTopicNames.contains(topicNames.get(2))); + Assertions.assertTrue(latestTopicNames.contains(topicNames.get(1))); + } + } } diff --git a/docs/web_server/web_api_topics_chinese.md b/docs/web_server/web_api_topics_chinese.md index acf641dd87..efea6f4e29 100644 --- a/docs/web_server/web_api_topics_chinese.md +++ b/docs/web_server/web_api_topics_chinese.md @@ -255,3 +255,13 @@ JSON Response 範例 } } ``` +## 刪除 topic +```shell +DELETE /topics/{topicName} +``` + +cURL 範例 + +```shell +curl -X DELETE "http://localhost:8001/topics/mytopic" +``` \ No newline at end of file