2023-06-08 16:02:36 +00:00
|
|
|
#pragma once
|
|
|
|
|
2023-06-09 12:30:08 +00:00
|
|
|
#include <mutex>
|
2023-06-08 16:02:36 +00:00
|
|
|
#include <string>
|
|
|
|
#include <memory>
|
|
|
|
#include <optional>
|
|
|
|
#include <exception>
|
|
|
|
|
|
|
|
#pragma GCC diagnostic push
|
2023-06-09 12:29:19 +00:00
|
|
|
#pragma GCC diagnostic ignored "-Wpragmas"
|
2023-06-08 16:02:36 +00:00
|
|
|
#pragma GCC diagnostic ignored "-Wc99-extensions"
|
|
|
|
#pragma GCC diagnostic ignored "-Wconversion"
|
2023-06-09 12:29:19 +00:00
|
|
|
#pragma GCC diagnostic ignored "-Wpedantic"
|
2023-06-08 16:02:36 +00:00
|
|
|
#include <hiredis.h>
|
|
|
|
#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<redisReply, decltype(&freeReplyObject)>;
|
|
|
|
|
|
|
|
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<typename... Args>
|
|
|
|
RedisReply command(const char* format, Args... args) {
|
|
|
|
std::lock_guard<std::mutex> guard(this->_mutex);
|
|
|
|
redisReply* raw_reply = static_cast<redisReply*>(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<std::string> get(const std::string& key);
|
|
|
|
void set(const std::string& key, const std::string& value, time_t expiry);
|
|
|
|
|
|
|
|
std::optional<std::string> 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;
|
|
|
|
};
|