extended statement_cache with message bus events

This commit is contained in:
2025-08-10 22:12:13 +02:00
parent 60cef7e938
commit 4f017ac1de
4 changed files with 87 additions and 62 deletions
+22 -21
View File
@@ -16,14 +16,25 @@ public:
std::chrono::milliseconds max_wait{250};
};
struct execution_metrics {
std::chrono::steady_clock::time_point lock_attempt_start;
std::chrono::steady_clock::time_point lock_acquired{};
std::chrono::steady_clock::time_point execution_start{};
std::chrono::steady_clock::time_point execution_end{};
size_t lock_attempts{0};
};
explicit statement_cache_proxy(std::unique_ptr<statement_impl>&& stmt, connection_pool &pool, const size_t connection_id)
: statement_proxy(std::move(stmt))
, pool_(pool)
, connection_id_(connection_id) {}
utils::result<size_t, utils::error> execute(interface::parameter_binder& bindings) override {
auto result = try_with_retry([this, &bindings]() -> utils::result<size_t, utils::error> {
execution_metrics metrics{std::chrono::steady_clock::now()};
auto result = try_with_retry([this, &bindings, &metrics]() -> utils::result<size_t, utils::error> {
if (!try_lock()) {
++metrics.lock_attempts;
return utils::failure(utils::error{
error_code::STATEMENT_LOCKED,
"Failed to execute statement because it is already in use"
@@ -45,8 +56,11 @@ public:
}
utils::result<std::unique_ptr<query_result_impl>, utils::error> fetch(interface::parameter_binder& bindings) override {
auto result = try_with_retry([this, &bindings]() -> utils::result<std::unique_ptr<query_result_impl>, utils::error> {
execution_metrics metrics{std::chrono::steady_clock::now()};
auto result = try_with_retry([this, &bindings, &metrics]() -> utils::result<std::unique_ptr<query_result_impl>, utils::error> {
if (!try_lock()) {
++metrics.lock_attempts;
return utils::failure(utils::error{
error_code::STATEMENT_LOCKED,
"Failed to execute statement because it is already in use"
@@ -114,10 +128,11 @@ private:
};
}
statement_cache::statement_cache(connection_pool &pool, const size_t max_size)
statement_cache::statement_cache(utils::message_bus &bus, connection_pool &pool, const size_t max_size)
: max_size_(max_size)
, pool_(pool)
, dialect_(backend_provider::instance().connection_dialect(pool_.info().type)) {}
, dialect_(backend_provider::instance().connection_dialect(pool_.info().type))
, bus_(bus) {}
utils::result<statement, utils::error> statement_cache::acquire(const query_context& ctx) {
std::unique_lock lock(mutex_);
@@ -128,7 +143,7 @@ utils::result<statement, utils::error> statement_cache::acquire(const query_cont
if (const auto it = cache_map_.find(key); it != cache_map_.end()) {
usage_list_.splice(usage_list_.begin(), usage_list_, it->second.position);
it->second.last_access = now;
push(statement_cache_event::Type::Accessed, ctx.sql);
bus_.publish<statement_accessed_event>({ctx.sql, std::chrono::steady_clock::now()});
return utils::ok(it->second.stmt);
}
// Prepare a new statement
@@ -149,7 +164,7 @@ utils::result<statement, utils::error> statement_cache::acquire(const query_cont
const auto& key_to_remove = usage_list_.back();
cache_map_.erase(key_to_remove);
usage_list_.pop_back();
push(statement_cache_event::Type::Evicted, ctx.sql);
bus_.publish<statement_evicted_event>({ctx.sql, std::chrono::steady_clock::now()});
}
usage_list_.push_front(key);
@@ -160,7 +175,7 @@ utils::result<statement, utils::error> statement_cache::acquire(const query_cont
std::chrono::steady_clock::now(),
usage_list_.begin()}
}).first;
push(statement_cache_event::Type::Added, ctx.sql);
bus_.publish<statement_added_event>({ctx.sql, std::chrono::steady_clock::now()});
return utils::ok(it->second.stmt);
}
@@ -176,18 +191,4 @@ bool statement_cache::empty() const {
return cache_map_.empty();
}
void statement_cache::subscribe(statement_cache_observer_interface &observer) {
observers_.push_back(&observer);
}
void statement_cache::push(statement_cache_event::Type type, const std::string &sql) const {
using Clock = std::chrono::steady_clock;
const auto ts = Clock::now();
const statement_cache_event evt{type, sql, ts};
for (auto& obs : observers_) {
if (obs) {
obs->on_event(evt);
}
}
}
}