refactor(server/db): Move database connection logic to separate class

Implements a DbBuilder class to streamline the creation of database connections for both SQLite and MySQL storage types.

Enhances error handling for database setup and ensures that necessary directories are created dynamically based on configuration settings.

This refactor improves code maintainability and readability, consolidating connection logic into a dedicated builder class.
This commit is contained in:
Sakura Akeno Isayeki 2025-04-21 14:04:07 +02:00
parent 99e37ccba4
commit 0021f9884d
No known key found for this signature in database
GPG key ID: BAB781B71FD2E7E6
2 changed files with 92 additions and 31 deletions

89
TShockAPI/DB/DbBuilder.cs Normal file
View file

@ -0,0 +1,89 @@
using System.Data;
using System.Diagnostics;
using System.IO;
using Microsoft.Data.Sqlite;
using MySql.Data.MySqlClient;
using TerrariaApi.Server;
using TShockAPI.Configuration;
namespace TShockAPI.DB;
/// <summary>
/// Provides logic to build a DB connection.
/// </summary>
public sealed class DbBuilder
{
private readonly TShock _caller;
private readonly TShockConfig _config;
private readonly string _savePath;
/// <summary>
/// Initializes a new instance of the <see cref="DbBuilder"/> class.
/// </summary>
/// <param name="caller">The TShock instance calling this DbBuilder.</param>
/// <param name="config">The TShock configuration, supplied by <see cref="TShock.Config" /> at init.</param>
/// <param name="savePath">The savePath registered by TShock. See <see cref="TShock.SavePath" />.</param>
public DbBuilder(TShock caller, TShockConfig config, string savePath)
{
_caller = caller;
_config = config;
_savePath = savePath;
}
/// <summary>
/// Builds a DB connection based on the provided configuration.
/// </summary>
/// <param name="config">The TShock configuration.</param>
/// <remarks>
/// Default settings will result in a local sqlite database file named "tshock.db" in the current directory to be used as server DB.
/// </remarks>
public IDbConnection BuildDbConnection()
{
string dbType = _config.Settings.StorageType.ToLowerInvariant();
return dbType switch
{
"sqlite" => BuildSqliteConnection(),
"mysql" => BuildMySqlConnection(),
_ => throw new("Invalid storage type")
};
}
private SqliteConnection BuildSqliteConnection()
{
string dbFilePath = Path.Combine(_savePath, _config.Settings.SqliteDBPath);
if (Path.GetDirectoryName(dbFilePath) is not { } dbDirPath)
{
throw new DirectoryNotFoundException($"The SQLite database path '{dbFilePath}' could not be found.");
}
Directory.CreateDirectory(dbDirPath);
return new($"Data Source={dbFilePath}");
}
private MySqlConnection BuildMySqlConnection()
{
try
{
string[] hostport = _config.Settings.MySqlHost.Split(':');
MySqlConnectionStringBuilder connStrBuilder = new()
{
Server = hostport[0],
Port = hostport.Length > 1 ? uint.Parse(hostport[1]) : 3306,
Database = _config.Settings.MySqlDbName,
UserID = _config.Settings.MySqlUsername,
Password = _config.Settings.MySqlPassword
};
return new(connStrBuilder.ToString());
}
catch (MySqlException e)
{
ServerApi.LogWriter.PluginWriteLine(_caller, e.ToString(), TraceLevel.Error);
throw new("MySql not setup correctly", e);
}
}
}

View file

@ -314,37 +314,9 @@ namespace TShockAPI
// Further exceptions are written to TShock's log from now on. // Further exceptions are written to TShock's log from now on.
try try
{ {
if (Config.Settings.StorageType.ToLower() == "sqlite") // Build database
{ DbBuilder dbBuilder = new(this, Config, SavePath);
string sql = Path.Combine(SavePath, Config.Settings.SqliteDBPath); DB = dbBuilder.BuildDbConnection();
Directory.CreateDirectory(Path.GetDirectoryName(sql));
DB = new Microsoft.Data.Sqlite.SqliteConnection(string.Format("Data Source={0}", sql));
}
else if (Config.Settings.StorageType.ToLower() == "mysql")
{
try
{
var hostport = Config.Settings.MySqlHost.Split(':');
DB = new MySqlConnection();
DB.ConnectionString =
String.Format("Server={0}; Port={1}; Database={2}; Uid={3}; Pwd={4};",
hostport[0],
hostport.Length > 1 ? hostport[1] : "3306",
Config.Settings.MySqlDbName,
Config.Settings.MySqlUsername,
Config.Settings.MySqlPassword
);
}
catch (MySqlException ex)
{
ServerApi.LogWriter.PluginWriteLine(this, ex.ToString(), TraceLevel.Error);
throw new Exception("MySql not setup correctly");
}
}
else
{
throw new Exception("Invalid storage type");
}
if (Config.Settings.UseSqlLogs) if (Config.Settings.UseSqlLogs)
Log = new SqlLog(DB, logFilename, LogClear); Log = new SqlLog(DB, logFilename, LogClear);