Browse Source

Fixed rapid reconnects and reconnects triggering before a successful connect

tags/1.0-rc
RogueException 9 years ago
parent
commit
baadeb4c6f
1 changed files with 38 additions and 28 deletions
  1. +38
    -28
      src/Discord.Net/DiscordSocketClient.cs

+ 38
- 28
src/Discord.Net/DiscordSocketClient.cs View File

@@ -35,6 +35,7 @@ namespace Discord
private int _unavailableGuilds; private int _unavailableGuilds;
private long _lastGuildAvailableTime; private long _lastGuildAvailableTime;
private int _nextAudioId; private int _nextAudioId;
private bool _canReconnect;


/// <summary> Gets the shard if of this client. </summary> /// <summary> Gets the shard if of this client. </summary>
public int ShardId { get; } public int ShardId { get; }
@@ -114,7 +115,7 @@ namespace Discord
protected override async Task OnLogoutAsync() protected override async Task OnLogoutAsync()
{ {
if (ConnectionState != ConnectionState.Disconnected) if (ConnectionState != ConnectionState.Disconnected)
await DisconnectInternalAsync(null).ConfigureAwait(false);
await DisconnectInternalAsync(null, false).ConfigureAwait(false);


_voiceRegions = ImmutableDictionary.Create<string, VoiceRegion>(); _voiceRegions = ImmutableDictionary.Create<string, VoiceRegion>();
} }
@@ -125,7 +126,7 @@ namespace Discord
await _connectionLock.WaitAsync().ConfigureAwait(false); await _connectionLock.WaitAsync().ConfigureAwait(false);
try try
{ {
await ConnectInternalAsync().ConfigureAwait(false);
await ConnectInternalAsync(false).ConfigureAwait(false);
} }
finally { _connectionLock.Release(); } finally { _connectionLock.Release(); }


