chore: update to .net 8

This commit is contained in:
alyssa 2024-12-23 00:51:58 +00:00
parent 9716922ab5
commit 2d564535af
26 changed files with 1453 additions and 4487 deletions

View file

@ -24,8 +24,9 @@ internal partial class Database: IDatabase
private readonly IMetrics _metrics;
private readonly DbConnectionCountHolder _countHolder;
private readonly DatabaseMigrator _migrator;
private readonly string _connectionString;
private readonly string _messagesConnectionString;
private readonly NpgsqlDataSource _dataSource;
private readonly NpgsqlDataSource _dataSourceMessages;
public Database(CoreConfig config, DbConnectionCountHolder countHolder, ILogger logger,
IMetrics metrics, DatabaseMigrator migrator)
@ -54,14 +55,31 @@ internal partial class Database: IDatabase
return builder.ConnectionString;
}
_connectionString = connectionString(_config.Database);
_messagesConnectionString = connectionString(_config.MessagesDatabase ?? _config.Database);
NpgsqlDataSource createDataSource(string connectionString)
{
var dataSourceBuilder = new NpgsqlDataSourceBuilder(connectionString);
dataSourceBuilder.UseNodaTime();
// Register our custom types to Npgsql
// Without these it'll still *work* but break at the first launch + probably cause other small issues
dataSourceBuilder.MapComposite<ProxyTag>("proxy_tag");
dataSourceBuilder.MapEnum<PrivacyLevel>("privacy_level");
return dataSourceBuilder.Build();
}
_dataSource = createDataSource(connectionString(_config.Database));
_dataSourceMessages = createDataSource(connectionString(_config.MessagesDatabase ?? _config.Database));
}
private static readonly PostgresCompiler _compiler = new();
public static void InitStatic()
{
// map postgres `timestamp` to NodaTime.Instant instead of NodaTime.LocalDateTime
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
DefaultTypeMap.MatchNamesWithUnderscores = true;
// Dapper by default tries to pass ulongs to Npgsql, which rejects them since PostgreSQL technically
@ -71,8 +89,7 @@ internal partial class Database: IDatabase
SqlMapper.AddTypeHandler(new UlongEncodeAsLongHandler());
SqlMapper.AddTypeHandler(new UlongArrayHandler());
NpgsqlConnection.GlobalTypeMapper.UseNodaTime();
// With the thing we add above, Npgsql already handles NodaTime integration
// With the thing we add above (in `createDataSource`), Npgsql already handles NodaTime integration
// This makes Dapper confused since it thinks it has to convert it anyway and doesn't understand the types
// So we add a custom type handler that literally just passes the type through to Npgsql
SqlMapper.AddTypeHandler(new PassthroughTypeHandler<Instant>());
@ -89,11 +106,6 @@ internal partial class Database: IDatabase
SqlMapper.AddTypeHandler(new NumericIdArrayHandler<SwitchId, int>(i => new SwitchId(i)));
SqlMapper.AddTypeHandler(new NumericIdArrayHandler<GroupId, int>(i => new GroupId(i)));
SqlMapper.AddTypeHandler(new NumericIdArrayHandler<AbuseLogId, int>(i => new AbuseLogId(i)));
// Register our custom types to Npgsql
// Without these it'll still *work* but break at the first launch + probably cause other small issues
NpgsqlConnection.GlobalTypeMapper.MapComposite<ProxyTag>("proxy_tag");
NpgsqlConnection.GlobalTypeMapper.MapEnum<PrivacyLevel>("privacy_level");
}
// TODO: make sure every SQL query is behind a logged query method
@ -104,7 +116,7 @@ internal partial class Database: IDatabase
// Create a connection and open it
// We wrap it in PKConnection for tracing purposes
var conn = new PKConnection(new NpgsqlConnection(messages ? _messagesConnectionString : _connectionString), _countHolder, _logger, _metrics);
var conn = new PKConnection((messages ? _dataSourceMessages : _dataSource).CreateConnection(), _countHolder, _logger, _metrics);
await conn.OpenAsync();
return conn;
}

