Example #1
0
        private void Acquire(TimeSpan timeout)
        {
            var isLockAcquired = false;

            try
            {
                var now             = DateTime.Now;
                var lockTimeoutTime = now.Add(timeout);

                while (!isLockAcquired && (lockTimeoutTime >= now))
                {
                    isLockAcquired = Acquire();
                    if (!isLockAcquired)
                    {
                        _signal.Wait($@"{nameof(MongoDistributedLock)}.{_resource}", timeout);
                        now = DateTime.Now;
                    }
                }
            }
            catch (OperationCanceledException)
            {
                // The signal wait timed out
            }
            catch (Exception ex)
            {
                throw new MongoDistributedLockException($"Could not place a lock on the resource \'{_resource}\': Check inner exception for details.", ex);
            }

            if (!isLockAcquired)
            {
                throw new DistributedLockTimeoutException(
                          $"Could not place a lock on the resource \'{_resource}\': The lock request timed out.");
            }
        }
Example #2
0
        public IFetchedJob Dequeue(string[] queues, CancellationToken cancellationToken)
        {
            if (queues == null)
            {
                throw new ArgumentNullException(nameof(queues));
            }

            if (queues.Length == 0)
            {
                throw new ArgumentException("Queue array must be non-empty.", nameof(queues));
            }


            var filter          = Builders <JobQueueDto> .Filter;
            var fetchConditions = new[]
            {
                filter.Eq(_ => _.FetchedAt, null),
                filter.Lt(_ => _.FetchedAt, DateTime.UtcNow.AddSeconds(_storageOptions.InvisibilityTimeout.Negate().TotalSeconds))
            };
            var fetchConditionsIndex = 0;

            var options = new FindOneAndUpdateOptions <JobQueueDto>
            {
                IsUpsert       = false,
                ReturnDocument = ReturnDocument.After
            };

            JobQueueDto fetchedJob = null;

            while (fetchedJob == null)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var fetchCondition = fetchConditions[fetchConditionsIndex];

                foreach (var queue in queues)
                {
                    fetchedJob = _database.JobQueue.FindOneAndUpdate(
                        fetchCondition & filter.Eq(_ => _.Queue, queue),
                        Builders <JobQueueDto> .Update.Set(_ => _.FetchedAt, DateTime.UtcNow),
                        options,
                        cancellationToken);
                    if (fetchedJob != null)
                    {
                        break;
                    }
                }

                if (fetchedJob == null)
                {
                    // No more jobs found in any of the requested queues...
                    if (fetchConditionsIndex == fetchConditions.Length - 1)
                    {
                        // ...and we are out of fetch conditions as well.
                        // Wait for a while before polling again.
                        var waitNames = queues.Select(q => $@"JobQueue.{q}");
                        _signal.Wait(waitNames.ToArray(), cancellationToken);
                    }
                }

                // Move on to next fetch condition
                fetchConditionsIndex = (fetchConditionsIndex + 1) % fetchConditions.Length;
            }

            return(new MongoFetchedJob(_database, fetchedJob.Id, fetchedJob.JobId, fetchedJob.Queue));
        }