private async Task RestoreBackup(MyBackup backup)
        {
            var rnd           = new Random();
            var restoreDbName =
                $"Restored_{new string(Enumerable.Repeat(_chars, rnd.Next(5, 10)).Select(x => x[rnd.Next(x.Length)]).ToArray())}";

            var restoreConfig = new RestoreBackupConfiguration
            {
                DatabaseName   = restoreDbName,
                BackupLocation = backup.BackupPath
            };
            var restoreBackupTask = new RestoreBackupOperation(restoreConfig);

            using (var session = DocumentStore.OpenAsyncSession())
            {
                var succeeded = true;
                try
                {
                    ReportInfo($"Starting to restore DB: {restoreDbName}");
                    var re = DocumentStore.GetRequestExecutor(DocumentStore.Database);
                    var restoreBackupTaskCommand = restoreBackupTask.GetCommand(DocumentStore.Conventions, session.Advanced.Context);
                    await re.ExecuteAsync(re.TopologyNodes.First(q => q.ClusterTag == backup.BackupStatus.NodeTag),
                                          null, session.Advanced.Context, restoreBackupTaskCommand, shouldRetry : false);

                    var getOperationStateTask        = new GetOperationStateOperation(restoreBackupTaskCommand.Result.OperationId);
                    var getOperationStateTaskCommand = getOperationStateTask.GetCommand(DocumentStore.Conventions, session.Advanced.Context);

                    await re.ExecuteAsync(re.TopologyNodes.First(q => q.ClusterTag == backup.BackupStatus.NodeTag),
                                          null, session.Advanced.Context, getOperationStateTaskCommand, shouldRetry : false);

                    while (getOperationStateTaskCommand.Result.Status == OperationStatus.InProgress)
                    {
                        await Task.Delay(2000);

                        await re.ExecuteAsync(re.TopologyNodes.First(q => q.ClusterTag == backup.BackupStatus.NodeTag),
                                              null, session.Advanced.Context, getOperationStateTaskCommand, shouldRetry : false);
                    }
                }
                catch (Exception e)
                {
                    ReportFailure($"Restoring DB: {restoreDbName} Failed", e);
                    succeeded = false;
                }

                for (var i = 0; i < MyBackupsList.Count; i++)
                {
                    if (MyBackupsList[i].BackupTaskId == backup.BackupTaskId)
                    {
                        MyBackupsList[i].RestoreResult = succeeded ? RestoreResult.Succeeded : RestoreResult.Failed;
                        break;
                    }
                }
            }
        }
Beispiel #2
0
        public async Task can_backup_and_restore_snapshot()
        {
            var backupPath = NewDataPath(suffix: "BackupFolder");

            using (var store = GetDocumentStore())
            {
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "oren" }, "users/1");

                    await session.SaveChangesAsync();
                }

                var config = new PeriodicBackupConfiguration
                {
                    BackupType    = BackupType.Snapshot,
                    LocalSettings = new LocalSettings
                    {
                        FolderPath = backupPath
                    },
                    IncrementalBackupFrequency = "* * * * *" //every minute
                };

                var result = await store.Admin.Server.SendAsync(new UpdatePeriodicBackupOperation(config, store.Database));

                var periodicBackupTaskId = result.TaskId;

                var operation = new GetPeriodicBackupStatusOperation(store.Database, periodicBackupTaskId);
                SpinWait.SpinUntil(() =>
                {
                    var getPeriodicBackupResult = store.Admin.Server.Send(operation);
                    return(getPeriodicBackupResult.Status?.LastEtag > 0);
                }, TimeSpan.FromMinutes(2));

                var etagForBackups = store.Admin.Server.Send(operation).Status.LastEtag;
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "ayende" }, "users/2");

                    await session.StoreAsync(new User { Name = "ayende" }, "users/3");

                    await session.SaveChangesAsync();
                }

                SpinWait.SpinUntil(() =>
                {
                    var newLastEtag = store.Admin.Server.Send(operation).Status.LastEtag;
                    return(newLastEtag != etagForBackups);
                }, TimeSpan.FromMinutes(2));

                // restore the database with a different name
                const string restoredDatabaseName = "restored_database_snapshot";
                var          restoreConfiguration = new RestoreBackupConfiguration
                {
                    BackupLocation = Directory.GetDirectories(backupPath).First(),
                    DatabaseName   = restoredDatabaseName
                };
                var restoreBackupTask = new RestoreBackupOperation(restoreConfiguration);
                var restoreResult     = store.Admin.Server.Send(restoreBackupTask);
                var stateRequest      = new GetOperationStateOperation(restoreResult.OperationId, true);
                store.Admin.Server.Send(stateRequest);

                SpinWait.SpinUntil(() =>
                {
                    var state = store.Admin.Server.Send(stateRequest);
                    return(state.Status == OperationStatus.Completed);
                }, TimeSpan.FromMinutes(2));

                using (var session = store.OpenAsyncSession(restoredDatabaseName))
                {
                    var users = await session.LoadAsync <User>(new[] { "users/1", "users/2" });

                    Assert.True(users.Any(x => x.Value.Name == "oren"));
                    Assert.True(users.Any(x => x.Value.Name == "ayende"));
                }
            }
        }
