public async Task <TaskAggregate> UpdateTaskAsync(TaskModel updatingTask, IEnumerable <string> usersIds,
                                                          IEnumerable <string> labelsIds)
        {
            TaskAggregate currentTask = await _tasksRepository.GetTaskAsync(updatingTask.Id);

            if (currentTask == null)
            {
                throw new NotFoundException($"Task with id = {updatingTask.Id} not found");
            }

            if (currentTask.Version != updatingTask.Version)
            {
                throw new VersionsNotMatchException();
            }

            TaskRelatedData taskData = await GetAndCheckTaskRelatedDataAsync(updatingTask, usersIds, labelsIds);

            EnsureProjectNotChanged(currentTask, taskData);

            var(removingCollections, addingCollections) = DetermineAddedAndRemovedItems(currentTask, taskData);
            var list = taskData.List;

            var addedMembersRecords   = _mapper.Map <IEnumerable <UserModel>, IEnumerable <TaskUserRecord> >(addingCollections.Users);
            var removedMembersRecords = _mapper.Map <IEnumerable <UserModel>, IEnumerable <TaskUserRecord> >(removingCollections.Users);
            var addedLabelsRecords    = _mapper.Map <IEnumerable <LabelModel>, IEnumerable <TaskLabelRecord> >(addingCollections.Labels);
            var removedLabelsRecords  = _mapper.Map <IEnumerable <LabelModel>, IEnumerable <TaskLabelRecord> >(removingCollections.Labels);

            var outboxMessage = OutboxMessageModel.Create(
                new TaskUpdatedMessage
            {
                TaskId         = updatingTask.Id,
                Title          = updatingTask.Title,
                ProjectId      = list.ProjectId,
                ProjectTitle   = list.ProjectTitle,
                ListId         = list.Id,
                ListTitle      = list.Title,
                RemovedMembers = removedMembersRecords,
                AddedMembers   = addedMembersRecords,
                RemovedLabels  = removedLabelsRecords,
                AddedLabels    = addedLabelsRecords
            }, Topics.Tasks, MessageActions.Updated);


            return(await _tasksRepository.UpdateTaskAsync(updatingTask, addingCollections.ToTaskCollections(),
                                                          removingCollections.ToTaskCollections(), outboxMessage));
        }
        public async Task <TaskAggregate> UpdateTaskAsync(TaskModel updatingTask, IEnumerable <string> usersIds,
                                                          IEnumerable <string> labelsIds)
        {
            TaskAggregate currentTask = await _tasksRepository.GetTaskAsync(updatingTask.Id);

            if (currentTask == null)
            {
                throw new NotFoundException($"Task with id = {updatingTask.Id} not found");
            }

            if (currentTask.Version != updatingTask.Version)
            {
                throw new VersionsNotMatchException();
            }

            TaskRelatedData taskData = await GetAndCheckTaskRelatedDataAsync(updatingTask, usersIds, labelsIds);

            EnsureProjectNotChanged(currentTask, taskData);

            var(removingCollections, addingCollections) = DetermineAddedAndRemovedItems(currentTask, taskData);
            var list = taskData.List;

            var addedMembersRecords   = _mapper.Map <IEnumerable <UserModel>, IEnumerable <TaskUserRecord> >(addingCollections.Users);
            var removedMembersRecords = _mapper.Map <IEnumerable <UserModel>, IEnumerable <TaskUserRecord> >(removingCollections.Users);
            var addedLabelsRecords    = _mapper.Map <IEnumerable <LabelModel>, IEnumerable <TaskLabelRecord> >(addingCollections.Labels);
            var removedLabelsRecords  = _mapper.Map <IEnumerable <LabelModel>, IEnumerable <TaskLabelRecord> >(removingCollections.Labels);

            var outboxMessage = OutboxMessageModel.Create(
                new TaskUpdatedMessage
            {
                TaskId         = updatingTask.Id,
                Title          = updatingTask.Title,
                ProjectId      = list.ProjectId,
                ProjectTitle   = list.ProjectTitle,
                ListId         = list.Id,
                ListTitle      = list.Title,
                RemovedMembers = removedMembersRecords,
                AddedMembers   = addedMembersRecords,
                RemovedLabels  = removedLabelsRecords,
                AddedLabels    = addedLabelsRecords
            }, Topics.Tasks, MessageActions.Updated);

            updatingTask.Version += 1;

            var updatedTask = await _tasksRepository.UpdateTaskAsync(updatingTask, addingCollections.ToTaskCollections(),
                                                                     removingCollections.ToTaskCollections(), outboxMessage);


            string cacheKey = string.Format(CacheSettings.TaskIdCacheKeyPattern, updatedTask.Id);

            List <Task> cacheInvalidationTasks = new List <Task>();

            cacheInvalidationTasks.Add(_cache.SetCacheValueAsync(cacheKey, updatedTask, CacheSettings.TaskIdCacheLifetime));

            foreach (var user in usersIds)
            {
                string userCacheKey = string.Format(CacheSettings.UserTasksCacheKeyPattern, user);
                cacheInvalidationTasks.Add(_cache.RemoveAsync(userCacheKey));
            }

            foreach (var user in removingCollections.Users)
            {
                string userCacheKey = string.Format(CacheSettings.UserTasksCacheKeyPattern, user.Id);
                cacheInvalidationTasks.Add(_cache.RemoveAsync(userCacheKey));
            }

            await Task.WhenAll(cacheInvalidationTasks);

            return(updatedTask);
        }