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; }
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; }
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); }
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); }
/// <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); }
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; }
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; }
public ColidLockBuilder WithInstanceSummary(RedLockInstanceSummary instanceSummary) { _lock.InstanceSummary = instanceSummary; return(this); }