Skip to content

Commit

Permalink
[redis][refactoring] Adding Redis in server and some code refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
Nikolay Ryzhov committed May 8, 2024
1 parent 4a2a9b0 commit d84d53c
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 15 deletions.
8 changes: 5 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ add_executable(${PROJECT_NAME}
src/main.cc
src/server/endpoints/endpoints.cc
src/server/endpoints/endpoints.h
src/database/wrapper.cc
src/database/wrapper.h
src/database/postgres-wrapper.cc
src/database/postgres-wrapper.h
src/database/redis-wrapper.cc
src/database/redis-wrapper.h
src/utils/utils.h
src/utils/logger.h
src/server/server.cc
Expand All @@ -51,4 +53,4 @@ if(APPLE)
endif()

target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Wpedantic -Werror)
target_link_libraries(${PROJECT_NAME} PRIVATE ${PostgreSQL_LIBRARIES} GTest::gtest_main)
target_link_libraries(${PROJECT_NAME} PRIVATE ${PostgreSQL_LIBRARIES} GTest::gtest_main -lhiredis)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "wrapper.h"
#include "postgres-wrapper.h"

#include <stdexcept>

Expand Down
File renamed without changes.
42 changes: 42 additions & 0 deletions src/database/redis-wrapper.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include "redis-wrapper.h"

#include <stdexcept>

#include "utils/logger.h"

namespace fm {

Redis::Redis(const std::string& host, int32_t port) {
context = redisConnect(host.c_str(), port);
if (context != nullptr && context->err) {
throw std::runtime_error(context->errstr);
} else {
Logger::Get().Write("Success Redis connection.");
}
}

Redis::~Redis() { redisFree(context); }

redisResponse set(Redis& redis, const std::string& key, const std::string& value) {
redisReply* reply;
reply = static_cast<redisReply*>(redisCommand(redis.context, "SETEX %s 10 %s", key.c_str(), value.c_str()));

std::string replyStr(reply->str, reply->len);
int8_t status = reply->type;

freeReplyObject(reply);
return {status, replyStr};
}

redisResponse get(Redis& redis, const std::string& key) {
redisReply* reply;
reply = static_cast<redisReply*>(redisCommand(redis.context, "GET %s", key.c_str()));

std::string replyStr(reply->str, reply->len);
int8_t status = reply->type;

freeReplyObject(reply);
return {status, replyStr};
}

} // namespace fm
30 changes: 30 additions & 0 deletions src/database/redis-wrapper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once

#include <cstdint>
#include <string>

#include "json.hpp"

using json = nlohmann::json;

#include <hiredis/hiredis.h>

namespace fm {

using redisResponse = std::pair<int8_t, std::string>; // status code, reply string

class Redis {
public:
Redis(const std::string& host, int32_t port);
~Redis();
Redis(const Redis& other) = delete;
Redis(Redis&& other) = delete;

private:
redisContext* context;

friend redisResponse set(Redis& redis, const std::string& key, const std::string& value);
friend redisResponse get(Redis& redis, const std::string& key);
};

} // namespace fm
35 changes: 25 additions & 10 deletions src/server/endpoints/endpoints.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,41 +11,56 @@ namespace fs = std::filesystem;

namespace fm {

EndPointsHandler::EndPointsHandler() : database(Utils::GetDatabaseConfig(fs::path{".local/database.conf"})) {
EndPointsHandler::EndPointsHandler() : database{Utils::GetDatabaseConfig(fs::path{".local/database.conf"})}, redis{"127.0.0.1", 6379} {
prepare(database, "add_actor", "INSERT INTO actor (actorname, gender, birthday) VALUES ($1, $2, $3)", 3, nullptr);
prepare(database, "add_film", "INSERT INTO film (title, description, release_date, rating, actors) VALUES ($1, $2, $3, $4, $5)", 5, nullptr);
}

response EndPointsHandler::AddActor(const Actor &actor) {
json response;
response["message"] = "Successfully adding a new user " + actor.name;
const char *paramValues[3] = {actor.name.c_str(), actor.gender.c_str(), actor.date.c_str()};
constexpr int32_t paramsCount = 3;
const char *paramValues[paramsCount] = {actor.name.c_str(), actor.gender.c_str(), actor.date.c_str()};

execPrepared(database, "add_actor", 3, paramValues);
execPrepared(database, "add_actor", paramsCount, paramValues);

return {200, response.dump(JSON_DUMP)};
}

response EndPointsHandler::GetActors() {
if (auto content = get(redis, "actors"); content.first == REDIS_REPLY_STRING) {
return {200, content.second};
} else {
json response = get(database, "SELECT * FROM actor");

return {200, response.dump(JSON_DUMP)};
std::string responseStr = response.dump(JSON_DUMP);
set(redis, "actors", responseStr);
return {200, responseStr};
}
return {500, "Redis/Postgres error."};
}

response EndPointsHandler::AddFilm(const Film& film) {
json response;
response["message"] = "Successfully adding a new film " + film.title;
const char *paramValues[5] = {film.title.c_str(), film.description.c_str(), film.release_date.c_str(), film.rating.c_str(), film.ids.c_str()};
constexpr int32_t paramsCount = 5;
const char *paramValues[paramsCount] = {film.title.c_str(), film.description.c_str(), film.release_date.c_str(), film.rating.c_str(), film.ids.c_str()};

execPrepared(database, "add_film", 5, paramValues);
execPrepared(database, "add_film", paramsCount, paramValues);

return {200, response.dump(JSON_DUMP)};
}

response EndPointsHandler::GetFilms() {
json response = get(database, "SELECT f.id, f.title, f.description, f.release_date, f.rating, array_agg(a.actorname) AS actors FROM film f LEFT JOIN actor a ON a.id = ANY(f.actors) GROUP BY f.id;");

return {200, response.dump(JSON_DUMP)};
if (auto content = get(redis, "films"); content.first == REDIS_REPLY_STRING) {
return {200, content.second};
} else {
json response = get(database, "SELECT f.id, f.title, f.description, f.release_date, f.rating, array_agg(a.actorname) AS actors FROM film f LEFT JOIN actor a ON a.id = ANY(f.actors) GROUP BY f.id;");
std::string responseStr = response.dump(JSON_DUMP);
set(redis, "films", responseStr);
return {200, responseStr};
}

return {500, "Redis/Postgres error."};
}

} // namespace fm
4 changes: 3 additions & 1 deletion src/server/endpoints/endpoints.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

#include <string>
#include <vector>
#include "../../database/wrapper.h"
#include "database/postgres-wrapper.h"
#include "database/redis-wrapper.h"
#include <cstdint>

namespace fm {
Expand Down Expand Up @@ -32,6 +33,7 @@ class EndPointsHandler {
response GetFilms();
private:
PGConnection database;
Redis redis;
};

} // namespace fm

0 comments on commit d84d53c

Please sign in to comment.