From 11540856324899e5f08d21682182dcc9d47c576d Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Thu, 18 Feb 2021 11:54:10 -0300 Subject: [PATCH] Add api method 'stop' This change gives CLI users a 'stop' command to shutdown a daemon. - Server side gRPC boilerpate was added to :proto and :daemon. - When the new GrpcShutdownService accepts a 'stop' request from the CLI, it calls UserThread.runAfter(BisqHeadlessApp.getShutDownHandler(), 500, MILLISECONDS); - Method help file 'stop-help.txt' was added to :core. - Client side gRPC boiler plate and 'stop' implementation was added to :cli. --- cli/src/main/java/bisq/cli/CliMain.java | 14 +++++ cli/src/main/java/bisq/cli/GrpcStubs.java | 3 + cli/src/main/java/bisq/cli/Method.java | 3 +- core/src/main/resources/help/stop-help.txt | 22 +++++++ .../java/bisq/daemon/grpc/GrpcServer.java | 2 + .../bisq/daemon/grpc/GrpcShutdownService.java | 59 +++++++++++++++++++ proto/src/main/proto/grpc.proto | 15 +++++ 7 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 core/src/main/resources/help/stop-help.txt create mode 100644 daemon/src/main/java/bisq/daemon/grpc/GrpcShutdownService.java diff --git a/cli/src/main/java/bisq/cli/CliMain.java b/cli/src/main/java/bisq/cli/CliMain.java index 16ba360ea2d..fd717b6d584 100644 --- a/cli/src/main/java/bisq/cli/CliMain.java +++ b/cli/src/main/java/bisq/cli/CliMain.java @@ -48,6 +48,7 @@ import bisq.proto.grpc.SendBtcRequest; import bisq.proto.grpc.SetTxFeeRatePreferenceRequest; import bisq.proto.grpc.SetWalletPasswordRequest; +import bisq.proto.grpc.StopRequest; import bisq.proto.grpc.TakeOfferRequest; import bisq.proto.grpc.TxInfo; import bisq.proto.grpc.UnlockWalletRequest; @@ -193,6 +194,7 @@ public static void run(String[] args) { var offersService = grpcStubs.offersService; var paymentAccountsService = grpcStubs.paymentAccountsService; var priceService = grpcStubs.priceService; + var shutdownService = grpcStubs.shutdownService; var tradesService = grpcStubs.tradesService; var versionService = grpcStubs.versionService; var walletsService = grpcStubs.walletsService; @@ -741,6 +743,16 @@ public static void run(String[] args) { out.println(disputeAgentType + " registered"); return; } + case stop: { + if (new SimpleMethodOptionParser(args).parse().isForHelp()) { + out.println(getMethodHelp(helpService, method)); + return; + } + var request = StopRequest.newBuilder().build(); + shutdownService.stop(request); + out.println("server shutdown signal received"); + return; + } default: { throw new RuntimeException(format("unhandled method '%s'", method)); } @@ -894,6 +906,8 @@ private static void printHelp(OptionParser parser, @SuppressWarnings("SameParame "Encrypt wallet with password, or set new password on encrypted wallet"); stream.format(rowFormat, "", "[--new-wallet-password=]", ""); stream.println(); + stream.format(rowFormat, stop.name(), "", "Shut down the server"); + stream.println(); stream.println("Method Help Usage: bisq-cli [options] --help"); stream.println(); } catch (IOException ex) { diff --git a/cli/src/main/java/bisq/cli/GrpcStubs.java b/cli/src/main/java/bisq/cli/GrpcStubs.java index 2094eb743c4..b9b7ffe8923 100644 --- a/cli/src/main/java/bisq/cli/GrpcStubs.java +++ b/cli/src/main/java/bisq/cli/GrpcStubs.java @@ -23,6 +23,7 @@ import bisq.proto.grpc.OffersGrpc; import bisq.proto.grpc.PaymentAccountsGrpc; import bisq.proto.grpc.PriceGrpc; +import bisq.proto.grpc.ShutdownServerGrpc; import bisq.proto.grpc.TradesGrpc; import bisq.proto.grpc.WalletsGrpc; @@ -39,6 +40,7 @@ public class GrpcStubs { public final OffersGrpc.OffersBlockingStub offersService; public final PaymentAccountsGrpc.PaymentAccountsBlockingStub paymentAccountsService; public final PriceGrpc.PriceBlockingStub priceService; + public final ShutdownServerGrpc.ShutdownServerBlockingStub shutdownService; public final TradesGrpc.TradesBlockingStub tradesService; public final WalletsGrpc.WalletsBlockingStub walletsService; @@ -60,6 +62,7 @@ public GrpcStubs(String apiHost, int apiPort, String apiPassword) { this.offersService = OffersGrpc.newBlockingStub(channel).withCallCredentials(credentials); this.paymentAccountsService = PaymentAccountsGrpc.newBlockingStub(channel).withCallCredentials(credentials); this.priceService = PriceGrpc.newBlockingStub(channel).withCallCredentials(credentials); + this.shutdownService = ShutdownServerGrpc.newBlockingStub(channel).withCallCredentials(credentials); this.tradesService = TradesGrpc.newBlockingStub(channel).withCallCredentials(credentials); this.walletsService = WalletsGrpc.newBlockingStub(channel).withCallCredentials(credentials); } diff --git a/cli/src/main/java/bisq/cli/Method.java b/cli/src/main/java/bisq/cli/Method.java index 266e95751fa..67b582f13c6 100644 --- a/cli/src/main/java/bisq/cli/Method.java +++ b/cli/src/main/java/bisq/cli/Method.java @@ -53,5 +53,6 @@ public enum Method { takeoffer, unlockwallet, unsettxfeerate, - withdrawfunds + withdrawfunds, + stop } diff --git a/core/src/main/resources/help/stop-help.txt b/core/src/main/resources/help/stop-help.txt new file mode 100644 index 00000000000..ad28fc24bd1 --- /dev/null +++ b/core/src/main/resources/help/stop-help.txt @@ -0,0 +1,22 @@ +stop + +NAME +---- +stop - stop the server + +SYNOPSIS +-------- +stop + +DESCRIPTION +----------- +Shutdown the RPC server. + +OPTIONS +------- + +EXAMPLES +-------- +To shutdown the server: +$ ./bisq-cli --password=xyz --port=9998 stop + diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcServer.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcServer.java index 540ac3071e8..f031539e067 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcServer.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcServer.java @@ -54,6 +54,7 @@ public GrpcServer(CoreContext coreContext, GrpcOffersService offersService, GrpcPaymentAccountsService paymentAccountsService, GrpcPriceService priceService, + GrpcShutdownService shutdownService, GrpcVersionService versionService, GrpcGetTradeStatisticsService tradeStatisticsService, GrpcTradesService tradesService, @@ -65,6 +66,7 @@ public GrpcServer(CoreContext coreContext, .addService(interceptForward(offersService, offersService.interceptors())) .addService(interceptForward(paymentAccountsService, paymentAccountsService.interceptors())) .addService(interceptForward(priceService, priceService.interceptors())) + .addService(shutdownService) .addService(interceptForward(tradeStatisticsService, tradeStatisticsService.interceptors())) .addService(interceptForward(tradesService, tradesService.interceptors())) .addService(interceptForward(versionService, versionService.interceptors())) diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcShutdownService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcShutdownService.java new file mode 100644 index 00000000000..3ab445f9a5e --- /dev/null +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcShutdownService.java @@ -0,0 +1,59 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.daemon.grpc; + +import bisq.core.app.BisqHeadlessApp; + +import bisq.common.UserThread; + +import bisq.proto.grpc.ShutdownServerGrpc; +import bisq.proto.grpc.StopReply; +import bisq.proto.grpc.StopRequest; + +import io.grpc.stub.StreamObserver; + +import javax.inject.Inject; + +import lombok.extern.slf4j.Slf4j; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +@Slf4j +class GrpcShutdownService extends ShutdownServerGrpc.ShutdownServerImplBase { + + private final GrpcExceptionHandler exceptionHandler; + + @Inject + public GrpcShutdownService(GrpcExceptionHandler exceptionHandler) { + this.exceptionHandler = exceptionHandler; + } + + @Override + public void stop(StopRequest req, + StreamObserver responseObserver) { + try { + log.info("Shutdown request received."); + var reply = StopReply.newBuilder().build(); + responseObserver.onNext(reply); + responseObserver.onCompleted(); + UserThread.runAfter(BisqHeadlessApp.getShutDownHandler(), 500, MILLISECONDS); + } catch (Throwable cause) { + exceptionHandler.handleException(cause, responseObserver); + } + } +} diff --git a/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto index 085c3f90741..693975145f2 100644 --- a/proto/src/main/proto/grpc.proto +++ b/proto/src/main/proto/grpc.proto @@ -235,6 +235,21 @@ message GetTradeStatisticsReply { repeated TradeStatistics3 TradeStatistics = 1; } +/////////////////////////////////////////////////////////////////////////////////////////// +// Shutdown +/////////////////////////////////////////////////////////////////////////////////////////// + +service ShutdownServer { + rpc Stop (StopRequest) returns (StopReply) { + } +} + +message StopRequest { +} + +message StopReply { +} + /////////////////////////////////////////////////////////////////////////////////////////// // Trades ///////////////////////////////////////////////////////////////////////////////////////////