mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-03 09:56:38 -05:00
cli: extract connection exception handler, -rpcwait logic
to ConnectAndCallRPC() to be callable for individual connections. This is needed for RPCs that need to be called and handled sequentially, rather than alone or in a batch. For example, when fetching the balances for each loaded wallet, -getinfo will call RPC listwallets, and then, depending on the result, RPC getbalances. It may be somewhat helpful to review this commit with `git show -w`.
This commit is contained in:
parent
5f19155e5b
commit
29f2cbdeb7
1 changed files with 62 additions and 49 deletions
|
@ -418,6 +418,40 @@ static UniValue CallRPC(BaseRequestHandler *rh, const std::string& strMethod, co
|
|||
return reply;
|
||||
}
|
||||
|
||||
/**
|
||||
* ConnectAndCallRPC wraps CallRPC with -rpcwait and an exception handler.
|
||||
*
|
||||
* @param[in] rh Pointer to RequestHandler.
|
||||
* @param[in] strMethod Reference to const string method to forward to CallRPC.
|
||||
* @returns the RPC response as a UniValue object.
|
||||
* @throws a CConnectionFailed std::runtime_error if connection failed or RPC server still in warmup.
|
||||
*/
|
||||
static UniValue ConnectAndCallRPC(BaseRequestHandler* rh, const std::string& strMethod, const std::vector<std::string>& args)
|
||||
{
|
||||
UniValue response(UniValue::VOBJ);
|
||||
// Execute and handle connection failures with -rpcwait.
|
||||
const bool fWait = gArgs.GetBoolArg("-rpcwait", false);
|
||||
do {
|
||||
try {
|
||||
response = CallRPC(rh, strMethod, args);
|
||||
if (fWait) {
|
||||
const UniValue& error = find_value(response, "error");
|
||||
if (!error.isNull() && error["code"].get_int() == RPC_IN_WARMUP) {
|
||||
throw CConnectionFailed("server in warmup");
|
||||
}
|
||||
}
|
||||
break; // Connection succeeded, no need to retry.
|
||||
} catch (const CConnectionFailed&) {
|
||||
if (fWait) {
|
||||
UninterruptibleSleep(std::chrono::milliseconds{1000});
|
||||
} else {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
} while (fWait);
|
||||
return response;
|
||||
}
|
||||
|
||||
static int CommandLineRPC(int argc, char *argv[])
|
||||
{
|
||||
std::string strPrint;
|
||||
|
@ -485,62 +519,41 @@ static int CommandLineRPC(int argc, char *argv[])
|
|||
method = args[0];
|
||||
args.erase(args.begin()); // Remove trailing method name from arguments vector
|
||||
}
|
||||
const UniValue reply = ConnectAndCallRPC(rh.get(), method, args);
|
||||
|
||||
// Execute and handle connection failures with -rpcwait
|
||||
const bool fWait = gArgs.GetBoolArg("-rpcwait", false);
|
||||
do {
|
||||
try {
|
||||
const UniValue reply = CallRPC(rh.get(), method, args);
|
||||
// Parse reply
|
||||
UniValue result = find_value(reply, "result");
|
||||
const UniValue& error = find_value(reply, "error");
|
||||
if (!error.isNull()) {
|
||||
// Error
|
||||
strPrint = "error: " + error.write();
|
||||
nRet = abs(error["code"].get_int());
|
||||
if (error.isObject()) {
|
||||
const UniValue& errCode = find_value(error, "code");
|
||||
const UniValue& errMsg = find_value(error, "message");
|
||||
strPrint = errCode.isNull() ? "" : ("error code: " + errCode.getValStr() + "\n");
|
||||
|
||||
// Parse reply
|
||||
const UniValue& result = find_value(reply, "result");
|
||||
const UniValue& error = find_value(reply, "error");
|
||||
|
||||
if (!error.isNull()) {
|
||||
// Error
|
||||
int code = error["code"].get_int();
|
||||
if (fWait && code == RPC_IN_WARMUP)
|
||||
throw CConnectionFailed("server in warmup");
|
||||
strPrint = "error: " + error.write();
|
||||
nRet = abs(code);
|
||||
if (error.isObject())
|
||||
{
|
||||
UniValue errCode = find_value(error, "code");
|
||||
UniValue errMsg = find_value(error, "message");
|
||||
strPrint = errCode.isNull() ? "" : "error code: "+errCode.getValStr()+"\n";
|
||||
|
||||
if (errMsg.isStr())
|
||||
strPrint += "error message:\n"+errMsg.get_str();
|
||||
|
||||
if (errCode.isNum() && errCode.get_int() == RPC_WALLET_NOT_SPECIFIED) {
|
||||
strPrint += "\nTry adding \"-rpcwallet=<filename>\" option to bitcoin-cli command line.";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Result
|
||||
if (result.isNull())
|
||||
strPrint = "";
|
||||
else if (result.isStr())
|
||||
strPrint = result.get_str();
|
||||
else
|
||||
strPrint = result.write(2);
|
||||
if (errMsg.isStr()) {
|
||||
strPrint += ("error message:\n" + errMsg.get_str());
|
||||
}
|
||||
if (errCode.isNum() && errCode.get_int() == RPC_WALLET_NOT_SPECIFIED) {
|
||||
strPrint += "\nTry adding \"-rpcwallet=<filename>\" option to bitcoin-cli command line.";
|
||||
}
|
||||
// Connection succeeded, no need to retry.
|
||||
break;
|
||||
}
|
||||
catch (const CConnectionFailed&) {
|
||||
if (fWait)
|
||||
UninterruptibleSleep(std::chrono::milliseconds{1000});
|
||||
else
|
||||
throw;
|
||||
} else {
|
||||
// Result
|
||||
if (result.isNull()) {
|
||||
strPrint = "";
|
||||
} else if (result.isStr()) {
|
||||
strPrint = result.get_str();
|
||||
} else {
|
||||
strPrint = result.write(2);
|
||||
}
|
||||
} while (fWait);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
strPrint = std::string("error: ") + e.what();
|
||||
nRet = EXIT_FAILURE;
|
||||
}
|
||||
catch (...) {
|
||||
} catch (...) {
|
||||
PrintExceptionContinue(nullptr, "CommandLineRPC()");
|
||||
throw;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue