using API.Schema; using API.Schema.Jobs; using API.Schema.NotificationConnectors; using log4net; using log4net.Config; namespace API; public static class Tranga { public static Thread NotificationSenderThread { get; } = new (NotificationSender); public static Thread JobStarterThread { get; } = new (JobStarter); private static readonly Dictionary RunningJobs = new(); private static readonly ILog Log = LogManager.GetLogger(typeof(Tranga)); internal static void StartLogger() { BasicConfigurator.Configure(); } private static void NotificationSender(object? pgsqlContext) { if(pgsqlContext is null) return; PgsqlContext context = (PgsqlContext)pgsqlContext; IQueryable staleNotifications = context.Notifications.Where(n => n.Urgency < NotificationUrgency.Normal); context.Notifications.RemoveRange(staleNotifications); context.SaveChanges(); while (true) { SendNotifications(context, NotificationUrgency.High); SendNotifications(context, NotificationUrgency.Normal); SendNotifications(context, NotificationUrgency.Low); context.SaveChanges(); Thread.Sleep(2000); } } private static void SendNotifications(PgsqlContext context, NotificationUrgency urgency) { List notifications = context.Notifications.Where(n => n.Urgency == urgency).ToList(); if (notifications.Any()) { DateTime max = notifications.MaxBy(n => n.Date)!.Date; if (DateTime.Now.Subtract(max) > TrangaSettings.NotificationUrgencyDelay(urgency)) { foreach (NotificationConnector notificationConnector in context.NotificationConnectors) { foreach (Notification notification in notifications) notificationConnector.SendNotification(notification.Title, notification.Message); } context.Notifications.RemoveRange(notifications); } } context.SaveChanges(); } private static void JobStarter(object? pgsqlContext) { if(pgsqlContext is null) return; PgsqlContext context = (PgsqlContext)pgsqlContext; string TRANGA = "\n\n _______ \n|_ _|.----..---.-..-----..-----..---.-.\n | | | _|| _ || || _ || _ |\n |___| |__| |___._||__|__||___ ||___._|\n |_____| \n\n"; Log.Info(TRANGA); List newJobs = new(); while (true) { List completedJobs = context.Jobs.Where(j => j.state == JobState.Completed).ToList(); foreach (Job job in completedJobs) if(job.RecurrenceMs < 1) context.Jobs.Remove(job); else { job.LastExecution = DateTime.UtcNow; job.state = JobState.Waiting; context.Jobs.Update(job); } List runJobs = context.Jobs.Where(j => j.state <= JobState.Running && j.NextExecution < DateTime.UtcNow).ToList(); foreach (Job job in runJobs) { Thread t = new (() => { newJobs.AddRange(job.Run()); }); RunningJobs.Add(t, job); t.Start(); context.Jobs.Update(job); } context.Jobs.AddRange(newJobs); newJobs.Clear(); (Thread, Job)[] removeFromThreadsList = RunningJobs.Where(t => !t.Key.IsAlive) .Select(t => (t.Key, t.Value)).ToArray(); foreach ((Thread thread, Job job) thread in removeFromThreadsList) { RunningJobs.Remove(thread.thread); context.Jobs.Update(thread.job); } context.SaveChanges(); Thread.Sleep(2000); } } }