public async Task <TaskAggregate> UpdateTaskAsync(TaskModel updatingTask, OutboxMessageModel outboxMessage) { string taskId = updatingTask.Id; int version = updatingTask.Version + 1; var updateQuery = $"update {_tableName} set " + $"title = '{updatingTask.Title}', " + $"description = '{updatingTask.Description}', " + $"listid = '{updatingTask.ListId}', " + $"state = {(int)updatingTask.State}, " + $"duedate = {GetQueryNullableEscapedValue(updatingTask.DueDate)} " + $"where id = '{taskId}'; "; string insertOutboxMessageQuery = ConstructInsertMessageQuery(outboxMessage); updateQuery += insertOutboxMessageQuery; int res = await _connection.ExecuteAsync(updateQuery); if (res <= 0) { throw new DatabaseException("Update task failed"); } return(await GetTaskAsync(updatingTask.Id)); }
internal async Task <UserModel> UpdateUserAsync(UserModel updatingUser) { var curentUser = await _repository.GetUserAsync(updatingUser.Id); if (curentUser == null) { throw new NotFoundException($"User with id {updatingUser.Id} not found"); } if (curentUser.Version != updatingUser.Version) { throw new VersionsNotMatchException(); } updatingUser.Version = curentUser.Version + 1; var message = OutboxMessageModel.Create( new UserCreatedUpdatedMessage { UserId = updatingUser.Id, Username = updatingUser.Username }, Topics.Users, MessageActions.Updated ); var updatedUser = await _repository.UpdateUserAsync(updatingUser, message); return(updatedUser); }
public async Task <ProjectModel> CreateProjectAsync(ProjectModel newProject, string requestId) { if (!(await CheckAndSaveRequestIdAsync(requestId))) { throw new AlreadyHandledException(); } try { newProject.Init(); var outboxMessage = OutboxMessageModel.Create( new ProjectCreatedUpdatedMessage { ProjectId = newProject.Id, Title = newProject.Title }, Topics.Projects, MessageActions.Created); return(await _projectsRepository.CreateProjectAsync(newProject, outboxMessage)); } catch (Exception) { //rollback request id await _requestsRepository.DeleteRequestIdAsync(requestId); throw; } }
protected override async Task RollbackTransactionInternalAsync(TransactionBase transaction) { Console.WriteLine("Rollback started"); var moveTransaction = MoveTaskTransaction.CreateFromBase(transaction); if (moveTransaction.MovedMembers.IsNullOrEmpty()) { Console.WriteLine("Nothing to rollback"); return; } string projectId = moveTransaction.ProjectId; var projectMembersById = (await _projectMembersRepository.GetProjectsMembersAsync(projectId: projectId)).ToDictionary(m => m.UserId); foreach (var movedMember in moveTransaction.MovedMembers) { var member = projectMembersById[movedMember]; var outboxMessage = OutboxMessageModel.Create( new ProjectMemberDeletedMessage { Username = member.Username, UserId = member.UserId, ProjectId = projectId, ProjectTitle = member.ProjectTitle }, Topics.ProjectMembers, MessageActions.Deleted); await _projectMembersRepository.DeleteMemberFromProjectAsync(projectId, movedMember, outboxMessage); } Console.WriteLine("Rollback completed"); }
private async Task <string> UpdateHoursWithNewProjectAsync(string messageString) { Console.WriteLine("Prepare hours stage started"); MoveTaskHandleHoursMessage message = JsonConvert.DeserializeObject <MoveTaskHandleHoursMessage>(messageString); string transactionId = message.TransactionId; var transaction = await _transactionsRepository.GetTransactionAsync(transactionId); if (transaction != null && transaction.State == TransactionStates.Denied) { return($"Transaction {transactionId} already denied"); } var moveTaskTransaction = transaction == null ? MoveTaskTransaction.Create(transactionId, message.TaskId, message.ProjectId) : MoveTaskTransaction.CreateFromBase(transaction); moveTaskTransaction.State = TransactionStates.Processing; string projectTitle = "undefined"; string taskId = message.TaskId; var task = await _tasksRepository.GetTaskAsync(taskId); if (task != null) { string projectId = task.ProjectId; var project = await _projectsRepository.GetProjectAsync(projectId); projectTitle = project?.Title; } string postfix = $"(from {projectTitle})"; moveTaskTransaction.AppliedPostfix = postfix; var taskWorkingHours = (await _workingHoursRepository.GetProjectTaskMemberWorkingHoursAsync(taskId: moveTaskTransaction.TaskId)).ToList(); List <string> affectedRecordsIds = new List <string>(); foreach (var workingHoursRecord in taskWorkingHours) { workingHoursRecord.Description += postfix; await _workingHoursRepository.UpdateWorkingHoursRecordAsync(workingHoursRecord); affectedRecordsIds.Add(workingHoursRecord.Id); } moveTaskTransaction.AffectedRecordsIds = affectedRecordsIds; moveTaskTransaction.UpdateData(); var outboxMessage = OutboxMessageModel.Create( new MoveTaskHoursHandledMessage { TransactionId = moveTaskTransaction.Id, }, Topics.WorkingHours, TransactionMessageActions.MoveTask_HandleHoursCompleted); await _transactionsRepository.CreateOrUpdateTransactionAsync(moveTaskTransaction, outboxMessage); return($"Working hours updated successful"); }
private Task HandleMembersMovedAsync(TransactionBase transaction, BaseTransactionMessage message, TransactionsRepository repository) { var membersMovedMesasge = message as MoveTaskMembersMovedMessage; if (transaction == null) { Console.WriteLine($"Transaction for moved task members not found"); return(Task.CompletedTask); } var moveTaskTransaction = MoveTaskTransaction.CreateFromBase(transaction); moveTaskTransaction.AreMembersPrepared = true; moveTaskTransaction.Message = "Handle task hours with new project"; var outboxMessage = OutboxMessageModel.Create( new MoveTaskHandleHoursMessage() { TransactionId = transaction.Id, ProjectId = moveTaskTransaction.ProjectId, TaskId = moveTaskTransaction.ObjectId }, Topics.Tasks, TransactionMessageActions.MoveTask_HandleHoursRequested); return(repository.CreateOrUpdateTransactionAsync(moveTaskTransaction, outboxMessage)); }
public async Task UpdateProjectMebmerRoleAsync(ProjectMemberModel updatingMember) { ProjectMemberModel currentMember = await _projectMembersRepository .GetProjectMemberAsync(updatingMember.ProjectId, updatingMember.UserId); if (currentMember == null) { throw new NotFoundException($"User with id = {updatingMember.UserId} not found in project with id {updatingMember.ProjectId}"); } (string projectTitle, string username) = await EnsureProjectAndUserExistAsync(updatingMember.ProjectId, updatingMember.UserId); var outboxMessage = OutboxMessageModel.Create( new ProjectMemberCreatedUpdatedMessage { ProjectId = updatingMember.ProjectId, ProjectTitle = projectTitle, UserId = updatingMember.UserId, Username = username, Role = updatingMember.Role }, Topics.ProjectMembers, MessageActions.Updated ); await _projectMembersRepository.UpdateProjectMemberAsync(updatingMember, outboxMessage); }
public async Task <LabelModel> UpdateLabelAsync(LabelModel updatingLabel) { LabelModel currentLabel = await _labelsRepository.GetLabelByIdAsync(updatingLabel.Id); if (currentLabel == null) { throw new NotFoundException($"Label with id = {updatingLabel.Id} not found"); } if (currentLabel.Version != updatingLabel.Version) { throw new VersionsNotMatchException(); } var outboxMessage = OutboxMessageModel.Create( new LabelCreatedUpdatedMessage { LabelId = updatingLabel.Id, OldTitle = currentLabel.Title, Title = updatingLabel.Title, Color = updatingLabel.Color }, Topics.Labels, MessageActions.Updated); return(await _labelsRepository.UpdateLabelAsync(updatingLabel, outboxMessage)); }
public async Task <LabelModel> CreateLabelAsync(LabelModel newLabel, string requestId) { if (!(await CheckAndSaveRequestIdAsync(requestId))) { throw new AlreadyHandledException(); } try { newLabel.Init(); var outboxMessage = OutboxMessageModel.Create( new LabelCreatedUpdatedMessage { LabelId = newLabel.Id, Title = newLabel.Title, Color = newLabel.Color }, Topics.Labels, MessageActions.Created); return(await _labelsRepository.CreateLabelAsync(newLabel, outboxMessage)); } catch (Exception) { //rollback request id await _requestsRepository.DeleteRequestIdAsync(requestId); throw; } }
public async Task <TaskAggregate> CreateTaskAsync(TaskModel newTask, IEnumerable <string> usersIds, IEnumerable <string> labelsIds, string requestId) { if (!(await CheckAndSaveRequestIdAsync(requestId))) { throw new AlreadyHandledException(); } try { newTask.Init(); TaskRelatedData taskData = await GetAndCheckTaskRelatedDataAsync(newTask, usersIds, labelsIds); var list = taskData.List; var taskCollections = new TaskCollections { Members = usersIds, Labels = labelsIds }; var membersRecords = _mapper.Map <IEnumerable <UserModel>, IEnumerable <TaskUserRecord> >(taskData.Users); var labelsRecords = _mapper.Map <IEnumerable <LabelModel>, IEnumerable <TaskLabelRecord> >(taskData.Labels); var outboxMessage = OutboxMessageModel.Create( new TaskCreatedMessage { TaskId = newTask.Id, Title = newTask.Title, ProjectId = list.ProjectId, ProjectTitle = list.ProjectTitle, ListId = list.Id, ListTitle = list.Title, Members = membersRecords, Labels = labelsRecords }, Topics.Tasks, MessageActions.Created); var createdTask = await _tasksRepository.CreateTaskAsync(newTask, taskCollections, outboxMessage); List <Task> cacheInvalidationTasks = new List <Task>(); foreach (var user in usersIds) { string userCacheKey = string.Format(CacheSettings.UserTasksCacheKeyPattern, user); cacheInvalidationTasks.Add(_cache.RemoveAsync(userCacheKey)); } await Task.WhenAll(cacheInvalidationTasks); return(createdTask); } catch (Exception) { //rollback request id await _requestsRepository.DeleteRequestIdAsync(requestId); throw; } }
public Task DeleteMemberFromProjectAsync(string projectId, string userId, OutboxMessageModel outboxMessage) { string deleteQuery = $"delete from {_tableName} where userid = '{userId}' and projectId = '{projectId}';"; string insertOutboxMessageQuery = ConstructInsertMessageQuery(outboxMessage); deleteQuery += insertOutboxMessageQuery; return(_connection.ExecuteAsync(deleteQuery)); }
private async Task HandleListPreparedAsync(TransactionBase transaction, BaseTransactionMessage message, TransactionsRepository repository, TasksRepository tasksRepository) { var listPreparedMessage = message as MoveTaskListPreparedMessage; if (transaction == null) { Console.WriteLine($"Transaction for prepared list {listPreparedMessage.ListId} not found"); return; } var moveTaskTransaction = MoveTaskTransaction.CreateFromBase(transaction); string newListId = listPreparedMessage.ListId; moveTaskTransaction.ListId = newListId; moveTaskTransaction.IsListPrepared = true; moveTaskTransaction.UpdateData(); string taskId = moveTaskTransaction.ObjectId; IEnumerable <string> taskMembersIds = await tasksRepository.GetTaskMembersIdsAsync(taskId); OutboxMessageModel nextMessage = default(OutboxMessageModel); if (!taskMembersIds.IsNullOrEmpty()) { var task = await tasksRepository.GetTaskAsync(taskId); moveTaskTransaction.Message = "Move members to project"; nextMessage = OutboxMessageModel.Create( new MoveTaskMoveMembersMessage() { TransactionId = transaction.Id, TargetProjectId = moveTaskTransaction.ProjectId, SourceProjectId = task.ProjectId, TaskMembers = taskMembersIds }, Topics.Tasks, TransactionMessageActions.MoveTask_MoveMembersRequested); } else { moveTaskTransaction.AreMembersPrepared = true; moveTaskTransaction.Message = "Handle task hours with new project"; nextMessage = OutboxMessageModel.Create( new MoveTaskHandleHoursMessage() { TransactionId = transaction.Id, ProjectId = moveTaskTransaction.ProjectId, TaskId = taskId }, Topics.Tasks, TransactionMessageActions.MoveTask_HandleHoursRequested); } await repository.CreateOrUpdateTransactionAsync(moveTaskTransaction, nextMessage); }
public async Task <UserModel> UpdateUserAsync(UserModel updatingUser, OutboxMessageModel message) { string userId = updatingUser.Id; var currentUser = await GetUserAsync(userId); if (currentUser == null) { throw new NotFoundException($"User with id {userId} not found"); } if (currentUser.Region == updatingUser.Region) { return(await _repositories[updatingUser.Region] .UpdateUserAsync(updatingUser, message)); } string newShardKey = updatingUser.Region.ToUpper(); string oldShardKey = currentUser.Region.ToUpper(); EnsureUserRegionExists(newShardKey); EnsureUserRegionExists(oldShardKey); var oldShardRepository = _repositories[oldShardKey]; var newShardRepository = _repositories[newShardKey]; var newModel = new UserModel(); _mapper.Map <UserModel, UserModel>(updatingUser, newModel); newModel.CreatedDate = currentUser.CreatedDate; try { var replacedUserModel = await newShardRepository.CreateUserAsync(newModel, message); await SetUserShardAsync(userId, newShardKey); await oldShardRepository.DeleteUserSilentAsync(userId); return(replacedUserModel); } catch (Exception) { //rollback changes await newShardRepository.DeleteOutboxMessageAsync(message.Id); await newShardRepository.DeleteUserSilentAsync(userId); await SetUserShardAsync(userId, oldShardKey); var oldUser = await oldShardRepository.GetUserAsync(userId); if (oldUser == null) { await oldShardRepository.CreateUserSilentAsync(currentUser); } throw; } }
public Task DeleteListAsync(string listId) { var outboxMessage = OutboxMessageModel.Create( new ListDeletedMessage { ListId = listId, }, Topics.Lists, MessageActions.Deleted); return(_listsRepository.DeleteListAsync(listId, outboxMessage)); }
public RavendbOutboxMessageModel(OutboxMessageModel baseModel) { Init(); Index = DateTimeOffset.UtcNow.Ticks; Message = baseModel.Message; Topic = baseModel.Topic; Action = baseModel.Action; IsInProcess = baseModel.IsInProcess; OutboxMessageId = baseModel.GetHashCode(); }
private Task HandleNoMembersToMoveAsync(MoveTaskTransaction moveTaskTransaction) { moveTaskTransaction.UpdateData(); var outboxMessage = OutboxMessageModel.Create( new MoveTaskMembersMovedMessage { TransactionId = moveTaskTransaction.Id, }, Topics.ProjectMembers, TransactionMessageActions.MoveTask_MoveMembersCompleted); return(_transactionsRepository.CreateOrUpdateTransactionAsync(moveTaskTransaction, outboxMessage)); }
public async Task <UserModel> CreateUserAsync(UserModel user, OutboxMessageModel message) { await _connection.StoreAsync(user); if (message != null) { await _connection.StoreAsync(message.ToRavendDb()); } await _connection.SaveChangesAsync(); return(user); }
public async Task DeleteUserAsync(string userId, OutboxMessageModel message) { var userShardingRecord = await _localRepository.GetUserShardAsync(userId); if (userShardingRecord == null) { return; } await _repositories[userShardingRecord.ShardKey].DeleteUserAsync(userId, message); await DeleteUserShardRecordAsync(userId); }
internal async Task <(bool isSuccess, string error)> DeleteUserAsync(string userId) { var message = OutboxMessageModel.Create( new UserDeletedMessage { UserId = userId }, Topics.Users, MessageActions.Deleted ); await _repository.DeleteUserAsync(userId, message); return(true, string.Empty); }
public Task DeleteTaskAsync(string taskId, OutboxMessageModel outboxMessage) { string deleteTaskQuery = $"delete from {_tableName} where id = '{taskId}' ; "; string deleteTaskMembersQuery = ConstructQueryToDeleteTaskJoinData(_membersJoinTableName, taskId); string deleteTaskLabelsQuery = ConstructQueryToDeleteTaskJoinData(_labelsJoinTableName, taskId); string insertMessageQuery = ConstructInsertMessageQuery(outboxMessage); string resultDeleteQuery = deleteTaskMembersQuery + deleteTaskLabelsQuery + deleteTaskQuery + insertMessageQuery; return(_connection.ExecuteAsync(resultDeleteQuery)); }
public async Task <UserModel> UpdateUserAsync(UserModel updatingUser, OutboxMessageModel message) { var currentUser = await GetUserAsync(updatingUser.Id); currentUser.Username = updatingUser.Username; currentUser.Region = updatingUser.Region; currentUser.PhoneNumber = updatingUser.PhoneNumber; currentUser.Email = updatingUser.Email; await _connection.StoreAsync(message.ToRavendDb()); await _connection.SaveChangesAsync(); return(currentUser); }
public async Task <TaskAggregate> CreateTaskAsync(TaskModel newTask, IEnumerable <string> usersIds, IEnumerable <string> labelsIds, string requestId) { if (!(await CheckAndSaveRequestIdAsync(requestId))) { throw new AlreadyHandledException(); } try { newTask.Init(); TaskRelatedData taskData = await GetAndCheckTaskRelatedDataAsync(newTask, usersIds, labelsIds); var list = taskData.List; var taskCollections = new TaskCollections { Members = usersIds, Labels = labelsIds }; var membersRecords = _mapper.Map <IEnumerable <UserModel>, IEnumerable <TaskUserRecord> >(taskData.Users); var labelsRecords = _mapper.Map <IEnumerable <LabelModel>, IEnumerable <TaskLabelRecord> >(taskData.Labels); var outboxMessage = OutboxMessageModel.Create( new TaskCreatedMessage { TaskId = newTask.Id, Title = newTask.Title, ProjectId = list.ProjectId, ProjectTitle = list.ProjectTitle, ListId = list.Id, ListTitle = list.Title, Members = membersRecords, Labels = labelsRecords }, Topics.Tasks, MessageActions.Created); return(await _tasksRepository.CreateTaskAsync(newTask, taskCollections, outboxMessage)); } catch (Exception) { //rollback request id await _requestsRepository.DeleteRequestIdAsync(requestId); throw; } }
public async Task <UserModel> CreateUserAsync(UserModel user) { user.Init(); var message = OutboxMessageModel.Create( new UserCreatedUpdatedMessage { UserId = user.Id, Username = user.Username }, Topics.Users, MessageActions.Created ); var createdUser = await _repository.CreateUserAsync(user, message); return(createdUser); }
protected override Task RollbackTransactionInternalAsync(TransactionBase transaction) { var moveTransaction = MoveTaskTransaction.CreateFromBase(transaction); if (!moveTransaction.IsListCreated || moveTransaction.ListId == null) { return(Task.CompletedTask); //nothing to do here } var outboxMessage = OutboxMessageModel.Create( new ListDeletedMessage { ListId = moveTransaction.ListId, }, Topics.Lists, MessageActions.Deleted); return(_listsRepository.DeleteListAsync(moveTransaction.ListId, outboxMessage)); }
public async Task RemoveMemberFromProjectAsync(string projectId, string userId) { (ProjectModel project, UserModel user) = await GetProjectAndUserAsync(projectId, userId); var outboxMessage = OutboxMessageModel.Create( new ProjectMemberDeletedMessage { ProjectId = projectId, ProjectTitle = project?.Title, UserId = userId, Username = user?.Username }, Topics.ProjectMembers, MessageActions.Deleted ); await _projectMembersRepository.DeleteMemberFromProjectAsync(projectId, userId, outboxMessage); }
public async Task DeleteUserAsync(string userId, OutboxMessageModel message) { var user = await GetUserAsyncInternal(userId); if (user == null) { return; } _connection.Delete(user); if (message != null) { await _connection.StoreAsync(message.ToRavendDb()); } await _connection.SaveChangesAsync(); }
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 DeleteLabelAsync(string labelId) { var label = await _labelsRepository.GetLabelByIdAsync(labelId); if (label == null) { return; } var outboxMessage = OutboxMessageModel.Create( new LabelDeletedMessage { LabelId = labelId, Title = label.Title }, Topics.Labels, MessageActions.Deleted); await _labelsRepository.DeleteLabelAsync(labelId, outboxMessage); }
public async Task <LabelModel> CreateLabelAsync(LabelModel newLabel, OutboxMessageModel message) { string insertQuery = $"insert into {_tableName} (id, title, color, createddate, version) " + $"values('{newLabel.Id}', '{newLabel.Title}', '{newLabel.Color}', '{newLabel.CreatedDate}', {newLabel.Version});"; string insertMessageQuery = ConstructInsertMessageQuery(message); insertQuery += insertMessageQuery; int res = await _connection.ExecuteAsync(insertQuery); if (res <= 0) { throw new DatabaseException("Create label failed"); } return(await GetLabelByIdAsync(newLabel.Id)); }
public async Task <ProjectModel> CreateProjectAsync(ProjectModel newProject, OutboxMessageModel message) { string insertQuery = $"insert into {_tableName} (id, title, description, createddate, begindate, enddate, version) " + $"values('{newProject.Id}', '{newProject.Title}', '{newProject.Description}', '{newProject.CreatedDate}', {GetQueryNullableEscapedValue(newProject.BeginDate)}, {GetQueryNullableEscapedValue(newProject.EndDate)}, {newProject.Version});"; string insertMessageQuery = ConstructInsertMessageQuery(message); insertQuery += insertMessageQuery; int res = await _connection.ExecuteAsync(insertQuery); if (res <= 0) { throw new DatabaseException("Create project failed"); } return(await GetProjectByIdAsync(newProject.Id)); }