#pragma once #include #include #include #include #include #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpragmas" #pragma GCC diagnostic ignored "-Wc99-extensions" #pragma GCC diagnostic ignored "-Wconversion" #pragma GCC diagnostic ignored "-Wpedantic" #include #pragma GCC diagnostic pop class RedisException : public std::exception { public: RedisException(const char* error_) : error(error_) {} RedisException(const char* error_, size_t length) : error(error_, length) {} const char* what() const noexcept { return this->error.c_str(); } std::string error; }; using RedisReply = std::unique_ptr; class Redis { public: Redis(const Redis&) = delete; Redis operator=(const Redis&) = delete; Redis(const std::string& address, int port); Redis(const std::string& unix); ~Redis(); template RedisReply command(const char* format, Args... args) { std::lock_guard guard(this->_mutex); redisReply* raw_reply = static_cast(redisCommand(this->_context, format, args...)); if (!raw_reply) { throw RedisException(this->_context->errstr); } RedisReply reply(raw_reply, freeReplyObject); if (reply->type == REDIS_REPLY_ERROR) { throw RedisException(reply->str, reply->len); } return reply; } void auth(const std::string& username, const std::string& password); void auth(const std::string& password); time_t ttl(const std::string& key); bool expire(const std::string& key, time_t expiry); bool expire_nx(const std::string& key, time_t expiry); std::optional get(const std::string& key); void set(const std::string& key, const std::string& value, time_t expiry); std::optional hget(const std::string& key, const std::string& field); void hset(const std::string& key, const std::string& field, const std::string& value); private: redisContext* _context; std::mutex _mutex; bool _fake_expire_nx = false; };