Automatically reconnect to the server using an exponential backoff algorithm if we lose our connection.

This commit is contained in:
Starbeamrainbowlabs 2018-12-02 16:31:54 +00:00
parent 002ec0f7d9
commit 19be6f8425
Signed by: sbrl
GPG Key ID: 1BE5172E637709C2
1 changed files with 48 additions and 6 deletions

View File

@ -29,7 +29,21 @@ namespace RhinoReminds
public string ReminderFilePath { get; set; } = "./reminders.xml";
private ReminderList reminderList = new ReminderList();
private XmppClient client;
/// <summary>
/// The number of seconds to wait before trying to reconnect to the
/// server again if we loose our connection again.
/// </summary>
private int nextBackoffDelay = 1;
private int defaultBackoffDelay = 1;
private float backoffDelayMultiplier = 2;
/// <summary>
/// If a connection attempt doesn't succeed in this number of seconds,
/// give up and try again later.
/// </summary>
private int giveUpTimeout = 30;
public ClientListener(string inJid, string inPassword)
{
@ -51,19 +65,36 @@ namespace RhinoReminds
client.SubscriptionRequest += subscriptionRequestHandler;
// Connect to the server. This starts it's own thread that doesn't block the program exiting, apparently
client.Connect();
while (!client.Connected)
await Task.Delay(100);
Console.WriteLine($"[Rhino/Setup] Connected as {Jid}");
await connect();
//client.SetStatus(Availability.Online);
await watchForReminders();
}
private async Task<bool> connect()
{
if (client.Connected)
return true;
DateTime startTime = DateTime.Now;
client.Connect();
while (!client.Connected)
{
if ((DateTime.Now - startTime).TotalSeconds > giveUpTimeout)
return false;
await Task.Delay(100);
}
Console.WriteLine($"[Rhino/Setup] Connected as {Jid}");
return true;
}
#region XMPP Event Handling
private bool subscriptionRequestHandler(Jid from)
{
if (!AllowedDomains.Contains("*") && !AllowedDomains.Contains(from.Domain)) {
@ -77,6 +108,13 @@ namespace RhinoReminds
private void errorHandler(object sender, S22.Xmpp.Im.ErrorEventArgs e)
{
Console.Error.WriteLine($"Error {e.Reason}: {e.Exception}");
Console.Error.WriteLine($"Reconnecting in {TimeSpan.FromSeconds(nextBackoffDelay).ToString()}.");
Task.Delay(nextBackoffDelay * 1000).Wait();
if (!connect().Result)
nextBackoffDelay = (int)Math.Ceiling(nextBackoffDelay * backoffDelayMultiplier);
else
nextBackoffDelay = defaultBackoffDelay;
}
private void messageHandlerRoot(object sender, MessageEventArgs eventArgs)
@ -96,6 +134,9 @@ namespace RhinoReminds
}
}
#endregion
public void SetAvatar(string avatarFilepath)
{
if (!client.Connected)
@ -219,6 +260,7 @@ namespace RhinoReminds
}
}
#region Outgoing
/// <summary>
/// Sends a chat message to the specified JID.