-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Implement RedisCache class for Redis storage backend - Add unit tests for Redis cache functionality - Update CMake configuration for Redis support Fixes #484
- Loading branch information
1 parent
476faef
commit 4a4faba
Showing
4 changed files
with
170 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
#include "RedisCache.h" | ||
|
||
#ifdef OPENMIND_STORAGE_REDIS | ||
|
||
#include <hiredis/hiredis.h> | ||
#include <stdexcept> | ||
#include <cstdarg> | ||
|
||
namespace omnn::rt::storage { | ||
|
||
RedisCache::RedisCache(const std::string_view& host, int port, int timeout_ms) | ||
: _context(nullptr, redisFree) | ||
, _host(host) | ||
, _port(port) | ||
, _timeout_ms(timeout_ms) | ||
{ | ||
ensureConnection(); | ||
} | ||
|
||
RedisCache::~RedisCache() = default; | ||
|
||
void RedisCache::ensureConnection() { | ||
if (_context) return; | ||
|
||
struct timeval timeout = { 0, _timeout_ms * 1000 }; | ||
redisContext* c = redisConnectWithTimeout(_host.c_str(), _port, timeout); | ||
if (c == nullptr || c->err) { | ||
if (c) { | ||
std::string error = c->errstr; | ||
redisFree(c); | ||
throw std::runtime_error("Redis connection error: " + error); | ||
} else { | ||
throw std::runtime_error("Redis connection error: can't allocate redis context"); | ||
} | ||
} | ||
_context.reset(c); | ||
} | ||
|
||
std::unique_ptr<redisReply, void(*)(redisReply*)> RedisCache::executeCommand(const char* format, ...) { | ||
ensureConnection(); | ||
|
||
va_list ap; | ||
va_start(ap, format); | ||
redisReply* reply = (redisReply*)redisvCommand(_context.get(), format, ap); | ||
va_end(ap); | ||
|
||
if (!reply) { | ||
throw std::runtime_error("Redis command failed"); | ||
} | ||
|
||
// Cast freeReplyObject to the correct function pointer type | ||
auto deleter = reinterpret_cast<void(*)(redisReply*)>(freeReplyObject); | ||
return std::unique_ptr<redisReply, void(*)(redisReply*)>(reply, deleter); | ||
} | ||
|
||
std::string RedisCache::GetOne(const std::string_view& key) { | ||
auto reply = executeCommand("GET %b", key.data(), key.size()); | ||
|
||
if (reply->type == REDIS_REPLY_NIL) { | ||
return ""; | ||
} | ||
|
||
if (reply->type != REDIS_REPLY_STRING) { | ||
throw std::runtime_error("Unexpected Redis reply type for GET"); | ||
} | ||
|
||
return std::string(reply->str, reply->len); | ||
} | ||
|
||
bool RedisCache::Set(const std::string_view& key, const std::string_view& v) { | ||
auto reply = executeCommand("SET %b %b", key.data(), key.size(), v.data(), v.size()); | ||
|
||
return reply->type == REDIS_REPLY_STATUS && | ||
std::string_view(reply->str, reply->len) == "OK"; | ||
} | ||
|
||
bool RedisCache::Clear(const std::string_view& key) { | ||
auto reply = executeCommand("DEL %b", key.data(), key.size()); | ||
|
||
return reply->type == REDIS_REPLY_INTEGER && reply->integer > 0; | ||
} | ||
|
||
bool RedisCache::ResetAllDB(const path_str_t& path) { | ||
auto reply = executeCommand("FLUSHDB"); | ||
|
||
return reply->type == REDIS_REPLY_STATUS && | ||
std::string_view(reply->str, reply->len) == "OK"; | ||
} | ||
|
||
} // namespace omnn::rt::storage | ||
|
||
#endif // OPENMIND_STORAGE_REDIS |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#pragma once | ||
#include "CacheBase.h" | ||
|
||
#ifdef OPENMIND_STORAGE_REDIS | ||
|
||
#include <memory> | ||
#include <string> | ||
#include <string_view> | ||
|
||
struct redisContext; // Forward declaration | ||
struct redisReply; // Forward declaration | ||
|
||
namespace omnn::rt::storage { | ||
|
||
using path_str_t = boost::filesystem::path; | ||
|
||
class RedisCache : public CacheBase { | ||
std::unique_ptr<redisContext, void(*)(redisContext*)> _context; | ||
const std::string _host; | ||
const int _port; | ||
const int _timeout_ms; | ||
|
||
public: | ||
RedisCache(const std::string_view& host = "localhost", | ||
int port = 6379, | ||
int timeout_ms = 1000); | ||
~RedisCache() override; | ||
|
||
std::string GetOne(const std::string_view& key) override; | ||
bool Set(const std::string_view& key, const std::string_view& v) override; | ||
bool Clear(const std::string_view& key) override; | ||
bool ResetAllDB(const path_str_t& path) override; | ||
|
||
private: | ||
void ensureConnection(); | ||
std::unique_ptr<redisReply, void(*)(redisReply*)> executeCommand(const char* format, ...); | ||
}; | ||
|
||
} // namespace omnn::rt::storage | ||
|
||
#endif // OPENMIND_STORAGE_REDIS |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,4 @@ | ||
test() | ||
test() | ||
|
||
# Redis cache tests are automatically included by the test() macro | ||
# when OPENMIND_STORAGE_REDIS is defined |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
#define BOOST_TEST_MODULE redis_cache_test | ||
#include <boost/test/unit_test.hpp> | ||
#include "../RedisCache.h" | ||
|
||
#ifdef OPENMIND_STORAGE_REDIS | ||
|
||
using namespace omnn::rt::storage; | ||
|
||
BOOST_AUTO_TEST_CASE(redis_cache_basic_operations) { | ||
RedisCache cache("localhost", 6379); | ||
|
||
// Test Set and GetOne | ||
BOOST_CHECK(cache.Set("test_key", "test_value")); | ||
BOOST_CHECK_EQUAL(cache.GetOne("test_key"), "test_value"); | ||
|
||
// Test Clear | ||
BOOST_CHECK(cache.Clear("test_key")); | ||
BOOST_CHECK_EQUAL(cache.GetOne("test_key"), ""); | ||
|
||
// Test ResetAllDB | ||
BOOST_CHECK(cache.Set("key1", "value1")); | ||
BOOST_CHECK(cache.Set("key2", "value2")); | ||
BOOST_CHECK(cache.ResetAllDB("")); | ||
BOOST_CHECK_EQUAL(cache.GetOne("key1"), ""); | ||
BOOST_CHECK_EQUAL(cache.GetOne("key2"), ""); | ||
} | ||
|
||
BOOST_AUTO_TEST_CASE(redis_cache_error_handling) { | ||
// Test connection to non-existent Redis server | ||
BOOST_CHECK_THROW(RedisCache("nonexistent", 6379), std::runtime_error); | ||
} | ||
|
||
#endif // OPENMIND_STORAGE_REDIS |