Files
sqltoolsservice/src/Microsoft.SqlTools.ServiceLayer/Agent/AgentService.cs
Benjamin Russell 97a106c575 Removing a lot of redundant async/await wrappers (#1486)
* Removing a lot of redundant async/await wrappers

* Removing kusto changes
2022-06-05 08:26:21 -07:00

1537 lines
63 KiB
C#

//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Threading.Tasks;
using System.Xml;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Smo.Agent;
using Microsoft.SqlTools.Hosting.Protocol;
using Microsoft.SqlTools.ServiceLayer.Agent.Contracts;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Hosting;
using Microsoft.SqlTools.ServiceLayer.Management;
using Microsoft.SqlTools.ServiceLayer.Utility;
namespace Microsoft.SqlTools.ServiceLayer.Agent
{
/// <summary>
/// Main class for Agent Service functionality
/// </summary>
public class AgentService
{
private ConnectionService connectionService = null;
private static readonly Lazy<AgentService> instance = new Lazy<AgentService>(() => new AgentService());
/// <summary>
/// Construct a new AgentService instance with default parameters
/// </summary>
public AgentService()
{
}
/// <summary>
/// Gets the singleton instance object
/// </summary>
public static AgentService Instance
{
get { return instance.Value; }
}
/// <summary>
/// Internal for testing purposes only
/// </summary>
internal ConnectionService ConnectionServiceInstance
{
get
{
if (connectionService == null)
{
connectionService = ConnectionService.Instance;
}
return connectionService;
}
set
{
connectionService = value;
}
}
/// <summary>
/// Service host object for sending/receiving requests/events.
/// Internal for testing purposes.
/// </summary>
internal IProtocolEndpoint ServiceHost
{
get;
set;
}
/// <summary>
/// Initializes the service instance
/// </summary>
public void InitializeService(ServiceHost serviceHost)
{
this.ServiceHost = serviceHost;
// Jobs request handlers
this.ServiceHost.SetRequestHandler(AgentJobsRequest.Type, HandleAgentJobsRequest);
this.ServiceHost.SetRequestHandler(AgentJobHistoryRequest.Type, HandleJobHistoryRequest);
this.ServiceHost.SetRequestHandler(AgentJobActionRequest.Type, HandleJobActionRequest);
this.ServiceHost.SetRequestHandler(CreateAgentJobRequest.Type, HandleCreateAgentJobRequest);
this.ServiceHost.SetRequestHandler(UpdateAgentJobRequest.Type, HandleUpdateAgentJobRequest);
this.ServiceHost.SetRequestHandler(DeleteAgentJobRequest.Type, HandleDeleteAgentJobRequest);
this.ServiceHost.SetRequestHandler(AgentJobDefaultsRequest.Type, HandleAgentJobDefaultsRequest);
// Job Steps request handlers
this.ServiceHost.SetRequestHandler(CreateAgentJobStepRequest.Type, HandleCreateAgentJobStepRequest);
this.ServiceHost.SetRequestHandler(UpdateAgentJobStepRequest.Type, HandleUpdateAgentJobStepRequest);
this.ServiceHost.SetRequestHandler(DeleteAgentJobStepRequest.Type, HandleDeleteAgentJobStepRequest);
// Alerts request handlers
this.ServiceHost.SetRequestHandler(AgentAlertsRequest.Type, HandleAgentAlertsRequest);
this.ServiceHost.SetRequestHandler(CreateAgentAlertRequest.Type, HandleCreateAgentAlertRequest);
this.ServiceHost.SetRequestHandler(UpdateAgentAlertRequest.Type, HandleUpdateAgentAlertRequest);
this.ServiceHost.SetRequestHandler(DeleteAgentAlertRequest.Type, HandleDeleteAgentAlertRequest);
// Operators request handlers
this.ServiceHost.SetRequestHandler(AgentOperatorsRequest.Type, HandleAgentOperatorsRequest);
this.ServiceHost.SetRequestHandler(CreateAgentOperatorRequest.Type, HandleCreateAgentOperatorRequest);
this.ServiceHost.SetRequestHandler(UpdateAgentOperatorRequest.Type, HandleUpdateAgentOperatorRequest);
this.ServiceHost.SetRequestHandler(DeleteAgentOperatorRequest.Type, HandleDeleteAgentOperatorRequest);
// Proxy Accounts request handlers
this.ServiceHost.SetRequestHandler(AgentProxiesRequest.Type, HandleAgentProxiesRequest);
this.ServiceHost.SetRequestHandler(CreateAgentProxyRequest.Type, HandleCreateAgentProxyRequest);
this.ServiceHost.SetRequestHandler(UpdateAgentProxyRequest.Type, HandleUpdateAgentProxyRequest);
this.ServiceHost.SetRequestHandler(DeleteAgentProxyRequest.Type, HandleDeleteAgentProxyRequest);
// Schedule request handlers
this.ServiceHost.SetRequestHandler(AgentSchedulesRequest.Type, HandleAgentSchedulesRequest);
this.ServiceHost.SetRequestHandler(CreateAgentScheduleRequest.Type, HandleCreateAgentScheduleRequest);
this.ServiceHost.SetRequestHandler(UpdateAgentScheduleRequest.Type, HandleUpdateAgentScheduleRequest);
this.ServiceHost.SetRequestHandler(DeleteAgentScheduleRequest.Type, HandleDeleteAgentScheduleRequest);
// Notebook request handlers
this.ServiceHost.SetRequestHandler(AgentNotebooksRequest.Type, HandleAgentNotebooksRequest);
this.ServiceHost.SetRequestHandler(AgentNotebookHistoryRequest.Type, HandleAgentNotebookHistoryRequest);
this.ServiceHost.SetRequestHandler(AgentNotebookMaterializedRequest.Type, HandleAgentNotebookMaterializedRequest);
this.ServiceHost.SetRequestHandler(AgentNotebookTemplateRequest.Type, HandleAgentNotebookTemplateRequest);
this.ServiceHost.SetRequestHandler(CreateAgentNotebookRequest.Type, HandleCreateAgentNotebookRequest);
this.ServiceHost.SetRequestHandler(DeleteAgentNotebookRequest.Type, HandleDeleteAgentNotebooksRequest);
this.ServiceHost.SetRequestHandler(UpdateAgentNotebookRequest.Type, HandleUpdateAgentNotebookRequest);
this.ServiceHost.SetRequestHandler(UpdateAgentNotebookRunPinRequest.Type, HandleUpdateAgentNotebookRunPinRequest);
this.ServiceHost.SetRequestHandler(UpdateAgentNotebookRunNameRequest.Type, HandleUpdateAgentNotebookRunNameRequest);
this.ServiceHost.SetRequestHandler(DeleteNotebookMaterializedRequest.Type, HandleDeleteNotebookMaterializedRequest);
serviceHost.RegisterShutdownTask((_, _) =>
{
DeleteAgentNotebooksTempFiles();
return Task.FromResult(0);
});
}
#region "Jobs Handlers"
/// <summary>
/// Handle request to get Agent job activities
/// </summary>
internal async Task HandleAgentJobsRequest(AgentJobsParams parameters, RequestContext<AgentJobsResult> requestContext)
{
try
{
var result = new AgentJobsResult();
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(
parameters.OwnerUri,
out connInfo);
if (connInfo != null)
{
var serverConnection = ConnectionService.OpenServerConnection(connInfo);
var fetcher = new JobFetcher(serverConnection);
var filter = new JobActivityFilter();
var jobs = fetcher.FetchJobs(filter);
var agentJobs = new List<AgentJobInfo>();
if (jobs != null)
{
foreach (var job in jobs.Values)
{
agentJobs.Add(AgentUtilities.ConvertToAgentJobInfo(job));
}
}
result.Success = true;
result.Jobs = agentJobs.ToArray();
serverConnection.SqlConnectionObject.Close();
}
await requestContext.SendResult(result);
}
catch (Exception e)
{
await requestContext.SendError(e);
}
}
/// <summary>
/// Handle request to get Agent Job history
/// </summary>
internal async Task HandleJobHistoryRequest(AgentJobHistoryParams parameters, RequestContext<AgentJobHistoryResult> requestContext)
{
try
{
var result = new AgentJobHistoryResult();
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(
parameters.OwnerUri,
out connInfo);
if (connInfo != null)
{
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
var jobServer = dataContainer.Server.JobServer;
var jobs = jobServer.Jobs;
Tuple<SqlConnectionInfo, DataTable, ServerConnection> tuple = CreateSqlConnection(connInfo, parameters.JobId);
SqlConnectionInfo sqlConnInfo = tuple.Item1;
DataTable dt = tuple.Item2;
ServerConnection connection = tuple.Item3;
// Send Steps, Alerts and Schedules with job history in background
// Add steps to the job if any
JobStepCollection steps = jobs[parameters.JobName].JobSteps;
var jobSteps = new List<AgentJobStepInfo>();
foreach (JobStep step in steps)
{
jobSteps.Add(AgentUtilities.ConvertToAgentJobStepInfo(step, parameters.JobId, parameters.JobName));
}
result.Steps = jobSteps.ToArray();
// Add schedules to the job if any
JobScheduleCollection schedules = jobs[parameters.JobName].JobSchedules;
var jobSchedules = new List<AgentScheduleInfo>();
foreach (JobSchedule schedule in schedules)
{
jobSchedules.Add(AgentUtilities.ConvertToAgentScheduleInfo(schedule));
}
result.Schedules = jobSchedules.ToArray();
// Alerts
AlertCollection alerts = jobServer.Alerts;
var jobAlerts = new List<Alert>();
foreach (Alert alert in alerts)
{
if (alert.JobName == parameters.JobName)
{
jobAlerts.Add(alert);
}
}
result.Alerts = AgentUtilities.ConvertToAgentAlertInfo(jobAlerts);
// Add histories
int count = dt.Rows.Count;
List<AgentJobHistoryInfo> jobHistories = new List<AgentJobHistoryInfo>();
if (count > 0)
{
var job = dt.Rows[0];
Guid jobId = (Guid)job[AgentUtilities.UrnJobId];
int runStatus = Convert.ToInt32(job[AgentUtilities.UrnRunStatus], System.Globalization.CultureInfo.InvariantCulture);
var t = new LogSourceJobHistory(parameters.JobName, sqlConnInfo, null, runStatus, jobId, null);
var tlog = t as ILogSource;
tlog.Initialize();
var logEntries = t.LogEntries;
// Finally add the job histories
jobHistories = AgentUtilities.ConvertToAgentJobHistoryInfo(logEntries, job, steps);
result.Histories = jobHistories.ToArray();
result.Success = true;
tlog.CloseReader();
}
await requestContext.SendResult(result);
}
}
catch (Exception e)
{
await requestContext.SendError(e);
}
}
/// <summary>
/// Handle request to Run a Job
/// </summary>
internal async Task HandleJobActionRequest(AgentJobActionParams parameters, RequestContext<ResultStatus> requestContext)
{
var result = new ResultStatus();
try
{
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(
parameters.OwnerUri,
out connInfo);
if (connInfo != null)
{
var serverConnection = ConnectionService.OpenServerConnection(connInfo);
var jobHelper = new JobHelper(serverConnection);
jobHelper.JobName = parameters.JobName;
switch (parameters.Action)
{
case "run":
jobHelper.Start();
break;
case "stop":
jobHelper.Stop();
break;
case "delete":
jobHelper.Delete();
break;
case "enable":
jobHelper.Enable(true);
break;
case "disable":
jobHelper.Enable(false);
break;
default:
break;
}
result.Success = true;
await requestContext.SendResult(result);
}
}
catch (Exception e)
{
result.Success = false;
result.ErrorMessage = e.Message;
Exception exception = e.InnerException;
while (exception != null)
{
result.ErrorMessage += Environment.NewLine + "\t" + exception.Message;
exception = exception.InnerException;
}
await requestContext.SendResult(result);
}
}
internal async Task HandleCreateAgentJobRequest(CreateAgentJobParams parameters, RequestContext<CreateAgentJobResult> requestContext)
{
var result = await ConfigureAgentJob(
parameters.OwnerUri,
parameters.Job.Name,
parameters.Job,
ConfigAction.Create,
ManagementUtils.asRunType(parameters.TaskExecutionMode));
await requestContext.SendResult(new CreateAgentJobResult()
{
Success = result.Item1,
ErrorMessage = result.Item2
});
}
internal async Task HandleUpdateAgentJobRequest(UpdateAgentJobParams parameters, RequestContext<UpdateAgentJobResult> requestContext)
{
var result = await ConfigureAgentJob(
parameters.OwnerUri,
parameters.OriginalJobName,
parameters.Job,
ConfigAction.Update,
ManagementUtils.asRunType(parameters.TaskExecutionMode));
await requestContext.SendResult(new UpdateAgentJobResult()
{
Success = result.Item1,
ErrorMessage = result.Item2
});
}
internal async Task HandleDeleteAgentJobRequest(DeleteAgentJobParams parameters, RequestContext<ResultStatus> requestContext)
{
var result = await ConfigureAgentJob(
parameters.OwnerUri,
parameters.Job.Name,
parameters.Job,
ConfigAction.Drop,
ManagementUtils.asRunType(parameters.TaskExecutionMode));
await requestContext.SendResult(new ResultStatus()
{
Success = result.Item1,
ErrorMessage = result.Item2
});
}
internal async Task HandleCreateAgentJobStepRequest(CreateAgentJobStepParams parameters, RequestContext<CreateAgentJobStepResult> requestContext)
{
Tuple<bool, string> result = await ConfigureAgentJobStep(
parameters.OwnerUri,
parameters.Step,
ConfigAction.Create,
RunType.RunNow);
await requestContext.SendResult(new CreateAgentJobStepResult()
{
Success = result.Item1,
ErrorMessage = result.Item2
});
}
internal async Task HandleUpdateAgentJobStepRequest(UpdateAgentJobStepParams parameters, RequestContext<UpdateAgentJobStepResult> requestContext)
{
Tuple<bool, string> result = await ConfigureAgentJobStep(
parameters.OwnerUri,
parameters.Step,
ConfigAction.Update,
RunType.RunNow);
await requestContext.SendResult(new UpdateAgentJobStepResult()
{
Success = result.Item1,
ErrorMessage = result.Item2
});
}
internal async Task HandleDeleteAgentJobStepRequest(DeleteAgentJobStepParams parameters, RequestContext<ResultStatus> requestContext)
{
Tuple<bool, string> result = await ConfigureAgentJobStep(
parameters.OwnerUri,
parameters.Step,
ConfigAction.Drop,
RunType.RunNow);
await requestContext.SendResult(new ResultStatus()
{
Success = result.Item1,
ErrorMessage = result.Item2
});
}
internal async Task HandleAgentJobDefaultsRequest(AgentJobDefaultsParams parameters, RequestContext<AgentJobDefaultsResult> requestContext)
{
var result = new AgentJobDefaultsResult();
try
{
JobData jobData;
CDataContainer dataContainer;
CreateJobData(parameters.OwnerUri, "default", out dataContainer, out jobData);
// current connection user name for
result.Owner = dataContainer.ServerConnection.TrueLogin;
var categories = jobData.Categories;
result.Categories = new AgentJobCategory[categories.Length];
for (int i = 0; i < categories.Length; ++i)
{
result.Categories[i] = new AgentJobCategory
{
Id = categories[i].SmoCategory.ID,
Name = categories[i].SmoCategory.Name
};
}
result.Success = true;
}
catch (Exception ex)
{
result.Success = false;
result.ErrorMessage = ex.ToString();
}
await requestContext.SendResult(result);
}
#endregion // "Jobs Handlers"
#region "Alert Handlers"
/// <summary>
/// Handle request to get the alerts list
/// </summary>
internal async Task HandleAgentAlertsRequest(AgentAlertsParams parameters, RequestContext<AgentAlertsResult> requestContext)
{
var result = new AgentAlertsResult();
try
{
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(parameters.OwnerUri, out connInfo);
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
int alertsCount = dataContainer.Server.JobServer.Alerts.Count;
var alerts = new AgentAlertInfo[alertsCount];
for (int i = 0; i < alertsCount; ++i)
{
var alert = dataContainer.Server.JobServer.Alerts[i];
alerts[i] = new AgentAlertInfo
{
Id = alert.ID,
Name = alert.Name,
DelayBetweenResponses = alert.DelayBetweenResponses,
EventDescriptionKeyword = alert.EventDescriptionKeyword,
EventSource = alert.EventSource,
HasNotification = alert.HasNotification,
IncludeEventDescription = (Contracts.NotifyMethods)alert.IncludeEventDescription,
IsEnabled = alert.IsEnabled,
JobId = alert.JobID.ToString(),
JobName = alert.JobName,
LastOccurrenceDate = alert.LastOccurrenceDate.ToString(),
LastResponseDate = alert.LastResponseDate.ToString(),
MessageId = alert.MessageID,
NotificationMessage = alert.NotificationMessage,
OccurrenceCount = alert.OccurrenceCount,
PerformanceCondition = alert.PerformanceCondition,
Severity = alert.Severity,
DatabaseName = alert.DatabaseName,
CountResetDate = alert.CountResetDate.ToString(),
CategoryName = alert.CategoryName,
AlertType = (Contracts.AlertType)alert.AlertType,
WmiEventNamespace = alert.WmiEventNamespace,
WmiEventQuery = alert.WmiEventQuery
};
}
result.Alerts = alerts;
result.Success = true;
}
catch (Exception ex)
{
result.Success = false;
result.ErrorMessage = ex.ToString();
}
await requestContext.SendResult(result);
}
/// <summary>
/// Handle request to create an alert
/// </summary>
internal async Task HandleCreateAgentAlertRequest(CreateAgentAlertParams parameters, RequestContext<CreateAgentAlertResult> requestContext)
{
var result = await ConfigureAgentAlert(
parameters.OwnerUri,
parameters.Alert.Name,
parameters.Alert,
ConfigAction.Create,
RunType.RunNow);
await requestContext.SendResult(new CreateAgentAlertResult()
{
Success = result.Item1,
ErrorMessage = result.Item2
});
}
/// <summary>
/// Handle request to update an alert
/// </summary>
internal async Task HandleUpdateAgentAlertRequest(UpdateAgentAlertParams parameters, RequestContext<UpdateAgentAlertResult> requestContext)
{
var result = await ConfigureAgentAlert(
parameters.OwnerUri,
parameters.OriginalAlertName,
parameters.Alert,
ConfigAction.Update,
RunType.RunNow);
await requestContext.SendResult(new UpdateAgentAlertResult()
{
Success = result.Item1,
ErrorMessage = result.Item2
});
}
/// <summary>
/// Handle request to delete an alert
/// </summary>
internal async Task HandleDeleteAgentAlertRequest(DeleteAgentAlertParams parameters, RequestContext<ResultStatus> requestContext)
{
var result = await ConfigureAgentAlert(
parameters.OwnerUri,
parameters.Alert.Name,
parameters.Alert,
ConfigAction.Drop,
RunType.RunNow);
await requestContext.SendResult(new ResultStatus()
{
Success = result.Item1,
ErrorMessage = result.Item2
});
}
#endregion // "Alert Handlers"
#region "Operator Handlers"
internal async Task HandleAgentOperatorsRequest(AgentOperatorsParams parameters, RequestContext<AgentOperatorsResult> requestContext)
{
var result = new AgentOperatorsResult();
try
{
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(parameters.OwnerUri, out connInfo);
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
int operatorCount = dataContainer.Server.JobServer.Operators.Count;
var operators = new AgentOperatorInfo[operatorCount];
for (int i = 0; i < operatorCount; ++i)
{
var item = dataContainer.Server.JobServer.Operators[i];
operators[i] = new AgentOperatorInfo
{
Name = item.Name,
Id = item.ID,
EmailAddress = item.EmailAddress,
Enabled = item.Enabled,
LastEmailDate = item.LastEmailDate.ToString(),
LastNetSendDate = item.LastNetSendDate.ToString(),
LastPagerDate = item.LastPagerDate.ToString(),
PagerAddress = item.PagerAddress,
CategoryName = item.CategoryName,
PagerDays = (Contracts.WeekDays)item.PagerDays,
SaturdayPagerEndTime = item.SaturdayPagerEndTime.ToString(),
SaturdayPagerStartTime = item.SaturdayPagerEndTime.ToString(),
SundayPagerEndTime = item.SundayPagerEndTime.ToString(),
SundayPagerStartTime = item.SundayPagerStartTime.ToString(),
NetSendAddress = item.NetSendAddress,
WeekdayPagerStartTime = item.WeekdayPagerStartTime.ToString(),
WeekdayPagerEndTime = item.WeekdayPagerEndTime.ToString()
};
}
result.Operators = operators;
result.Success = true;
}
catch (Exception ex)
{
result.Success = false;
result.ErrorMessage = ex.ToString();
}
await requestContext.SendResult(result);
}
internal async Task HandleCreateAgentOperatorRequest(
CreateAgentOperatorParams parameters,
RequestContext<AgentOperatorResult> requestContext)
{
var result = await ConfigureAgentOperator(
parameters.OwnerUri,
parameters.Operator,
ConfigAction.Create,
RunType.RunNow);
await requestContext.SendResult(new AgentOperatorResult()
{
Success = result.Item1,
ErrorMessage = result.Item2,
Operator = parameters.Operator
});
}
internal async Task HandleUpdateAgentOperatorRequest(
UpdateAgentOperatorParams parameters,
RequestContext<AgentOperatorResult> requestContext)
{
var result = await ConfigureAgentOperator(
parameters.OwnerUri,
parameters.Operator,
ConfigAction.Update,
RunType.RunNow);
await requestContext.SendResult(new AgentOperatorResult()
{
Success = result.Item1,
ErrorMessage = result.Item2,
Operator = parameters.Operator
});
}
internal async Task HandleDeleteAgentOperatorRequest(
DeleteAgentOperatorParams parameters,
RequestContext<ResultStatus> requestContext)
{
var result = await ConfigureAgentOperator(
parameters.OwnerUri,
parameters.Operator,
ConfigAction.Drop,
RunType.RunNow);
await requestContext.SendResult(new ResultStatus()
{
Success = result.Item1,
ErrorMessage = result.Item2
});
}
#endregion // "Operator Handlers"
#region "Proxy Handlers"
internal async Task HandleAgentProxiesRequest(AgentProxiesParams parameters, RequestContext<AgentProxiesResult> requestContext)
{
var result = new AgentProxiesResult();
try
{
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(parameters.OwnerUri, out connInfo);
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
int proxyCount = dataContainer.Server.JobServer.ProxyAccounts.Count;
var proxies = new AgentProxyInfo[proxyCount];
for (int i = 0; i < proxyCount; ++i)
{
var proxy = dataContainer.Server.JobServer.ProxyAccounts[i];
proxies[i] = new AgentProxyInfo
{
Id = proxy.ID,
AccountName = proxy.Name,
Description = proxy.Description,
CredentialName = proxy.CredentialName,
CredentialIdentity = proxy.CredentialIdentity,
CredentialId = proxy.CredentialID,
IsEnabled = proxy.IsEnabled
};
}
result.Proxies = proxies;
result.Success = true;
}
catch (Exception ex)
{
result.Success = false;
result.ErrorMessage = ex.ToString();
}
await requestContext.SendResult(result);
}
internal async Task HandleCreateAgentProxyRequest(CreateAgentProxyParams parameters, RequestContext<AgentProxyResult> requestContext)
{
var result = await ConfigureAgentProxy(
parameters.OwnerUri,
parameters.Proxy.AccountName,
parameters.Proxy,
ConfigAction.Create,
RunType.RunNow);
await requestContext.SendResult(new AgentProxyResult()
{
Success = result.Item1,
ErrorMessage = result.Item2,
Proxy = parameters.Proxy
});
}
internal async Task HandleUpdateAgentProxyRequest(UpdateAgentProxyParams parameters, RequestContext<AgentProxyResult> requestContext)
{
var result = await ConfigureAgentProxy(
parameters.OwnerUri,
parameters.Proxy.AccountName,
parameters.Proxy,
ConfigAction.Update,
RunType.RunNow);
await requestContext.SendResult(new AgentProxyResult()
{
Success = result.Item1,
ErrorMessage = result.Item2,
Proxy = parameters.Proxy
});
}
internal async Task HandleDeleteAgentProxyRequest(DeleteAgentProxyParams parameters, RequestContext<ResultStatus> requestContext)
{
var result = await ConfigureAgentProxy(
parameters.OwnerUri,
parameters.Proxy.AccountName,
parameters.Proxy,
ConfigAction.Drop,
RunType.RunNow);
await requestContext.SendResult(new ResultStatus()
{
Success = result.Item1,
ErrorMessage = result.Item2
});
}
#endregion // "Proxy Handlers"
#region "Schedule Handlers"
internal async Task HandleAgentSchedulesRequest(AgentSchedulesParams parameters, RequestContext<AgentSchedulesResult> requestContext)
{
var result = new AgentSchedulesResult();
try
{
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(parameters.OwnerUri, out connInfo);
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
int scheduleCount = dataContainer.Server.JobServer.SharedSchedules.Count;
var schedules = new AgentScheduleInfo[scheduleCount];
for (int i = 0; i < scheduleCount; ++i)
{
var schedule = dataContainer.Server.JobServer.SharedSchedules[i];
var scheduleData = new JobScheduleData(schedule);
schedules[i] = new AgentScheduleInfo();
schedules[i].Id = schedule.ID;
schedules[i].Name = schedule.Name;
schedules[i].IsEnabled = schedule.IsEnabled;
schedules[i].FrequencyTypes = (Contracts.FrequencyTypes)schedule.FrequencyTypes;
schedules[i].FrequencySubDayTypes = (Contracts.FrequencySubDayTypes)schedule.FrequencySubDayTypes;
schedules[i].FrequencySubDayInterval = schedule.FrequencySubDayInterval;
schedules[i].FrequencyRelativeIntervals = (Contracts.FrequencyRelativeIntervals)schedule.FrequencyRelativeIntervals;
schedules[i].FrequencyRecurrenceFactor = schedule.FrequencyRecurrenceFactor;
schedules[i].FrequencyInterval = schedule.FrequencyInterval;
schedules[i].DateCreated = schedule.DateCreated;
schedules[i].ActiveStartTimeOfDay = schedule.ActiveStartTimeOfDay;
schedules[i].ActiveStartDate = schedule.ActiveStartDate;
schedules[i].ActiveEndTimeOfDay = schedule.ActiveEndTimeOfDay;
schedules[i].JobCount = schedule.JobCount;
schedules[i].ActiveEndDate = schedule.ActiveEndDate;
schedules[i].ScheduleUid = schedule.ScheduleUid;
schedules[i].Description = scheduleData.Description;
}
result.Schedules = schedules;
result.Success = true;
}
catch (Exception ex)
{
result.Success = false;
result.ErrorMessage = ex.ToString();
}
await requestContext.SendResult(result);
}
internal async Task HandleCreateAgentScheduleRequest(CreateAgentScheduleParams parameters, RequestContext<AgentScheduleResult> requestContext)
{
var result = await ConfigureAgentSchedule(
parameters.OwnerUri,
parameters.Schedule,
ConfigAction.Create,
RunType.RunNow);
await requestContext.SendResult(new AgentScheduleResult()
{
Success = result.Item1,
ErrorMessage = result.Item2,
Schedule = parameters.Schedule
});
}
internal async Task HandleUpdateAgentScheduleRequest(UpdateAgentScheduleParams parameters, RequestContext<AgentScheduleResult> requestContext)
{
var result = await ConfigureAgentSchedule(
parameters.OwnerUri,
parameters.Schedule,
ConfigAction.Update,
RunType.RunNow);
await requestContext.SendResult(new AgentScheduleResult()
{
Success = result.Item1,
ErrorMessage = result.Item2,
Schedule = parameters.Schedule
});
}
internal async Task HandleDeleteAgentScheduleRequest(DeleteAgentScheduleParams parameters, RequestContext<ResultStatus> requestContext)
{
var result = await ConfigureAgentSchedule(
parameters.OwnerUri,
parameters.Schedule,
ConfigAction.Drop,
RunType.RunNow);
await requestContext.SendResult(new ResultStatus()
{
Success = result.Item1,
ErrorMessage = result.Item2
});
}
#endregion // "Schedule Handlers"
#region "Helpers"
internal void ExecuteAction(ManagementActionBase action, RunType runType)
{
var executionHandler = new ExecutonHandler(action);
executionHandler.RunNow(runType, this);
if (executionHandler.ExecutionResult == ExecutionMode.Failure)
{
if (executionHandler.ExecutionFailureException != null)
{
throw executionHandler.ExecutionFailureException;
}
else
{
throw new Exception("Failed to execute action");
}
}
}
internal async Task<Tuple<bool, string>> ConfigureAgentJob(
string ownerUri,
string originalJobName,
AgentJobInfo jobInfo,
ConfigAction configAction,
RunType runType)
{
try
{
JobData jobData;
CDataContainer dataContainer;
CreateJobData(ownerUri, originalJobName, out dataContainer, out jobData, configAction, jobInfo);
using (JobActions actions = new JobActions(dataContainer, jobData, configAction))
{
ExecuteAction(actions, runType);
}
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(ownerUri, out connInfo);
if (connInfo != null)
{
dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
}
// Execute step actions if they exist
if (configAction != ConfigAction.Drop && jobInfo.JobSteps != null && jobInfo.JobSteps.Length > 0)
{
foreach (AgentJobStepInfo step in jobInfo.JobSteps)
{
configAction = ConfigAction.Create;
foreach (JobStep jobStep in dataContainer.Server.JobServer.Jobs[originalJobName].JobSteps)
{
// any changes made to step other than name or ordering
if ((step.StepName == jobStep.Name && step.Id == jobStep.ID) ||
// if the step name was changed
(step.StepName != jobStep.Name && step.Id == jobStep.ID) ||
// if the step ordering was changed
(step.StepName == jobStep.Name && step.Id != jobStep.ID))
{
configAction = ConfigAction.Update;
break;
}
}
await ConfigureAgentJobStep(ownerUri, step, configAction, runType, jobData, dataContainer);
}
}
// Execute schedule actions if they exist
if (jobInfo.JobSchedules != null && jobInfo.JobSchedules.Length > 0)
{
foreach (AgentScheduleInfo schedule in jobInfo.JobSchedules)
{
await ConfigureAgentSchedule(ownerUri, schedule, configAction, runType, jobData, dataContainer);
}
}
// Execute alert actions if they exist
if (jobInfo.Alerts != null && jobInfo.Alerts.Length > 0)
{
foreach (AgentAlertInfo alert in jobInfo.Alerts)
{
alert.JobId = jobData.Job.JobID.ToString();
await ConfigureAgentAlert(ownerUri, alert.Name, alert, configAction, runType, jobData, dataContainer);
}
}
return new Tuple<bool, string>(true, string.Empty);
}
catch (Exception ex)
{
return new Tuple<bool, string>(false, ex.ToString());
}
}
internal Task<Tuple<bool, string>> ConfigureAgentJobStep(
string ownerUri,
AgentJobStepInfo stepInfo,
ConfigAction configAction,
RunType runType,
JobData jobData = null,
CDataContainer dataContainer = null)
{
return Task.Run(() =>
{
try
{
if (string.IsNullOrWhiteSpace(stepInfo.JobName))
{
return new Tuple<bool, string>(false, "JobName cannot be null");
}
if (jobData == null)
{
CreateJobData(ownerUri, stepInfo.JobName, out dataContainer, out jobData);
}
using (var actions = new JobStepsActions(dataContainer, jobData, stepInfo, configAction))
{
ExecuteAction(actions, runType);
}
return new Tuple<bool, string>(true, string.Empty);
}
catch (Exception ex)
{
// log exception here
return new Tuple<bool, string>(false, ex.ToString());
}
});
}
internal Task<Tuple<bool, string>> ConfigureAgentAlert(
string ownerUri,
string alertName,
AgentAlertInfo alert,
ConfigAction configAction,
RunType runType,
JobData jobData = null,
CDataContainer dataContainer = null)
{
return Task<Tuple<bool, string>>.Run(() =>
{
try
{
// If the alert is being created outside of a job
if (string.IsNullOrWhiteSpace(alert.JobName))
{
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(ownerUri, out connInfo);
dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
}
else
{
if (jobData == null)
{
// If the alert is being created inside a job
CreateJobData(ownerUri, alert.JobName, out dataContainer, out jobData);
}
}
STParameters param = new STParameters(dataContainer.Document);
param.SetParam("alert", alertName);
if (alert != null)
{
using (AgentAlertActions actions = new AgentAlertActions(dataContainer, alertName, alert, configAction, jobData))
{
ExecuteAction(actions, runType);
}
}
return new Tuple<bool, string>(true, string.Empty);
}
catch (Exception ex)
{
return new Tuple<bool, string>(false, ex.ToString());
}
});
}
internal Task<Tuple<bool, string>> ConfigureAgentOperator(
string ownerUri,
AgentOperatorInfo operatorInfo,
ConfigAction configAction,
RunType runType)
{
return Task.Run(() =>
{
try
{
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(ownerUri, out connInfo);
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
STParameters param = new STParameters(dataContainer.Document);
param.SetParam("operator", operatorInfo.Name);
using (AgentOperatorActions actions = new AgentOperatorActions(dataContainer, operatorInfo, configAction))
{
ExecuteAction(actions, runType);
}
return new Tuple<bool, string>(true, string.Empty);
}
catch (Exception ex)
{
return new Tuple<bool, string>(false, ex.ToString());
}
});
}
internal Task<Tuple<bool, string>> ConfigureAgentProxy(
string ownerUri,
string accountName,
AgentProxyInfo proxy,
ConfigAction configAction,
RunType runType)
{
return Task.Run(() =>
{
try
{
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(ownerUri, out connInfo);
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
STParameters param = new STParameters(dataContainer.Document);
param.SetParam("proxyaccount", accountName);
using (AgentProxyAccountActions actions = new AgentProxyAccountActions(dataContainer, proxy, configAction))
{
ExecuteAction(actions, runType);
}
return new Tuple<bool, string>(true, string.Empty);
}
catch (Exception ex)
{
return new Tuple<bool, string>(false, ex.ToString());
}
});
}
internal Task<Tuple<bool, string>> ConfigureAgentSchedule(
string ownerUri,
AgentScheduleInfo schedule,
ConfigAction configAction,
RunType runType,
JobData jobData = null,
CDataContainer dataContainer = null)
{
return Task.Run(() =>
{
try
{
if (jobData == null)
{
CreateJobData(ownerUri, schedule.JobName, out dataContainer, out jobData);
}
const string UrnFormatStr = "Server/JobServer[@Name='{0}']/Job[@Name='{1}']/Schedule[@Name='{2}']";
string serverName = dataContainer.Server.Name.ToUpper();
string scheduleUrn = string.Format(UrnFormatStr, serverName, jobData.Job.Name, schedule.Name);
STParameters param = new STParameters(dataContainer.Document);
param.SetParam("urn", scheduleUrn);
using (JobSchedulesActions actions = new JobSchedulesActions(dataContainer, jobData, schedule, configAction))
{
ExecuteAction(actions, runType);
}
return new Tuple<bool, string>(true, string.Empty);
}
catch (Exception ex)
{
return new Tuple<bool, string>(false, ex.ToString());
}
});
}
private void CreateJobData(
string ownerUri,
string jobName,
out CDataContainer dataContainer,
out JobData jobData,
ConfigAction configAction = ConfigAction.Create,
AgentJobInfo jobInfo = null)
{
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(ownerUri, out connInfo);
dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
XmlDocument jobDoc = CreateJobXmlDocument(dataContainer.Server.Name.ToUpper(), jobName);
dataContainer.Init(jobDoc.InnerXml);
STParameters param = new STParameters(dataContainer.Document);
string originalName = jobInfo != null && !string.Equals(jobName, jobInfo.Name) ? jobName : string.Empty;
param.SetParam("job", configAction == ConfigAction.Update ? jobName : string.Empty);
param.SetParam("jobid", string.Empty);
jobData = new JobData(dataContainer, jobInfo, configAction);
}
public static XmlDocument CreateJobXmlDocument(string svrName, string jobName)
{
// XML element strings
const string XmlFormDescElementName = "formdescription";
const string XmlParamsElementName = "params";
const string XmlJobElementName = "job";
const string XmlUrnElementName = "urn";
const string UrnFormatStr = "Server/JobServer[@Name='{0}']/Job[@Name='{1}']";
// Write out XML.
StringWriter textWriter = new StringWriter();
XmlTextWriter xmlWriter = new XmlTextWriter(textWriter);
xmlWriter.WriteStartElement(XmlFormDescElementName);
xmlWriter.WriteStartElement(XmlParamsElementName);
xmlWriter.WriteElementString(XmlJobElementName, jobName);
xmlWriter.WriteElementString(XmlUrnElementName, string.Format(UrnFormatStr, svrName, jobName));
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
xmlWriter.Close();
// Create an XML document.
XmlDocument doc = new XmlDocument();
XmlTextReader rdr = new XmlTextReader(new System.IO.StringReader(textWriter.ToString()));
rdr.MoveToContent();
doc.LoadXml(rdr.ReadOuterXml());
return doc;
}
private Tuple<SqlConnectionInfo, DataTable, ServerConnection> CreateSqlConnection(ConnectionInfo connInfo, String jobId)
{
var serverConnection = ConnectionService.OpenServerConnection(connInfo);
var server = new Server(serverConnection);
var filter = new JobHistoryFilter();
filter.JobID = new Guid(jobId);
var dt = server.JobServer.EnumJobHistory(filter);
var sqlConnInfo = new SqlConnectionInfo(serverConnection, SqlServer.Management.Common.ConnectionType.SqlConnection);
return new Tuple<SqlConnectionInfo, DataTable, ServerConnection>(sqlConnInfo, dt, serverConnection);
}
internal async Task HandleAgentNotebooksRequest(AgentNotebooksParams parameters, RequestContext<AgentNotebooksResult> requestContext)
{
var result = new AgentNotebooksResult();
try
{
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(
parameters.OwnerUri,
out connInfo);
result.Success = true;
result.Notebooks = AgentNotebookHelper.GetAgentNotebooks(connInfo).Result;
}
catch (Exception e)
{
result.Success = false;
result.ErrorMessage = e.ToString();
}
await requestContext.SendResult(result);
}
internal async Task HandleAgentNotebookHistoryRequest(
AgentNotebookHistoryParams parameters, RequestContext<AgentNotebookHistoryResult> requestContext)
{
var result = new AgentNotebookHistoryResult();
try
{
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(
parameters.OwnerUri,
out connInfo);
result = await GetAgentNotebookHistories(
connInfo,
parameters.JobId,
parameters.JobName,
parameters.TargetDatabase
);
result.Success = true;
}
catch (Exception e)
{
result.Success = false;
result.ErrorMessage = e.ToString();
}
await requestContext.SendResult(result);
}
internal async Task HandleAgentNotebookMaterializedRequest(AgentNotebookMaterializedParams parameters, RequestContext<AgentNotebookMaterializedResult> requestContext)
{
var result = new AgentNotebookMaterializedResult();
try
{
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(
parameters.OwnerUri,
out connInfo);
result.NotebookMaterialized = AgentNotebookHelper.GetMaterializedNotebook(connInfo, parameters.NotebookMaterializedId, parameters.TargetDatabase).Result;
result.Success = true;
}
catch (Exception e)
{
result.Success = false;
result.ErrorMessage = e.ToString();
}
await requestContext.SendResult(result);
}
internal async Task HandleAgentNotebookTemplateRequest(AgentNotebookTemplateParams parameters, RequestContext<AgentNotebookTemplateResult> requestContext)
{
var result = new AgentNotebookTemplateResult();
try
{
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(
parameters.OwnerUri,
out connInfo);
result.NotebookTemplate = await AgentNotebookHelper.GetTemplateNotebook(connInfo, parameters.JobId, parameters.TargetDatabase);
result.Success = true;
}
catch (Exception e)
{
result.Success = false;
result.ErrorMessage = e.ToString();
}
await requestContext.SendResult(result);
}
internal async Task HandleCreateAgentNotebookRequest(CreateAgentNotebookParams parameters, RequestContext<CreateAgentNotebookResult> requestContext)
{
var result = new CreateAgentNotebookResult();
try
{
// storing result
result.Success = true;
await AgentNotebookHelper.CreateNotebook(
this,
parameters.OwnerUri,
parameters.Notebook,
parameters.TemplateFilePath,
ManagementUtils.asRunType(parameters.TaskExecutionMode)
);
}
catch (Exception e)
{
result.Success = false;
result.ErrorMessage = e.ToString();
}
await requestContext.SendResult(result);
}
internal async Task HandleDeleteAgentNotebooksRequest(DeleteAgentNotebookParams parameters, RequestContext<ResultStatus> requestContext)
{
var result = new ResultStatus();
try
{
// Calling delete notebook helper function
await AgentNotebookHelper.DeleteNotebook(
this,
parameters.OwnerUri,
parameters.Notebook,
ManagementUtils.asRunType(parameters.TaskExecutionMode)
);
result.Success = true;
}
catch (Exception e)
{
result.Success = false;
result.ErrorMessage = e.ToString();
}
await requestContext.SendResult(result);
}
internal async Task HandleUpdateAgentNotebookRequest(UpdateAgentNotebookParams parameters, RequestContext<UpdateAgentNotebookResult> requestContext)
{
var result = new UpdateAgentNotebookResult();
try
{
// Calling update helper function
await AgentNotebookHelper.UpdateNotebook(
this,
parameters.OwnerUri,
parameters.OriginalNotebookName,
parameters.Notebook,
parameters.TemplateFilePath,
ManagementUtils.asRunType(parameters.TaskExecutionMode));
result.Success = true;
}
catch (Exception e)
{
result.Success = false;
result.ErrorMessage = e.ToString();
}
await requestContext.SendResult(result);
}
internal async Task HandleUpdateAgentNotebookRunNameRequest(UpdateAgentNotebookRunNameParams parameters, RequestContext<ResultStatus> requestContext)
{
var result = new ResultStatus();
try
{
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(
parameters.OwnerUri,
out connInfo);
// Calling update helper function
await AgentNotebookHelper.UpdateMaterializedNotebookName(
connInfo,
parameters.agentNotebookHistory,
parameters.TargetDatabase,
parameters.MaterializedNotebookName);
result.Success = true;
}
catch (Exception e)
{
result.Success = false;
result.ErrorMessage = e.ToString();
}
await requestContext.SendResult(result);
}
internal async Task HandleUpdateAgentNotebookRunPinRequest(UpdateAgentNotebookRunPinParams parameters, RequestContext<ResultStatus> requestContext)
{
var result = new ResultStatus();
try
{
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(
parameters.OwnerUri,
out connInfo);
// Calling update helper function
await AgentNotebookHelper.UpdateMaterializedNotebookPin(
connInfo,
parameters.agentNotebookHistory,
parameters.TargetDatabase,
parameters.MaterializedNotebookPin);
result.Success = true;
}
catch (Exception e)
{
result.Success = false;
result.ErrorMessage = e.ToString();
}
await requestContext.SendResult(result);
}
internal async Task HandleDeleteNotebookMaterializedRequest(DeleteMaterializedNotebookParams parameters, RequestContext<ResultStatus> requestContext)
{
var result = new ResultStatus();
try
{
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(
parameters.OwnerUri,
out connInfo);
// Calling update helper function
await AgentNotebookHelper.DeleteMaterializedNotebook(
connInfo,
parameters.agentNotebookHistory,
parameters.TargetDatabase);
result.Success = true;
}
catch (Exception e)
{
result.Success = false;
result.ErrorMessage = e.ToString();
}
await requestContext.SendResult(result);
}
public async Task<AgentNotebookHistoryResult> GetAgentNotebookHistories
(
ConnectionInfo connInfo,
string jobId,
string jobName,
string targetDatabase
)
{
AgentNotebookHistoryResult result = new AgentNotebookHistoryResult();
// fetching Job information
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
var jobServer = dataContainer.Server.JobServer;
var jobs = jobServer.Jobs;
Tuple<SqlConnectionInfo, DataTable, ServerConnection> tuple = CreateSqlConnection(connInfo, jobId);
SqlConnectionInfo sqlConnInfo = tuple.Item1;
DataTable dt = tuple.Item2;
// add steps to the job if any
JobStepCollection steps = jobs[jobName].JobSteps;
var jobSteps = new List<AgentJobStepInfo>();
foreach (JobStep step in steps)
{
jobSteps.Add(AgentUtilities.ConvertToAgentJobStepInfo(step, jobId, jobName));
}
result.Steps = jobSteps.ToArray();
// add schedules to the job if any
JobScheduleCollection schedules = jobs[jobName].JobSchedules;
var jobSchedules = new List<AgentScheduleInfo>();
foreach (JobSchedule schedule in schedules)
{
jobSchedules.Add(AgentUtilities.ConvertToAgentScheduleInfo(schedule));
}
result.Schedules = jobSchedules.ToArray();
// add histories
int count = dt.Rows.Count;
List<AgentNotebookHistoryInfo> notebookHistories = new List<AgentNotebookHistoryInfo>();
if (count > 0)
{
var job = dt.Rows[0];
Guid tempjobId = (Guid)job[AgentUtilities.UrnJobId];
int runStatus = Convert.ToInt32(job[AgentUtilities.UrnRunStatus], System.Globalization.CultureInfo.InvariantCulture);
var t = new LogSourceJobHistory(jobName, sqlConnInfo, null, runStatus, tempjobId, null);
var tlog = t as ILogSource;
tlog.Initialize();
var logEntries = t.LogEntries;
var jobHistories = AgentUtilities.ConvertToAgentNotebookHistoryInfo(logEntries, job, steps);
// fetching notebook part of histories
Dictionary<string, DataRow> notebookHistoriesDict = new Dictionary<string, DataRow>();
DataTable materializedNotebookTable = await AgentNotebookHelper.GetAgentNotebookHistories(connInfo, jobId, targetDatabase);
foreach (DataRow materializedNotebookRow in materializedNotebookTable.Rows)
{
notebookHistoriesDict.Add(materializedNotebookRow["job_runtime"].ToString(), materializedNotebookRow);
}
// adding notebook information to job histories
foreach (var jobHistory in jobHistories)
{
string jobRuntime = jobHistory.RunDate.ToString("yyyyMMddHHmmss");
AgentNotebookHistoryInfo notebookHistory = jobHistory;
if (notebookHistoriesDict.ContainsKey(jobRuntime))
{
notebookHistory.MaterializedNotebookId = (int)notebookHistoriesDict[jobRuntime]["materialized_id"];
notebookHistory.MaterializedNotebookErrorInfo = notebookHistoriesDict[jobRuntime]["notebook_error"] as string;
notebookHistory.MaterializedNotebookName = notebookHistoriesDict[jobRuntime]["notebook_name"] as string;
notebookHistory.MaterializedNotebookPin = (bool)notebookHistoriesDict[jobRuntime]["pin"];
notebookHistory.MaterializedNotebookDeleted = (bool)notebookHistoriesDict[jobRuntime]["is_deleted"];
}
if (notebookHistory.MaterializedNotebookDeleted)
{
continue;
}
notebookHistories.Add(notebookHistory);
}
result.Histories = notebookHistories.ToArray();
tlog.CloseReader();
}
return result;
}
#endregion // "Helpers"
internal void DeleteAgentNotebooksTempFiles()
{
if (FileUtilities.SafeDirectoryExists(FileUtilities.AgentNotebookTempFolder))
{
FileUtilities.SafeDirectoryDelete(FileUtilities.AgentNotebookTempFolder, true);
}
}
}
}