aboutsummaryrefslogtreecommitdiff
path: root/src/zen/cmds/cache_cmd.cpp
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2025-09-05 13:02:27 +0200
committerGitHub Enterprise <[email protected]>2025-09-05 13:02:27 +0200
commit45b0307d42b22e04cee63467a8fdb898a2d8d552 (patch)
tree905b3eb62af89269be5b15f4c407d900ce86f7f3 /src/zen/cmds/cache_cmd.cpp
parentAvoid mutating executable paths when copying files during full service instal... (diff)
downloadarchived-zen-45b0307d42b22e04cee63467a8fdb898a2d8d552.tar.xz
archived-zen-45b0307d42b22e04cee63467a8fdb898a2d8d552.zip
refactor zen command return value handling (#487)
- Improvement: Use consistent language for command line argument parsing errors - Improvement: Changed zen command parsing errors to output help first and error last to make it easier to spot the error - Improvement: Refactor zen command return codes to conform to valid Linux range (0-255) kSuccess = 0, kOtherError = 1, kBadInput = 2, kOutOfMemory = 16, kOutOfDisk = 17, kAssertError = 70, kHttpOtherClientError = 80, kHttpCantConnectError = 81, kHttpNotFound = 66, // NotFound(404) kHttpUnauthorized = 77, // Unauthorized(401), kHttpSLLError = 82, kHttpForbidden = 83, // Forbidden(403) kHttpTimeout = 84, // RequestTimeout(408) kHttpConflict = 85, // Conflict(409) kHttpNoHost = 86, kHttpOtherServerError = 90, kHttpInternalServerError = 91, // InternalServerError(500) kHttpServiceUnavailable = 69, // ServiceUnavailable(503) kHttpBadGateway = 92, // BadGateway(502) kHttpGatewayTimeout = 93, // GatewayTimeout(504)
Diffstat (limited to 'src/zen/cmds/cache_cmd.cpp')
-rw-r--r--src/zen/cmds/cache_cmd.cpp198
1 files changed, 79 insertions, 119 deletions
diff --git a/src/zen/cmds/cache_cmd.cpp b/src/zen/cmds/cache_cmd.cpp
index 90f428b29..ea7ad79ee 100644
--- a/src/zen/cmds/cache_cmd.cpp
+++ b/src/zen/cmds/cache_cmd.cpp
@@ -70,59 +70,53 @@ DropCommand::DropCommand()
DropCommand::~DropCommand() = default;
-int
+void
DropCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
{
ZEN_UNUSED(GlobalOptions);
if (!ParseOptions(argc, argv))
{
- return 0;
+ return;
}
m_HostName = ResolveTargetHostSpec(m_HostName);
if (m_HostName.empty())
{
- throw zen::OptionParseException("unable to resolve server specification");
+ throw OptionParseException("Unable to resolve server specification", m_Options.help());
}
if (m_NamespaceName.empty())
{
- throw zen::OptionParseException("Drop command requires a namespace");
+ throw OptionParseException("'--namespace' is required", m_Options.help());
}
- cpr::Session Session;
+ std::string Url;
+ std::string DropDescription;
+
if (m_BucketName.empty())
{
- ZEN_CONSOLE("Dropping cache namespace '{}' from '{}'", m_NamespaceName, m_HostName);
- Session.SetUrl({fmt::format("{}/z$/{}", m_HostName, m_NamespaceName)});
+ DropDescription = fmt::format("cache namespace '{}' from '{}'", m_NamespaceName, m_HostName);
+ Url = fmt::format("/z$/{}", m_NamespaceName);
}
else
{
- ZEN_CONSOLE("Dropping cache bucket '{}/{}' from '{}'", m_NamespaceName, m_BucketName, m_HostName);
- Session.SetUrl({fmt::format("{}/z$/{}/{}", m_HostName, m_NamespaceName, m_BucketName)});
+ DropDescription = fmt::format("cache bucket '{}/{}' from '{}'", m_NamespaceName, m_BucketName, m_HostName);
+ Url = fmt::format("/z$/{}/{}", m_NamespaceName, m_BucketName);
}
- cpr::Response Result = Session.Delete();
-
- if (zen::IsHttpSuccessCode(Result.status_code))
- {
- ZEN_CONSOLE("OK: drop succeeded");
-
- return 0;
- }
+ ZEN_CONSOLE("Dropping {}", DropDescription);
- if (Result.status_code)
+ HttpClient Http(m_HostName);
+ if (HttpClient::Response Response = Http.Delete(Url))
{
- ZEN_CONSOLE_ERROR("Drop failed: {}: {} ({})", Result.status_code, Result.reason, Result.text);
+ ZEN_CONSOLE("{}", Response.ToText());
}
else
{
- ZEN_CONSOLE_ERROR("Drop failed: {}", Result.error.message);
+ Response.ThrowError(fmt::format("Failed to drop {}", DropDescription));
}
-
- return 1;
}
CacheInfoCommand::CacheInfoCommand()
@@ -144,87 +138,76 @@ CacheInfoCommand::CacheInfoCommand()
CacheInfoCommand::~CacheInfoCommand() = default;
-int
+void
CacheInfoCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
{
ZEN_UNUSED(GlobalOptions);
if (!ParseOptions(argc, argv))
{
- return 0;
+ return;
}
m_HostName = ResolveTargetHostSpec(m_HostName);
if (m_HostName.empty())
{
- throw zen::OptionParseException("unable to resolve server specification");
+ throw OptionParseException("Unable to resolve server specification", m_Options.help());
}
- cpr::Session Session;
- Session.SetHeader(cpr::Header{{"Accept", "application/json"}});
+ std::string Url;
if (m_HostName.empty())
{
if (!m_SizeInfoBucketNames.empty())
{
- throw zen::OptionParseException("--bucketsizes option needs a --namespace");
+ throw OptionParseException("'--bucketsizes' requires '--namespace'", m_Options.help());
}
if (m_BucketSizeInfo)
{
- throw zen::OptionParseException("--bucketsizes option needs a --namespace and a --bucket");
+ throw OptionParseException("'--bucketsize' requires '--namespace' and '--bucket'", m_Options.help());
}
ZEN_CONSOLE("Info on cache from '{}'", m_HostName);
- Session.SetUrl({fmt::format("{}/z$", m_HostName)});
+ Url = "/z$";
}
else if (m_BucketName.empty())
{
if (m_BucketSizeInfo)
{
- throw zen::OptionParseException("--bucketsizes option needs a --bucket");
+ throw OptionParseException(fmt::format("'--bucketsize' requires '--namespace' and '--bucket' ('{}')", m_BucketName),
+ m_Options.help());
}
ZEN_CONSOLE("Info on cache namespace '{}' from '{}'", m_NamespaceName, m_HostName);
- Session.SetUrl({fmt::format("{}/z$/{}", m_HostName, m_NamespaceName)});
+ Url = fmt::format("/z$/{}", m_NamespaceName);
}
else
{
if (!m_SizeInfoBucketNames.empty())
{
- throw zen::OptionParseException("--bucketsizes option can not be used together with --bucket option");
+ throw OptionParseException("'--bucketsizes' conflicts with '--bucket'", m_Options.help());
}
ZEN_CONSOLE("Info on cache bucket '{}/{}' from '{}'", m_NamespaceName, m_BucketName, m_HostName);
- Session.SetUrl({fmt::format("{}/z$/{}/{}", m_HostName, m_NamespaceName, m_BucketName)});
+ Url = fmt::format("/z$/{}/{}", m_NamespaceName, m_BucketName);
}
- cpr::Parameters Parameters;
+ HttpClient::KeyValueMap Parameters;
if (!m_SizeInfoBucketNames.empty())
{
- Parameters.Add({"bucketsizes", m_SizeInfoBucketNames});
+ Parameters.Entries.insert({"bucketsizes", m_SizeInfoBucketNames});
}
if (m_BucketSizeInfo)
{
- Parameters.Add({"bucketsize", "true"});
- }
-
- Session.SetParameters(Parameters);
- cpr::Response Result = Session.Get();
-
- if (zen::IsHttpSuccessCode(Result.status_code))
- {
- ZEN_CONSOLE("{}", Result.text);
-
- return 0;
+ Parameters.Entries.insert({"bucketsize", "true"});
}
- if (Result.status_code)
+ HttpClient Http(m_HostName);
+ if (HttpClient::Response Response = Http.Get(Url, HttpClient::Accept(ZenContentType::kJSON), Parameters))
{
- ZEN_CONSOLE_ERROR("Info failed: {}: {} ({})", Result.status_code, Result.reason, Result.text);
+ ZEN_CONSOLE("{}", Response.ToText());
}
else
{
- ZEN_CONSOLE_ERROR("Info failed: {}", Result.error.message);
+ Response.ThrowError("Info failed");
}
-
- return 1;
}
CacheStatsCommand::CacheStatsCommand()
@@ -235,46 +218,32 @@ CacheStatsCommand::CacheStatsCommand()
CacheStatsCommand::~CacheStatsCommand() = default;
-int
+void
CacheStatsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
{
ZEN_UNUSED(GlobalOptions);
if (!ParseOptions(argc, argv))
{
- return 0;
+ return;
}
m_HostName = ResolveTargetHostSpec(m_HostName);
if (m_HostName.empty())
{
- throw zen::OptionParseException("unable to resolve server specification");
+ throw OptionParseException("Unable to resolve server specification", m_Options.help());
}
- cpr::Session Session;
- Session.SetUrl({fmt::format("{}/stats/z$", m_HostName)});
- Session.SetHeader(cpr::Header{{"Accept", "application/json"}});
-
- cpr::Response Result = Session.Get();
-
- if (zen::IsHttpSuccessCode(Result.status_code))
- {
- ZEN_CONSOLE("{}", Result.text);
-
- return 0;
- }
-
- if (Result.status_code)
+ HttpClient Http(m_HostName);
+ if (HttpClient::Response Response = Http.Get("/stats/z$", HttpClient::Accept(ZenContentType::kJSON)))
{
- ZEN_CONSOLE_ERROR("Info failed: {}: {} ({})", Result.status_code, Result.reason, Result.text);
+ ZEN_CONSOLE("{}", Response.ToText());
}
else
{
- ZEN_CONSOLE_ERROR("Info failed: {}", Result.error.message);
+ Response.ThrowError("Info failed");
}
-
- return 1;
}
CacheDetailsCommand::CacheDetailsCommand()
@@ -296,87 +265,82 @@ CacheDetailsCommand::CacheDetailsCommand()
CacheDetailsCommand::~CacheDetailsCommand() = default;
-int
+void
CacheDetailsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
{
ZEN_UNUSED(GlobalOptions);
if (!ParseOptions(argc, argv))
{
- return 0;
+ return;
}
m_HostName = ResolveTargetHostSpec(m_HostName);
if (m_HostName.empty())
{
- throw zen::OptionParseException("unable to resolve server specification");
+ throw OptionParseException("Unable to resolve server specification", m_Options.help());
}
- cpr::Session Session;
- cpr::Parameters Parameters;
+ HttpClient::KeyValueMap Parameters;
if (m_Details)
{
- Parameters.Add({"details", "true"});
+ Parameters.Entries.insert({"details", "true"});
}
if (m_AttachmentDetails)
{
- Parameters.Add({"attachmentdetails", "true"});
+ Parameters.Entries.insert({"attachmentdetails", "true"});
}
+
+ HttpClient::KeyValueMap Headers;
if (m_CSV)
{
- Parameters.Add({"csv", "true"});
+ Parameters.Entries.insert({"csv", "true"});
}
else
{
- Session.SetHeader(cpr::Header{{"Accept", "application/json"}});
+ Headers = HttpClient::Accept(ZenContentType::kJSON);
}
+ std::string Url;
if (!m_ValueKey.empty())
{
- if (m_Namespace.empty() || m_Bucket.empty())
+ if (m_Namespace.empty())
+ {
+ throw OptionParseException("'--namespace' is required", m_Options.help());
+ }
+ if (m_Bucket.empty())
{
- throw OptionParseException("Provide namespace and bucket name");
+ throw OptionParseException("'--bucket' is required", m_Options.help());
}
- Session.SetUrl({fmt::format("{}/z$/details$/{}/{}/{}", m_HostName, m_Namespace, m_Bucket, m_ValueKey)});
+ Url = fmt::format("/z$/details$/{}/{}/{}", m_Namespace, m_Bucket, m_ValueKey);
}
else if (!m_Bucket.empty())
{
if (m_Namespace.empty())
{
- throw OptionParseException("Provide namespace name");
+ throw OptionParseException("'--namespace' is required", m_Options.help());
}
- Session.SetUrl({fmt::format("{}/z$/details$/{}/{}", m_HostName, m_Namespace, m_Bucket)});
+ Url = fmt::format("/z$/details$/{}/{}", m_Namespace, m_Bucket);
}
else if (!m_Namespace.empty())
{
- Session.SetUrl({fmt::format("{}/z$/details$/{}", m_HostName, m_Namespace)});
+ Url = fmt::format("/z$/details$/{}", m_Namespace);
}
else
{
- Session.SetUrl({fmt::format("{}/z$/details$", m_HostName)});
+ Url = "/z$/details$";
}
- Session.SetParameters(Parameters);
-
- cpr::Response Result = Session.Get();
- if (zen::IsHttpSuccessCode(Result.status_code))
- {
- ZEN_CONSOLE("{}", Result.text);
-
- return 0;
- }
-
- if (Result.status_code)
+ HttpClient Http(m_HostName);
+ if (HttpClient::Response Response = Http.Get(Url, Headers, Parameters))
{
- ZEN_CONSOLE_ERROR("Info failed: {}: {} ({})", Result.status_code, Result.reason, Result.text);
+ ZEN_CONSOLE("{}", Response.ToText());
}
else
{
- ZEN_CONSOLE_ERROR("Info failed: {}", Result.error.message);
+ Response.ThrowError("Info failed");
}
-
- return 1;
}
CacheGenerateCommand::CacheGenerateCommand()
@@ -407,21 +371,21 @@ CacheGenerateCommand::CacheGenerateCommand()
CacheGenerateCommand::~CacheGenerateCommand() = default;
-int
+void
CacheGenerateCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
{
ZEN_UNUSED(GlobalOptions);
if (!ParseOptions(argc, argv))
{
- return 0;
+ return;
}
m_HostName = ResolveTargetHostSpec(m_HostName);
if (m_HostName.empty())
{
- throw zen::OptionParseException("unable to resolve server specification");
+ throw OptionParseException("Unable to resolve server specification", m_Options.help());
}
if (m_MaxSize == 0 && m_MinSize == 0)
@@ -542,8 +506,6 @@ CacheGenerateCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** a
{
ZEN_INFO("Creating data, {} requests remaining", WorkLatch.Remaining());
}
-
- return 0;
}
CacheGetCommand::CacheGetCommand()
@@ -570,7 +532,7 @@ CacheGetCommand::CacheGetCommand()
CacheGetCommand::~CacheGetCommand() = default;
-int
+void
CacheGetCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
{
ZEN_UNUSED(GlobalOptions);
@@ -579,35 +541,35 @@ CacheGetCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
if (!ParseOptions(argc, argv))
{
- return 0;
+ return;
}
m_HostName = ResolveTargetHostSpec(m_HostName);
if (m_HostName.empty())
{
- throw zen::OptionParseException("unable to resolve server specification");
+ throw OptionParseException("Unable to resolve server specification", m_Options.help());
}
if (m_Namespace.empty())
{
- throw zen::OptionParseException("cache-get command requires a namespace");
+ throw OptionParseException("'--namespace' is required", m_Options.help());
}
if (m_Bucket.empty())
{
- throw zen::OptionParseException("cache-get command requires a bucket");
+ throw OptionParseException("'--bucket' is required", m_Options.help());
}
if (m_ValueKey.empty())
{
- throw zen::OptionParseException("cache-get command requires a value key");
+ throw OptionParseException("'--valuekey' is required", m_Options.help());
}
IoHash ValueId;
if (!IoHash::TryParse(m_ValueKey, ValueId))
{
- throw zen::OptionParseException("cache-get --valuekey option requires a valid IoHash string");
+ throw OptionParseException(fmt::format("'--value-key' ('{}') is malformed", m_ValueKey), m_Options.help());
}
IoHash AttachmentHash;
@@ -615,7 +577,7 @@ CacheGetCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
{
if (!IoHash::TryParse(m_AttachmentHash, AttachmentHash))
{
- throw zen::OptionParseException("cache-get --attachmenthash option requires a valid IoHash string");
+ throw OptionParseException(fmt::format("'--attachmenthash' ('{}') is malformed", m_AttachmentHash), m_Options.help());
}
}
@@ -681,8 +643,6 @@ CacheGetCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
{
Result.ThrowError("Failed to fetch data"sv);
}
-
- return 0;
}
} // namespace zen