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; } } } }
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")); } } }
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; } } } }