129 lines
4.1 KiB
C++
129 lines
4.1 KiB
C++
|
#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<std::string> 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<std::string> 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");
|
||
|
}
|
||
|
}
|