srctree

Robin Linden parent 3fba8e23 978115cd
protocol: Implement a simple in-memory cache

filename was Deleted added: 98, removed: 2, total 96
@@ -0,0 +1,41 @@
// SPDX-FileCopyrightText: 2024 Robin Lindén <dev@robinlinden.eu>
//
// SPDX-License-Identifier: BSD-2-Clause
 
#ifndef PROTOCOL_IN_MEMORY_CACHE_H_
#define PROTOCOL_IN_MEMORY_CACHE_H_
 
#include "protocol/iprotocol_handler.h"
#include "protocol/response.h"
 
#include "uri/uri.h"
 
#include <tl/expected.hpp>
 
#include <map>
#include <memory>
#include <utility>
 
namespace protocol {
 
// TODO(robinlinden): Eviction, invalidation, and partitioning.
class InMemoryCache : public IProtocolHandler {
public:
explicit InMemoryCache(std::unique_ptr<IProtocolHandler> handler) : handler_{std::move(handler)} {}
 
[[nodiscard]] tl::expected<Response, Error> handle(uri::Uri const &uri) override {
if (auto it = cache_.find(uri); it != cend(cache_)) {
return it->second;
}
 
return cache_[uri] = handler_->handle(uri);
}
 
private:
std::unique_ptr<IProtocolHandler> handler_;
std::map<uri::Uri, tl::expected<Response, Error>> cache_;
};
 
} // namespace protocol
 
#endif
 
filename was Deleted added: 98, removed: 2, total 96
@@ -0,0 +1,55 @@
// SPDX-FileCopyrightText: 2024 Robin Lindén <dev@robinlinden.eu>
//
// SPDX-License-Identifier: BSD-2-Clause
 
#include "protocol/in_memory_cache.h"
 
#include "protocol/iprotocol_handler.h"
#include "protocol/response.h"
 
#include "etest/etest2.h"
#include "uri/uri.h"
 
#include <tl/expected.hpp>
 
#include <memory>
#include <utility>
 
using namespace protocol;
 
namespace {
 
class FakeProtocolHandler final : public protocol::IProtocolHandler {
public:
explicit FakeProtocolHandler(int &calls, protocol::Response response)
: calls_{calls}, response_{std::move(response)} {}
 
tl::expected<protocol::Response, protocol::Error> handle(uri::Uri const &) override {
++calls_;
return response_;
}
 
private:
int &calls_;
tl::expected<protocol::Response, protocol::Error> response_;
};
 
} // namespace
 
int main() {
etest::Suite s{};
 
s.add_test("cache returns cached response", [](etest::IActions &a) {
int calls{};
auto response = Response{.body{"hello"}};
InMemoryCache cache{std::make_unique<FakeProtocolHandler>(calls, response)};
uri::Uri const uri;
a.expect_eq(calls, 0);
a.expect_eq(cache.handle(uri), response);
a.expect_eq(calls, 1);
a.expect_eq(cache.handle(uri), response);
a.expect_eq(calls, 1);
});
 
return s.run();
}