/// <summary> /// Fetch the next restore request to be processed. Status = ACCEPTED /// </summary> /// <returns>RestoreReqResponse</returns> public async Task <RestoreReqResponse> GetRestoreRequest() { RestoreReqResponse reqRespData = null; CloudTable restoreReqTable = GetCloudTable(); EventDateDetails dateDetails = new EventDateDetails(DateTime.Now); var whereCondition = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, $"{dateDetails.year.ToString()}_{dateDetails.WeekNumber.ToString()}"); var statusCondition = TableQuery.GenerateFilterCondition("CurrentStatus", QueryComparisons.Equal, Constants.Constants.RESTORE_STATUS_ACCEPTED); string query = TableQuery.CombineFilters(whereCondition, TableOperators.And, statusCondition); TableQuery <RestoreReqEntity> partitionQuery = new TableQuery <RestoreReqEntity>().Where(query); partitionQuery.TakeCount = 1; // Return only one record at a time; TableQuerySegment <RestoreReqEntity> resultSegment = await restoreReqTable.ExecuteQuerySegmentedAsync(partitionQuery, null); if ((resultSegment.Results != null) && (resultSegment.Results.Count == 1)) { foreach (RestoreReqEntity entity in resultSegment.Results) { reqRespData = JsonConvert.DeserializeObject <RestoreReqResponse>(entity.RestoreReqRespDataJSON); } } ; return(reqRespData); }
/// <summary> /// Insert restore request entity in the storage table /// </summary> /// <param name="restoreRequest"></param> /// <returns></returns> public async Task InsertRestoreRequest(RestoreReqResponse restoreRequest) { CloudTable restoreReqTable = GetCloudTable(); IRestoreReqEntity restoreEntity = new RestoreReqEntity(restoreRequest); // Create the TableOperation object that inserts the restore request entity. TableOperation insertOperation = TableOperation.Insert(restoreEntity); // Execute the insert operation. await restoreReqTable.ExecuteAsync(insertOperation); }
public async Task <ActionResult <RestoreReqResponse> > Run( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "restore/blobs")] HttpRequest req, Microsoft.Extensions.Logging.ILogger log) { log.LogInformation($"PerformRestore: Invoked at: {DateTime.Now}"); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); RestoreReqResponse reqRespData = await ValidateInput(req); if (string.IsNullOrEmpty(reqRespData.ExceptionMessage)) { try { // First check if async restore is requested if (reqRespData.ReqType.Equals(Constants.RESTORE_REQUEST_TYPE_ASYNC)) { reqRespData.Status = Constants.RESTORE_STATUS_ACCEPTED; reqRespData.StatusLocationUri = $"{req.Scheme}://{req.Host}{req.PathBase}/api/restore/"; await _restoreTable.InsertRestoreRequest(reqRespData); } else { log.LogInformation($"PerformRestore: Start date : {reqRespData.StDate.ToString("MM/dd/yyyy")}, End date {reqRespData.EnDate.ToString("MM/dd/yyyy")}. Proceeding with restore process ..."); if (!String.IsNullOrEmpty(reqRespData.ContainerName)) { log.LogInformation($"PerformRestore: Container Name : {reqRespData.ContainerName}"); } await _restoreBackup.Run(reqRespData); }; log.LogInformation($"PerformRestore: Completed execution at: {DateTime.Now}"); } catch (Exception ex) { log.LogError($"PerformRestore: Exception occurred. Exception: {@ex.ToString()}"); reqRespData.ExceptionMessage = $"Encountered exception : {@ex.ToString()}"; reqRespData.Status = Constants.RESTORE_STATUS_FAILED; } } ; stopWatch.Stop(); reqRespData.ExecutionTime = DateTimeUtil.getTimeString(stopWatch.Elapsed); return(reqRespData); }
/// <summary> /// Get the current status/details of a restore request /// </summary> public RestoreReqResponse GetRestoreReqDetails(string datestr, string guid) { CloudTable restoreReqTable = GetCloudTable(); RestoreReqResponse restoreReqStatus = null; // Execute 'point' query to retrieve the restore request details - TableOperation retrieveOperation = TableOperation.Retrieve <RestoreReqEntity>(datestr, guid); var retrieveResult = restoreReqTable.Execute(retrieveOperation); if (retrieveResult.Result != null) { RestoreReqEntity reqEntity = (RestoreReqEntity)retrieveResult.Result; restoreReqStatus = JsonConvert.DeserializeObject <RestoreReqResponse>(reqEntity.RestoreReqRespDataJSON); } ; return(restoreReqStatus); }
public ActionResult <RestoreReqResponse> Run0( [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "restore/{datestr}/{guid}")] HttpRequest req, string datestr, string guid, ILogger log) { log.LogInformation($"GetRestoreStatus: Invoked at: {DateTime.Now}"); RestoreReqResponse restoreDetails = _restoreTable.GetRestoreReqDetails(datestr, guid); if (restoreDetails == null) { restoreDetails = new RestoreReqResponse(); restoreDetails.Status = Constants.RESTORE_STATUS_UNKNOWN; restoreDetails.ExceptionMessage = $"Couldn't find a restore request for year_weekno:{datestr} and guid:{guid}. Check the URI."; } ; log.LogInformation($"GetRestoreStatus: Completed execution at: {DateTime.Now}"); return(restoreDetails); }
/// <summary> /// Update a restore request entity in the storage table /// </summary> /// <param>RestoreReqResponse</param> public async Task UpdateRestoreRequest(RestoreReqResponse restoreRequest) { string url = restoreRequest.StatusLocationUri; string guid = url.Substring(url.LastIndexOf("/") + 1); url = url.Substring(0, url.LastIndexOf("/")); string datestr = url.Substring(url.LastIndexOf("/") + 1); RestoreReqEntity reqEntity = new RestoreReqEntity(); reqEntity.PartitionKey = datestr; reqEntity.RowKey = guid; reqEntity.CurrentStatus = restoreRequest.Status; reqEntity.RestoreReqRespDataJSON = JsonConvert.SerializeObject(restoreRequest); CloudTable restoreReqTable = GetCloudTable(); TableOperation mergeOperation = TableOperation.InsertOrMerge(reqEntity); // Execute the merge operation TableResult result = await restoreReqTable.ExecuteAsync(mergeOperation); }
/// <summary> /// Run method /// 1: Reads messages from the table storage in ascending order. /// 2: Executes the delete or create operation on the destination blob. /// </summary> /// <returns></returns> public async Task Run(RestoreReqResponse reqResponse) { _logger.LogDebug("Begin: RestoreBackupWorker.Run"); //Since there can be many records around 84K for a day, let's read the records day by day and perform the restore operation List <Tuple <int, int, DateTime> > dates = GetDatesForDateRange(reqResponse.StDate, reqResponse.EnDate); _logger.LogInformation($"Number of dates determined.---{dates.Count()}"); int totalSuccessCount = 0; int totalFailureCount = 0; foreach (Tuple <int, int, DateTime> dateData in dates) { _logger.LogInformation($"Starting restore for Year {dateData.Item1} Week {dateData.Item2} and Date {dateData.Item3.ToString("MM/dd/yyyy")}"); var blobEvents = await _logRepository.GetBLOBEvents(dateData.Item1, dateData.Item2, dateData.Item3, dateData.Item3.AddDays(1)); _logger.LogInformation($"Found {blobEvents.Count} for {dateData.Item1} and Date {dateData.Item3.ToString("MM/dd/yyyy")}"); if (blobEvents != null && blobEvents.Count > 0) { foreach (EventData eventData in blobEvents) { try { if (eventData.ReceivedEventData is BlobEvent <CreatedEventData> ) { BlobEvent <CreatedEventData> createdBlob = (BlobEvent <CreatedEventData>)eventData.ReceivedEventData; if (eventData.DestinationBlobInfo != null) { if ((!String.IsNullOrEmpty(reqResponse.ContainerName)) && (!String.Equals(eventData.DestinationBlobInfo.OrgContainerName, reqResponse.ContainerName))) { continue; } if ((reqResponse.BlobNames != null) && (!reqResponse.BlobNames.Contains(eventData.DestinationBlobInfo.OrgBlobName))) { continue; } _logger.LogInformation($"Going to perform copy as it is a created event {createdBlob.data.url}"); await _blobRepository.CopyBlobFromBackupToRestore(eventData.DestinationBlobInfo); } else { _logger.LogInformation($"Copy of the blob will be ignored as at the time of backup the blob was not present at source. One of the cause can be , a delete has been performed already on this blob. {createdBlob.data.url}"); continue; } } else if (eventData.ReceivedEventData is BlobEvent <DeletedEventData> ) { BlobEvent <DeletedEventData> deletedBlob = (BlobEvent <DeletedEventData>)eventData.ReceivedEventData; if (reqResponse.SkipDeletes.ToUpper(new CultureInfo("en-US", false)).Equals(Constants.Constants.RESTORE_SKIP_DELETES_YES)) { continue; } if ((!String.IsNullOrEmpty(reqResponse.ContainerName)) && (!deletedBlob.data.url.Contains(reqResponse.ContainerName))) { continue; } if ((reqResponse.BlobNames != null) && (!reqResponse.BlobNames.Exists(x => deletedBlob.data.url.Contains(x)))) { continue; } _logger.LogInformation($"Going to perform delete as it is a deleted event {deletedBlob.data.url}"); await _blobRepository.DeleteBlobFromRestore(eventData.ReceivedEventData); } else { _logger.LogInformation($"Currently only Created and Deleted events are supported. Event Data: {eventData.ReceivedEventDataJSON}"); continue; } totalSuccessCount++; } catch (Exception ex) { totalFailureCount++; _logger.LogError($"Exception while restoring event {eventData.ReceivedEventDataJSON}. Exception {ex.ToString()}"); } if (reqResponse.ReqType.Equals(Constants.Constants.RESTORE_REQUEST_TYPE_ASYNC) && (totalSuccessCount % _updateFrequencyCount == 0)) { reqResponse.TotalSuccessCount = totalSuccessCount; reqResponse.TotalFailureCount = totalFailureCount; await _restoreTblRepository.UpdateRestoreRequest(reqResponse); } ; } ; // Update the processed record count for async restore request } } ; // End of outer For loop _logger.LogInformation($"Restore Success records count: {totalSuccessCount}. Restore Failure records count: {totalFailureCount}."); reqResponse.TotalSuccessCount = totalSuccessCount; reqResponse.TotalFailureCount = totalFailureCount; _logger.LogDebug("End: RestoreBackupWorker.Run"); }
private async Task <RestoreReqResponse> ValidateInput(HttpRequest req) { string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); RestoreReqResponse reqRespData = JsonConvert.DeserializeObject <RestoreReqResponse>(requestBody); if (String.IsNullOrEmpty(reqRespData.StartDate) || String.IsNullOrEmpty(reqRespData.EndDate)) { reqRespData.ExceptionMessage = "Start and End dates are incorrect and/or missing!"; reqRespData.Status = Constants.RESTORE_STATUS_FAILED; return(reqRespData); } ; DateTime startDate = DateTime.MinValue; DateTime endDate = DateTime.MinValue; bool startDateParsed = false; bool endDateParsed = false; startDateParsed = DateTime.TryParse(reqRespData.StartDate, out startDate); endDateParsed = DateTime.TryParse(reqRespData.EndDate, out endDate); if (!startDateParsed || !endDateParsed) { reqRespData.ExceptionMessage = $"Unable to parse start and end dates. Provide dates in mm/dd/yyyy format. Start date value {reqRespData.StartDate} End date value {reqRespData.EndDate}. "; reqRespData.Status = Constants.RESTORE_STATUS_FAILED; return(reqRespData); } ; if (startDate > endDate) { reqRespData.ExceptionMessage = "Start date cannot be greater than End date."; reqRespData.Status = Constants.RESTORE_STATUS_FAILED; return(reqRespData); } ; reqRespData.StDate = startDate; reqRespData.EnDate = endDate; if ((reqRespData.BlobNames != null)) { if (String.IsNullOrEmpty(reqRespData.ContainerName)) { reqRespData.ExceptionMessage = $"Container name is required to restore blobs!"; reqRespData.Status = Constants.RESTORE_STATUS_FAILED; return(reqRespData); } ; } ; if (!String.IsNullOrEmpty(reqRespData.ReqType)) { if (!reqRespData.ReqType.Equals(Constants.RESTORE_REQUEST_TYPE_SYNC) && !reqRespData.ReqType.Equals(Constants.RESTORE_REQUEST_TYPE_ASYNC)) { reqRespData.ExceptionMessage = $"Request Type '{reqRespData.ReqType}' is invalid. Value should be either 'Sync' or 'Async'!"; reqRespData.Status = Constants.RESTORE_STATUS_FAILED; } ; } ; return(reqRespData); }
/// <summary> /// Main for restore. /// </summary> /// <param name="args"></param> static async Task Main(string[] args) { try { if (args == null || args.Length < 2) { Console.WriteLine("In order to restore the backup please provide start and end date. Date format is mm/dd/yyyy!"); Console.ReadKey(); return; } DateTime startDate = DateTime.MinValue; DateTime endDate = DateTime.MinValue; bool startDateParsed = false; bool endDateParsed = false; // if (args.Length == 2) ID05192020.o // { startDateParsed = DateTime.TryParse(args[0], out startDate); endDateParsed = DateTime.TryParse(args[1], out endDate); // } if (!startDateParsed || !endDateParsed) { Console.WriteLine($"Unable to parse start and end date. Provide dates in mm/dd/yyyy format. Start date value {args[0]} End date value {args[1]}. "); Console.ReadKey(); return; } if (startDate > endDate) { Console.WriteLine($"Start date cannot be greater than end date."); Console.ReadKey(); return; } string containerName = (args.Length > 2) ? args[2] : null; // ID05192020.n // Console.WriteLine($"Here are the captured values. Start date : {startDate.ToString("MM/dd/yyyy")} End date {endDate.ToString("MM/dd/yyyy")}."); ID05192020.o Console.WriteLine($"Here are the captured values. Start date : {startDate.ToString("MM/dd/yyyy")} End date : {endDate.ToString("MM/dd/yyyy")}. Container Name : {containerName}"); // ID05192020.n Console.WriteLine($"Please enter \"Y\" to continue performing the restore'"); string response = Console.ReadKey().Key.ToString(); if (!response.ToLower().Equals("y")) { Console.WriteLine($"Press any key to exit!"); Console.ReadKey(); return; } //to do start the restore process. // Create service collection var serviceCollection = new ServiceCollection(); ConfigureServices(serviceCollection); // Create service provider _serviceProvider = serviceCollection.BuildServiceProvider(); var config = _serviceProvider.GetService <IConfigurationRoot>(); var logger = _serviceProvider.GetService <ILogger <RestoreBackupWorker> >(); IRestoreBackup restoreBackup = _serviceProvider.GetService <IRestoreBackup>(); // Run the restore process // await restoreBackup.Run(startDate, endDate); ID05192020.o // await restoreBackup.Run(startDate, endDate, containerName); // ID05202020.o // ID05202020.sn RestoreReqResponse reqResData = new RestoreReqResponse(); reqResData.StDate = startDate; reqResData.EnDate = endDate; reqResData.ContainerName = containerName; await restoreBackup.Run(reqResData); // ID05202020.en Console.WriteLine($"Press any key to exit!"); Console.ReadLine(); } catch (Exception ex) { Console.WriteLine($"An exception occurred. {ex.ToString()}"); } }
/// <summary> /// Run method /// 1: Reads the messages from the table storage in ascending order. /// 2: Peform the delete or create operation on the destination blob. /// </summary> /// <returns></returns> // public async Task Run(DateTime startDate, DateTime endDate, String contName) ID05202020.o public async Task Run(RestoreReqResponse reqResponse) // ID05202020.n { _logger.LogDebug("Inside RestoreBackupWorker.Run"); //Since there can be many records around 84K for a day, let's read the records day by day and perform the restore operation // List<Tuple<int,int, DateTime>> dates = GetDatesForDateRange(startDate, endDate); ID05202020.o List <Tuple <int, int, DateTime> > dates = GetDatesForDateRange(reqResponse.StDate, reqResponse.EnDate); // ID05202020.n _logger.LogInformation($"Number of dates determined.---{dates.Count()}"); int totalSuccessCount = 0; int totalFailureCount = 0; foreach (Tuple <int, int, DateTime> dateData in dates) { _logger.LogInformation($"Starting restore for Year {dateData.Item1} Week {dateData.Item2} and Date {dateData.Item3.ToString("MM/dd/yyyy")}"); var blobEvents = await _storageRepository.GetBLOBEvents(dateData.Item1, dateData.Item2, dateData.Item3, dateData.Item3.AddDays(1)); _logger.LogInformation($"Found {blobEvents.Count} for {dateData.Item1} and Date {dateData.Item3.ToString("MM/dd/yyyy")}"); if (blobEvents != null && blobEvents.Count > 0) { foreach (EventData eventData in blobEvents) { try { if (eventData.RecievedEventData is BlobEvent <CreatedEventData> ) { BlobEvent <CreatedEventData> createdBlob = (BlobEvent <CreatedEventData>)eventData.RecievedEventData; if (eventData.DestinationBlobInfo != null) { // ID05192020.sn if ((!String.IsNullOrEmpty(reqResponse.ContainerName)) && (!String.Equals(eventData.DestinationBlobInfo.OrgContainerName, reqResponse.ContainerName))) // ID05202020.n { continue; } if ((!String.IsNullOrEmpty(reqResponse.BlobName)) && (!String.Equals(eventData.DestinationBlobInfo.OrgBlobName, reqResponse.BlobName))) // ID05202020.n { continue; } _logger.LogDebug($"I/U Orig. Container:{eventData.DestinationBlobInfo.OrgContainerName},Req. Container:{reqResponse.ContainerName}"); _logger.LogDebug($"I/U Orig. Blob:{eventData.DestinationBlobInfo.OrgBlobName},Req. Blob:{reqResponse.BlobName}"); _logger.LogInformation($"Going to perform copy as it is a created event {createdBlob.data.url}"); // ID05192020.en await _blobRepository.CopyBlobFromBackupToRestore(eventData.DestinationBlobInfo); } else { _logger.LogInformation($"Copy of the blob will be ignored as at the time of backup the blob was not present at source. One of the cause can be , a delete has been performed already on this blob. {createdBlob.data.url}"); continue; // ID05202020.n } } else if (eventData.RecievedEventData is BlobEvent <DeletedEventData> ) { BlobEvent <DeletedEventData> deletedBlob = (BlobEvent <DeletedEventData>)eventData.RecievedEventData; // ID05192020.sn if (reqResponse.SkipDeletes.ToUpper(new CultureInfo("en-US", false)).Equals(Yes)) // ID05202020.n { continue; } if ((!String.IsNullOrEmpty(reqResponse.ContainerName)) && (!deletedBlob.data.url.Contains(reqResponse.ContainerName))) // ID05202020.n { continue; } if ((!String.IsNullOrEmpty(reqResponse.BlobName)) && (!deletedBlob.data.url.Contains(reqResponse.BlobName))) // ID05202020.n { continue; } _logger.LogDebug($"D Req. Container:{reqResponse.ContainerName}"); _logger.LogDebug($"D Req. Blob:{reqResponse.BlobName}"); _logger.LogInformation($"Going to delete as it is a deleted event {deletedBlob.data.url}"); // ID05192020.en await _blobRepository.DeleteBlobFromRestore(eventData.RecievedEventData); } else { _logger.LogInformation($"Currently Created and Deleted events are supported. Event Data: {eventData.RecievedEventDataJSON}"); continue; // ID05202020.n } totalSuccessCount++; } catch (Exception ex) { totalFailureCount++; _logger.LogError($"Exception while restoring event {eventData.RecievedEventDataJSON}. Exception {ex.ToString()}"); } } } } _logger.LogInformation($" Restore Success records count {totalSuccessCount}. Restore Failure records count {totalFailureCount}."); reqResponse.TotalSuccessCount = totalSuccessCount; reqResponse.TotalFailureCount = totalFailureCount; _logger.LogDebug("Completed RestoreBackupWorker.Run"); }
public async Task Run( [TimerTrigger("%RestoreTriggerSchedule%")] TimerInfo callTimer, Microsoft.Extensions.Logging.ILogger log) { if (callTimer.IsPastDue) { log.LogInformation("PerformBackup: Timer is running late!"); } log.LogInformation($"PerformRestoreAsync: Invoked at: {DateTime.Now}"); Stopwatch stopWatch = new Stopwatch(); RestoreReqResponse reqRespData = null; try { // Fetch an asynchronous restore request reqRespData = await _restoreTable.GetRestoreRequest(); if (reqRespData != null) { stopWatch.Start(); // Update the status of the restore request to in-progress reqRespData.Status = Constants.RESTORE_STATUS_INPROCESS; reqRespData.StartTime = DateTime.Now.ToString(); await _restoreTable.UpdateRestoreRequest(reqRespData); // Execute the restore process DateTime startDate = DateTime.MinValue; DateTime endDate = DateTime.MinValue; DateTime.TryParse(reqRespData.StartDate, out startDate); DateTime.TryParse(reqRespData.EndDate, out endDate); reqRespData.StDate = startDate; reqRespData.EnDate = endDate; log.LogInformation($"PerformRestore: Start date : {reqRespData.StDate.ToString("MM/dd/yyyy")}, End date {reqRespData.EnDate.ToString("MM/dd/yyyy")}. Proceeding with restore process ..."); if (!String.IsNullOrEmpty(reqRespData.ContainerName)) { log.LogInformation($"PerformRestore: Container Name : {reqRespData.ContainerName}"); } await _restoreBackup.Run(reqRespData); // Update the status of the restore request to completed reqRespData.Status = Constants.RESTORE_STATUS_COMPLETED; reqRespData.EndTime = DateTime.Now.ToString(); stopWatch.Stop(); reqRespData.ExecutionTime = DateTimeUtil.getTimeString(stopWatch.Elapsed); await _restoreTable.UpdateRestoreRequest(reqRespData); } } catch (Exception ex) { log.LogError($"PerformRestoreAsync: Exception occurred while processing message. Exception: {@ex.ToString()}"); // Update the status of the restore request to exception if (reqRespData != null) { reqRespData.Status = Constants.RESTORE_STATUS_FAILED; reqRespData.ExceptionMessage = $"PerformRestoreAsync: Encountered Exception: {@ex.ToString()}"; reqRespData.EndTime = DateTime.Now.ToString(); stopWatch.Stop(); reqRespData.ExecutionTime = DateTimeUtil.getTimeString(stopWatch.Elapsed); await _restoreTable.UpdateRestoreRequest(reqRespData); } ; } stopWatch = null; log.LogInformation($"PerformRestoreAsync: Completed execution at: {DateTime.Now}"); }
public async Task <ActionResult <RestoreReqResponse> > Run( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "restore/blobs")] HttpRequest req, Microsoft.Extensions.Logging.ILogger log) { log.LogInformation($"PerformRestore: Invoked at: {DateTime.Now}"); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); RestoreReqResponse reqRespData = JsonConvert.DeserializeObject <RestoreReqResponse>(requestBody); if (String.IsNullOrEmpty(reqRespData.StartDate) || String.IsNullOrEmpty(reqRespData.EndDate)) { reqRespData.ExceptionMessage = "Request is missing JSON payload containing start and end dates!"; stopWatch.Stop(); reqRespData.ExecutionTime = getTimeString(stopWatch.Elapsed); return(reqRespData); } ; DateTime startDate = DateTime.MinValue; DateTime endDate = DateTime.MinValue; bool startDateParsed = false; bool endDateParsed = false; startDateParsed = DateTime.TryParse(reqRespData.StartDate, out startDate); endDateParsed = DateTime.TryParse(reqRespData.EndDate, out endDate); if (!startDateParsed || !endDateParsed) { reqRespData.ExceptionMessage = $"Unable to parse start and end dates. Provide dates in mm/dd/yyyy format. Start date value {reqRespData.StartDate} End date value {reqRespData.EndDate}. "; stopWatch.Stop(); reqRespData.ExecutionTime = getTimeString(stopWatch.Elapsed); return(reqRespData); } ; if (startDate > endDate) { reqRespData.ExceptionMessage = "Start date cannot be greater than end date."; stopWatch.Stop(); reqRespData.ExecutionTime = getTimeString(stopWatch.Elapsed); return(reqRespData); } ; log.LogInformation($"PerformRestore: Start date : {startDate.ToString("MM/dd/yyyy")}, End date {endDate.ToString("MM/dd/yyyy")}. Proceeding with restore process ..."); reqRespData.StDate = startDate; reqRespData.EnDate = endDate; // ID05192020.sn if (!String.IsNullOrEmpty(reqRespData.ContainerName)) { log.LogInformation($"PerformRestore: Container Name : {reqRespData.ContainerName}"); } if (!String.IsNullOrEmpty(reqRespData.BlobName)) { if (String.IsNullOrEmpty(reqRespData.ContainerName)) { reqRespData.ExceptionMessage = $"To restore File : {reqRespData.BlobName}, container name is required!"; stopWatch.Stop(); reqRespData.ExecutionTime = getTimeString(stopWatch.Elapsed); return(reqRespData); } ; } ; // ID05192020.en try { // Run the restore process await _restoreBackup.Run(reqRespData); } catch (Exception ex) { log.LogError($"PerformRestore: Exception occurred. Exception: {@ex.ToString()}"); reqRespData.ExceptionMessage = $"Encountered exception : {@ex.ToString()}"; stopWatch.Stop(); reqRespData.ExecutionTime = getTimeString(stopWatch.Elapsed); return(reqRespData); } log.LogInformation($"PerformRestore: Completed execution at: {DateTime.Now}"); stopWatch.Stop(); reqRespData.ExecutionTime = getTimeString(stopWatch.Elapsed); // return (ActionResult) new OkObjectResult("Restore process finished OK"); ID05202020.o return(reqRespData); // ID05202020.n }