Implemented new event system

This commit is contained in:
Marcel Baumgartner
2023-04-20 20:18:38 +02:00
parent be608101c1
commit 30ec2820db
3 changed files with 142 additions and 0 deletions

View File

@@ -0,0 +1,132 @@
using System.Diagnostics;
using Logging.Net;
namespace Moonlight.App.Events;
public class EventSystem
{
private Dictionary<int, object> Storage = new();
private List<Subscriber> Subscribers = new();
private readonly bool Debug = true;
private readonly bool DisableWarning = false;
private readonly TimeSpan TookToLongTime = TimeSpan.FromSeconds(1);
public Task On<T>(string id, object handle, Func<T, Task> action)
{
if(Debug)
Logger.Debug($"{handle} subscribed to '{id}'");
lock (Subscribers)
{
if (!Subscribers.Any(x => x.Id == id && x.Handle == handle))
{
Subscribers.Add(new ()
{
Action = action,
Handle = handle,
Id = id
});
}
}
return Task.CompletedTask;
}
public Task Emit(string id, object? d = null)
{
int hashCode = -1;
if (d != null)
{
hashCode = d.GetHashCode();
Storage.TryAdd(hashCode, d);
}
Subscriber[] subscribers;
lock (Subscribers)
{
subscribers = Subscribers
.Where(x => x.Id == id)
.ToArray();
}
var tasks = new List<Task>();
foreach (var subscriber in subscribers)
{
tasks.Add(new Task(() =>
{
int storageId = hashCode + 0; // To create a copy of the hash code
object? data = null;
if (storageId != -1)
{
if (Storage.TryGetValue(storageId, out var value))
{
data = value;
}
else
{
Logger.Warn($"Object with the hash '{storageId}' was not present in the storage");
return;
}
}
var stopWatch = new Stopwatch();
stopWatch.Start();
var del = (Delegate)subscriber.Action;
((Task)del.DynamicInvoke(data)!).Wait();
stopWatch.Stop();
if (!DisableWarning)
{
if (stopWatch.Elapsed.TotalMilliseconds > TookToLongTime.TotalMilliseconds)
{
Logger.Warn($"Subscriber {subscriber.Handle} for event '{subscriber.Id}' took long to process. {stopWatch.Elapsed.TotalMilliseconds}ms");
}
}
if (Debug)
{
Logger.Debug($"Subscriber {subscriber.Handle} for event '{subscriber.Id}' took {stopWatch.Elapsed.TotalMilliseconds}ms");
}
}));
}
foreach (var task in tasks)
{
task.Start();
}
Task.Run(() =>
{
Task.WaitAll(tasks.ToArray());
Storage.Remove(hashCode);
Logger.Debug($"Completed all event tasks for '{id}' and removed object from storage");
});
if(Debug)
Logger.Debug($"Completed event emit '{id}'");
return Task.CompletedTask;
}
public Task Off(string id, object handle)
{
if(Debug)
Logger.Debug($"{handle} unsubscribed to '{id}'");
lock (Subscribers)
{
Subscribers.RemoveAll(x => x.Id == id && x.Handle == handle);
}
return Task.CompletedTask;
}
}

View File

@@ -0,0 +1,8 @@
namespace Moonlight.App.Events;
public class Subscriber
{
public string Id { get; set; }
public object Action { get; set; }
public object Handle { get; set; }
}

View File

@@ -4,6 +4,7 @@ using CurrieTechnologies.Razor.SweetAlert2;
using Logging.Net; using Logging.Net;
using Moonlight.App.ApiClients.CloudPanel; using Moonlight.App.ApiClients.CloudPanel;
using Moonlight.App.Database; using Moonlight.App.Database;
using Moonlight.App.Events;
using Moonlight.App.Helpers; using Moonlight.App.Helpers;
using Moonlight.App.LogMigrator; using Moonlight.App.LogMigrator;
using Moonlight.App.Repositories; using Moonlight.App.Repositories;
@@ -105,6 +106,7 @@ namespace Moonlight
builder.Services.AddScoped<WebSpaceService>(); builder.Services.AddScoped<WebSpaceService>();
builder.Services.AddScoped<StatisticsViewService>(); builder.Services.AddScoped<StatisticsViewService>();
builder.Services.AddSingleton<DateTimeService>(); builder.Services.AddSingleton<DateTimeService>();
builder.Services.AddSingleton<EventSystem>();
builder.Services.AddScoped<GoogleOAuth2Service>(); builder.Services.AddScoped<GoogleOAuth2Service>();
builder.Services.AddScoped<DiscordOAuth2Service>(); builder.Services.AddScoped<DiscordOAuth2Service>();