From 997ffca114ec18b9734cba281c8ecbbee8c524b8 Mon Sep 17 00:00:00 2001 From: Kenneth Skovhede Date: Sun, 13 Mar 2016 18:01:01 +0100 Subject: [PATCH] Implemented a list delay to work around the eventually consistent issue. This fixes #1546 --- .../Library/Backend/AmazonCloudDrive/AmzCD.cs | 22 +++++++++++++++++++ .../Backend/AmazonCloudDrive/Strings.cs | 4 +++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Duplicati/Library/Backend/AmazonCloudDrive/AmzCD.cs b/Duplicati/Library/Backend/AmazonCloudDrive/AmzCD.cs index 9091a728d..14f7251cc 100644 --- a/Duplicati/Library/Backend/AmazonCloudDrive/AmzCD.cs +++ b/Duplicati/Library/Backend/AmazonCloudDrive/AmzCD.cs @@ -28,8 +28,10 @@ namespace Duplicati.Library.Backend.AmazonCloudDrive { private const string AUTHID_OPTION = "authid"; private const string LABELS_OPTION = "amzcd-labels"; + private const string DELAY_OPTION = "amzcd-consistency-delay"; private const string DEFAULT_LABELS = "duplicati,backup"; + private const string DEFAULT_DELAY = "15s"; private const int PAGE_SIZE = 200; @@ -49,6 +51,8 @@ namespace Duplicati.Library.Backend.AmazonCloudDrive private OAuthHelper m_oauth; private Dictionary m_filecache; private string m_userid; + private DateTime m_waitUntil; + private TimeSpan m_delayTimeSpan; public AmzCD() { @@ -70,9 +74,18 @@ namespace Duplicati.Library.Backend.AmazonCloudDrive if (options.ContainsKey(LABELS_OPTION)) labels = options[LABELS_OPTION]; + string delay = DEFAULT_DELAY; + if (options.ContainsKey(DELAY_OPTION)) + delay = options[DELAY_OPTION]; + if (!string.IsNullOrWhiteSpace(labels)) m_labels = labels.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + if (string.IsNullOrWhiteSpace(delay)) + m_delayTimeSpan = new TimeSpan(0); + else + m_delayTimeSpan = Library.Utility.Timeparser.ParseTimeSpan(delay); + m_oauth = new OAuthHelper(authid, this.ProtocolKey) { AutoAuthHeader = true }; m_userid = authid.Split(new string[] {":"}, StringSplitOptions.RemoveEmptyEntries).First(); } @@ -225,6 +238,8 @@ namespace Duplicati.Library.Backend.AmazonCloudDrive #region IStreamingBackend implementation public void Put(string remotename, System.IO.Stream stream) { + m_waitUntil = DateTime.Now + m_delayTimeSpan; + var overwrite = FileCache.ContainsKey(remotename); var fileid = overwrite ? m_filecache[remotename] : null; @@ -277,6 +292,10 @@ namespace Duplicati.Library.Backend.AmazonCloudDrive #region IBackend implementation public List List() { + var wait = m_waitUntil - DateTime.Now; + if (wait.Ticks > 0) + System.Threading.Thread.Sleep(wait); + var query = string.Format("{0}/nodes?filters=parents:{1}&limit={2}", MetadataUrl, Utility.Uri.UrlEncode(CurrentDirectory.ID), PAGE_SIZE); var res = new List(); string nextToken = null; @@ -337,6 +356,8 @@ namespace Duplicati.Library.Backend.AmazonCloudDrive { try { + m_waitUntil = DateTime.Now + m_delayTimeSpan; + using(m_oauth.GetResponse(string.Format("{0}/trash/{1}", MetadataUrl, GetFileID(remotename)), null, "PUT")) { } @@ -378,6 +399,7 @@ namespace Duplicati.Library.Backend.AmazonCloudDrive return new List(new ICommandLineArgument[] { new CommandLineArgument(AUTHID_OPTION, CommandLineArgument.ArgumentType.Password, Strings.AmzCD.AuthidShort, Strings.AmzCD.AuthidLong(OAuthHelper.OAUTH_LOGIN_URL("amzcd"))), new CommandLineArgument(LABELS_OPTION, CommandLineArgument.ArgumentType.String, Strings.AmzCD.LabelsShort, Strings.AmzCD.LabelsLong, DEFAULT_LABELS), + new CommandLineArgument(DELAY_OPTION, CommandLineArgument.ArgumentType.Timespan, Strings.AmzCD.DelayShort, Strings.AmzCD.DelayLong, DEFAULT_DELAY), }); } } diff --git a/Duplicati/Library/Backend/AmazonCloudDrive/Strings.cs b/Duplicati/Library/Backend/AmazonCloudDrive/Strings.cs index 0d05dec03..3749d7515 100644 --- a/Duplicati/Library/Backend/AmazonCloudDrive/Strings.cs +++ b/Duplicati/Library/Backend/AmazonCloudDrive/Strings.cs @@ -28,6 +28,8 @@ namespace Duplicati.Library.Backend.Strings public static string LabelsShort { get { return LC.L(@"The labels to set"); } } public static string LabelsLong { get { return LC.L(@"Use this option to set labels on the files and folders created"); } } public static string MultipleEntries(string folder, string parent) { return LC.L(@"There is more than one item named ""{0}"" in the folder ""{1}"""); } - } + public static string DelayShort { get { return LC.L(@"The consistency delay"); } } + public static string DelayLong { get { return LC.L(@"Amazon Cloud drive needs a small delay for results to stay consistent."); } } + } }