Retire idle persistent MySQL connections
This commit is contained in:
+56
-9
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user