async Task AttemptRollbackPhase(int sandboxId, SandboxPhaseHistory phaseToRemove) { try { _logger.LogWarning($"Rolling back phase for sandbox {sandboxId}."); if (phaseToRemove != null) { if (phaseToRemove.Id > 0) { var sandboxFromDb = await _sandboxModelService.GetByIdAsync(sandboxId, UserOperation.Sandbox_IncreasePhase, true); if (sandboxFromDb.PhaseHistory.Count > 0 && sandboxFromDb.PhaseHistory.Contains(phaseToRemove)) { _logger.LogWarning($"Rolling back phase rollback for sandbox {sandboxId}. Phase item: {phaseToRemove.Id}, phase: {phaseToRemove.Phase}"); sandboxFromDb.PhaseHistory.Remove(phaseToRemove); await _db.SaveChangesAsync(); } else { _logger.LogWarning($"Attempted phase rollback for sandbox {sandboxId} aborted. Phase record not found associated to Sandbox"); } } else { _logger.LogWarning($"Attempted phase rollback for sandbox {sandboxId} aborted. Phase record Id was 0"); } } else { _logger.LogWarning($"Attempted phase rollback for sandbox {sandboxId} aborted. Phase record was NULL"); } } catch (Exception ex) { var additionalInfo = phaseToRemove != null ? $"Phase item: {phaseToRemove.Id}, phase: {phaseToRemove.Phase}" : ""; _logger.LogError(ex, $"Attempted phase rollback for sandbox {sandboxId} failed. {additionalInfo}"); } }
public async Task <SandboxDetails> MoveToNextPhaseAsync(int sandboxId, CancellationToken cancellation = default) { _logger.LogInformation(_sandboxNextPhaseEventId, "Sandbox {0}: Starting", sandboxId); SandboxPhaseHistory newestHistoryItem = null; bool dataMightHaveBeenChanged = false; try { var user = await _userService.GetCurrentUserAsync(); var sandboxFromDb = await GetSandboxForPhaseShift(sandboxId); var currentPhaseItem = SandboxPhaseUtil.GetCurrentPhaseHistoryItem(sandboxFromDb); if (currentPhaseItem == null) { SandboxPhaseUtil.InitiatePhaseHistory(sandboxFromDb, user); currentPhaseItem = SandboxPhaseUtil.GetCurrentPhaseHistoryItem(sandboxFromDb); } var nextPhase = SandboxPhaseUtil.GetNextPhase(sandboxFromDb); await ValidatePhaseMoveThrowIfNot(sandboxFromDb, currentPhaseItem.Phase, nextPhase, cancellation); _logger.LogInformation(_sandboxNextPhaseEventId, "Sandbox {0}: Moving from {1} to {2}", sandboxId, currentPhaseItem.Phase, nextPhase); newestHistoryItem = new SandboxPhaseHistory() { Counter = currentPhaseItem.Counter + 1, Phase = nextPhase, CreatedBy = user.UserName }; dataMightHaveBeenChanged = true; sandboxFromDb.PhaseHistory.Add(newestHistoryItem); await _db.SaveChangesAsync(); _logger.LogInformation(_sandboxNextPhaseEventId, "Sandbox {0}: Phase added to db. Proceeding to make data available", sandboxId); if (nextPhase == SandboxPhase.DataAvailable) { await MakeDatasetsAvailable(sandboxFromDb, cancellation); } _logger.LogInformation(_sandboxNextPhaseEventId, "Sandbox {0}: Done", sandboxId); return(await GetSandboxDetailsInternalAsync(sandboxId)); } catch (Exception ex) { _logger.LogWarning(_sandboxNextPhaseEventId, ex, "Sandbox {0}: Phase shift failed.", sandboxId); if (dataMightHaveBeenChanged) { _logger.LogWarning(_sandboxNextPhaseEventId, ex, "Data might have been changed. Rolling back"); await MakeDatasetsUnAvailable(sandboxId); await AttemptRollbackPhase(sandboxId, newestHistoryItem); } throw; } }