Example #1
0
        public static async Task RestoreAsync(RestoreCommand restoreCommand, ILogger logger, CancellationToken cancellationToken)
        {
            await using var connection = restoreCommand.CreateConnectionMars();

            var state = new RestoreState(logger, restoreCommand, connection);

            state.LogStarting();

            await state.EnsuredIndexsExistsAsync();

            await Task.WhenAll(
                state.LoadServerInfosAsync(),
                state.LoadDatabasesAsync(),
                state.LoadRestoreHistoryAsync(),
                state.PrepareRestoreJobAsync());

            logger.Information($"{state.Directories.Count} directories found");
            logger.Information("Starting...");
            var po = new ParallelizeOption
            {
                FailMode = Fail.Smart,
                MaxDegreeOfParallelism = restoreCommand.Threads
            };

            IRestoreMethod method = restoreCommand.Brentozar
                ? (IRestoreMethod) new BrentozarRestoreMethod(state, connection)
                : new NativeRestoreMethod(state);

            await state.Directories
            .ParallelizeAsync((item, cancel) => RestoreBackupAsync(method, item, state), po, cancellationToken)
            .ForEachAsync((value, token) =>
            {
                state.Accumulated = state.Accumulated.Add(value.Item.Elapsed);
                return(Task.CompletedTask);
            });

            var report = await state.GetReportStateAsync();

            state.LogFinished(report);

            var slack = new SlackSender(new SlackClient(logger));
            await slack.ReportAsync(report, state.RestoreCommand.SlackChannel, state.RestoreCommand.SlackSecret, state.RestoreCommand.SlackOnlyOnError, state.RestoreCommand.SlackTitle);

            await report.SendMailAsync(state.RestoreCommand.Email, state.RestoreCommand.Smtp, cancellationToken);

            if (report.Status.HasFlag(ReportStatus.Error))
            {
                Environment.ExitCode = 1;
            }
        }
Example #2
0
        private static async Task <RestoreItem> RestoreBackupAsync(IRestoreMethod restoreMethod, RestoreItem item, RestoreState state)
        {
            RestoreCommand restoreCommand = state.RestoreCommand;

            state.Loggger.Debug($"Starting restore for {item.Name}");
            item.SetStart();

            await using var sqlConnection = restoreCommand.CreateConnectionMars();
            Exception exception;

            if (restoreCommand.FullOnly)
            {
                exception = await restoreMethod.RestoreFullAsync(item);
            }
            else
            {
                bool startFromFull = StartFromFull(state, item);
                exception = await restoreMethod.RestoreFullDiffLogAsync(item, startFromFull);
            }

            var incremented = state.Increment();

            state.Loggger.Information($"[{incremented}/{state.Directories.Count}] OK : {item.Name} {item.Stats()}");

            if (exception != null)
            {
                state.ExceptionBackupFull.Add((exception, item));
                item.SetError(exception);
                state.Loggger.Error(exception, $"Error restoring {item.Name}");
                return(item);
            }

            try
            {
                Exception scriptException = null;

                if (restoreCommand.RunRecovery)
                {
                    var recoveryException = await restoreMethod.RunRecoveryAsync(item);

                    if (recoveryException != null)
                    {
                        state.ExceptionBackupFull.Add((recoveryException, item));
                        item.SetError(recoveryException);
                        throw recoveryException;
                    }

                    scriptException = await PostScriptExecuteAsync(state, item);

                    await RunDbccCheckDb(state, item);
                }

                if (scriptException != null)
                {
                    state.ExceptionBackupFull.Add((scriptException, item));
                    item.SetError(scriptException);
                }

                if (restoreCommand.IsUncheckedModeEnable)
                {
                    try
                    {
                        // overwrite destination if exists
                        var target = Path.Combine(restoreCommand.Checked.FullName, item.Name);
                        if (Directory.Exists(target))
                        {
                            Directory.Delete(target, true);
                        }
                        item.BaseDirectoryInfo.MoveTo(target);
                    }
                    catch (Exception e)
                    {
                        state.Loggger.Error(e, $"Error moving {item.Name}");
                        return(item);
                    }
                }

                if (scriptException != null)
                {
                    return(item);
                }
            }
            catch (Exception e)
            {
                item.SetError(e);
                return(item);
            }

            item.SetSuccess();
            state.OkBackupFull.Add(item);

            state.Loggger.Debug($"Finished restore for {item.Name}");
            return(item);
        }