#include "hiredis_wrapper.h" Redis::Redis(const std::string& address, int port) { this->_context = redisConnect(address.c_str(), port); if (!this->_context) { throw std::bad_alloc(); } if (this->_context->err) { RedisException e(this->_context->errstr); redisFree(this->_context); throw e; } } Redis::Redis(const std::string& unix) { this->_context = redisConnectUnix(unix.c_str()); if (!this->_context) { throw std::bad_alloc(); } if (this->_context->err) { RedisException e(this->_context->errstr); redisFree(this->_context); throw e; } } Redis::~Redis() { redisFree(this->_context); } void Redis::auth(const std::string& username, const std::string& password) { RedisReply reply = this->command("AUTH %s %s", username.c_str(), password.c_str()); if (reply->type == REDIS_REPLY_STATUS) { // good :D } else { throw std::runtime_error("AUTH gave an unexpected return type"); } } void Redis::auth(const std::string& password) { RedisReply reply = this->command("AUTH %s", password.c_str()); if (reply->type == REDIS_REPLY_STATUS) { // good :D } else { throw std::runtime_error("AUTH gave an unexpected return type"); } } time_t Redis::ttl(const std::string& key) { RedisReply reply = this->command("TTL %s", key.c_str()); if (reply->type == REDIS_REPLY_INTEGER) { return reply->integer; } else { throw std::runtime_error("TTL gave an unexpected return type"); } } bool Redis::expire(const std::string& key, time_t expiry) { RedisReply reply = this->command("EXPIRE %s %d", key.c_str(), expiry); if (reply->type == REDIS_REPLY_INTEGER) { return reply->integer == 1; } else { throw std::runtime_error("EXPIRE gave an unexpected return type"); } } bool Redis::expire_nx(const std::string& key, time_t expiry) { if (this->_fake_expire_nx) { time_t current_expiry = this->ttl(key); if (current_expiry < 0) { return this->expire(key, expiry); } return false; } RedisReply reply(nullptr, freeReplyObject); try{ reply = this->command("EXPIRE %s %d NX", key.c_str(), expiry); } catch (const RedisException& e) { if (e.error == "ERR wrong number of arguments for 'expire' command") { this->_fake_expire_nx = true; return this->expire_nx(key, expiry); } throw; } if (reply->type == REDIS_REPLY_INTEGER) { return reply->integer == 1; } else { throw std::runtime_error("EXPIRE NX gave an unexpected return type"); } } std::optional Redis::get(const std::string& key) { RedisReply reply = this->command("GET %s", key.c_str()); if (reply->type == REDIS_REPLY_STRING) { return std::string(reply->str, reply->len); } else if (reply->type == REDIS_REPLY_NIL) { return std::nullopt; } else { throw std::runtime_error("GET gave an unexpected return type"); } } void Redis::set(const std::string& key, const std::string& value, time_t expiry) { RedisReply reply = this->command("SET %s %s EX %d", key.c_str(), value.c_str(), expiry); if (reply->type == REDIS_REPLY_STATUS) { // good :D } else { throw std::runtime_error("SET gave an unexpected return type"); } } std::optional Redis::hget(const std::string& key, const std::string& field) { RedisReply reply = this->command("HGET %s %s", key.c_str(), field.c_str()); if (reply->type == REDIS_REPLY_STRING) { return std::string(reply->str, reply->len); } else if (reply->type == REDIS_REPLY_NIL) { return std::nullopt; } else { throw std::runtime_error("HGET gave an unexpected return type"); } } void Redis::hset(const std::string& key, const std::string& field, const std::string& value) { RedisReply reply = this->command("HSET %s %s %s", key.c_str(), field.c_str(), value.c_str()); if (reply->type == REDIS_REPLY_INTEGER) { // good :D } else { throw std::runtime_error("SET gave an unexpected return type"); } }