Removed public access to database config
Database connection is now acquired directly via Configuration instead of an object within it.
This commit is contained in:
parent
e9a4e3e726
commit
0401bfce2d
3 changed files with 64 additions and 35 deletions
|
@ -1,56 +1,43 @@
|
|||
using Newtonsoft.Json.Linq;
|
||||
using Npgsql;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Noikoio.RegexBot.ConfigItem
|
||||
{
|
||||
class DatabaseConfig
|
||||
{
|
||||
private readonly bool _enabled;
|
||||
private readonly string _host;
|
||||
private readonly string _user;
|
||||
private readonly string _pass;
|
||||
private readonly string _dbname;
|
||||
private readonly string _parsemsg;
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether database storage is available.
|
||||
/// </summary>
|
||||
public bool Available => _enabled;
|
||||
/// <summary>
|
||||
/// Constructor error message (only if not enabled)
|
||||
/// </summary>
|
||||
public string ParseMsg => _parsemsg;
|
||||
|
||||
public DatabaseConfig(JToken ctok)
|
||||
{
|
||||
if (ctok == null || ctok.Type != JTokenType.Object)
|
||||
{
|
||||
_enabled = false;
|
||||
_parsemsg = "Database configuration not defined.";
|
||||
return;
|
||||
throw new DatabaseConfigLoadException("");
|
||||
}
|
||||
var conf = (JObject)ctok;
|
||||
|
||||
_host = conf["hostname"]?.Value<string>() ?? "localhost"; // default to localhost
|
||||
|
||||
_user = conf["username"]?.Value<string>();
|
||||
if (string.IsNullOrWhiteSpace(_user))
|
||||
throw new DatabaseConfigLoadException("Value for username is not defined.");
|
||||
|
||||
_pass = conf["password"]?.Value<string>();
|
||||
if (string.IsNullOrWhiteSpace(_pass))
|
||||
throw new DatabaseConfigLoadException(
|
||||
$"Value for password is not defined. {nameof(RegexBot)} only supports password authentication.");
|
||||
|
||||
_dbname = conf["database"]?.Value<string>();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(_user) || string.IsNullOrWhiteSpace(_pass) || string.IsNullOrWhiteSpace(_dbname))
|
||||
{
|
||||
_parsemsg = "One or more required values are invalid or not defined.";
|
||||
_enabled = false;
|
||||
}
|
||||
|
||||
_parsemsg = null;
|
||||
_enabled = true;
|
||||
if (string.IsNullOrWhiteSpace(_dbname))
|
||||
throw new DatabaseConfigLoadException("Value for database name is not defined.");
|
||||
}
|
||||
|
||||
public async Task<NpgsqlConnection> GetOpenConnectionAsync()
|
||||
internal async Task<NpgsqlConnection> GetOpenConnectionAsync()
|
||||
{
|
||||
if (!Available) return null;
|
||||
|
||||
var cs = new NpgsqlConnectionStringBuilder()
|
||||
{
|
||||
Host = _host,
|
||||
|
@ -63,5 +50,10 @@ namespace Noikoio.RegexBot.ConfigItem
|
|||
await db.OpenAsync();
|
||||
return db;
|
||||
}
|
||||
|
||||
internal class DatabaseConfigLoadException : Exception
|
||||
{
|
||||
public DatabaseConfigLoadException(string message) : base(message) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ namespace Noikoio.RegexBot
|
|||
|
||||
public string BotUserToken => _botToken;
|
||||
public string CurrentGame => _currentGame;
|
||||
public DatabaseConfig Database => _dbConfig;
|
||||
|
||||
public ServerConfig[] Servers => _servers;
|
||||
|
||||
|
@ -72,22 +71,44 @@ namespace Noikoio.RegexBot
|
|||
/// <summary>
|
||||
/// Loads essential, unchanging values needed for bot startup. Returns false on failure.
|
||||
/// </summary>
|
||||
public bool LoadInitialConfig()
|
||||
internal bool LoadInitialConfig()
|
||||
{
|
||||
var lt = LoadFile();
|
||||
lt.Wait();
|
||||
JObject conf = lt.Result;
|
||||
if (conf == null) return false;
|
||||
|
||||
var log = Logger.GetLogger(LogPrefix);
|
||||
|
||||
_botToken = conf["bot-token"]?.Value<string>();
|
||||
if (String.IsNullOrWhiteSpace(_botToken))
|
||||
{
|
||||
Logger.GetLogger(LogPrefix)("Error: Bot token not defined. Cannot continue.").Wait();
|
||||
log("Error: Bot token not defined. Cannot continue.").Wait();
|
||||
return false;
|
||||
}
|
||||
_currentGame = conf["playing"]?.Value<string>();
|
||||
|
||||
_dbConfig = new DatabaseConfig(conf["database"]);
|
||||
// Database configuration:
|
||||
// Either it exists or it doesn't. Read config, but also attempt to make a database connection
|
||||
// right here, or else make it known that database support is disabled for this instance.
|
||||
try
|
||||
{
|
||||
_dbConfig = new DatabaseConfig(conf["database"]);
|
||||
var conn = _dbConfig.GetOpenConnectionAsync().GetAwaiter().GetResult();
|
||||
conn.Dispose();
|
||||
}
|
||||
catch (DatabaseConfig.DatabaseConfigLoadException ex)
|
||||
{
|
||||
if (ex.Message == "") log("Database configuration not found.").Wait();
|
||||
else log("Error within database config: " + ex.Message).Wait();
|
||||
_dbConfig = null;
|
||||
}
|
||||
catch (Npgsql.NpgsqlException ex)
|
||||
{
|
||||
log("An error occurred while establishing initial database connection: " + ex.Message).Wait();
|
||||
_dbConfig = null;
|
||||
}
|
||||
// Modules that will not enable due to lack of database access should say so in their constructors.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -179,7 +200,23 @@ namespace Noikoio.RegexBot
|
|||
_servers = newservers.ToArray();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value stating if database access is available.
|
||||
/// Specifically, indicates if <see cref="GetOpenDatabaseConnectionAsync"/> will return a non-null value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Ideally, this value remains constant on runtime. It does not take into account
|
||||
/// the possibility of the database connection failing during the program's run time.
|
||||
/// </remarks>
|
||||
public bool DatabaseAvailable => _dbConfig != null;
|
||||
/// <summary>
|
||||
/// Gets an opened connection to the SQL database, if available.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// An <see cref="Npgsql.NpgsqlConnection"/> in the opened state,
|
||||
/// or null if an SQL database is not available.
|
||||
/// </returns>
|
||||
public Task<Npgsql.NpgsqlConnection> GetOpenDatabaseConnectionAsync() => _dbConfig?.GetOpenConnectionAsync();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ namespace Noikoio.RegexBot.EntityCache
|
|||
if (lresult != null) return lresult;
|
||||
|
||||
// Database cache search
|
||||
var db = await RegexBot.Config.Database.GetOpenConnectionAsync();
|
||||
var db = await RegexBot.Config.GetOpenDatabaseConnectionAsync();
|
||||
if (db == null) return null; // Database not available for query.
|
||||
using (db) return await DbQueryAsync(db, guild, user);
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ namespace Noikoio.RegexBot.EntityCache
|
|||
if (lresult.Count() != 0) return lresult;
|
||||
|
||||
// Database cache search
|
||||
var db = await RegexBot.Config.Database.GetOpenConnectionAsync();
|
||||
var db = await RegexBot.Config.GetOpenDatabaseConnectionAsync();
|
||||
if (db == null) return null; // Database not available for query.
|
||||
using (db) return await DbQueryAsync(db, guild, name, disc);
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ namespace Noikoio.RegexBot.EntityCache
|
|||
{
|
||||
var result = new List<CacheUser>();
|
||||
|
||||
using (db = await RegexBot.Config.Database.GetOpenConnectionAsync())
|
||||
using (db = await RegexBot.Config.GetOpenDatabaseConnectionAsync())
|
||||
{
|
||||
using (var c = db.CreateCommand())
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue