mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-05 01:25:45 -05:00
generic way to support scriptable operations (#438)
* implemented a generic way to support scriptable operations
This commit is contained in:
@@ -7,13 +7,11 @@ using System;
|
||||
using System.Linq;
|
||||
using System.Data.Common;
|
||||
using System.Data.SqlClient;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection;
|
||||
using Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.TaskServices;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
using System.Collections.Concurrent;
|
||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
@@ -28,107 +26,6 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
||||
public const string LastBackupTaken = "lastBackupTaken";
|
||||
private ConcurrentDictionary<string, RestoreDatabaseTaskDataObject> sessions = new ConcurrentDictionary<string, RestoreDatabaseTaskDataObject>();
|
||||
|
||||
/// <summary>
|
||||
/// Create a backup task for execution and cancellation
|
||||
/// </summary>
|
||||
/// <param name="sqlTask"></param>
|
||||
/// <returns></returns>
|
||||
internal async Task<TaskResult> RestoreTaskAsync(SqlTask sqlTask)
|
||||
{
|
||||
sqlTask.AddMessage(SR.TaskInProgress, SqlTaskStatus.InProgress, true);
|
||||
RestoreDatabaseTaskDataObject restoreDataObject = sqlTask.TaskMetadata.Data as RestoreDatabaseTaskDataObject;
|
||||
TaskResult taskResult = null;
|
||||
|
||||
if (restoreDataObject != null)
|
||||
{
|
||||
// Create a task to perform backup
|
||||
return await Task.Factory.StartNew(() =>
|
||||
{
|
||||
TaskResult result = new TaskResult();
|
||||
try
|
||||
{
|
||||
if (restoreDataObject.IsValid)
|
||||
{
|
||||
ExecuteRestore(restoreDataObject, sqlTask);
|
||||
result.TaskStatus = SqlTaskStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.TaskStatus = SqlTaskStatus.Failed;
|
||||
if (restoreDataObject.ActiveException != null)
|
||||
{
|
||||
result.ErrorMessage = restoreDataObject.ActiveException.Message;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.ErrorMessage = SR.RestoreNotSupported;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.TaskStatus = SqlTaskStatus.Failed;
|
||||
result.ErrorMessage = ex.Message;
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
result.ErrorMessage += Environment.NewLine + ex.InnerException.Message;
|
||||
}
|
||||
if (restoreDataObject != null && restoreDataObject.ActiveException != null)
|
||||
{
|
||||
result.ErrorMessage += Environment.NewLine + restoreDataObject.ActiveException.Message;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult = new TaskResult();
|
||||
taskResult.TaskStatus = SqlTaskStatus.Failed;
|
||||
}
|
||||
|
||||
return taskResult;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Async task to cancel restore
|
||||
/// </summary>
|
||||
public async Task<TaskResult> CancelTaskAsync(SqlTask sqlTask)
|
||||
{
|
||||
RestoreDatabaseTaskDataObject restoreDataObject = sqlTask.TaskMetadata.Data as RestoreDatabaseTaskDataObject;
|
||||
TaskResult taskResult = null;
|
||||
|
||||
|
||||
if (restoreDataObject != null && restoreDataObject.IsValid)
|
||||
{
|
||||
// Create a task for backup cancellation request
|
||||
return await Task.Factory.StartNew(() =>
|
||||
{
|
||||
|
||||
foreach (Restore restore in restoreDataObject.RestorePlan.RestoreOperations)
|
||||
{
|
||||
restore.Abort();
|
||||
}
|
||||
|
||||
|
||||
return new TaskResult
|
||||
{
|
||||
TaskStatus = SqlTaskStatus.Canceled
|
||||
};
|
||||
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult = new TaskResult();
|
||||
taskResult.TaskStatus = SqlTaskStatus.Failed;
|
||||
}
|
||||
|
||||
return taskResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates response which includes information about the server given to restore (default data location, db names with backupsets)
|
||||
/// </summary>
|
||||
@@ -166,7 +63,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
||||
{
|
||||
if (restoreDataObject != null && restoreDataObject.IsValid)
|
||||
{
|
||||
UpdateRestorePlan(restoreDataObject);
|
||||
restoreDataObject.UpdateRestoreTaskObject();
|
||||
|
||||
if (restoreDataObject != null && restoreDataObject.IsValid)
|
||||
{
|
||||
@@ -227,6 +124,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
||||
response.ErrorMessage += Environment.NewLine;
|
||||
response.ErrorMessage += ex.InnerException.Message;
|
||||
}
|
||||
Logger.Write(LogLevel.Normal, $"Failed to create restore plan. error: { response.ErrorMessage}");
|
||||
}
|
||||
return response;
|
||||
|
||||
@@ -295,63 +193,11 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a restore data object that includes the plan to do the restore operation
|
||||
/// </summary>
|
||||
/// <param name="requestParam"></param>
|
||||
/// <returns></returns>
|
||||
private void UpdateRestorePlan(RestoreDatabaseTaskDataObject restoreDataObject)
|
||||
{
|
||||
bool shouldCreateNewPlan = restoreDataObject.ShouldCreateNewPlan();
|
||||
|
||||
if (!string.IsNullOrEmpty(restoreDataObject.RestoreParams.BackupFilePaths))
|
||||
{
|
||||
restoreDataObject.AddFiles(restoreDataObject.RestoreParams.BackupFilePaths);
|
||||
}
|
||||
restoreDataObject.RestorePlanner.ReadHeaderFromMedia = restoreDataObject.RestoreParams.ReadHeaderFromMedia;
|
||||
|
||||
RestoreOptionFactory.Instance.SetAndValidate(RestoreOptionsHelper.SourceDatabaseName, restoreDataObject);
|
||||
RestoreOptionFactory.Instance.SetAndValidate(RestoreOptionsHelper.TargetDatabaseName, restoreDataObject);
|
||||
|
||||
if (shouldCreateNewPlan)
|
||||
{
|
||||
restoreDataObject.CreateNewRestorePlan();
|
||||
}
|
||||
|
||||
restoreDataObject.UpdateRestorePlan();
|
||||
|
||||
}
|
||||
|
||||
|
||||
private bool CanChangeTargetDatabase(RestoreDatabaseTaskDataObject restoreDataObject)
|
||||
{
|
||||
return DatabaseUtils.IsSystemDatabaseConnection(restoreDataObject.Server.ConnectionContext.DatabaseName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the restore operation
|
||||
/// </summary>
|
||||
/// <param name="requestParam"></param>
|
||||
public void ExecuteRestore(RestoreDatabaseTaskDataObject restoreDataObject, SqlTask sqlTask = null)
|
||||
{
|
||||
// Restore Plan should be already created and updated at this point
|
||||
UpdateRestorePlan(restoreDataObject);
|
||||
|
||||
if (restoreDataObject != null && CanRestore(restoreDataObject))
|
||||
{
|
||||
try
|
||||
{
|
||||
restoreDataObject.SqlTask = sqlTask;
|
||||
restoreDataObject.Execute();
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException(SR.RestoreNotSupported);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user