Feature: Event on connection lost
I have the issue that my service monitoring my TS server is apparently loosing Query connection after hours/days.
Would be good to have a event to notify me of that, such that I can trigger a reconnect.
I think firing a event from here would work?: https://github.com/nikeee/TeamSpeak3QueryAPI/blob/master/src/TeamSpeak3QueryApi/QueryClient.cs#L394
why not make a loop that checks if the bool function IsConnected() of TeamSpeakClient.Client is false?
why not make a loop that checks if the bool function IsConnected() of TeamSpeakClient.Client is false?
I tried that at first, didn't work. Right now my workaround is to simply send "version" command on a 4 minute timer, to make sure it doesn't idle kick me. That has ran flawlessly for weeks now.
Hey @dedmen ,
there is a much smarter solution by just added the event. You just need to add your QueryClient.cs like this.
Adding the Eventhandler
public class QueryClient : IDisposable
{
public EventHandler OnConnectionLost;
/// <summary>Gets the remote host of the Query API client.</summary>
/// <returns>The remote host of the Query API client.</returns>
public string Host { get; }
Adding the firing method
After that you need to create the virtual method the fire the event. I´ve added this code before the constructors but it doesen´t matter where you add it.
#region Events
public virtual void EventConnectionLost(EventArgs e)
{
OnConnectionLost?.Invoke(this, e);
}
#endregion
Firing the method if the connection is lost
Now you just need to fire the method if the client lost the connection. That on line 407. There you just type EventConnectionLost(EventArgs.Empty);. But to be sure here is the whole class of ResponseProcessingLoop
private CancellationTokenSource ResponseProcessingLoop()
{
var cts = _cts = new CancellationTokenSource();
Task.Run(async () =>
{
while (!cts.Token.IsCancellationRequested)
{
string line = null;
try
{
line = await _reader.ReadLineAsync().WithCancellation(cts.Token).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
break;
}
Debug.WriteLine(line);
if (line == null)
{
cts.Cancel();
continue;
}
if (string.IsNullOrWhiteSpace(line))
continue;
var s = line.Trim();
if (s.StartsWith("error", StringComparison.OrdinalIgnoreCase))
{
Debug.Assert(_currentCommand != null);
var error = ParseError(s);
_currentCommand.Error = error;
InvokeResponse(_currentCommand);
}
else if (s.StartsWith("notify", StringComparison.OrdinalIgnoreCase))
{
s = s.Remove(0, "notify".Length);
var not = ParseNotification(s);
InvokeNotification(not);
}
else
{
Debug.Assert(_currentCommand != null);
_currentCommand.RawResponse = s;
_currentCommand.ResponseDictionary = ParseResponse(s);
}
}
IsConnected = false;
EventConnectionLost(EventArgs.Empty);
});
return cts;
}
That´s it. Now you can easy check for a lost connection without traffic waste 👍 . Now to be fair here is my example how I check the connection.
Example
_client.Client.OnConnectionLost += async (sender, e) =>
{
Log.Error($"Instance {Instance.Alias}: Verbindung zum Server verloren...");
Log.Error($"Instance {Instance.Alias}: Verbindungsversuch wird in {TIME_TO_RETRY} erneut versucht...");
await Task.Delay(TIME_TO_RETRY);
_ = Connect();
};
I hope you can work with this :)
I hope you can work with this
Yeah thats exactly what I was requesting. Why not make a pull request and get it added to the library?
I will make a pull request if I am finished with fixing all problems. There are also a problem if the user is banned. There will be no QueryExecaption casted. Currently in my project I added the whole source and not the package to develop live with the source. I just read this issue and create you fast fix 👍