public void WriteCsvMinuteInterval_over_timeout_raises_WriteCsvException() { var csvWriter = new CsvWriter(); var minuteInterval = 30; //confirm file was written var maxTrys = 5; DateTime?lastWroteCsv = null; IPowerService powerService = Mock.Create <IPowerService>(); Mock.Arrange(() => powerService.GetTradesAsync(_testDateTime)).Returns(() => new Task <IEnumerable <PowerTrade> >(() => { var waitTimepan = new TimeSpan(0, 0, _timeOut.Seconds + 2); var stopwatch = new Stopwatch(); stopwatch.Start(); while (stopwatch.ElapsedMilliseconds < waitTimepan.TotalMilliseconds) { Thread.Sleep(0); } return(_powerTrades); })); //first try five times no error should be thrown it will be logged and a retry allowed for (int i = 1; i <= maxTrys; i++) { Assert.DoesNotThrow(() => lastWroteCsv = csvWriter.WriteCsvMinuteInterval(_fileFolder, _fileName, _fileDateFormat, _fileSuffix, _delimiter, _columnOneName, _columnTwoName, _dataDateFormat, minuteInterval, _testDateTime, powerService, _timeOut, lastWroteCsv)); } //final time is over maximum number of retries so should throw an exception Assert.Throws <WriteCsvException>(() => lastWroteCsv = csvWriter.WriteCsvMinuteInterval(_fileFolder, _fileName, _fileDateFormat, _fileSuffix, _delimiter, _columnOneName, _columnTwoName, _dataDateFormat, minuteInterval, _testDateTime, powerService, _timeOut, lastWroteCsv)); }
//Confirm the WriteCvException is being logged in the correct format public void WriteCsvMinuteInterval_PowerServiceException_is_caught_and_logged() { var csvWriter = new CsvWriter(); var minuteInterval = 30; //confirm file was written var logFileName = "PositionAggregatorLogFile.txt"; var maxTrys = 5; DateTime?lastWroteCsv = null; File.Delete(logFileName); IPowerService powerService = Mock.Create <IPowerService>(); Mock.Arrange(() => powerService.GetTradesAsync(_testDateTime)).Throws <PowerServiceException>("Power Service Exception"); //first try five times and confirm log file is written correctly for (int i = 1; i <= maxTrys; i++) { lastWroteCsv = csvWriter.WriteCsvMinuteInterval(_fileFolder, _fileName, _fileDateFormat, _fileSuffix, _delimiter, _columnOneName, _columnTwoName, _dataDateFormat, minuteInterval, _testDateTime, powerService, _timeOut, lastWroteCsv); } //confirm the log file has been written Assert.IsTrue(File.Exists(logFileName)); var assembly = Assembly.GetExecutingAssembly(); var resourceName = "TDomain.PositionAggregatorLogFile.txt"; var logFileExampleText = ""; using (StreamReader reader = new StreamReader(assembly.GetManifestResourceStream(resourceName))) { logFileExampleText = reader.ReadToEnd(); } var logFileText = File.ReadAllText(logFileName); //confirm the log file has been written correctly. contents will differ due to timing of runs so realistically good enough to just check the lengths Assert.AreEqual(logFileExampleText.Length, logFileText.Length); }
//Write the csv file if the current time is at the minute Interval and no other file has been written by the process. Otherwise write the file. public DateTime?WriteCsvMinuteInterval(string fileFolder, string fileName, string fileDateFormat, string fileSuffix, string delimiter, string columnOneName, string columnTwoName, string dataDateFormat, int minuteInterval, DateTime?asAt, IPowerService powerService, TimeSpan timeout, DateTime?lastWroteCsv, bool overwriteExisting = true) { //use at parameter to override what time the method believes it is. This is useful for testing. //using Universal time means do not have to worry about clocks changing DateTime nowDateTime = asAt ?? DateTime.Now.ToUniversalTime(); //if null then this is a first run so write the file if if (lastWroteCsv == null || (nowDateTime.Minute % minuteInterval == 0 && (nowDateTime.Day != lastWroteCsv.Value.Day || nowDateTime.Hour != lastWroteCsv.Value.Hour || nowDateTime.Minute != lastWroteCsv.Value.Minute))) { try { var writeFile = GetFullFileName(fileFolder, fileName, fileDateFormat, fileSuffix, nowDateTime); var fileExists = File.Exists(writeFile); if (overwriteExisting == true || (!fileExists)) { _tryWriteCsv++; var tradesTask = powerService.GetTradesAsync(nowDateTime); if (!tradesTask.Wait(timeout)) { var exceptionMessage = "The operation to retrieve power trades has timed out. Timeout value used was " + timeout.Seconds + " seconds. The date parameter passed was " + nowDateTime.ToString("R"); throw new WriteCsvException(exceptionMessage); } var trades = tradesTask.Result; var position = new Position(trades, nowDateTime); WriteCsv(writeFile, delimiter, columnOneName, columnTwoName, dataDateFormat, position); _tryWriteCsv = 0; return(nowDateTime); } } catch (Exception ex) when(ex is PowerServiceException || ex is WriteCsvException || ex is AggregateException) { //Will retry the procedure a specified number of times when the above errors are called because they are potentially recoverable if (_tryWriteCsv <= _maxTryWriteCsv) { //log and allow retry on next timer interval var exceptionMessages = ex.GetExceptionMessages(); var errorMessage = "An error has occured trying to write the csv file. This is attempt number " + _tryWriteCsv + ". A maximum of " + _maxTryWriteCsv + " attempts will be made to write the file " + ". Detailed information is below.\r\n\r\n" + exceptionMessages; _logger.Error(ex, errorMessage); } else { throw; } } } // by default assume csv not written return(lastWroteCsv); }
public async Task <IEnumerable <PowerDataCommon.domain.PowerTrade> > ReadDataAsync(DateTime tenor) { try { return(_dtoConverter.TranslateToDomainObject(await _powerService.GetTradesAsync(tenor).ConfigureAwait(false))); } catch (PowerServiceException pex) { log.Value.Error(pex); } return(Enumerable.Empty <PowerDataCommon.domain.PowerTrade>()); }
private async Task <IEnumerable <PowerTrade> > GetTradesAsync(DateTime dateTime) { try { var result = await _powerService.GetTradesAsync(dateTime); return(result); } catch (Exception e) { //Ensure that as much information as possible is obtained from service Log.Error(e, "Error obtaining trades from Power Service"); throw; } }
public async Task <ReadOnlyCollection <PowerTrade> > GetPowerTradeAsync() { int retries = 0, maxRetries = 3; _log.Info("Attempting to Retrieving power trades"); while (retries < maxRetries) { try { var results = await _powerService.GetTradesAsync(DateTime.Now); _log.Info($"Power trades successfully retrieved in the {retries + 1} attempt"); if (results != null) { var powerTradesReadOnlyList = results.ToList().AsReadOnly(); _log.Info($"Received {powerTradesReadOnlyList.Count} trades"); return(powerTradesReadOnlyList); } } catch (PowerServiceException serviceException) { _log.Error(serviceException.ToString()); _log.Error($"Power service failed to retrieve the Power Trades at attempt No:{retries+1}"); retries++; if (retries >= maxRetries) { _log.Error("Max retries reached"); } else { _log.Error("Sourcing the data once again after 2 seconds"); await Task.Delay(2000); } } } return(null); }
//Confirm the WriteCvException is being logged in the correct format public void WriteCsvMinuteInterval_PowerServiceException_raised_sequentially_over_maximum_trys_throws_error() { var minuteInterval = 30; var asAt = _testDateTime.AddMinutes(29); //confirm file was written var maxTrys = 5; var csvWriter = new CsvWriter(); DateTime?lastWroteCsv = null; IPowerService powerService = Mock.Create <IPowerService>(); Mock.Arrange(() => powerService.GetTradesAsync(_testDateTime)).Throws <AggregateException>("Power Service exception"); //first try five times no error should be thrown it will be logged and a retry allowed for (int i = 1; i <= maxTrys; i++) { Assert.DoesNotThrow(() => lastWroteCsv = csvWriter.WriteCsvMinuteInterval(_fileFolder, _fileName, _fileDateFormat, _fileSuffix, _delimiter, _columnOneName, _columnTwoName, _dataDateFormat, minuteInterval, _testDateTime, powerService, _timeOut, lastWroteCsv)); } //final time is over maximum number of retries so should throw an exception Assert.Throws <AggregateException>(() => lastWroteCsv = csvWriter.WriteCsvMinuteInterval(_fileFolder, _fileName, _fileDateFormat, _fileSuffix, _delimiter, _columnOneName, _columnTwoName, _dataDateFormat, minuteInterval, _testDateTime, powerService, _timeOut, lastWroteCsv)); }
public async Task CreateReportAsync(int retryAttemps, string outputPath) { //Gets report date - date used to call PowerService var reportDate = _dateProvider.GetReportDate(); //Repe for (int i = 0; i < retryAttemps; i++) { try { if (log.IsInfoEnabled) { log.Info($"Creating report attempt {i+1} of {retryAttemps} for report date {reportDate.Date}."); } if (log.IsInfoEnabled) { log.Info("Retreving power trades."); } //Gets PowerTrade var powerTrades = await _powerService.GetTradesAsync(reportDate); if (log.IsInfoEnabled) { log.Info("Power trades retreived."); } if (log.IsInfoEnabled) { log.Info("Calculating interday report positions."); } //Calculates interDay positions. var interDayPositions = powerTrades.Where(trade => trade.Date.Date == reportDate.Date) .SelectMany(trades => trades.Periods) .GroupBy(periods => periods.Period) .Select(group => new InterdayPowerReportPosition(group.Key, group.Sum(p => p.Volume))) .OrderBy(data => data.PositionId) .ToArray(); if (log.IsInfoEnabled) { log.Info("Interday positions calculated."); } if (log.IsInfoEnabled) { log.Info("Exporting report."); } //Exports report, using injected exporter. _exporter.Export(outputPath, _dateProvider.GetExtractDateTime(), interDayPositions); if (log.IsInfoEnabled) { log.Info("Report Exported."); } if (log.IsInfoEnabled) { log.Info("Report has been created successfully."); } return; } catch (Exception ex) { log.Error(ex, "Create Report Error."); //If no more attempts we can ommit delay. if (i + 1 == retryAttemps) { log.Info("Report couldn't be created."); return; } } //Delays next attempt about 10 second. In the test project, delay is eliminated. await BackgroundScheduler.Default.Delay(TimeSpan.FromSeconds(10)); } }
public void Setup() { //Set up the power service var testPeriods = new PowerPeriod[] { new PowerPeriod() { Period = 1, Volume = 1000 }, new PowerPeriod() { Period = 2, Volume = 2000 }, new PowerPeriod() { Period = 3, Volume = 3000 }, new PowerPeriod() { Period = 4, Volume = 4000 }, new PowerPeriod() { Period = 5, Volume = 5000 }, new PowerPeriod() { Period = 6, Volume = 6000 }, new PowerPeriod() { Period = 7, Volume = 7000 }, new PowerPeriod() { Period = 8, Volume = 8000 }, new PowerPeriod() { Period = 9, Volume = 9000 }, new PowerPeriod() { Period = 10, Volume = 10000 }, new PowerPeriod() { Period = 11, Volume = 11000 }, new PowerPeriod() { Period = 12, Volume = 12000 }, new PowerPeriod() { Period = 13, Volume = 13000 }, new PowerPeriod() { Period = 14, Volume = 14000 }, new PowerPeriod() { Period = 15, Volume = 15000 }, new PowerPeriod() { Period = 16, Volume = 16000 }, new PowerPeriod() { Period = 17, Volume = 17000 }, new PowerPeriod() { Period = 18, Volume = 18000 }, new PowerPeriod() { Period = 19, Volume = 19000 }, new PowerPeriod() { Period = 20, Volume = 20000 }, new PowerPeriod() { Period = 21, Volume = 21000 }, new PowerPeriod() { Period = 22, Volume = 22000 }, new PowerPeriod() { Period = 23, Volume = 23000 }, new PowerPeriod() { Period = 24, Volume = 24000 }, }; var tradeOne = Mock.Create <PowerTrade>(); Mock.Arrange(() => tradeOne.Date).Returns(_testDateTime); Mock.Arrange(() => tradeOne.Periods).Returns(testPeriods); var tradeTwo = Mock.Create <PowerTrade>(); Mock.Arrange(() => tradeTwo.Date).Returns(_testDateTime.AddHours(1)); Mock.Arrange(() => tradeTwo.Periods).Returns(testPeriods); var tradeThree = Mock.Create <PowerTrade>(); Mock.Arrange(() => tradeThree.Date).Returns(_testDateTime.AddHours(2)); Mock.Arrange(() => tradeThree.Periods).Returns(testPeriods); _powerTrades = new List <PowerTrade>() { tradeOne, tradeTwo, tradeThree }; //simulate a short call time on the PowerService.GetTradesAsync var powerTradesTask = new Task <IEnumerable <PowerTrade> >(() => _powerTrades); powerTradesTask.Start(); powerTradesTask.Wait(); Mock.Arrange(() => _powerService.GetTradesAsync(_testDateTime)).Returns(powerTradesTask); Mock.Arrange(() => _powerService.GetTrades(_testDateTime)).Returns(_powerTrades); //set up the expected data to be written by the csv writer var assembly = Assembly.GetExecutingAssembly(); var resourceName = "TDomain.PositionExample.csv"; using (StreamReader reader = new StreamReader(assembly.GetManifestResourceStream(resourceName))) { _csvExampleText = reader.ReadToEnd(); } if (!System.IO.Directory.Exists(_fileFolder)) { Directory.CreateDirectory(_fileFolder); } }