private void handle_message(PreRunMessage message) { this.Log().Debug(ChocolateyLoggers.Verbose, "[Pending] Removing all pending packages that should not be considered installed..."); var pendingFiles = _fileSystem.get_files(ApplicationParameters.PackagesLocation, ApplicationParameters.PackagePendingFileName, SearchOption.AllDirectories).ToList(); foreach (var pendingFile in pendingFiles.or_empty_list_if_null()) { var packageFolder = _fileSystem.get_directory_name(pendingFile); var packageFolderName = _fileSystem.get_directory_info_for(packageFolder).Name; var pendingSkipFiles = _fileSystem.get_files(packageFolder, PENDING_SKIP_FILE, SearchOption.AllDirectories).ToList(); if (pendingSkipFiles.Count != 0) { this.Log().Warn("Pending file found for {0}, but a {1} file was also found. Skipping removal".format_with(packageFolderName, PENDING_SKIP_FILE)); continue; } // wait for the file to be at least x seconds old // this allows commands running from the package for configuring sources, etc var fileInfo = _fileSystem.get_file_info_for(pendingFile); if (fileInfo.CreationTimeUtc.AddSeconds(PENDING_FILE_AGE_SECONDS) > _dateTimeService.get_current_date_time()) { this.Log().Debug("Pending file found for {0}, but the file is not {1} seconds old yet.".format_with(packageFolderName, PENDING_FILE_AGE_SECONDS)); continue; } this.Log().Warn("[Pending] Removing incomplete install for '{0}'".format_with(packageFolderName)); FaultTolerance.retry(2, () => _fileSystem.delete_directory_if_exists(packageFolder, recursive: true, overrideAttributes: true, isSilent: true), 500, isSilent: true); } }
private void allow_retries(Action action) { FaultTolerance.retry( TIMES_TO_TRY_OPERATION, action, waitDurationMilliseconds: 200, increaseRetryByMilliseconds: 100); }
private void allow_retries(Action action, bool isSilent = false) { FaultTolerance.retry( TimesToRetryOperation, action, waitDurationMilliseconds: OperationRetryTimeMilliseconds, increaseRetryByMilliseconds: IncreaseRetryMilliseconds, isSilent: isSilent); }
public void should_throw_an_error_if_retries_are_reached() { reset(); Assert.Throws <Exception>( () => FaultTolerance.retry(2, () => { throw new Exception("YIKES"); }, waitDurationMilliseconds: 0), "YIKES" ); }
public void should_not_allow_the_number_of_retries_to_be_zero() { reset(); FaultTolerance.retry( 0, () => { }); }
public void should_return_immediately_when_successful() { reset(); var i = 0; FaultTolerance.retry(3, () => { i += 1; }, waitDurationMilliseconds: 0); i.ShouldEqual(1); MockLogger.MessagesFor(LogLevel.Warn).Count.ShouldEqual(0); }
private void handle_message(PreRunMessage message) { this.Log().Debug(ChocolateyLoggers.Verbose, "[Pending] Removing all pending packages that should not be considered installed..."); var pendingFiles = _fileSystem.get_files(ApplicationParameters.PackagesLocation, ApplicationParameters.PackagePendingFileName, SearchOption.AllDirectories).ToList(); foreach (var pendingFile in pendingFiles.or_empty_list_if_null()) { var packageFolder = _fileSystem.get_directory_name(pendingFile); this.Log().Warn("[Pending] Removing incomplete install for '{0}'".format_with(_fileSystem.get_directory_info_for(packageFolder).Name)); FaultTolerance.retry(2, () => _fileSystem.delete_directory_if_exists(packageFolder, recursive: true, overrideAttributes: true, isSilent: true), 500, isSilent: true); } }
public void should_log_warning_each_time() { reset(); try { FaultTolerance.retry(3, () => { throw new Exception("YIKES"); }, waitDurationMilliseconds: 0); } catch { // don't care } MockLogger.MessagesFor(LogLevel.Warn).Count.ShouldEqual(2); }
public void should_retry_the_number_of_times_specified() { reset(); var i = 0; try { FaultTolerance.retry(10, () => { i += 1; throw new Exception("YIKES"); }, waitDurationMilliseconds: 0); } catch { // don't care } i.ShouldEqual(10); }
public XmlType deserialize <XmlType>(string xmlFilePath, int retryCount) { return(FaultTolerance.retry(retryCount, () => GlobalMutex.enter( () => { this.Log().Trace("Entered mutex to deserialize '{0}'".format_with(xmlFilePath)); return FaultTolerance.try_catch_with_logging_exception( () => { var xmlSerializer = new XmlSerializer(typeof(XmlType)); using (var fileStream = _fileSystem.open_file_readonly(xmlFilePath)) using (var fileReader = new StreamReader(fileStream)) using (var xmlReader = XmlReader.Create(fileReader)) { if (!xmlSerializer.CanDeserialize(xmlReader)) { this.Log().Warn("Cannot deserialize response of type {0}", typeof(XmlType)); return default(XmlType); } try { return (XmlType)xmlSerializer.Deserialize(xmlReader); } catch (InvalidOperationException ex) { // Check if its just a malformed document. if (ex.Message.Contains("There is an error in XML document")) { // If so, check for a backup file and try an parse that. if (_fileSystem.file_exists(xmlFilePath + ".backup")) { using (var backupStream = _fileSystem.open_file_readonly(xmlFilePath + ".backup")) using (var backupReader = new StreamReader(backupStream)) using (var backupXmlReader = XmlReader.Create(backupReader)) { var validConfig = (XmlType)xmlSerializer.Deserialize(backupXmlReader); // If there's no errors and it's valid, go ahead and replace the bad file with the backup. if (validConfig != null) { // Close fileReader so that we can copy the file without it being locked. fileReader.Close(); _fileSystem.copy_file(xmlFilePath + ".backup", xmlFilePath, overwriteExisting: true); } return validConfig; } } } throw; } finally { foreach (var updateFile in _fileSystem.get_files(_fileSystem.get_directory_name(xmlFilePath), "*.update").or_empty_list_if_null()) { this.Log().Debug("Removing '{0}'".format_with(updateFile)); FaultTolerance.try_catch_with_logging_exception( () => _fileSystem.delete_file(updateFile), errorMessage: "Unable to remove update file", logDebugInsteadOfError: true, isSilent: true ); } } } }, "Error deserializing response of type {0}".format_with(typeof(XmlType)), throwError: true); }, MUTEX_TIMEOUT), waitDurationMilliseconds: 200, increaseRetryByMilliseconds: 200)); }
public void serialize <XmlType>(XmlType xmlType, string xmlFilePath, bool isSilent) { _fileSystem.create_directory_if_not_exists(_fileSystem.get_directory_name(xmlFilePath)); FaultTolerance.retry(3, () => GlobalMutex.enter( () => { this.Log().Trace("Entered mutex to serialize '{0}'".format_with(xmlFilePath)); FaultTolerance.try_catch_with_logging_exception( () => { var xmlSerializer = new XmlSerializer(typeof(XmlType)); this.Log().Trace("Opening memory stream for xml file creation."); using (var memoryStream = new MemoryStream()) using (var streamWriter = new StreamWriter(memoryStream, encoding: new UTF8Encoding(encoderShouldEmitUTF8Identifier: true)) { AutoFlush = true } ){ xmlSerializer.Serialize(streamWriter, xmlType); streamWriter.Flush(); // Grab the hash of both files and compare them. this.Log().Trace("Hashing original file at '{0}'".format_with(xmlFilePath)); var originalFileHash = _hashProvider.hash_file(xmlFilePath); memoryStream.Position = 0; if (!originalFileHash.is_equal_to(_hashProvider.hash_stream(memoryStream))) { this.Log().Trace("The hashes were different."); // If there wasn't a file there in the first place, just write the new one out directly. if (string.IsNullOrEmpty(originalFileHash)) { this.Log().Debug("There was no original file at '{0}'".format_with(xmlFilePath)); memoryStream.Position = 0; _fileSystem.write_file(xmlFilePath, () => memoryStream); this.Log().Trace("Closing xml memory stream."); memoryStream.Close(); streamWriter.Close(); return; } // Otherwise, create an update file, and resiliently move it into place. var tempUpdateFile = xmlFilePath + "." + Process.GetCurrentProcess().Id + ".update"; this.Log().Trace("Creating a temp file at '{0}'".format_with(tempUpdateFile)); memoryStream.Position = 0; this.Log().Trace("Writing file '{0}'".format_with(tempUpdateFile)); _fileSystem.write_file(tempUpdateFile, () => memoryStream); memoryStream.Close(); streamWriter.Close(); this.Log().Trace("Replacing file '{0}' with '{1}'.".format_with(xmlFilePath, tempUpdateFile)); _fileSystem.replace_file(tempUpdateFile, xmlFilePath, xmlFilePath + ".backup"); } } }, errorMessage: "Error serializing type {0}".format_with(typeof(XmlType)), throwError: true, isSilent: isSilent); }, MUTEX_TIMEOUT), waitDurationMilliseconds: 200, increaseRetryByMilliseconds: 200); }
public void should_not_allow_the_number_of_retries_to_be_zero() { reset(); Assert.Throws <ApplicationException>(() => FaultTolerance.retry(0, () => { })); }