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)); }