Retire idle persistent MySQL connections

This commit is contained in:
root
2026-07-20 13:00:29 +00:00
parent 4d68377704
commit 80eaf0b69b
9 changed files with 182 additions and 11 deletions
+56 -9
View File
@@ -153,6 +153,7 @@ struct WasmWorkerConfig
u64 epoch_period_ms = 50;
u64 invocation_timeout_ms = 30000;
u64 mysql_persistent_pool_size = 8;
u64 mysql_persistent_pool_idle_timeout_seconds = 300;
bool profile_hostcall_cpu = false;
bool profile_thread_runtime = false;
bool verbose = false;
@@ -1271,6 +1272,14 @@ static bool wasm_read_metadata_file(const String& path, std::vector<u8>& metadat
class WasmWorkspace;
#ifdef UCE_WASM_HOST_CONNECTORS
struct WasmMySQLPersistentConnection
{
MySQL* db = 0;
std::chrono::steady_clock::time_point idle_since;
};
#endif
class WasmWorker
{
public:
@@ -1283,25 +1292,59 @@ public:
#ifdef UCE_WASM_HOST_CONNECTORS
~WasmWorker()
{
for(auto* db : mysql_persistent_pool)
delete db;
for(auto& entry : mysql_persistent_pool)
delete entry.db;
}
void mysql_evict_idle(std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now())
{
if(cfg.mysql_persistent_pool_idle_timeout_seconds == 0)
return;
auto timeout = std::chrono::seconds(cfg.mysql_persistent_pool_idle_timeout_seconds);
for(size_t i = 0; i < mysql_persistent_pool.size();)
{
auto& entry = mysql_persistent_pool[i];
if(entry.idle_since != std::chrono::steady_clock::time_point() && now - entry.idle_since >= timeout)
{
delete entry.db;
mysql_persistent_pool.erase(mysql_persistent_pool.begin() + i);
continue;
}
i++;
}
}
void mysql_release(MySQL* db)
{
if(!db)
return;
db->request_leases = 0;
for(auto& entry : mysql_persistent_pool)
if(entry.db == db)
{
entry.idle_since = std::chrono::steady_clock::now();
return;
}
}
MySQL* mysql_checkout(const String& host, const String& username, const String& password, const String& database, bool& reused, bool& persistent)
{
mysql_evict_idle();
reused = false;
persistent = false;
for(size_t i = 0; i < mysql_persistent_pool.size(); i++)
{
MySQL* db = mysql_persistent_pool[i];
MySQL* db = mysql_persistent_pool[i].db;
if(!db || !db->connection || db->request_host != host || db->request_username != username || db->request_password != password || db->request_database != database)
continue;
if(db->reset_connection())
{
mysql_persistent_pool[i].idle_since = std::chrono::steady_clock::time_point();
if(i + 1 < mysql_persistent_pool.size())
{
auto entry = mysql_persistent_pool[i];
mysql_persistent_pool.erase(mysql_persistent_pool.begin() + i);
mysql_persistent_pool.push_back(db);
mysql_persistent_pool.push_back(entry);
}
reused = true;
persistent = true;
@@ -1326,15 +1369,17 @@ public:
{
while(mysql_persistent_pool.size() >= cfg.mysql_persistent_pool_size)
{
delete mysql_persistent_pool.front();
delete mysql_persistent_pool.front().db;
mysql_persistent_pool.erase(mysql_persistent_pool.begin());
}
mysql_persistent_pool.push_back(db);
WasmMySQLPersistentConnection entry;
entry.db = db;
mysql_persistent_pool.push_back(entry);
}
return(db);
}
std::vector<MySQL*> mysql_persistent_pool;
std::vector<WasmMySQLPersistentConnection> mysql_persistent_pool;
#endif
String init()
@@ -1931,8 +1976,7 @@ public:
if(db)
delete db; // ~SQLite disconnects
for(auto* db : mysql_request_pool)
if(db)
db->request_leases = 0;
worker.mysql_release(db);
for(auto* db : mysql_request_owned)
if(db)
delete db; // ~MySQL disconnects
@@ -4597,6 +4641,9 @@ inline WasmResponse wasm_worker_serve(WasmWorker& worker, const Request& request
WasmResponse response;
f64 serve_started = time_precise();
auto workspace_start = std::chrono::steady_clock::now();
#ifdef UCE_WASM_HOST_CONNECTORS
worker.mysql_evict_idle(workspace_start);
#endif
f64 cpu_started = wasm_thread_cpu_time();
struct rusage thread_runtime_start = {};
bool thread_runtime_profiled = worker.cfg.profile_thread_runtime && getrusage(RUSAGE_THREAD, &thread_runtime_start) == 0;