public async Task UpdateAtomicAsync(Func <Task <TDocument> > updateAsync, Func <TDocument, Task> afterUpdateAsync = null)
        {
            if (_isDistributed)
            {
                try
                {
                    _ = await _distributedCache.GetStringAsync(_options.CacheIdKey);
                }
                catch
                {
                    await DocumentStore.CancelAsync();

                    throw new InvalidOperationException($"Can't update the '{typeof(TDocument).Name}' if not able to access the distributed cache");
                }
            }

            var delegates = ShellScope.GetOrCreateFeature <UpdateDelegates>();

            if (delegates.UpdateDelegateAsync == null ||
                !delegates.UpdateDelegateAsync.GetInvocationList().Contains(updateAsync))
            {
                delegates.UpdateDelegateAsync += () => updateAsync();
            }

            if (afterUpdateAsync != null &&
                (delegates.AfterUpdateDelegateAsync == null ||
                 !delegates.AfterUpdateDelegateAsync.GetInvocationList().Contains(afterUpdateAsync)))
            {
                delegates.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 delegates.UpdateDelegateAsync.GetInvocationList())
                {
                    document = await((UpdateDelegate)d)();
                }

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

                await SetInternalAsync(document);

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