diff --git a/src/main/java/io/github/protocol/bookkeeper/AutoRecovery.java b/src/main/java/io/github/protocol/bookkeeper/AutoRecovery.java index e8e1e3f..8ac9a3f 100644 --- a/src/main/java/io/github/protocol/bookkeeper/AutoRecovery.java +++ b/src/main/java/io/github/protocol/bookkeeper/AutoRecovery.java @@ -1,4 +1,22 @@ package io.github.protocol.bookkeeper; public interface AutoRecovery { + + AutoRecoveryStatus autoRecoveryStatus() throws BookkeeperAdminException; + + void recoveryBookie(RecoveryBookieReqData reqData) throws BookkeeperAdminException; + + UnderReplicatedLedger listUnderReplicatedLedger(ListUnderReplicatedLedgerReqData reqData) + throws BookkeeperAdminException; + + Auditor whoIsAuditor() throws BookkeeperAdminException; + + void triggerAudit() throws BookkeeperAdminException; + + void lostBookieRecoveryDelay() throws BookkeeperAdminException; + + void lostBookieRecoveryDelay(int delaySeconds) throws BookkeeperAdminException; + + void decommission(String bookieId) throws BookkeeperAdminException; + } diff --git a/src/main/java/io/github/protocol/bookkeeper/AutoRecoveryImpl.java b/src/main/java/io/github/protocol/bookkeeper/AutoRecoveryImpl.java index 7e14b4e..4bb46d6 100644 --- a/src/main/java/io/github/protocol/bookkeeper/AutoRecoveryImpl.java +++ b/src/main/java/io/github/protocol/bookkeeper/AutoRecoveryImpl.java @@ -1,9 +1,133 @@ package io.github.protocol.bookkeeper; +import com.fasterxml.jackson.core.type.TypeReference; + +import java.io.IOException; +import java.net.http.HttpResponse; +import java.util.HashMap; +import java.util.Map; + public class AutoRecoveryImpl implements AutoRecovery { private final InnerHttpClient innerHttpClient; public AutoRecoveryImpl(InnerHttpClient innerHttpClient) { this.innerHttpClient = innerHttpClient; } + + @Override + public AutoRecoveryStatus autoRecoveryStatus() throws BookkeeperAdminException { + try { + HttpResponse resp = innerHttpClient.get(UrlConst.AUTO_RECOVERY_STATUS); + return JacksonService.toRefer(resp.body(), new TypeReference() { + }); + } catch (Exception e) { + throw new BookkeeperAdminException(e); + } + } + + @Override + public void recoveryBookie(RecoveryBookieReqData reqData) throws BookkeeperAdminException { + try { + innerHttpClient.put(UrlConst.AUTO_RECOVERY, reqData); + } catch (IOException | InterruptedException e) { + throw new BookkeeperAdminException(e); + } + } + + @Override + public UnderReplicatedLedger listUnderReplicatedLedger(ListUnderReplicatedLedgerReqData reqData) + throws BookkeeperAdminException { + try { + String url = UrlConst.AUTO_RECOVERY_LIST_UNDER_REPLICATED_LEDGER; + if (reqData.isPrintMissingReplica()) { + url += "?&printmissingreplica=true"; + } else { + url += "?&printmissingreplica=false"; + } + if (reqData.getExcludingBookieId() != null && !"".equals(reqData.getExcludingBookieId())) { + url = url + "&excludingmissingreplica=" + reqData.getExcludingBookieId(); + } + if (reqData.getIncludingBookieId() != null && !"".equals(reqData.getIncludingBookieId())) { + url = url + "&missingreplica=" + reqData.getIncludingBookieId(); + } + HttpResponse resp = innerHttpClient.get(url); + if ((resp.statusCode() < 200 || resp.statusCode() >= 300) && resp.body() != null) { + throw new BookkeeperAdminException(resp.body()); + } + return JacksonService.toRefer(resp.body(), new TypeReference() { + }); + } catch (Exception e) { + throw new BookkeeperAdminException(e); + } + } + + @Override + public Auditor whoIsAuditor() throws BookkeeperAdminException { + try { + HttpResponse resp = innerHttpClient.get(UrlConst.AUTO_RECOVERY_WHO_IS_AUDITOR); + + if ((resp.statusCode() < 200 || resp.statusCode() >= 300) && resp.body() != null) { + throw new BookkeeperAdminException(resp.body()); + } + return JacksonService.toRefer(resp.body(), new TypeReference() { + }); + } catch (Exception e) { + throw new BookkeeperAdminException(e); + } + } + + @Override + public void triggerAudit() throws BookkeeperAdminException { + try { + HttpResponse resp = innerHttpClient.put(UrlConst.AUTO_RECOVERY_TRIGGER_AUDIT); + if ((resp.statusCode() < 200 || resp.statusCode() >= 300) && resp.body() != null) { + throw new BookkeeperAdminException(resp.body()); + } + } catch (IOException | InterruptedException e) { + throw new BookkeeperAdminException(e); + } + } + + @Override + public void lostBookieRecoveryDelay() throws BookkeeperAdminException { + try { + HttpResponse resp = innerHttpClient.put(UrlConst.AUTO_RECOVERY_LOST_BOOKIE_RECOVERY_DELAY); + if ((resp.statusCode() < 200 || resp.statusCode() >= 300) && resp.body() != null) { + throw new BookkeeperAdminException(resp.body()); + } + } catch (IOException | InterruptedException e) { + throw new BookkeeperAdminException(e); + } + } + + @Override + public void lostBookieRecoveryDelay(int delaySeconds) throws BookkeeperAdminException { + Map reqDate = new HashMap<>(); + reqDate.put("delay_seconds", delaySeconds); + try { + HttpResponse resp = innerHttpClient.put(UrlConst.AUTO_RECOVERY_LOST_BOOKIE_RECOVERY_DELAY, reqDate); + if ((resp.statusCode() < 200 || resp.statusCode() >= 300) && resp.body() != null) { + throw new BookkeeperAdminException(resp.body()); + } + } catch (IOException | InterruptedException e) { + throw new BookkeeperAdminException(e); + } + } + + @Override + public void decommission(String bookieId) throws BookkeeperAdminException { + if (bookieId == null || "".equals(bookieId)) { + throw new BookkeeperAdminException("bookie is empty"); + } + Map reqDate = new HashMap<>(); + reqDate.put("bookie_src", bookieId); + try { + HttpResponse resp = innerHttpClient.put(UrlConst.AUTO_RECOVERY_DECOMMISSION, reqDate); + if ((resp.statusCode() < 200 || resp.statusCode() >= 300) && resp.body() != null) { + throw new BookkeeperAdminException(resp.body()); + } + } catch (IOException | InterruptedException e) { + throw new BookkeeperAdminException(e); + } + } } diff --git a/src/test/java/io/github/protocol/bookkeeper/AutoRecoveryImplTest.java b/src/test/java/io/github/protocol/bookkeeper/AutoRecoveryImplTest.java index 8bd0ab0..e2f231f 100644 --- a/src/test/java/io/github/protocol/bookkeeper/AutoRecoveryImplTest.java +++ b/src/test/java/io/github/protocol/bookkeeper/AutoRecoveryImplTest.java @@ -2,7 +2,11 @@ import io.github.embedded.bookkeeper.core.EmbeddedBookkeeperServer; import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.Collections; public class AutoRecoveryImplTest { @@ -23,4 +27,51 @@ public static void setup() throws Exception { public static void teardown() throws Exception { SERVER.close(); } + + @Test + public void testAutoRecoveryStatus() throws BookkeeperAdminException { + AutoRecoveryStatus status = autoRecovery.autoRecoveryStatus(); + Assertions.assertNotNull(status); + Assertions.assertTrue(status.isEnabled()); + } + + @Test + public void testRecoveryBookie() throws BookkeeperAdminException { + RecoveryBookieReqData reqData = new RecoveryBookieReqData(); + reqData.setBookieSrc(Collections.singletonList("localhost:3181")); + reqData.setDeleteCookie(false); + autoRecovery.recoveryBookie(reqData); + } + + @Test + public void testListUnderReplicatedLedger() { + ListUnderReplicatedLedgerReqData reqData = new ListUnderReplicatedLedgerReqData(); + reqData.setPrintMissingReplica(true); + Assertions.assertThrows(BookkeeperAdminException.class, () -> autoRecovery.listUnderReplicatedLedger(reqData)); + } + + @Test + public void testWhoIsAuditor() { + Assertions.assertThrows(BookkeeperAdminException.class, () -> autoRecovery.whoIsAuditor()); + } + + @Test + public void testTriggerAudit() { + Assertions.assertThrows(BookkeeperAdminException.class, () -> autoRecovery.triggerAudit()); + } + + @Test + public void testLostBookieRecoveryDelayByDefault() { + Assertions.assertThrows(BookkeeperAdminException.class, () -> autoRecovery.lostBookieRecoveryDelay()); + } + + @Test + public void testLostBookieRecoveryDelay() throws BookkeeperAdminException { + autoRecovery.lostBookieRecoveryDelay(5); + } + + @Test + public void testDecommission() throws BookkeeperAdminException { + autoRecovery.decommission("localhost:3181"); + } }