@@ -136,17 +137,17 @@ namespace Discord
await _guildDownloadTask.ConfigureAwait(false); await _guildDownloadTask.ConfigureAwait(false);
} }
} }
private async Task ConnectInternalAsync()
private async Task ConnectInternalAsync(bool isReconnecting)
{ {
if (LoginState != LoginState.LoggedIn) if (LoginState != LoginState.LoggedIn)
throw new InvalidOperationException("You must log in before connecting."); throw new InvalidOperationException("You must log in before connecting.");


if (_reconnectCancelToken != null && !_reconnectCancelToken.IsCancellationRequested)
if (!isReconnecting && _reconnectCancelToken != null && !_reconnectCancelToken.IsCancellationRequested)
_reconnectCancelToken.Cancel(); _reconnectCancelToken.Cancel();


var state = ConnectionState; var state = ConnectionState;
if (state == ConnectionState.Connecting || state == ConnectionState.Connected) if (state == ConnectionState.Connecting || state == ConnectionState.Connected)
await DisconnectInternalAsync(null).ConfigureAwait(false);
await DisconnectInternalAsync(null, isReconnecting).ConfigureAwait(false);


ConnectionState = ConnectionState.Connecting; ConnectionState = ConnectionState.Connecting;
await _gatewayLogger.InfoAsync("Connecting").ConfigureAwait(false); await _gatewayLogger.InfoAsync("Connecting").ConfigureAwait(false);
@@ -164,12 +165,13 @@ namespace Discord
await ApiClient.SendIdentifyAsync().ConfigureAwait(false); await ApiClient.SendIdentifyAsync().ConfigureAwait(false);


await _connectTask.Task.ConfigureAwait(false); await _connectTask.Task.ConfigureAwait(false);
_canReconnect = true;
ConnectionState = ConnectionState.Connected; ConnectionState = ConnectionState.Connected;
await _gatewayLogger.InfoAsync("Connected").ConfigureAwait(false); await _gatewayLogger.InfoAsync("Connected").ConfigureAwait(false);
} }
catch (Exception) catch (Exception)
{ {
await DisconnectInternalAsync(null).ConfigureAwait(false);
await DisconnectInternalAsync(null, isReconnecting).ConfigureAwait(false);
throw; throw;
} }
} }
@@ -180,7 +182,7 @@ namespace Discord
await _connectionLock.WaitAsync().ConfigureAwait(false); await _connectionLock.WaitAsync().ConfigureAwait(false);
try try
{ {
await DisconnectInternalAsync(null).ConfigureAwait(false);
await DisconnectInternalAsync(null, false).ConfigureAwait(false);
} }
finally { _connectionLock.Release(); } finally { _connectionLock.Release(); }
} }
@@ -190,14 +192,18 @@ namespace Discord
await _connectionLock.WaitAsync().ConfigureAwait(false); await _connectionLock.WaitAsync().ConfigureAwait(false);
try try
{ {
await DisconnectInternalAsync(ex).ConfigureAwait(false);
await DisconnectInternalAsync(ex, false).ConfigureAwait(false);
} }
finally { _connectionLock.Release(); } finally { _connectionLock.Release(); }
} }
private async Task DisconnectInternalAsync(Exception ex)
private async Task DisconnectInternalAsync(Exception ex, bool isReconnecting)
{ {
if (_reconnectCancelToken != null && !_reconnectCancelToken.IsCancellationRequested)
_reconnectCancelToken.Cancel();
if (!isReconnecting)
{
_canReconnect = false;
if (_reconnectCancelToken != null && !_reconnectCancelToken.IsCancellationRequested)
_reconnectCancelToken.Cancel();
}


ulong guildId; ulong guildId;


@@ -242,7 +248,8 @@ namespace Discord
await _connectionLock.WaitAsync().ConfigureAwait(false); await _connectionLock.WaitAsync().ConfigureAwait(false);
try try
{ {
await DisconnectInternalAsync(null).ConfigureAwait(false);
if (!_canReconnect || _reconnectTask != null) return;
await DisconnectInternalAsync(null, true).ConfigureAwait(false);
_reconnectCancelToken = new CancellationTokenSource(); _reconnectCancelToken = new CancellationTokenSource();
_reconnectTask = ReconnectInternalAsync(_reconnectCancelToken.Token); _reconnectTask = ReconnectInternalAsync(_reconnectCancelToken.Token);
} }
@@ -253,34 +260,37 @@ namespace Discord
try try
{ {
int nextReconnectDelay = 1000; int nextReconnectDelay = 1000;
while (!cancelToken.IsCancellationRequested)
while (true)
{ {
await Task.Delay(nextReconnectDelay, cancelToken).ConfigureAwait(false);
nextReconnectDelay *= 2;
if (nextReconnectDelay > 30000)
nextReconnectDelay = 30000;

await _connectionLock.WaitAsync().ConfigureAwait(false);
try try
{ {
await Task.Delay(nextReconnectDelay, cancelToken).ConfigureAwait(false);
nextReconnectDelay *= 2;
if (nextReconnectDelay > 30000)
nextReconnectDelay = 30000;

await _connectionLock.WaitAsync().ConfigureAwait(false);
try
{
if (cancelToken.IsCancellationRequested) return;
await ConnectInternalAsync().ConfigureAwait(false);
}
finally { _connectionLock.Release(); }
if (cancelToken.IsCancellationRequested) return;
await ConnectInternalAsync(true).ConfigureAwait(false);
_reconnectTask = null;
return; return;
} }
catch (Exception ex) catch (Exception ex)
{ {
await _gatewayLogger.WarningAsync("Reconnect failed", ex).ConfigureAwait(false); await _gatewayLogger.WarningAsync("Reconnect failed", ex).ConfigureAwait(false);
} }
finally { _connectionLock.Release(); }
} }
} }
catch (OperationCanceledException) { }
finally
catch (OperationCanceledException)
{ {
_reconnectTask = null;
await _connectionLock.WaitAsync().ConfigureAwait(false);
try
{
await _gatewayLogger.DebugAsync("Reconnect cancelled").ConfigureAwait(false);
_reconnectTask = null;
}
finally { _connectionLock.Release(); }
} }
} }




Loading…
Cancel
Save