/// <summary>
        /// Tries to acquire an auto setup lock.
        /// </summary>
        /// <param name="distributedLock">
        /// The distributed lock.
        /// </param>
        /// <param name="lockOptions">
        /// The auto setup lock options.
        /// </param>
        /// <returns>
        /// The <see cref="ILocker"/> and <c>true</c> if successfully acquired.
        /// </returns>
        public static Task <(ILocker locker, bool locked)> TryAcquireAutoSetupLockAsync(this IDistributedLock distributedLock, LockOptions lockOptions)
        {
            TimeSpan timeout, expiration;

            if (distributedLock is ILocalLock)
            {
                // If it is a local lock, don't use any timeout and expiration.
                timeout = expiration = TimeSpan.MaxValue;
            }
            else
            {
                // If it is a distributed lock, use the configured timeout and expiration.
                var lockTimeout = lockOptions?.LockTimeout ?? 0;
                if (lockTimeout <= 0)
                {
                    lockTimeout = 60_000;
                }

                var lockExpiration = lockOptions?.LockExpiration ?? 0;
                if (lockExpiration <= 0)
                {
                    lockExpiration = 60_000;
                }

                timeout    = TimeSpan.FromMilliseconds(lockTimeout);
                expiration = TimeSpan.FromMilliseconds(lockExpiration);
            }

            return(distributedLock.TryAcquireLockAsync("AUTOSETUP_LOCK", timeout, expiration));
        }
Exemple #2
0
        public Task UpdateAtomicAsync(Func <Task <TDocument> > updateAsync)
        {
            if (updateAsync == null)
            {
                return(Task.CompletedTask);
            }

            _updateDelegateAsync += () => updateAsync();

            _documentStore.AfterCommitSuccess <TDocument>(async() =>
            {
                (var locker, var locked) = await _distributedLock.TryAcquireLockAsync(_lockKey, LockTimeout, LockExpiration);
                if (!locked)
                {
                    return;
                }

                await using var acquiredLock = locker;

                TDocument document = null;
                foreach (var d in _updateDelegateAsync.GetInvocationList())
                {
                    document = await((UpdateDelegate)d)();
                }

                document.Identifier ??= IdGenerator.GenerateId();

                await SetInternalAsync(document);
            });

            return(Task.CompletedTask);
        }
        /// <summary>
        /// Tries to acquire a lock on the background task if it is atomic and if the lock service is not a local lock, otherwise returns true with a null locker.
        /// </summary>
        public static Task <(ILocker locker, bool locked)> TryAcquireBackgroundTaskLockAsync(this IDistributedLock distributedLock, BackgroundTaskSettings settings)
        {
            if (distributedLock is ILocalLock || !settings.IsAtomic)
            {
                return(Task.FromResult <(ILocker, bool)>((null, true)));
            }

            return(distributedLock.TryAcquireLockAsync(
                       settings.Name + "_LOCK",
                       TimeSpan.FromMilliseconds(settings.LockTimeout),
                       TimeSpan.FromMilliseconds(settings.LockExpiration)));
        }
        /// <summary>
        /// Tries to acquire a lock before resuming this workflow instance, but only
        /// if it is an atomic workflow, otherwise returns true with a null locker.
        /// </summary>
        public static Task <(ILocker locker, bool locked)> TryAcquireWorkflowLockAsync(
            this IDistributedLock distributedLock,
            Workflow workflow)
        {
            if (workflow.IsAtomic)
            {
                return(distributedLock.TryAcquireLockAsync(
                           "WFI_" + workflow.WorkflowId + "_LOCK",
                           TimeSpan.FromMilliseconds(workflow.LockTimeout),
                           TimeSpan.FromMilliseconds(workflow.LockExpiration)));
            }

            return(Task.FromResult <(ILocker, bool)>((null, true)));
        }
        public Task UpdateAtomicAsync(Func <Task <TDocument> > updateAsync, Func <TDocument, Task> afterUpdateAsync = null)
        {
            if (updateAsync == null)
            {
                return(Task.CompletedTask);
            }

            _updateDelegateAsync += () => updateAsync();

            if (afterUpdateAsync != null)
            {
                _afterUpdateDelegateAsync += document => afterUpdateAsync(document);
            }

            DocumentStore.AfterCommitSuccess <TDocument>(async() =>
            {
                (var locker, var locked) = await _distributedLock.TryAcquireLockAsync(
                    _options.CacheKey + "_LOCK",
                    TimeSpan.FromMilliseconds(_options.LockTimeout),
                    TimeSpan.FromMilliseconds(_options.LockExpiration));

                if (!locked)
                {
                    return;
                }

                await using var acquiredLock = locker;

                TDocument document = null;
                foreach (var d in _updateDelegateAsync.GetInvocationList())
                {
                    document = await((UpdateDelegate)d)();
                }

                document.Identifier ??= IdGenerator.GenerateId();

                await SetInternalAsync(document);

                if (_afterUpdateDelegateAsync != null)
                {
                    foreach (var d in _afterUpdateDelegateAsync.GetInvocationList())
                    {
                        await((AfterUpdateDelegate)d)(document);
                    }
                }
            });

            return(Task.CompletedTask);
        }
Exemple #6
0
        public Task UpdateAtomicAsync(Func <Task <TDocument> > updateAsync, Func <TDocument, Task> afterUpdateAsync = null,
                                      TimeSpan?lockAcquireTimeout = null, TimeSpan?lockExpirationTime = null)
        {
            if (updateAsync == null)
            {
                return(Task.CompletedTask);
            }

            _updateDelegateAsync += () => updateAsync();

            if (afterUpdateAsync != null)
            {
                _afterUpdateDelegateAsync += document => afterUpdateAsync(document);
            }

            _documentStore.AfterCommitSuccess <TDocument>(async() =>
            {
                var timeout    = lockAcquireTimeout ?? DefaultLockTimeout;
                var expiration = lockExpirationTime ?? DefaultLockExpiration;

                (var locker, var locked) = await _distributedLock.TryAcquireLockAsync(_lockKey, timeout, expiration);
                if (!locked)
                {
                    return;
                }

                await using var acquiredLock = locker;

                TDocument document = null;
                foreach (var d in _updateDelegateAsync.GetInvocationList())
                {
                    document = await((UpdateDelegate)d)();
                }

                document.Identifier ??= IdGenerator.GenerateId();

                await SetInternalAsync(document);

                if (_afterUpdateDelegateAsync != null)
                {
                    foreach (var d in _afterUpdateDelegateAsync.GetInvocationList())
                    {
                        await((AfterUpdateDelegate)d)(document);
                    }
                }
            });

            return(Task.CompletedTask);
        }
        /// <summary>
        /// Tries to acquire a lock before starting an instance of this workflow type, if it is
        /// a singleton or if the event is exclusive, otherwise returns true with a null locker.
        /// </summary>
        public static Task <(ILocker locker, bool locked)> TryAcquireWorkflowTypeLockAsync(
            this IDistributedLock distributedLock,
            WorkflowType workflowType,
            bool isExclusiveEvent = false)
        {
            if (workflowType.IsSingleton || isExclusiveEvent)
            {
                return(distributedLock.TryAcquireLockAsync(
                           "WFT_" + workflowType.WorkflowTypeId + "_LOCK",
                           TimeSpan.FromMilliseconds(20_000),
                           TimeSpan.FromMilliseconds(20_000)));
            }

            return(Task.FromResult <(ILocker, bool)>((null, true)));
        }