Skip to content

Commit

Permalink
Optimization (#122)
Browse files Browse the repository at this point in the history
* optimization, logging source generators

* update dependencies

---------

Co-authored-by: AoshiW <ondru@SHIRO-V3>
Co-authored-by: AoshiW <[email protected]>
  • Loading branch information
3 people authored Dec 21, 2023
1 parent f833b1a commit d0c32b5
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 45 deletions.
23 changes: 23 additions & 0 deletions TwitchLib.PubSub/Extensions/LoggingExtesions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Microsoft.Extensions.Logging;
using System;

namespace TwitchLib.PubSub.Extensions
{
internal static partial class LoggingExtesions
{
[LoggerMessage(LogLevel.Error, "OnError in PubSub Websocket connection occured! Exception: {ex}")]
public static partial void LogOnError(this ILogger<TwitchPubSub> logger, Exception ex);

Check warning on line 9 in TwitchLib.PubSub/Extensions/LoggingExtesions.cs

View workflow job for this annotation

GitHub Actions / release-preview

Don't include a template for ex in the logging message since it is implicitly taken care of

[LoggerMessage(LogLevel.Debug, "Received Websocket OnMessage: {message}")]
public static partial void LogReceivednMessage(this ILogger<TwitchPubSub> logger, string message);

[LoggerMessage(LogLevel.Warning, "PubSub Websocket connection closed")]
public static partial void LogConnectionClosed(this ILogger<TwitchPubSub> logger);

[LoggerMessage(LogLevel.Information, "PubSub Websocket connection established")]
public static partial void LogConnectionEstablished(this ILogger<TwitchPubSub> logger);

[LoggerMessage(LogLevel.Information, "[TwitchPubSub] {message}")]
public static partial void LogUnaccountedFor(this ILogger<TwitchPubSub> logger, string message);
}
}
26 changes: 26 additions & 0 deletions TwitchLib.PubSub/Models/Request.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Newtonsoft.Json;
using System.Collections.Generic;

namespace TwitchLib.PubSub.Models
{
internal class Request
{
[JsonProperty("type")]
public string Type { get; set; }

[JsonProperty("nonce")]
public string Nonce { get; set; }

[JsonProperty("data")]
public RequestData Data { get; set; }
}

internal class RequestData
{
[JsonProperty("topics")]
public List<string> Topics { get; set; }

[JsonProperty("auth_token", NullValueHandling = NullValueHandling.Ignore)]
public string AuthToken { get; set; }
}
}
14 changes: 11 additions & 3 deletions TwitchLib.PubSub/Models/Responses/Message.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,17 @@ public class Message
/// PubSub Message model constructor.
/// </summary>
/// <param name="jsonStr">The json string.</param>
public Message(string jsonStr)
public Message(string jsonStr) : this(JObject.Parse(jsonStr))
{
var json = JObject.Parse(jsonStr).SelectToken("data");
}

/// <summary>
/// PubSub Message model constructor.
/// </summary>
/// <param name="jsonObject">The json.</param>
internal Message(JObject jsonObject)
{
var json = jsonObject.SelectToken("data");
Topic = json.SelectToken("topic")?.ToString();
var encodedJsonMessage = json.SelectToken("message").ToString();
switch (Topic?.Split('.')[0])
Expand Down Expand Up @@ -71,7 +79,7 @@ public Message(string jsonStr)
break;
case "raid":
MessageData = new RaidEvents(encodedJsonMessage);
break;
break;
case "predictions-channel-v1":
MessageData = new PredictionEvents(encodedJsonMessage);
break;
Expand Down
14 changes: 11 additions & 3 deletions TwitchLib.PubSub/Models/Responses/Response.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,18 @@ public class Response
/// Response model constructor.
/// </summary>
/// <param name="json">The json.</param>
public Response(string json)
public Response(string json) : this(JObject.Parse(json))
{
Error = JObject.Parse(json).SelectToken("error")?.ToString();
Nonce = JObject.Parse(json).SelectToken("nonce")?.ToString();
}

/// <summary>
/// Response model constructor.
/// </summary>
/// <param name="json">The json.</param>
internal Response(JObject json)
{
Error = json.SelectToken("error")?.ToString();
Nonce = json.SelectToken("nonce")?.ToString();
if (string.IsNullOrWhiteSpace(Error))
Successful = true;
}
Expand Down
5 changes: 3 additions & 2 deletions TwitchLib.PubSub/TwitchLib.PubSub.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>latest</LangVersion>
<PackageId>TwitchLib.PubSub</PackageId>
<VersionPrefix>4.0.0</VersionPrefix>
<VersionSuffix>$(VersionSuffix)</VersionSuffix>
Expand All @@ -23,8 +24,8 @@
<GenerateDocumentationFile>True</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" />
<PackageReference Include="TwitchLib.Communication" Version="2.0.0" />
</ItemGroup>
</Project>
80 changes: 43 additions & 37 deletions TwitchLib.PubSub/TwitchPubSub.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
Expand All @@ -12,6 +12,7 @@
using TwitchLib.Communication.Models;
using TwitchLib.PubSub.Enums;
using TwitchLib.PubSub.Events;
using TwitchLib.PubSub.Extensions;
using TwitchLib.PubSub.Interfaces;
using TwitchLib.PubSub.Models;
using TwitchLib.PubSub.Models.Responses.Messages;
Expand All @@ -35,7 +36,7 @@ public class TwitchPubSub : ITwitchPubSub
/// The random
/// </summary>
private static readonly Random Random = new Random();

/// <summary>
/// The socket
/// </summary>
Expand Down Expand Up @@ -265,7 +266,7 @@ public class TwitchPubSub : ITwitchPubSub
/// <summary>
/// Fires when PubSub receives notice when a channel cancels the raid
/// </summary>
public event EventHandler<OnRaidCancelArgs> OnRaidCancel;
public event EventHandler<OnRaidCancelArgs> OnRaidCancel;
/// <inheritdoc />
/// <summary>
/// Fires when PubSub receives any data from Twitch
Expand Down Expand Up @@ -320,7 +321,7 @@ public TwitchPubSub(ILogger<TwitchPubSub> logger = null)
/// <param name="e">The <see cref="OnErrorEventArgs"/> instance containing the event data.</param>
private Task OnErrorAsync(object sender, OnErrorEventArgs e)
{
_logger?.LogError($"OnError in PubSub Websocket connection occured! Exception: {e.Exception}");
_logger?.LogOnError(e.Exception);
OnPubSubServiceError?.Invoke(this, new OnPubSubServiceErrorArgs { Exception = e.Exception });

return Task.CompletedTask;
Expand All @@ -333,7 +334,7 @@ private Task OnErrorAsync(object sender, OnErrorEventArgs e)
/// <param name="e">The <see cref="OnMessageEventArgs"/> instance containing the event data.</param>
private Task OnMessageAsync(object sender, OnMessageEventArgs e)
{
_logger?.LogDebug($"Received Websocket OnMessage: {e.Message}");
_logger?.LogReceivednMessage(e.Message);
OnLog?.Invoke(this, new OnLogArgs { Data = e.Message });
return ParseMessageAsync(e.Message);
}
Expand All @@ -345,7 +346,7 @@ private Task OnMessageAsync(object sender, OnMessageEventArgs e)
/// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
private Task Socket_OnDisconnectedAsync(object sender, EventArgs e)
{
_logger?.LogWarning("PubSub Websocket connection closed");
_logger?.LogConnectionClosed();
_pingTimer.Stop();
_pongTimer.Stop();
OnPubSubServiceClosed?.Invoke(this, null);
Expand All @@ -360,15 +361,15 @@ private Task Socket_OnDisconnectedAsync(object sender, EventArgs e)
/// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
private Task Socket_OnConnectedAsync(object sender, EventArgs e)
{
_logger?.LogInformation("PubSub Websocket connection established");
_logger?.LogConnectionEstablished();
_pingTimer.Interval = 180000;
_pingTimer.Elapsed += PingTimerTickAsync;
_pingTimer.Start();
OnPubSubServiceConnected?.Invoke(this, null);

return Task.CompletedTask;
}

/// <summary>
/// Pings the timer tick.
/// </summary>
Expand Down Expand Up @@ -414,12 +415,13 @@ private async void PongTimerTickAsync(object sender, ElapsedEventArgs e)
/// <param name="message">The message.</param>
private async Task ParseMessageAsync(string message)
{
var type = JObject.Parse(message).SelectToken("type")?.ToString();
var parsedJson = JObject.Parse(message);
var type = parsedJson.SelectToken("type")?.ToString();

switch (type?.ToLower())
{
case "response":
var resp = new Models.Responses.Response(message);
var resp = new Models.Responses.Response(parsedJson);
if (_previousRequests.Count != 0)
{
bool handled = false;
Expand Down Expand Up @@ -451,7 +453,7 @@ private async Task ParseMessageAsync(string message)
}
break;
case "message":
var msg = new Models.Responses.Message(message);
var msg = new Models.Responses.Message(parsedJson);
_topicToChannelId.TryGetValue(msg.Topic, out var channelId);
channelId = channelId ?? "";
switch (msg.Topic.Split('.')[0])
Expand Down Expand Up @@ -687,21 +689,27 @@ private async Task ParseMessageAsync(string message)
_pongReceived = true;
return;
case "reconnect":
await _socket.CloseAsync();
await _socket.CloseAsync();
break;
}

UnaccountedFor(message);
}

/// <summary>
/// Generates the nonce.
/// </summary>
/// <returns>System.String.</returns>
private static string GenerateNonce()
{
return new string(Enumerable.Repeat("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", 8)
.Select(s => s[Random.Next(s.Length)]).ToArray());
const string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Span<char> nonce = stackalloc char[8];
foreach (ref var c in nonce)
{
var index = Random.Next(chars.Length);
c = chars[index];
}
return nonce.ToString();
}

/// <summary>
Expand Down Expand Up @@ -730,7 +738,7 @@ public void SendTopics(string oauth = null, bool unlisten = false)
{
SendTopicsAsync(oauth, unlisten).GetAwaiter().GetResult();
}

/// <inheritdoc />
/// <summary>
/// Sends the topics.
Expand All @@ -746,36 +754,34 @@ public async Task SendTopicsAsync(string oauth = null, bool unlisten = false)

var nonce = GenerateNonce();

var topics = new JArray();
var topics = new List<string>(_topicList.Count);
_previousRequestsSemaphore.WaitOne();
try
{
foreach (var val in _topicList)
{
_previousRequests.Add(new PreviousRequest(nonce, PubSubRequestType.ListenToTopic, val));
topics.Add(new JValue(val));
topics.Add(val);
}
}
finally
{
_previousRequestsSemaphore.Release();
}

var jsonData = new JObject(
new JProperty("type", !unlisten ? "LISTEN" : "UNLISTEN"),
new JProperty("nonce", nonce),
new JProperty("data",
new JObject(
new JProperty("topics", topics)
)
)
);
if (oauth != null)
var request = new Request()
{
((JObject)jsonData.SelectToken("data"))?.Add(new JProperty("auth_token", oauth));
}
Type = unlisten ? "UNLISTEN" : "LISTEN",
Nonce = nonce,
Data = new()
{
Topics = topics,
AuthToken = oauth,
}
};

await _socket.SendAsync(jsonData.ToString());
var json = JsonConvert.SerializeObject(request);
await _socket.SendAsync(json);

_topicList.Clear();
}
Expand All @@ -786,7 +792,7 @@ public async Task SendTopicsAsync(string oauth = null, bool unlisten = false)
/// <param name="message">The message.</param>
private void UnaccountedFor(string message)
{
_logger?.LogInformation($"[TwitchPubSub] {message}");
_logger?.LogUnaccountedFor(message);
}

#region Listeners
Expand Down Expand Up @@ -970,7 +976,7 @@ public void ListenToPredictions(string channelTwitchId)
_topicToChannelId[topic] = channelTwitchId;
ListenToTopic(topic);
}

/// <inheritdoc />
/// <summary>
/// Message sent when a user earns a new Bits badge in a particular channel, and chooses to share the notification with chat.
Expand All @@ -982,7 +988,7 @@ public void ListenToChannelBitsBadgeUnlocks(string channelTwitchId)
_topicToChannelId[topic] = channelTwitchId;
ListenToTopic(topic);
}

/// <inheritdoc />
/// <summary>
/// The broadcaster or a moderator updates the low trust status of a user, or a new message has been sent in chat by a potential ban evader or a bans shared user.
Expand All @@ -1005,7 +1011,7 @@ public void Connect()
{
ConnectAsync().GetAwaiter().GetResult();
}

/// <inheritdoc />
public async Task ConnectAsync()
{
Expand All @@ -1017,7 +1023,7 @@ public void Disconnect()
{
DisconnectAsync().GetAwaiter().GetResult();
}

/// <inheritdoc />
public async Task DisconnectAsync()
{
Expand Down

0 comments on commit d0c32b5

Please sign in to comment.