Files
Polaris/code/controllers/subsystems/misc_slow.dm
2022-05-08 13:36:52 +01:00

97 lines
3.5 KiB
Plaintext

SUBSYSTEM_DEF(misc_slow)
name = "Misc Slow"
flags = SS_NO_INIT
runlevels = RUNLEVEL_LOBBY | RUNLEVEL_GAME | RUNLEVEL_POSTGAME
wait = 5 MINUTES
/// The number of times dbcon can fail in a row before being considered dead
var/static/const/DB_RECONNECTS_ALLOWED = 3
/// a list of (reconnects succeeded, reconnects failed) for dbcon
var/static/db_status = list(0, 0)
/// A convenience cache of db_status for stat_entry
var/static/db_info = "-"
/// The number of times dbcon_old can fail in a row before being considered dead
var/static/const/DB_OLD_RECONNECTS_ALLOWED = 3
/// a list of (reconnects succeeded, reconnects failed) for dbcon_old
var/static/db_old_status = list(0, 0)
/// A convenience cache of db_old_status for stat_entry
var/static/db_old_info = "-"
/datum/controller/subsystem/misc_slow/VV_static()
return ..() + list(
"DB_RECONNECTS_ALLOWED",
"DB_OLD_RECONNECTS_ALLOWED"
)
/datum/controller/subsystem/misc_slow/Recover()
RecoverDoReconnects()
/datum/controller/subsystem/misc_slow/stat_entry(msg)
..(list(
msg, "sql: [config.sql_enabled ? "Y" : "N"] | DB: [db_info] | DB Old: [db_old_info]"
).Join(null))
/datum/controller/subsystem/misc_slow/fire(resumed, no_mc_tick)
DoReconnects()
/// Clear the state of members related to db connection maintenance
/datum/controller/subsystem/misc_slow/proc/RecoverDoReconnects()
db_status = list(0, 0)
db_info = "-"
db_old_status = list(0, 0)
db_old_info = "-"
/// Run connection maintenance for dbcon and dbcon_old, if sql is enabled correct(ish).
/datum/controller/subsystem/misc_slow/proc/DoReconnects()
if (!config.sql_enabled)
return
if (!sqladdress || !sqlport || !sqllogin || !sqldb || !sqlfdbklogin || !sqlfdbkdb)
log_debug("SS [name]: SQL credentials misconfigured.")
return
var/db_dsn = "dbi:mysql:[sqlfdbkdb]:[sqladdress]:[sqlport]"
ReconnectDB("DB", dbcon, db_dsn, sqlfdbklogin, sqlfdbkpass, db_status, DB_RECONNECTS_ALLOWED)
db_info = "DEAD"
if (db_status[2] < DB_RECONNECTS_ALLOWED)
db_info = "R[db_status[1]],F[db_status[2]]"
var/db_old_dsn = "dbi:mysql:[sqldb]:[sqladdress]:[sqlport]"
ReconnectDB("Old DB", dbcon_old, db_old_dsn, sqllogin, sqlpass, db_old_status, DB_OLD_RECONNECTS_ALLOWED)
db_old_info = "DEAD"
if (db_old_status[2] < DB_OLD_RECONNECTS_ALLOWED)
db_old_info = "R[db_old_status[1]],F[db_old_status[2]]"
/// An ugly proc that attempts to reopen the passed database's connection if it has timed out or been lost.
/datum/controller/subsystem/misc_slow/proc/ReconnectDB(log_name, DBConnection/db, dsn, user, pass, list/status, limit)
if (status[2] >= limit) // We've failed too many times.
return
if (!isnull(db._db_con))
if (_dm_db_is_connected(db._db_con))
var/query = _dm_db_new_query() // Do a little dance to keep the connection interested.
if (_dm_db_execute(query, "SELECT 1;", db._db_con, null, null))
return
log_debug("SS [name]: [log_name] reconnecting.")
_dm_db_close(dbcon._db_con)
dbcon._db_con = null
var/connection = _dm_db_new_con()
var/success = _dm_db_connect(connection, dsn, user, pass, null, null)
if (success)
log_debug("SS [name]: [log_name] reconnected ([++status[1]]\th time).")
db._db_con = connection
status[2] = 0
return
log_debug("SS [name]: [log_name] reconnect failed ([++status[2]]\th time).")
if (status[1] < limit)
return
log_debug("SS [name]: [log_name] reconnect failed too many times. No more attempts will be made.")