Beispiel #3
0
        private async Task RestoreBackup(MyBackup backup)
        {
            var rnd           = new Random();
            var restoreDbName =
                $"Restored_{new string(Enumerable.Repeat(_chars, rnd.Next(5, 10)).Select(x => x[rnd.Next(x.Length)]).ToArray())}";

            var restoreConfig = new RestoreBackupConfiguration
            {
                DatabaseName   = restoreDbName,
                BackupLocation = backup.BackupPath
            };
            var restoreBackupTask = new RestoreBackupOperation(restoreConfig);

            using (var session = DocumentStore.OpenAsyncSession())
            {
                var reasonableTimeForBackup = Stopwatch.StartNew();
                var succeeded = true;
                try
                {
                    ReportInfo($"Starting to restore DB: {restoreDbName}");
                    var re = DocumentStore.GetRequestExecutor(DocumentStore.Database);
                    var restoreBackupTaskCommand =
                        restoreBackupTask.GetCommand(DocumentStore.Conventions, session.Advanced.Context);
                    await re.ExecuteAsync(re.TopologyNodes.First(q => q.ClusterTag.Equals(backup.BackupStatus.NodeTag)),
                                          null, session.Advanced.Context, restoreBackupTaskCommand, shouldRetry : false)
                    .ConfigureAwait(false);

                    var getOperationStateTask =
                        new GetOperationStateOperation(restoreBackupTaskCommand.Result.OperationId);
                    var getOperationStateTaskCommand =
                        getOperationStateTask.GetCommand(DocumentStore.Conventions, session.Advanced.Context);

                    await re.ExecuteAsync(re.TopologyNodes.First(q => q.ClusterTag.Equals(backup.BackupStatus.NodeTag)),
                                          null, session.Advanced.Context, getOperationStateTaskCommand, shouldRetry : false)
                    .ConfigureAwait(false);

                    while (getOperationStateTaskCommand.Result == null || getOperationStateTaskCommand.Result.Status == OperationStatus.InProgress)
                    {
                        await Task.Delay(2000).ConfigureAwait(false);

                        await re.ExecuteAsync(re.TopologyNodes.First(q => q.ClusterTag.Equals(backup.BackupStatus.NodeTag)),
                                              null, session.Advanced.Context, getOperationStateTaskCommand, shouldRetry : false)
                        .ConfigureAwait(false);

                        if (reasonableTimeForBackup.Elapsed > TimeSpan.FromMinutes(5))
                        {
                            ReportFailure($"Restoring DB: {restoreDbName} Failed, taskID {backup.BackupTaskId} - Waited {reasonableTimeForBackup.Elapsed} and task didn't finished", null);
                            succeeded = true; // marking as success in order to delete
                            // TODO : RavenDB-13684
                            break;
                        }
                    }
                }
                catch (RavenException re)
                {
                    if (re.InnerException is ArgumentException ae)
                    {
                        ReportInfo($"Probably somebody deleted the backup files, taskID {backup.BackupTaskId}, exception: {ae}");
                    }
                    else
                    {
                        ReportFailure($"Restoring DB: {restoreDbName} Failed, taskID {backup.BackupTaskId}", re);
                    }
                }
                catch (Exception e)
                {
                    ReportFailure($"Restoring DB: {restoreDbName} Failed, taskID {backup.BackupTaskId}", e);
                    succeeded = false;
                }

                if (succeeded)
                {
                    MyRestoreDbsList.Add(restoreDbName);
                }

                for (var i = 0; i < MyBackupsList.Count; i++)
                {
                    if (MyBackupsList[i].BackupTaskId == backup.BackupTaskId)
                    {
                        MyBackupsList[i].RestoreResult = succeeded ? RestoreResult.Succeeded : RestoreResult.Failed;
                        break;
                    }
                }
            }
        }