3#include <boost/algorithm/string/predicate.hpp> 
    4#include <userver/storages/redis/parse_reply.hpp> 
    5#include <userver/storages/redis/reply.hpp> 
    6#include <userver/storages/redis/request.hpp> 
   10namespace storages::
redis {
 
   12template <
typename ScriptResult, 
typename ReplyType = ScriptResult>
 
   13class [[nodiscard]] RequestEvalSha 
final {
 
   15  class EvalShaResult 
final {
 
   17    bool IsNoScriptError() 
const { 
return no_script_error_; }
 
   18    bool HasValue() 
const { 
return reply_.has_value(); }
 
   19    const ReplyType& Get() 
const { 
return *reply_; }
 
   20    ReplyType Extract() { 
return std::move(*reply_); }
 
   23    friend class RequestEvalSha;
 
   24    EvalShaResult() = 
default;
 
   25    explicit EvalShaResult(
bool no_script) : no_script_error_{no_script} {}
 
   26    EvalShaResult(ReplyType&& reply) : reply_(std::move(reply)) {}
 
   27    std::optional<ReplyType> reply_;
 
   28    bool no_script_error_ = 
false;
 
   31  explicit RequestEvalSha(RequestEvalShaCommon&& request)
 
   32      : request_(std::move(request)) {}
 
   34  void Wait() { request_.Wait(); }
 
   36  void IgnoreResult() 
const { request_.IgnoreResult(); }
 
   38  EvalShaResult 
Get(
const std::string& request_description = {}) {
 
   39    auto reply_ptr = request_.GetRaw();
 
   40    const auto& reply_data = reply_ptr->data;
 
   41    if (reply_data.IsError()) {
 
   42      const auto& msg = reply_data.GetError();
 
   43      if (boost::starts_with(msg, 
"NOSCRIPT")) {
 
   44        return EvalShaResult(
true);
 
   48    return ParseReply<ScriptResult, ReplyType>(std::move(reply_ptr),
 
   53  RequestEvalShaCommon request_;