feat: upgrade to .NET 6, refactor everything
This commit is contained in:
@@ -1,17 +1,13 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PluralKit.Core
|
||||
namespace PluralKit.Core;
|
||||
|
||||
public interface IPKCommand: IDbCommand, IAsyncDisposable
|
||||
{
|
||||
public interface IPKCommand: IDbCommand, IAsyncDisposable
|
||||
{
|
||||
public Task PrepareAsync(CancellationToken ct = default);
|
||||
public Task<int> ExecuteNonQueryAsync(CancellationToken ct = default);
|
||||
public Task<object?> ExecuteScalarAsync(CancellationToken ct = default);
|
||||
public Task<DbDataReader> ExecuteReaderAsync(CancellationToken ct = default);
|
||||
public Task<DbDataReader> ExecuteReaderAsync(CommandBehavior behavior, CancellationToken ct = default);
|
||||
}
|
||||
public Task PrepareAsync(CancellationToken ct = default);
|
||||
public Task<int> ExecuteNonQueryAsync(CancellationToken ct = default);
|
||||
public Task<object?> ExecuteScalarAsync(CancellationToken ct = default);
|
||||
public Task<DbDataReader> ExecuteReaderAsync(CancellationToken ct = default);
|
||||
public Task<DbDataReader> ExecuteReaderAsync(CommandBehavior behavior, CancellationToken ct = default);
|
||||
}
|
@@ -1,31 +1,29 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Npgsql;
|
||||
|
||||
namespace PluralKit.Core
|
||||
namespace PluralKit.Core;
|
||||
|
||||
public interface IPKConnection: IDbConnection, IAsyncDisposable
|
||||
{
|
||||
public interface IPKConnection: IDbConnection, IAsyncDisposable
|
||||
{
|
||||
public Guid ConnectionId { get; }
|
||||
public Guid ConnectionId { get; }
|
||||
|
||||
public Task OpenAsync(CancellationToken cancellationToken = default);
|
||||
public Task CloseAsync();
|
||||
public Task OpenAsync(CancellationToken cancellationToken = default);
|
||||
public Task CloseAsync();
|
||||
|
||||
public Task ChangeDatabaseAsync(string databaseName, CancellationToken ct = default);
|
||||
public Task ChangeDatabaseAsync(string databaseName, CancellationToken ct = default);
|
||||
|
||||
public ValueTask<IPKTransaction> BeginTransactionAsync(CancellationToken ct = default) => BeginTransactionAsync(IsolationLevel.Unspecified, ct);
|
||||
public ValueTask<IPKTransaction> BeginTransactionAsync(IsolationLevel level, CancellationToken ct = default);
|
||||
public ValueTask<IPKTransaction> BeginTransactionAsync(CancellationToken ct = default) =>
|
||||
BeginTransactionAsync(IsolationLevel.Unspecified, ct);
|
||||
|
||||
public NpgsqlBinaryImporter BeginBinaryImport(string copyFromCommand);
|
||||
public NpgsqlBinaryExporter BeginBinaryExport(string copyToCommand);
|
||||
public ValueTask<IPKTransaction> BeginTransactionAsync(IsolationLevel level, CancellationToken ct = default);
|
||||
|
||||
[Obsolete] new void Open();
|
||||
[Obsolete] new void Close();
|
||||
public NpgsqlBinaryImporter BeginBinaryImport(string copyFromCommand);
|
||||
public NpgsqlBinaryExporter BeginBinaryExport(string copyToCommand);
|
||||
|
||||
[Obsolete] new IDbTransaction BeginTransaction();
|
||||
[Obsolete] new IDbTransaction BeginTransaction(IsolationLevel il);
|
||||
}
|
||||
[Obsolete] new void Open();
|
||||
[Obsolete] new void Close();
|
||||
|
||||
[Obsolete] new IDbTransaction BeginTransaction();
|
||||
[Obsolete] new IDbTransaction BeginTransaction(IsolationLevel il);
|
||||
}
|
@@ -1,13 +1,9 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PluralKit.Core
|
||||
namespace PluralKit.Core;
|
||||
|
||||
public interface IPKTransaction: IDbTransaction, IAsyncDisposable
|
||||
{
|
||||
public interface IPKTransaction: IDbTransaction, IAsyncDisposable
|
||||
{
|
||||
public Task CommitAsync(CancellationToken ct = default);
|
||||
public Task RollbackAsync(CancellationToken ct = default);
|
||||
}
|
||||
public Task CommitAsync(CancellationToken ct = default);
|
||||
public Task RollbackAsync(CancellationToken ct = default);
|
||||
}
|
@@ -1,10 +1,7 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using App.Metrics;
|
||||
|
||||
@@ -14,113 +11,125 @@ using Npgsql;
|
||||
|
||||
using Serilog;
|
||||
|
||||
namespace PluralKit.Core
|
||||
namespace PluralKit.Core;
|
||||
|
||||
internal class PKCommand: DbCommand, IPKCommand
|
||||
{
|
||||
internal class PKCommand: DbCommand, IPKCommand
|
||||
private readonly ILogger _logger;
|
||||
private readonly IMetrics _metrics;
|
||||
|
||||
private readonly PKConnection _ourConnection;
|
||||
|
||||
public PKCommand(NpgsqlCommand inner, PKConnection ourConnection, ILogger logger, IMetrics metrics)
|
||||
{
|
||||
private NpgsqlCommand Inner { get; }
|
||||
|
||||
private readonly PKConnection _ourConnection;
|
||||
private readonly ILogger _logger;
|
||||
private readonly IMetrics _metrics;
|
||||
|
||||
public PKCommand(NpgsqlCommand inner, PKConnection ourConnection, ILogger logger, IMetrics metrics)
|
||||
{
|
||||
Inner = inner;
|
||||
_ourConnection = ourConnection;
|
||||
_logger = logger.ForContext<PKCommand>();
|
||||
_metrics = metrics;
|
||||
}
|
||||
|
||||
public override Task<int> ExecuteNonQueryAsync(CancellationToken ct) => LogQuery(Inner.ExecuteNonQueryAsync(ct));
|
||||
public override Task<object?> ExecuteScalarAsync(CancellationToken ct) => LogQuery(Inner.ExecuteScalarAsync(ct));
|
||||
protected override async Task<DbDataReader> ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken ct) => await LogQuery(Inner.ExecuteReaderAsync(behavior, ct));
|
||||
|
||||
public override Task PrepareAsync(CancellationToken ct = default) => Inner.PrepareAsync(ct);
|
||||
public override void Cancel() => Inner.Cancel();
|
||||
protected override DbParameter CreateDbParameter() => Inner.CreateParameter();
|
||||
|
||||
[AllowNull]
|
||||
public override string CommandText
|
||||
{
|
||||
get => Inner.CommandText;
|
||||
set => Inner.CommandText = value;
|
||||
}
|
||||
|
||||
public override int CommandTimeout
|
||||
{
|
||||
get => Inner.CommandTimeout;
|
||||
set => Inner.CommandTimeout = value;
|
||||
}
|
||||
|
||||
public override CommandType CommandType
|
||||
{
|
||||
get => Inner.CommandType;
|
||||
set => Inner.CommandType = value;
|
||||
}
|
||||
|
||||
public override UpdateRowSource UpdatedRowSource
|
||||
{
|
||||
get => Inner.UpdatedRowSource;
|
||||
set => Inner.UpdatedRowSource = value;
|
||||
}
|
||||
|
||||
protected override DbParameterCollection DbParameterCollection => Inner.Parameters;
|
||||
protected override DbTransaction? DbTransaction
|
||||
{
|
||||
get => Inner.Transaction;
|
||||
set => Inner.Transaction = value switch
|
||||
{
|
||||
NpgsqlTransaction npg => npg,
|
||||
PKTransaction pk => pk.Inner,
|
||||
_ => throw new ArgumentException($"Can't convert input type {value?.GetType()} to NpgsqlTransaction")
|
||||
};
|
||||
}
|
||||
|
||||
public override bool DesignTimeVisible
|
||||
{
|
||||
get => Inner.DesignTimeVisible;
|
||||
set => Inner.DesignTimeVisible = value;
|
||||
}
|
||||
|
||||
protected override DbConnection? DbConnection
|
||||
{
|
||||
get => Inner.Connection;
|
||||
set =>
|
||||
Inner.Connection = value switch
|
||||
{
|
||||
NpgsqlConnection npg => npg,
|
||||
PKConnection pk => pk.Inner,
|
||||
_ => throw new ArgumentException($"Can't convert input type {value?.GetType()} to NpgsqlConnection")
|
||||
};
|
||||
}
|
||||
|
||||
public override int ExecuteNonQuery() => throw SyncError(nameof(ExecuteNonQuery));
|
||||
public override object ExecuteScalar() => throw SyncError(nameof(ExecuteScalar));
|
||||
protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior) => throw SyncError(nameof(ExecuteDbDataReader));
|
||||
public override void Prepare() => throw SyncError(nameof(Prepare));
|
||||
|
||||
private async Task<T> LogQuery<T>(Task<T> task)
|
||||
{
|
||||
var start = SystemClock.Instance.GetCurrentInstant();
|
||||
try
|
||||
{
|
||||
return await task;
|
||||
}
|
||||
finally
|
||||
{
|
||||
var end = SystemClock.Instance.GetCurrentInstant();
|
||||
var elapsed = end - start;
|
||||
|
||||
_logger.Verbose("Executed query {Query} in {ElapsedTime} on connection {ConnectionId}", CommandText, elapsed, _ourConnection.ConnectionId);
|
||||
|
||||
// One "BCL compatible tick" is 100 nanoseconds
|
||||
var micros = elapsed.BclCompatibleTicks / 10;
|
||||
_metrics.Provider.Timer.Instance(CoreMetrics.DatabaseQuery, new MetricTags("query", CommandText))
|
||||
.Record(micros, TimeUnit.Microseconds, CommandText);
|
||||
}
|
||||
}
|
||||
|
||||
private static Exception SyncError(string caller) => throw new Exception($"Executed synchronous IDbCommand function {caller}!");
|
||||
Inner = inner;
|
||||
_ourConnection = ourConnection;
|
||||
_logger = logger.ForContext<PKCommand>();
|
||||
_metrics = metrics;
|
||||
}
|
||||
|
||||
private NpgsqlCommand Inner { get; }
|
||||
|
||||
protected override DbParameterCollection DbParameterCollection => Inner.Parameters;
|
||||
|
||||
protected override DbTransaction? DbTransaction
|
||||
{
|
||||
get => Inner.Transaction;
|
||||
set => Inner.Transaction = value switch
|
||||
{
|
||||
NpgsqlTransaction npg => npg,
|
||||
PKTransaction pk => pk.Inner,
|
||||
_ => throw new ArgumentException($"Can't convert input type {value?.GetType()} to NpgsqlTransaction")
|
||||
};
|
||||
}
|
||||
|
||||
public override bool DesignTimeVisible
|
||||
{
|
||||
get => Inner.DesignTimeVisible;
|
||||
set => Inner.DesignTimeVisible = value;
|
||||
}
|
||||
|
||||
protected override DbConnection? DbConnection
|
||||
{
|
||||
get => Inner.Connection;
|
||||
set =>
|
||||
Inner.Connection = value switch
|
||||
{
|
||||
NpgsqlConnection npg => npg,
|
||||
PKConnection pk => pk.Inner,
|
||||
_ => throw new ArgumentException($"Can't convert input type {value?.GetType()} to NpgsqlConnection")
|
||||
};
|
||||
}
|
||||
|
||||
public override Task<int> ExecuteNonQueryAsync(CancellationToken ct) =>
|
||||
LogQuery(Inner.ExecuteNonQueryAsync(ct));
|
||||
|
||||
public override Task<object?> ExecuteScalarAsync(CancellationToken ct) =>
|
||||
LogQuery(Inner.ExecuteScalarAsync(ct));
|
||||
|
||||
public override Task PrepareAsync(CancellationToken ct = default) => Inner.PrepareAsync(ct);
|
||||
public override void Cancel() => Inner.Cancel();
|
||||
|
||||
[AllowNull]
|
||||
public override string CommandText
|
||||
{
|
||||
get => Inner.CommandText;
|
||||
set => Inner.CommandText = value;
|
||||
}
|
||||
|
||||
public override int CommandTimeout
|
||||
{
|
||||
get => Inner.CommandTimeout;
|
||||
set => Inner.CommandTimeout = value;
|
||||
}
|
||||
|
||||
public override CommandType CommandType
|
||||
{
|
||||
get => Inner.CommandType;
|
||||
set => Inner.CommandType = value;
|
||||
}
|
||||
|
||||
public override UpdateRowSource UpdatedRowSource
|
||||
{
|
||||
get => Inner.UpdatedRowSource;
|
||||
set => Inner.UpdatedRowSource = value;
|
||||
}
|
||||
|
||||
public override int ExecuteNonQuery() => throw SyncError(nameof(ExecuteNonQuery));
|
||||
public override object ExecuteScalar() => throw SyncError(nameof(ExecuteScalar));
|
||||
public override void Prepare() => throw SyncError(nameof(Prepare));
|
||||
|
||||
protected override async Task<DbDataReader>
|
||||
ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken ct) =>
|
||||
await LogQuery(Inner.ExecuteReaderAsync(behavior, ct));
|
||||
|
||||
protected override DbParameter CreateDbParameter() => Inner.CreateParameter();
|
||||
|
||||
protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior) =>
|
||||
throw SyncError(nameof(ExecuteDbDataReader));
|
||||
|
||||
private async Task<T> LogQuery<T>(Task<T> task)
|
||||
{
|
||||
var start = SystemClock.Instance.GetCurrentInstant();
|
||||
try
|
||||
{
|
||||
return await task;
|
||||
}
|
||||
finally
|
||||
{
|
||||
var end = SystemClock.Instance.GetCurrentInstant();
|
||||
var elapsed = end - start;
|
||||
|
||||
_logger.Verbose("Executed query {Query} in {ElapsedTime} on connection {ConnectionId}", CommandText,
|
||||
elapsed, _ourConnection.ConnectionId);
|
||||
|
||||
// One "BCL compatible tick" is 100 nanoseconds
|
||||
var micros = elapsed.BclCompatibleTicks / 10;
|
||||
_metrics.Provider.Timer.Instance(CoreMetrics.DatabaseQuery, new MetricTags("query", CommandText))
|
||||
.Record(micros, TimeUnit.Microseconds, CommandText);
|
||||
}
|
||||
}
|
||||
|
||||
private static Exception SyncError(string caller) =>
|
||||
throw new Exception($"Executed synchronous IDbCommand function {caller}!");
|
||||
}
|
@@ -1,10 +1,7 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using App.Metrics;
|
||||
|
||||
@@ -14,102 +11,120 @@ using Npgsql;
|
||||
|
||||
using Serilog;
|
||||
|
||||
namespace PluralKit.Core
|
||||
namespace PluralKit.Core;
|
||||
|
||||
internal class PKConnection: DbConnection, IPKConnection
|
||||
{
|
||||
internal class PKConnection: DbConnection, IPKConnection
|
||||
private readonly DbConnectionCountHolder _countHolder;
|
||||
private readonly ILogger _logger;
|
||||
private readonly IMetrics _metrics;
|
||||
private bool _hasClosed;
|
||||
|
||||
private bool _hasOpened;
|
||||
private Instant _openTime;
|
||||
|
||||
public PKConnection(NpgsqlConnection inner, DbConnectionCountHolder countHolder, ILogger logger,
|
||||
IMetrics metrics)
|
||||
{
|
||||
public NpgsqlConnection Inner { get; }
|
||||
public Guid ConnectionId { get; }
|
||||
|
||||
private readonly DbConnectionCountHolder _countHolder;
|
||||
private readonly ILogger _logger;
|
||||
private readonly IMetrics _metrics;
|
||||
|
||||
private bool _hasOpened;
|
||||
private bool _hasClosed;
|
||||
private Instant _openTime;
|
||||
|
||||
public PKConnection(NpgsqlConnection inner, DbConnectionCountHolder countHolder, ILogger logger, IMetrics metrics)
|
||||
{
|
||||
Inner = inner;
|
||||
ConnectionId = Guid.NewGuid();
|
||||
_countHolder = countHolder;
|
||||
_logger = logger.ForContext<PKConnection>();
|
||||
_metrics = metrics;
|
||||
}
|
||||
|
||||
public override Task OpenAsync(CancellationToken ct)
|
||||
{
|
||||
if (_hasOpened) return Inner.OpenAsync(ct);
|
||||
_countHolder.Increment();
|
||||
_hasOpened = true;
|
||||
_openTime = SystemClock.Instance.GetCurrentInstant();
|
||||
_logger.Verbose("Opened database connection {ConnectionId}, new connection count {ConnectionCount}", ConnectionId, _countHolder.ConnectionCount);
|
||||
return Inner.OpenAsync(ct);
|
||||
}
|
||||
|
||||
public override Task CloseAsync() => Inner.CloseAsync();
|
||||
|
||||
protected override DbCommand CreateDbCommand() => new PKCommand(Inner.CreateCommand(), this, _logger, _metrics);
|
||||
|
||||
public void ReloadTypes() => Inner.ReloadTypes();
|
||||
|
||||
public new async ValueTask<IPKTransaction> BeginTransactionAsync(IsolationLevel level, CancellationToken ct = default) => new PKTransaction(await Inner.BeginTransactionAsync(level, ct));
|
||||
|
||||
public NpgsqlBinaryImporter BeginBinaryImport(string copyFromCommand) => Inner.BeginBinaryImport(copyFromCommand);
|
||||
public NpgsqlBinaryExporter BeginBinaryExport(string copyToCommand) => Inner.BeginBinaryExport(copyToCommand);
|
||||
|
||||
public override void ChangeDatabase(string databaseName) => Inner.ChangeDatabase(databaseName);
|
||||
public override Task ChangeDatabaseAsync(string databaseName, CancellationToken ct = default) => Inner.ChangeDatabaseAsync(databaseName, ct);
|
||||
protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel) => throw SyncError(nameof(BeginDbTransaction));
|
||||
protected override async ValueTask<DbTransaction> BeginDbTransactionAsync(IsolationLevel level, CancellationToken ct) => new PKTransaction(await Inner.BeginTransactionAsync(level, ct));
|
||||
|
||||
public override void Open() => throw SyncError(nameof(Open));
|
||||
public override void Close()
|
||||
{
|
||||
// Don't throw SyncError here, Dapper calls sync Close() internally so that sucks
|
||||
Inner.Close();
|
||||
}
|
||||
|
||||
IDbTransaction IPKConnection.BeginTransaction() => throw SyncError(nameof(BeginTransaction));
|
||||
IDbTransaction IPKConnection.BeginTransaction(IsolationLevel level) => throw SyncError(nameof(BeginTransaction));
|
||||
|
||||
[AllowNull]
|
||||
public override string ConnectionString
|
||||
{
|
||||
get => Inner.ConnectionString;
|
||||
set => Inner.ConnectionString = value;
|
||||
}
|
||||
|
||||
public override string Database => Inner.Database!;
|
||||
public override ConnectionState State => Inner.State;
|
||||
public override string DataSource => Inner.DataSource;
|
||||
public override string ServerVersion => Inner.ServerVersion;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
Inner.Dispose();
|
||||
if (_hasClosed) return;
|
||||
|
||||
LogClose();
|
||||
}
|
||||
|
||||
public override ValueTask DisposeAsync()
|
||||
{
|
||||
if (_hasClosed) return Inner.DisposeAsync();
|
||||
LogClose();
|
||||
return Inner.DisposeAsync();
|
||||
}
|
||||
|
||||
private void LogClose()
|
||||
{
|
||||
_countHolder.Decrement();
|
||||
_hasClosed = true;
|
||||
|
||||
var duration = SystemClock.Instance.GetCurrentInstant() - _openTime;
|
||||
_logger.Verbose("Closed database connection {ConnectionId} (open for {ConnectionDuration}), new connection count {ConnectionCount}", ConnectionId, duration, _countHolder.ConnectionCount);
|
||||
}
|
||||
|
||||
private static Exception SyncError(string caller) => throw new Exception($"Executed synchronous IDbCommand function {caller}!");
|
||||
Inner = inner;
|
||||
ConnectionId = Guid.NewGuid();
|
||||
_countHolder = countHolder;
|
||||
_logger = logger.ForContext<PKConnection>();
|
||||
_metrics = metrics;
|
||||
}
|
||||
|
||||
public NpgsqlConnection Inner { get; }
|
||||
public override string DataSource => Inner.DataSource;
|
||||
public override string ServerVersion => Inner.ServerVersion;
|
||||
public Guid ConnectionId { get; }
|
||||
|
||||
public override Task OpenAsync(CancellationToken ct)
|
||||
{
|
||||
if (_hasOpened) return Inner.OpenAsync(ct);
|
||||
_countHolder.Increment();
|
||||
_hasOpened = true;
|
||||
_openTime = SystemClock.Instance.GetCurrentInstant();
|
||||
_logger.Verbose("Opened database connection {ConnectionId}, new connection count {ConnectionCount}",
|
||||
ConnectionId, _countHolder.ConnectionCount);
|
||||
return Inner.OpenAsync(ct);
|
||||
}
|
||||
|
||||
public override Task CloseAsync() => Inner.CloseAsync();
|
||||
|
||||
public new async ValueTask<IPKTransaction>
|
||||
BeginTransactionAsync(IsolationLevel level, CancellationToken ct = default) =>
|
||||
new PKTransaction(await Inner.BeginTransactionAsync(level, ct));
|
||||
|
||||
public NpgsqlBinaryImporter BeginBinaryImport(string copyFromCommand) =>
|
||||
Inner.BeginBinaryImport(copyFromCommand);
|
||||
|
||||
public NpgsqlBinaryExporter BeginBinaryExport(string copyToCommand) => Inner.BeginBinaryExport(copyToCommand);
|
||||
|
||||
public override void ChangeDatabase(string databaseName) => Inner.ChangeDatabase(databaseName);
|
||||
|
||||
public override Task ChangeDatabaseAsync(string databaseName, CancellationToken ct = default) =>
|
||||
Inner.ChangeDatabaseAsync(databaseName, ct);
|
||||
|
||||
public override void Open() => throw SyncError(nameof(Open));
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
// Don't throw SyncError here, Dapper calls sync Close() internally so that sucks
|
||||
Inner.Close();
|
||||
}
|
||||
|
||||
IDbTransaction IPKConnection.BeginTransaction() => throw SyncError(nameof(BeginTransaction));
|
||||
|
||||
IDbTransaction IPKConnection.BeginTransaction(IsolationLevel level) =>
|
||||
throw SyncError(nameof(BeginTransaction));
|
||||
|
||||
[AllowNull]
|
||||
public override string ConnectionString
|
||||
{
|
||||
get => Inner.ConnectionString;
|
||||
set => Inner.ConnectionString = value;
|
||||
}
|
||||
|
||||
public override string Database => Inner.Database!;
|
||||
public override ConnectionState State => Inner.State;
|
||||
|
||||
public override ValueTask DisposeAsync()
|
||||
{
|
||||
if (_hasClosed) return Inner.DisposeAsync();
|
||||
LogClose();
|
||||
return Inner.DisposeAsync();
|
||||
}
|
||||
|
||||
protected override DbCommand CreateDbCommand() => new PKCommand(Inner.CreateCommand(), this, _logger, _metrics);
|
||||
|
||||
public void ReloadTypes() => Inner.ReloadTypes();
|
||||
|
||||
protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel) =>
|
||||
throw SyncError(nameof(BeginDbTransaction));
|
||||
|
||||
protected override async ValueTask<DbTransaction>
|
||||
BeginDbTransactionAsync(IsolationLevel level, CancellationToken ct) =>
|
||||
new PKTransaction(await Inner.BeginTransactionAsync(level, ct));
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
Inner.Dispose();
|
||||
if (_hasClosed) return;
|
||||
|
||||
LogClose();
|
||||
}
|
||||
|
||||
private void LogClose()
|
||||
{
|
||||
_countHolder.Decrement();
|
||||
_hasClosed = true;
|
||||
|
||||
var duration = SystemClock.Instance.GetCurrentInstant() - _openTime;
|
||||
_logger.Verbose(
|
||||
"Closed database connection {ConnectionId} (open for {ConnectionDuration}), new connection count {ConnectionCount}",
|
||||
ConnectionId, duration, _countHolder.ConnectionCount);
|
||||
}
|
||||
|
||||
private static Exception SyncError(string caller) =>
|
||||
throw new Exception($"Executed synchronous IDbCommand function {caller}!");
|
||||
}
|
@@ -1,31 +1,28 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Npgsql;
|
||||
|
||||
namespace PluralKit.Core
|
||||
namespace PluralKit.Core;
|
||||
|
||||
internal class PKTransaction: DbTransaction, IPKTransaction
|
||||
{
|
||||
internal class PKTransaction: DbTransaction, IPKTransaction
|
||||
public PKTransaction(NpgsqlTransaction inner)
|
||||
{
|
||||
public NpgsqlTransaction Inner { get; }
|
||||
|
||||
public PKTransaction(NpgsqlTransaction inner)
|
||||
{
|
||||
Inner = inner;
|
||||
}
|
||||
|
||||
public override void Commit() => throw SyncError(nameof(Commit));
|
||||
public override Task CommitAsync(CancellationToken ct = default) => Inner.CommitAsync(ct);
|
||||
|
||||
public override void Rollback() => throw SyncError(nameof(Rollback));
|
||||
public override Task RollbackAsync(CancellationToken ct = default) => Inner.RollbackAsync(ct);
|
||||
|
||||
protected override DbConnection DbConnection => Inner.Connection;
|
||||
public override IsolationLevel IsolationLevel => Inner.IsolationLevel;
|
||||
|
||||
private static Exception SyncError(string caller) => throw new Exception($"Executed synchronous IDbTransaction function {caller}!");
|
||||
Inner = inner;
|
||||
}
|
||||
|
||||
public NpgsqlTransaction Inner { get; }
|
||||
|
||||
protected override DbConnection DbConnection => Inner.Connection;
|
||||
|
||||
public override void Commit() => throw SyncError(nameof(Commit));
|
||||
public override Task CommitAsync(CancellationToken ct = default) => Inner.CommitAsync(ct);
|
||||
|
||||
public override void Rollback() => throw SyncError(nameof(Rollback));
|
||||
public override Task RollbackAsync(CancellationToken ct = default) => Inner.RollbackAsync(ct);
|
||||
public override IsolationLevel IsolationLevel => Inner.IsolationLevel;
|
||||
|
||||
private static Exception SyncError(string caller) =>
|
||||
throw new Exception($"Executed synchronous IDbTransaction function {caller}!");
|
||||
}
|
Reference in New Issue
Block a user