[KOE-115] Implemented automatic full resync trigger. Disabled by default for now.

This commit is contained in:
Patrick Simpson 2017-06-07 11:57:26 +02:00
parent 158be43e11
commit 16cb96699e
5 changed files with 127 additions and 4 deletions

View File

@ -77,6 +77,29 @@ namespace Acacia.Features.SyncState
}
[AcaciaOption("Enables or disables checking for stalled synchronsation. If this is detected, a full resynchronisation " +
"is suggested automatically")]
public bool CheckSyncStall
{
get { return GetOption(OPTION_CHECK_SYNC_STALL); }
set { SetOption(OPTION_CHECK_SYNC_STALL, value); }
}
private static readonly BoolOption OPTION_CHECK_SYNC_STALL = new BoolOption("CheckSyncStall", false);
[AcaciaOption("Sets the period that triggers a full resynchronisation suggestion. Note that the check is only performed " +
"when the synchronisation state is being updated, so the effective period may be longer than this.")]
public TimeSpan CheckSyncStallPeriod
{
get { return GetOption(OPTION_CHECK_SYNC_STALL_PERIOD); }
set { SetOption(OPTION_CHECK_SYNC_STALL_PERIOD, value); }
}
private static readonly TimeSpanOption OPTION_CHECK_SYNC_STALL_PERIOD = new TimeSpanOption("CheckSyncStallPeriod", new TimeSpan(0, 10, 0));
/// <summary>
/// The time at which a sync stall was first suspected, or null if this is not the case.
/// </summary>
private DateTime? _syncStallStarted;
private bool _syncStallAsked;
#endregion
// TODO: this is largely about progress bars, separate that?
@ -223,9 +246,13 @@ namespace Acacia.Features.SyncState
[SoapField(5)]
public string id;
/// <summary>
/// The key, which is a short folder id. Set when checking the values.
/// </summary>
public string Key
{
get { return id; }
get;
set;
}
}
@ -320,8 +347,11 @@ namespace Acacia.Features.SyncState
HashSet<string> syncingNow = new HashSet<string>();
// Check all syncing data
foreach (DeviceDetails.ContentData content in details.Content.Values)
foreach (KeyValuePair<string, DeviceDetails.ContentData> contentEntry in details.Content)
{
DeviceDetails.ContentData content = contentEntry.Value;
content.Key = contentEntry.Key;
if (content.IsSyncing)
{
// If the current session is not syncing, this is a restart. Clear stat
@ -370,6 +400,15 @@ namespace Acacia.Features.SyncState
debug.AppendLine(string.Format("Total: {0} / {1} ({2}%)", Done, Total, CalculatePercentage(Done, Total)));
Logger.Instance.Trace(_feature, "Syncing account {0}:\n{1}", _account, debug);
}
public bool HasFolderSynced(string folderId)
{
DeviceDetails.ContentData content;
if (!_syncContent.TryGetValue(folderId, out content))
return false;
return !string.IsNullOrWhiteSpace(content.synckey);
}
}
private void CheckSyncState(ZPushAccount account)
@ -406,6 +445,9 @@ namespace Acacia.Features.SyncState
// Update the total for all accounts
UpdateTotalSyncState();
// Check for stalls
CheckSyncStalled(account);
}
private void UpdateTotalSyncState()
@ -442,6 +484,60 @@ namespace Acacia.Features.SyncState
}
}
private void CheckSyncStalled(ZPushAccount account)
{
if (!CheckSyncStall)
return;
// Check the inbox folder
using (IFolder inbox = account.Account.Store.GetDefaultFolder(DefaultFolder.Inbox))
{
string syncId = (string)inbox.GetProperty(OutlookConstants.PR_ZPUSH_SYNC_ID);
// If it's syncing, it's not stalled
if (syncId != null && syncId != "0")
return;
// Check if the folder has synced. In that case, it's not stalled.
string folderId = (string)inbox.GetProperty(OutlookConstants.PR_ZPUSH_FOLDER_ID);
SyncSession sync = account.GetFeatureData<SyncSession>(this, null);
if (sync.HasFolderSynced(folderId))
return;
}
// It is not syncing, check for a stall
if (_syncStallStarted == null)
_syncStallStarted = DateTime.Now;
else if (_syncStallStarted.Value.Add(CheckSyncStallPeriod) <= DateTime.Now)
{
// We have a stall
if (!_syncStallAsked)
{
// Set the flag to prevent asking again
_syncStallAsked = true;
// And alert the user
SyncStalled(account);
}
}
}
private void SyncStalled(ZPushAccount account)
{
ThisAddIn.Instance.InUI(() =>
{
if (MessageBox.Show(ThisAddIn.Instance.Window,
string.Format(Properties.Resources.SyncState_Stalled_Body, account.DisplayName),
string.Format(Properties.Resources.SyncState_Stalled_Caption, account.DisplayName),
MessageBoxButtons.YesNo,
MessageBoxIcon.Error
) == DialogResult.Yes)
{
ThisAddIn.Instance.RestartResync(account);
}
});
}
private static int CalculatePercentage(long done, long total)
{
if (total == 0 || done == total)

View File

@ -132,8 +132,9 @@ namespace Acacia
#region EAS / ZPush
public const string PR_ZPUSH_MESSAGE_ID = PROP + "6B20" + PT_STRING8;
public const string PR_ZPUSH_SYNC_ID = PROP + "6A18" + PT_STRING8;
public const string PR_ZPUSH_FOLDER_ID = PROP + "6A19" + PT_STRING8;
public const string PR_ZPUSH_MESSAGE_ID = PROP + "6B20" + PT_STRING8;
// TODO: names for these, use MFCMAPI
public const string PR_EAS_SYNC1 = PROP + "6A17" + PT_BOOLEAN;

View File

@ -1201,6 +1201,24 @@ namespace Acacia.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to It appears synchronisation has stalled for account {0}. This can be fixed by performing a full resynchronisation. Would you like to perform this resynchronisation now?.
/// </summary>
internal static string SyncState_Stalled_Body {
get {
return ResourceManager.GetString("SyncState_Stalled_Body", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Synchronisation stalled - {0}.
/// </summary>
internal static string SyncState_Stalled_Caption {
get {
return ResourceManager.GetString("SyncState_Stalled_Caption", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Kopano.
/// </summary>

View File

@ -500,4 +500,12 @@
<data name="GABSync_Title" xml:space="preserve">
<value>Global Address Book</value>
</data>
<data name="SyncState_Stalled_Body" xml:space="preserve">
<value>It appears synchronisation has stalled for account {0}. This can be fixed by performing a full resynchronisation. Would you like to perform this resynchronisation now?</value>
<comment>{0} will be replaced with the account name</comment>
</data>
<data name="SyncState_Stalled_Caption" xml:space="preserve">
<value>Synchronisation stalled - {0}</value>
<comment>{0} will be replaced with the account name</comment>
</data>
</root>

View File

@ -71,7 +71,7 @@ namespace Acacia.Stubs
/// Restarts the application and removes the specified account files.
/// </summary>
/// <param name="accounts"></param>
void RestartResync(ZPushAccount[] accounts);
void RestartResync(params ZPushAccount[] accounts);
void Quit(bool closeWindows);