Beispiel #1
0
        protected virtual void Dispose(bool disposing)
        {
            logger.LogDebug($"Disposing {Resource} ({LockId})");

            if (isDisposed)
            {
                return;
            }

            if (disposing)
            {
                lock (lockObject)
                {
                    if (lockKeepaliveTimer != null)
                    {
                        lockKeepaliveTimer.Change(Timeout.Infinite, Timeout.Infinite);
                        lockKeepaliveTimer.Dispose();
                        lockKeepaliveTimer = null;
                    }
                }
            }

            Unlock();

            Status          = RedLockStatus.Unlocked;
            InstanceSummary = new RedLockInstanceSummary();

            isDisposed = true;
        }
Beispiel #2
0
 public ColidLock(string resource, string lockId, bool isAcquired, RedLockStatus status, RedLockInstanceSummary instanceSummary, int extendCount, Action <string> disposeAction)
 {
     Resource        = resource;
     LockId          = lockId;
     IsAcquired      = isAcquired;
     Status          = status;
     InstanceSummary = instanceSummary;
     ExtendCount     = extendCount;
     _disposeAction  = disposeAction;
 }
Beispiel #3
0
        private RedLockStatus GetFailedRedLockStatus(RedLockInstanceSummary lockResult)
        {
            if (lockResult.Acquired >= quorum)
            {
                // if we got here with a quorum then validity must have expired
                return(RedLockStatus.Expired);
            }

            if (lockResult.Acquired + lockResult.Conflicted >= quorum)
            {
                // we had enough instances for a quorum, but some were locked with another LockId
                return(RedLockStatus.Conflicted);
            }

            return(RedLockStatus.NoQuorum);
        }
Beispiel #4
0
        private async Task <(RedLockStatus, RedLockInstanceSummary)> AcquireAsync()
        {
            var lockSummary = new RedLockInstanceSummary();

            for (var i = 0; i < quorumRetryCount; i++)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var iteration = i + 1;
                logger.LogDebug($"Lock attempt {iteration}/{quorumRetryCount}: {Resource} ({LockId}), expiry: {expiryTime}");

                var stopwatch = Stopwatch.StartNew();

                lockSummary = await LockAsync().ConfigureAwait(false);

                var validityTicks = GetRemainingValidityTicks(stopwatch);

                logger.LogDebug($"Acquired locks for {Resource} ({LockId}) in {lockSummary.Acquired}/{redisCaches.Count} instances, quorum: {quorum}, validityTicks: {validityTicks}");

                if (lockSummary.Acquired >= quorum && validityTicks > 0)
                {
                    return(RedLockStatus.Acquired, lockSummary);
                }

                // we failed to get enough locks for a quorum, unlock everything and try again
                await UnlockAsync().ConfigureAwait(false);

                // only sleep if we have more retries left
                if (i < quorumRetryCount - 1)
                {
                    var sleepMs = ThreadSafeRandom.Next(quorumRetryDelayMs);

                    logger.LogDebug($"Sleeping {sleepMs}ms");

                    await TaskUtils.Delay(sleepMs, cancellationToken).ConfigureAwait(false);
                }
            }

            var status = GetFailedRedLockStatus(lockSummary);

            // give up
            logger.LogDebug($"Could not acquire quorum after {quorumRetryCount} attempts, giving up: {Resource} ({LockId}). {lockSummary}.");

            return(status, lockSummary);
        }
Beispiel #5
0
        /// <summary>
        /// Creates a colid lock
        /// </summary>
        /// <param name="resource">The resource string to lock on</param>
        /// <returns>colid lock</returns>
        private IRedLock CreateLock(string resource)
        {
            var lockId        = Guid.NewGuid().ToString();
            var acquired      = IsAcquired(resource);
            var redLockStatus = GetRedLockStatus(resource);
            var lockError     = acquired ? 0 : 1;

            var redLockInstanceSummary = new RedLockInstanceSummary(acquired ? 1 : 0, lockError, lockError);

            var colidLock = new ColidLock(resource, lockId, !_locks.ContainsKey(resource), redLockStatus, redLockInstanceSummary, 1, ReleaseLock);

            if (acquired)
            {
                _locks.TryAdd(resource, colidLock);
            }

            return(colidLock);
        }
Beispiel #6
0
        protected virtual async ValueTask DisposeAsync(bool disposing)
        {
            logger.LogDebug($"Disposing {Resource} ({LockId})");

            if (isDisposed)
            {
                return;
            }

            if (disposing)
            {
                StopKeepAliveTimer();
            }

            await UnlockAsync().ConfigureAwait(false);

            Status          = RedLockStatus.Unlocked;
            InstanceSummary = new RedLockInstanceSummary();

            isDisposed = true;
        }
Beispiel #7
0
        protected virtual void Dispose(bool disposing)
        {
            logger.LogDebug($"Disposing {Resource} ({LockId})");

            if (isDisposed)
            {
                return;
            }

            if (disposing)
            {
                StopKeepAliveTimer();
            }

            Unlock();

            Status          = RedLockStatus.Unlocked;
            InstanceSummary = new RedLockInstanceSummary();

            isDisposed = true;
        }
Beispiel #8
0
 public ColidLockBuilder WithInstanceSummary(RedLockInstanceSummary instanceSummary)
 {
     _lock.InstanceSummary = instanceSummary;
     return(this);
 }