Ejemplo n.º 1
0
        private Task[] CreateWaitTasks(string resource, int count, IDistributedLockMutex mutex)
        {
            var tasks = new Task[count];

            for (int i = 0; i < count; i++)
            {
                tasks[i] = Task.Factory.StartNew(() =>
                {
                    mutex.Wait(resource, TimeSpan.FromSeconds(2));
                }, TaskCreationOptions.LongRunning);
            }

            do
            {
                // wait until all tasks are running
                Thread.Sleep(100);
            } while (tasks.Any(t => t.Status != TaskStatus.Running));

            return(tasks);
        }
Ejemplo n.º 2
0
        private void Acquire(TimeSpan timeout)
        {
            try
            {
                // If result is null, then it means we acquired the lock
                var isLockAcquired  = false;
                var now             = DateTime.UtcNow;
                var lockTimeoutTime = now.Add(timeout);
                while (!isLockAcquired && (lockTimeoutTime >= now))
                {
                    // Acquire the lock if it does not exist - Notice: ReturnDocument.Before
                    var filter = Builders <DistributedLockDto> .Filter.Eq(_ => _.Resource, _resource);

                    var update = Builders <DistributedLockDto> .Update.SetOnInsert(_ => _.ExpireAt, DateTime.UtcNow.Add(_storageOptions.DistributedLockLifetime));

                    var options = new FindOneAndUpdateOptions <DistributedLockDto>
                    {
                        IsUpsert       = true,
                        ReturnDocument = ReturnDocument.Before
                    };

                    try
                    {
                        var result = _locks.FindOneAndUpdate(filter, update, options);

                        // If result is null, it means we acquired the lock
                        if (result == null)
                        {
                            if (Logger.IsTraceEnabled())
                            {
                                Logger.Trace($"{_resource} - Acquired");
                            }
                            isLockAcquired = true;
                        }
                        else
                        {
                            now = _mutex.Wait(_resource, CalculateTimeout(timeout));
                        }
                    }
                    catch (MongoCommandException)
                    {
                        // this can occur if two processes attempt to acquire a lock on the same resource simultaneously.
                        // unfortunately there doesn't appear to be a more specific exception type to catch.
                        now = _mutex.Wait(_resource, CalculateTimeout(timeout));
                    }
                }

                if (!isLockAcquired)
                {
                    throw new DistributedLockTimeoutException($"{_resource} - Could not place a lock: The lock request timed out.");
                }
            }
            catch (DistributedLockTimeoutException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new MongoDistributedLockException($"{_resource} - Could not place a lock", ex);
            }
        }