Skip to content

Commit

Permalink
Add expiry to the SET command
Browse files Browse the repository at this point in the history
  • Loading branch information
HemaZ committed Sep 14, 2024
1 parent f565188 commit 2a74fd6
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 11 deletions.
25 changes: 22 additions & 3 deletions include/RedisServer.hpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,29 @@
#ifndef REDIS_SERVER_HPP
#define REDIS_SERVER_HPP
#include <chrono>
#include <memory>
#include <mutex>
#include <optional>
#include <string>
#include <unordered_map>
#include <vector>
namespace Redis {

struct Record {
std::string data;
std::optional<std::chrono::time_point<std::chrono::system_clock>> expiry;
void setExpiry(int milliseconds) {
expiry = std::chrono::system_clock::now() +
std::chrono::milliseconds(milliseconds);
}
bool expired() const {
if (expiry == std::nullopt) {
return false;
}
return *expiry <= std::chrono::system_clock::now();
}
};

class Server {
public:
using SharedPtr = std::shared_ptr<Redis::Server>;
Expand All @@ -17,11 +34,13 @@ class Server {
handleMultipleCommands(const std::vector<std::string> &commands);

private:
std::optional<std::string> getValue(const std::string &key) const;
void setValue(const std::string &key, const std::string &value);
std::optional<std::string> getValue(const std::string &key);
void setValue(const std::string &key, const std::string &value,
std::optional<int> expiry = std::nullopt);
std::optional<std::string>
handleCommands(const std::vector<std::string> &commands);
std::unordered_map<std::string, std::string> data_;
std::string setCommand(const std::vector<std::string> &commands);
std::unordered_map<std::string, Record> data_;
std::mutex dataMutex_;
};
} // namespace Redis
Expand Down
41 changes: 33 additions & 8 deletions src/RedisServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,27 @@
#include "RESP/Parsing.hpp"
namespace Redis {

std::optional<std::string> Server::getValue(const std::string &key) const {
std::optional<std::string> Server::getValue(const std::string &key) {
if (data_.contains(key)) {
return data_.at(key);
const Record &record = data_.at(key);
if (!data_.at(key).expired()) {
return data_.at(key).data;
} else {
data_.erase(key);
}
}
return std::nullopt;
}

void Server::setValue(const std::string &key, const std::string &value) {
void Server::setValue(const std::string &key, const std::string &value,
std::optional<int> expiry) {
Record newRecord;
newRecord.data = value;
if (expiry) {
newRecord.setExpiry(*expiry);
}
std::lock_guard<std::mutex> lock(dataMutex_);
data_[key] = value;
data_[key] = newRecord;
}

std::optional<std::string>
Expand Down Expand Up @@ -44,13 +55,27 @@ Server::handleMultipleCommands(const std::vector<std::string> &commands) {
return "+" + commands[1] + "\r\n";
}
if (commands[0] == "set" || commands[0] == "SET") {
LOG_DEBUG("Setting the key {} to {}", commands[1], commands[2]);
setValue(commands[1], commands[2]);
return "+OK\r\n";
return setCommand(commands);
}
return std::nullopt;
}

std::string Server::setCommand(const std::vector<std::string> &commands) {
if (commands.size() != 3 && commands.size() != 5) {
return "$-1\r\n";
}
std::optional<int> expiry;
if (commands.size() == 5) {
try {
expiry = std::stoi(commands[4]);
LOG_INFO("Expiry time is {}ms", *expiry);
} catch (std::invalid_argument const &ex) {
LOG_ERROR("Expiry time is invalid {}", ex.what());
}
}
LOG_DEBUG("Setting the key {} to {}", commands[1], commands[2]);
setValue(commands[1], commands[2], expiry);
return "+OK\r\n";
}
std::optional<std::string>
Server::handleCommands(const std::vector<std::string> &commands) {
LOG_DEBUG("Commands Received {}", commands);
Expand Down

0 comments on commit 2a74fd6

Please sign in to comment.