View file

@ -99,12 +99,12 @@ internal partial class Database: IDatabase
public async Task<T> QuerySingleProcedure<T>(string queryName, object param)
{
using var conn = await Obtain();
return await conn.QueryFirstAsync<T>(queryName, param, commandType: CommandType.StoredProcedure);
return await conn.QueryFirstAsync<T>(queryName, param, commandType: CommandType.Text);
}
public async Task<IEnumerable<T>> QueryProcedure<T>(string queryName, object param)
{
using var conn = await Obtain();
return await conn.QueryAsync<T>(queryName, param, commandType: CommandType.StoredProcedure);
return await conn.QueryAsync<T>(queryName, param);
}
}

View file

@ -9,31 +9,33 @@ namespace PluralKit.Core;
/// </summary>
public class MessageContext
{
public SystemId? SystemId { get; }
public bool AllowAutoproxy { get; }
public SystemId? SystemId { get; }
public string? SystemTag { get; }
public string? SystemAvatar { get; }
public int? LatchTimeout { get; }
public bool CaseSensitiveProxyTags { get; }
public bool ProxyErrorMessageEnabled { get; }
public SystemConfig.ProxySwitchAction ProxySwitch { get; }
public string? NameFormat { get; }
public bool TagEnabled { get; }
public bool ProxyEnabled { get; }
public string? SystemGuildTag { get; }
public string? SystemGuildAvatar { get; }
public string? GuildNameFormat { get; }
public SwitchId? LastSwitch { get; }
public MemberId[] LastSwitchMembers { get; } = new MemberId[0];
public Instant? LastSwitchTimestamp { get; }
/// <summary>
/// Whether a system is being deleted (no actions should be taken, or commands ran)
/// </summary>
public ulong? LogChannel { get; }
public bool InBlacklist { get; }
public bool InLogBlacklist { get; }
public bool LogCleanupEnabled { get; }
public bool RequireSystemTag { get; }
public bool ProxyEnabled { get; }
public SwitchId? LastSwitch { get; }
public MemberId[] LastSwitchMembers { get; } = new MemberId[0];
public Instant? LastSwitchTimestamp { get; }
public string? SystemTag { get; }
public string? SystemGuildTag { get; }
public bool TagEnabled { get; }
public string? NameFormat { get; }
public string? GuildNameFormat { get; }
public string? SystemAvatar { get; }
public string? SystemGuildAvatar { get; }
public bool AllowAutoproxy { get; }
public int? LatchTimeout { get; }
public bool CaseSensitiveProxyTags { get; }
public bool ProxyErrorMessageEnabled { get; }
public SystemConfig.ProxySwitchAction ProxySwitch { get; }
public bool DenyBotUsage { get; }
}

View file

@ -28,9 +28,10 @@ public class ProxyMember
public string? WebhookAvatar { get; }
public string? Avatar { get; }
public bool AllowAutoproxy { get; }
public string? Color { get; }
public bool AllowAutoproxy { get; }
// If not set, this formatting will be applied to the proxy name
public static string DefaultFormat = "{name} {tag}";

View file

@ -3,9 +3,9 @@ namespace PluralKit.Core;
public partial class ModelRepository
{
public Task<MessageContext> GetMessageContext(ulong account, ulong guild, ulong channel, ulong thread)
=> _db.QuerySingleProcedure<MessageContext>("message_context",
new { account_id = account, guild_id = guild, channel_id = channel, thread_id = thread });
=> _db.QuerySingleProcedure<MessageContext>("select * from message_context(@account, @guild, @channel, @thread)",
new { account, guild, channel, thread });
public Task<IEnumerable<ProxyMember>> GetProxyMembers(ulong account, ulong guild)
=> _db.QueryProcedure<ProxyMember>("proxy_members", new { account_id = account, guild_id = guild });
=> _db.QueryProcedure<ProxyMember>("select * from proxy_members(@account, @guild)", new { account, guild });
}