using Medallion.Threading.Internal;
using Medallion.Threading.Internal.Data;
using System.Data;
#if NET7_0_OR_GREATER
using System.Data.Common;
#endif
namespace Medallion.Threading.Postgres;
///
/// Implements a distributed lock using Postgres advisory locks
/// (see https://www.postgresql.org/docs/12/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS)
///
public sealed partial class PostgresDistributedReaderWriterLock : IInternalDistributedReaderWriterLock
{
private readonly IDbDistributedLock _internalLock;
///
/// Constructs a lock with the given (effectively the lock name), ,
/// and
///
public PostgresDistributedReaderWriterLock(PostgresAdvisoryLockKey key, string connectionString, Action? options = null)
: this(key, PostgresDistributedLock.CreateInternalLock(key, connectionString, options))
{
}
///
/// Constructs a lock with the given (effectively the lock name) and .
///
public PostgresDistributedReaderWriterLock(PostgresAdvisoryLockKey key, IDbConnection connection)
: this(key, PostgresDistributedLock.CreateInternalLock(key, connection))
{
}
#if NET7_0_OR_GREATER
///
/// Constructs a lock with the given (effectively the lock name) and ,
/// and .
///
/// Not compatible with connection multiplexing.
///
public PostgresDistributedReaderWriterLock(PostgresAdvisoryLockKey key, DbDataSource dbDataSource, Action? options = null)
: this(key, PostgresDistributedLock.CreateInternalLock(key, dbDataSource, options))
{
}
#endif
private PostgresDistributedReaderWriterLock(PostgresAdvisoryLockKey key, IDbDistributedLock internalLock)
{
this.Key = key;
this._internalLock = internalLock;
}
///
/// The that uniquely identifies the lock on the database
///
public PostgresAdvisoryLockKey Key { get; }
string IDistributedReaderWriterLock.Name => this.Key.ToString();
ValueTask IInternalDistributedReaderWriterLock.InternalTryAcquireAsync(
TimeoutValue timeout,
CancellationToken cancellationToken,
bool isWrite) =>
this._internalLock.TryAcquireAsync(timeout, isWrite ? PostgresAdvisoryLock.ExclusiveLock : PostgresAdvisoryLock.SharedLock, cancellationToken, contextHandle: null)
.Wrap(h => new PostgresDistributedReaderWriterLockHandle(h));
}