extended statement_cache with message bus events
This commit is contained in:
@@ -7,6 +7,8 @@
|
||||
#include "matador/sql/error_code.hpp"
|
||||
#include "matador/sql/statement_cache.hpp"
|
||||
|
||||
#include "matador/utils/message_bus.hpp"
|
||||
|
||||
#include "../backend/test_backend_service.hpp"
|
||||
|
||||
#include "ConnectionPoolFixture.hpp"
|
||||
@@ -18,32 +20,47 @@
|
||||
using namespace matador::test;
|
||||
using namespace matador::sql;
|
||||
using namespace matador::query;
|
||||
using namespace matador::utils;
|
||||
|
||||
class RecordingObserver final : public statement_cache_observer_interface {
|
||||
class RecordingObserver final {
|
||||
public:
|
||||
void on_event(const statement_cache_event& evt) override {
|
||||
std::lock_guard lock(mutex);
|
||||
events.push(evt);
|
||||
explicit RecordingObserver(message_bus &bus) {
|
||||
subscriptions.push_back(bus.subscribe<statement_accessed_event>([this](const statement_accessed_event &ev) {
|
||||
std::lock_guard lock(mutex);
|
||||
events.push(message::from_ref(ev));
|
||||
}));
|
||||
subscriptions.push_back(bus.subscribe<statement_added_event>([this](const statement_added_event &ev) {
|
||||
std::lock_guard lock(mutex);
|
||||
events.push(message::from_ref(ev));
|
||||
}));
|
||||
subscriptions.push_back(bus.subscribe<statement_evicted_event>([this](const statement_evicted_event &ev) {
|
||||
std::lock_guard lock(mutex);
|
||||
events.push(message::from_ref(ev));
|
||||
}));
|
||||
}
|
||||
|
||||
std::optional<statement_cache_event> poll() {
|
||||
std::optional<message> poll() {
|
||||
std::lock_guard lock(mutex);
|
||||
if (events.empty()) return std::nullopt;
|
||||
if (events.empty()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
auto evt = events.front();
|
||||
events.pop();
|
||||
return evt;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<subscription> subscriptions;
|
||||
std::mutex mutex;
|
||||
std::queue<statement_cache_event> events;
|
||||
std::queue<message> events;
|
||||
};
|
||||
|
||||
TEST_CASE("Test statement cache", "[statement][cache]") {
|
||||
backend_provider::instance().register_backend("noop", std::make_unique<orm::test_backend_service>());
|
||||
|
||||
matador::utils::message_bus bus;
|
||||
connection_pool pool("noop://noop.db", 4);
|
||||
statement_cache cache(pool, 2);
|
||||
statement_cache cache(bus, pool, 2);
|
||||
|
||||
query_context ctx;
|
||||
ctx.sql = "SELECT * FROM person";
|
||||
@@ -83,9 +100,9 @@ TEST_CASE("Test LRU cache evicts oldest entries", "[statement][cache][evict]") {
|
||||
backend_provider::instance().register_backend("noop", std::make_unique<orm::test_backend_service>());
|
||||
|
||||
connection_pool pool("noop://noop.db", 4);
|
||||
statement_cache cache(pool, 2);
|
||||
RecordingObserver observer;
|
||||
cache.subscribe(observer);
|
||||
message_bus bus;
|
||||
statement_cache cache(bus, pool, 2);
|
||||
RecordingObserver observer(bus);
|
||||
|
||||
REQUIRE(cache.capacity() == 2);
|
||||
REQUIRE(cache.empty());
|
||||
@@ -116,8 +133,12 @@ TEST_CASE("Test LRU cache evicts oldest entries", "[statement][cache][evict]") {
|
||||
|
||||
int added = 0, evicted = 0;
|
||||
while (auto e = observer.poll()) {
|
||||
if (e->type == statement_cache_event::Type::Added) added++;
|
||||
if (e->type == statement_cache_event::Type::Evicted) evicted++;
|
||||
if (e->is<statement_added_event>()) {
|
||||
added++;
|
||||
}
|
||||
if (e->is<statement_evicted_event>()) {
|
||||
evicted++;
|
||||
}
|
||||
}
|
||||
REQUIRE(added >= 3);
|
||||
REQUIRE(evicted >= 1);
|
||||
@@ -127,9 +148,9 @@ TEST_CASE("Test statement reuse avoids reprepare", "[statement][cache][prepare]"
|
||||
backend_provider::instance().register_backend("noop", std::make_unique<orm::test_backend_service>());
|
||||
|
||||
connection_pool pool("noop://noop.db", 4);
|
||||
statement_cache cache(pool, 2);
|
||||
RecordingObserver observer;
|
||||
cache.subscribe(observer);
|
||||
message_bus bus;
|
||||
statement_cache cache(bus, pool, 2);
|
||||
RecordingObserver observer(bus);
|
||||
|
||||
REQUIRE(cache.capacity() == 2);
|
||||
REQUIRE(cache.empty());
|
||||
@@ -140,8 +161,6 @@ TEST_CASE("Test statement reuse avoids reprepare", "[statement][cache][prepare]"
|
||||
result = cache.acquire({"SELECT * FROM person"});
|
||||
REQUIRE(result);
|
||||
auto stmt2 = result.value();
|
||||
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("Multithreaded stress test", "[statement][cache][stress]") {
|
||||
@@ -157,9 +176,9 @@ TEST_CASE("Multithreaded stress test", "[statement][cache][stress]") {
|
||||
}
|
||||
|
||||
connection_pool pool("noop://noop.db", 4);
|
||||
statement_cache cache(pool, 5);
|
||||
RecordingObserver observer;
|
||||
cache.subscribe(observer);
|
||||
message_bus bus;
|
||||
statement_cache cache(bus, pool, 5);
|
||||
RecordingObserver observer(bus);
|
||||
|
||||
auto start_time = std::chrono::steady_clock::now();
|
||||
|
||||
@@ -203,7 +222,7 @@ TEST_CASE("Multithreaded stress test", "[statement][cache][stress]") {
|
||||
// Some events should be generated
|
||||
int accessed = 0;
|
||||
while (auto e = observer.poll()) {
|
||||
if (e->type == statement_cache_event::Type::Accessed) accessed++;
|
||||
if (e->is<statement_accessed_event>()) accessed++;
|
||||
}
|
||||
REQUIRE(accessed > 0);
|
||||
}
|
||||
@@ -212,12 +231,13 @@ TEST_CASE("Race condition simulation with mixed access", "[statement_cache][race
|
||||
backend_provider::instance().register_backend("noop", std::make_unique<orm::test_backend_service>());
|
||||
|
||||
connection_pool pool("noop://noop.db", 4);
|
||||
statement_cache cache(pool, 5);
|
||||
message_bus bus;
|
||||
statement_cache cache(bus, pool, 5);
|
||||
|
||||
constexpr int threads = 8;
|
||||
constexpr int operations = 500;
|
||||
|
||||
auto task = [&](int id) {
|
||||
auto task = [&](int /*id*/) {
|
||||
for (int i = 0; i < operations; ++i) {
|
||||
auto sql = "SELECT " + std::to_string(i % 10);
|
||||
auto result = cache.acquire({sql});
|
||||
|
||||
Reference in New Issue
Block a user