Example #1
0
 public LockingEngine(
     Func<long> timeProvider,
     ILogger logger,
     IEnumerable<LockingNode> lockingNodes,
     LockId lockId)
 {
     _timeProvider = timeProvider;
     _logger = logger;
     _lockId = lockId;
     _lockingNodes = lockingNodes;
 }
Example #2
0
        async static Task StartAttemptingAcquisition(
            LockingCoordinator lockingCoordinator,
            LockId lockId,
            ILogger logger,
            CancellationTokenSource lockingCancellationSource,
            IObserver<object> observer)
        {
            var holdingLock = false;
            var retryInterval = lockId.CalculateRetryInterval();
            var randomGenerator = new Random(Guid.NewGuid().GetHashCode());

            while (!lockingCancellationSource.IsCancellationRequested && !holdingLock)
            {
                try
                {
                    holdingLock = await lockingCoordinator.TryAcquireLock(lockId).ConfigureAwait(false);

                    if(holdingLock)
                    {
                        logger.ToInfoLog(string.Format("DISTRIBUTED LOCK ACQUIRED for {0}", lockId.Resource));
                    }
                    else
                    {
                        logger.ToDebugLog("Unable to acquire the lock, retrying...");

                        await TaskUtils.SilentlyCanceledDelay(
                            randomGenerator.Next(retryInterval.First(), retryInterval.Second()),
                            lockingCancellationSource.Token)
                        .ConfigureAwait(false);
                    }
                }
                catch (Exception ex)
                {
                    observer.OnError(ex);

                    if(lockingCoordinator != null)
                        await lockingCoordinator
                            .TryReleaseTheLock(lockId)
                            .ConfigureAwait(false);

                    holdingLock = false;
                }
            }
        }
Example #3
0
        public async Task<bool> TryAcquireLock(LockId lockId)
        {
            _logger.ToDebugLog("Trying to acquire the lock...");

            var startTime = _timeProvider();

            var lockAcquired = await TryAcquireLockOnAllNodes(lockId);

            var finishTime = _timeProvider();

            if (lockAcquired 
                && lockId.HasEnoughTimeBeforeExpire(startTime, finishTime)) return lockAcquired;

            if (!lockAcquired)
                _logger.ToDebugLog("Unable to acquire the lock. Releasing all...");
            else
                _logger.ToDebugLog("Lock correctly acquired but the time left to use it is not enough. Releasing all...");

            await TryReleaseTheLock(lockId);

            return false;
        }
Example #4
0
        public Task<bool> TryReleaseTheLock(LockId lockId)
        {
            _logger.ToDebugLog("Releasing the lock...");

            if (_redisClients == null 
                || _redisClients.Count == 0) return false.FromResult();

            return TryInParallelOnAllClients(async cli => await cli.Release(lockId));
        }
Example #5
0
 public Task<bool> TryConfirmTheLock(LockId lockId)
 {
     return TryInParallelOnAllClients(async cli => await cli.Confirm(lockId));
 }
Example #6
0
 async Task<bool> TryAcquireLockOnAllNodes(LockId lockId)
 {
     return 
         _redisClients.Count != 0 
         &&
         await TryInParallelOnAllClients(async cli => await cli.Set(lockId));
 }
Example #7
0
        async Task ReleaseLock(
            LockingCoordinator lockingCoordinator,
            LockId lockId,
            ILogger logger,
            CancellationTokenSource lockingCancellationSource,
            IObserver<object> observer)
        {
            try
            {
                if(!lockingCancellationSource.IsCancellationRequested)
                    lockingCancellationSource.Cancel();

                observer.OnNext(new LockReleaseStarted());

                logger.ToInfoLog(string.Format("Releasing the lock on {0}...", _lockId.Resource));

                if(lockingCoordinator != null)
                    await lockingCoordinator
                        .TryReleaseTheLock(lockId)
                        .ConfigureAwait(false);
                
                logger.ToInfoLog(string.Format("DISTRIBUTED LOCK RELEASED for {0}", _lockId.Resource));

                observer.OnNext(new LockReleased());

                lockingCoordinator.Dispose();
            }
            catch (Exception ex)
            {
                observer.OnError(ex);
            }
        }