diff options
| author | Dan Engelbrecht <[email protected]> | 2025-09-05 13:02:27 +0200 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2025-09-05 13:02:27 +0200 |
| commit | 45b0307d42b22e04cee63467a8fdb898a2d8d552 (patch) | |
| tree | 905b3eb62af89269be5b15f4c407d900ce86f7f3 /src/zen/cmds/cache_cmd.cpp | |
| parent | Avoid mutating executable paths when copying files during full service instal... (diff) | |
| download | archived-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.cpp | 198 |
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 |