#include #include #include #include #include #include #include #include #include #include "google/protobuf/empty.pb.h" #include "v1/primitives/bool.grpc.pb.h" #include "v1/primitives/bool.pb.h" #include "v1/primitives/int.grpc.pb.h" #include "v1/primitives/int.pb.h" #include "v1/primitives/string.grpc.pb.h" #include "v1/primitives/string.pb.h" #include "v1/collections/list.grpc.pb.h" #include "v1/collections/list.pb.h" #include "rediska/common/QueueMessage.hpp" #include "rediska/frontend/RequestManager.hpp" #include "rediska/frontend/server.hpp" #include "rediska/cache/lru/LRU.hpp" #include "rediska/data-structures/impl/ListDataStructure.hpp" namespace { class CacheWorker { public: CacheWorker(size_t cache_capacity = 1000) { cache_config_.maxCapacity = cache_capacity; cache_config_.ttl = 0; cache_config_.resetTTLOnAccess = true; auto callback = [this](auto result) { }; cache_ = std::make_unique(cache_config_, callback); } void Enqueue(QueueMessage msg) { std::lock_guard lock(mtx_); queue_.push(std::move(msg)); cv_.notify_one(); } void Run() { for (;;) { QueueMessage msg; { std::unique_lock lock(mtx_); cv_.wait(lock, [&] { return !queue_.empty(); }); msg = std::move(queue_.front()); queue_.pop(); } std::cout << "[cache-worker] key=" << msg.key << " type=" << static_cast(msg.type) << " op=" << static_cast(msg.operation) << std::endl; if (!msg.responder) continue; try { switch (msg.operation) { case OperationId::SET: { if (msg.type == CacheValueId::ARRAY) { auto list = std::make_shared(); if (std::holds_alternative(msg.arguments)) { auto& args = std::get(msg.arguments); for (auto& value : args.values) { list->handle(OperationId::LIST_PUSH_BACK, DSValue{}); } } cache_->set(std::string(msg.key), CacheValue{list}, 0); v1::collections::list::ListSetResponse response; msg.respond(response); } else { CacheValue value; if (msg.arguments.index() != 0) { auto& args = std::get(msg.arguments); value = args.value; } cache_->set(std::string(msg.key), std::move(value), 0); msg.respond(google::protobuf::Empty{}); } break; } case OperationId::GET: { cache_->get(std::string(msg.key)); // я не нашел пока полный callback, тут заглушки (TODO) if (msg.type == CacheValueId::BOOLEAN) { v1::primitives::boolean::BoolGetResponse response; response.set_value(true); msg.respond(response); } else if (msg.type == CacheValueId::INT) { v1::primitives::integer::IntGetResponse response; response.set_value(42); msg.respond(response); } else if (msg.type == CacheValueId::STRING) { v1::primitives::str::StringGetResponse response; response.set_value("cached_string_value"); msg.respond(response); } else if (msg.type == CacheValueId::ARRAY) { v1::collections::list::ListGetResponse response; msg.respond(response); } break; } case OperationId::DELETE: { cache_->applyTo(std::string(msg.key), OperationId::DELETE, std::move(msg.arguments)); if (msg.type == CacheValueId::BOOLEAN) { v1::primitives::boolean::BoolDeleteResponse response; response.set_removed_value(true); msg.respond(response); } else if (msg.type == CacheValueId::INT) { v1::primitives::integer::IntDeleteResponse response; response.set_removed_value(42); msg.respond(response); } else if (msg.type == CacheValueId::STRING) { v1::primitives::str::StringDeleteResponse response; response.set_removed_value("deleted_string"); msg.respond(response); } else if (msg.type == CacheValueId::ARRAY) { msg.respond(google::protobuf::Empty{}); } break; } case OperationId::LIST_PUSH_BACK: { cache_->applyTo(std::string(msg.key), OperationId::LIST_PUSH_BACK, std::move(msg.arguments)); msg.respond(google::protobuf::Empty{}); break; } case OperationId::LIST_POP_BACK: { cache_->applyTo(std::string(msg.key), OperationId::LIST_POP_BACK, std::move(msg.arguments)); v1::collections::list::PopBackResponse response; msg.respond(response); break; } case OperationId::LIST_INSERT: { cache_->applyTo(std::string(msg.key), OperationId::LIST_INSERT, std::move(msg.arguments)); msg.respond(google::protobuf::Empty{}); break; } case OperationId::LIST_ERASE: { cache_->applyTo(std::string(msg.key), OperationId::LIST_ERASE, std::move(msg.arguments)); msg.respond(google::protobuf::Empty{}); break; } default: break; } } catch (const std::exception& e) { std::cout << "Error processing message: " << e.what() << std::endl; } } } private: std::queue queue_; std::mutex mtx_; std::condition_variable cv_; std::unique_ptr cache_; cache::LRUConfig cache_config_; }; } // namespace int run_cache_server() { CacheWorker worker(1000); std::thread t([&] { worker.Run(); }); RunFrontendServer("0.0.0.0:50051", [&](QueueMessage msg) { worker.Enqueue(std::move(msg)); }); t.join(); return 0; }